~ubuntu-branches/ubuntu/trusty/argyll/trusty-proposed

« back to all changes in this revision

Viewing changes to libusb1/libusb/os/driver/transfer.c

  • Committer: Package Import Robot
  • Author(s): Artur Rona
  • Date: 2014-02-12 00:35:39 UTC
  • mfrom: (13.1.24 sid)
  • Revision ID: package-import@ubuntu.com-20140212003539-24tautzlitsiz61w
Tags: 1.5.1-5ubuntu1
* Merge from Debian unstable. (LP: #1275572) Remaining changes:
  - debian/control:
    + Build-depend on libtiff-dev rather than libtiff4-dev.
  - debian/control, debian/patches/06_fix_udev_rule.patch:
    + Fix udev rules to actually work; ENV{ACL_MANAGE} has
      stopped working ages ago, and with logind it's now the
      "uaccess" tag. Dropping also consolekit from Recommends.
  - debian/patches/drop-usb-db.patch:
    + Use hwdb builtin, instead of the obsolete usb-db
      in the udev rules.
* debian/patches/05_ftbfs-underlinkage.diff:
  - Dropped change, no needed anymore.
* Refresh the patches.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* LIBUSB-WIN32, Generic Windows USB Library
2
 
 * Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
3
 
 *
4
 
 * This program is free software; you can redistribute it and/or modify
5
 
 * it under the terms of the GNU General Public License as published by
6
 
 * the Free Software Foundation; either version 2 of the License, or
7
 
 * (at your option) any later version.
8
 
 *
9
 
 * This program is distributed in the hope that it will be useful,
10
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
 * GNU General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU General Public License
15
 
 * along with this program; if not, write to the Free Software
16
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 
 */
18
 
 
19
 
 
20
 
#include "libusb_driver.h"
21
 
 
22
 
 
23
 
typedef struct {
24
 
  URB *urb;
25
 
  int sequence;
26
 
} context_t;
27
 
 
28
 
static int sequence = 0;
29
 
 
30
 
NTSTATUS DDKAPI transfer_complete(DEVICE_OBJECT *device_object, 
31
 
                                  IRP *irp, void *context);
32
 
 
33
 
static NTSTATUS create_urb(libusb_device_t *dev, URB **urb, int direction, 
34
 
                           int urb_function, int endpoint, int packet_size, 
35
 
                           MDL *buffer, int size);
36
 
 
37
 
NTSTATUS transfer(libusb_device_t *dev, IRP *irp,
38
 
                  int direction, int urb_function, int endpoint, 
39
 
                  int packet_size, MDL *buffer, int size)
40
 
{
41
 
  IO_STACK_LOCATION *stack_location = NULL;
42
 
  context_t *context;
43
 
  NTSTATUS status = STATUS_SUCCESS;
44
 
 
45
 
  DEBUG_PRINT_NL();
46
 
 
47
 
  if(urb_function == URB_FUNCTION_ISOCH_TRANSFER)
48
 
    DEBUG_MESSAGE("transfer(): isochronous transfer");
49
 
  else
50
 
    DEBUG_MESSAGE("transfer(): bulk or interrupt transfer");
51
 
 
52
 
  if(direction == USBD_TRANSFER_DIRECTION_IN)
53
 
    DEBUG_MESSAGE("transfer(): direction in");
54
 
  else
55
 
    DEBUG_MESSAGE("transfer(): direction out");
56
 
 
57
 
  DEBUG_MESSAGE("transfer(): endpoint 0x%02x", endpoint);
58
 
 
59
 
  if(urb_function == URB_FUNCTION_ISOCH_TRANSFER)
60
 
    DEBUG_MESSAGE("transfer(): packet_size 0x%x", packet_size);
61
 
 
62
 
  DEBUG_MESSAGE("transfer(): size %d", size);
63
 
  DEBUG_MESSAGE("transfer(): sequence %d", sequence);
64
 
  DEBUG_PRINT_NL();
65
 
 
66
 
  if(!dev->config.value)
67
 
    {
68
 
      DEBUG_ERROR("transfer(): invalid configuration 0");
69
 
      remove_lock_release(dev);
70
 
      return complete_irp(irp, STATUS_INVALID_DEVICE_STATE, 0);
71
 
    }
72
 
  
73
 
  context = ExAllocatePool(NonPagedPool, sizeof(context_t));
74
 
 
75
 
  if(!context)
76
 
    {
77
 
      remove_lock_release(dev);
78
 
      return complete_irp(irp, STATUS_NO_MEMORY, 0);
79
 
    }
80
 
 
81
 
  status = create_urb(dev, &context->urb, direction, urb_function, 
82
 
                      endpoint, packet_size, buffer, size);
83
 
    
84
 
  if(!NT_SUCCESS(status))
85
 
    {
86
 
      ExFreePool(context);
87
 
      remove_lock_release(dev);
88
 
      return complete_irp(irp, status, 0);
89
 
    }
90
 
 
91
 
  context->sequence = sequence++;
92
 
 
93
 
  stack_location = IoGetNextIrpStackLocation(irp);
94
 
    
95
 
  stack_location->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
96
 
  stack_location->Parameters.Others.Argument1 = context->urb;
97
 
  stack_location->Parameters.DeviceIoControl.IoControlCode 
98
 
    = IOCTL_INTERNAL_USB_SUBMIT_URB;
99
 
    
100
 
  IoSetCompletionRoutine(irp, transfer_complete, context,
101
 
                         TRUE, TRUE, TRUE);
102
 
    
103
 
  return IoCallDriver(dev->target_device, irp);
104
 
}
105
 
 
106
 
 
107
 
NTSTATUS DDKAPI transfer_complete(DEVICE_OBJECT *device_object, IRP *irp, 
108
 
                                  void *context)
109
 
{
110
 
  context_t *c = (context_t *)context;
111
 
  int transmitted = 0;
112
 
  libusb_device_t *dev = device_object->DeviceExtension;
113
 
 
114
 
  if(irp->PendingReturned)
115
 
    {
116
 
      IoMarkIrpPending(irp);
117
 
    }
118
 
 
119
 
  if(NT_SUCCESS(irp->IoStatus.Status) 
120
 
     && USBD_SUCCESS(c->urb->UrbHeader.Status))
121
 
    {
122
 
      if(c->urb->UrbHeader.Function == URB_FUNCTION_ISOCH_TRANSFER)
123
 
        {
124
 
          transmitted = c->urb->UrbIsochronousTransfer.TransferBufferLength;
125
 
        }
126
 
      if(c->urb->UrbHeader.Function == URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER)
127
 
        {
128
 
          transmitted 
129
 
            = c->urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
130
 
        }
131
 
      
132
 
      DEBUG_MESSAGE("transfer_complete(): sequence %d: %d bytes transmitted", 
133
 
                    c->sequence, transmitted);
134
 
    }
135
 
  else
136
 
    {
137
 
      if(irp->IoStatus.Status == STATUS_CANCELLED)
138
 
        {
139
 
          DEBUG_ERROR("transfer_complete(): sequence %d: timeout error",
140
 
                      c->sequence);
141
 
        }
142
 
      else
143
 
        {
144
 
          DEBUG_ERROR("transfer_complete(): sequence %d: transfer failed: "
145
 
                      "status: 0x%x, urb-status: 0x%x", 
146
 
                      c->sequence, irp->IoStatus.Status, 
147
 
                      c->urb->UrbHeader.Status);
148
 
        }
149
 
    }
150
 
 
151
 
  ExFreePool(c->urb);
152
 
  ExFreePool(c);
153
 
 
154
 
  irp->IoStatus.Information = transmitted;
155
 
 
156
 
  remove_lock_release(dev);
157
 
 
158
 
  return STATUS_SUCCESS;
159
 
}
160
 
 
161
 
 
162
 
static NTSTATUS create_urb(libusb_device_t *dev, URB **urb, int direction, 
163
 
                           int urb_function, int endpoint, int packet_size, 
164
 
                           MDL *buffer, int size)
165
 
{
166
 
  USBD_PIPE_HANDLE pipe_handle = NULL;
167
 
  int num_packets = 0;
168
 
  int i, urb_size;
169
 
 
170
 
  *urb = NULL;
171
 
  
172
 
  if(!get_pipe_handle(dev, endpoint, &pipe_handle))
173
 
    {
174
 
      DEBUG_ERROR("create_urb(): getting endpoint pipe failed");
175
 
      return STATUS_INVALID_PARAMETER;
176
 
    }
177
 
  
178
 
  /* isochronous transfer */
179
 
  if(urb_function == URB_FUNCTION_ISOCH_TRANSFER)
180
 
    {
181
 
      num_packets = (size + packet_size - 1) / packet_size;
182
 
      
183
 
      if(num_packets > 255)
184
 
        {
185
 
          DEBUG_ERROR("create_urb(): transfer size too large");
186
 
          return STATUS_INVALID_PARAMETER;
187
 
        }
188
 
      
189
 
      urb_size = sizeof(struct _URB_ISOCH_TRANSFER)
190
 
        + sizeof(USBD_ISO_PACKET_DESCRIPTOR) * num_packets;
191
 
    }
192
 
  else /* bulk or interrupt transfer */
193
 
    {
194
 
      urb_size = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
195
 
    }
196
 
  
197
 
  *urb = ExAllocatePool(NonPagedPool, urb_size);
198
 
  
199
 
  if(!*urb)
200
 
    {
201
 
      DEBUG_ERROR("create_urb(): memory allocation error");
202
 
      return STATUS_NO_MEMORY;
203
 
    }
204
 
  
205
 
  memset(*urb, 0, urb_size);
206
 
  
207
 
  (*urb)->UrbHeader.Length = (USHORT)urb_size;
208
 
  (*urb)->UrbHeader.Function = (USHORT)urb_function;
209
 
  
210
 
  /* isochronous transfer */
211
 
  if(urb_function == URB_FUNCTION_ISOCH_TRANSFER)
212
 
    {
213
 
      (*urb)->UrbIsochronousTransfer.PipeHandle = pipe_handle;
214
 
      (*urb)->UrbIsochronousTransfer.TransferFlags 
215
 
        = direction | USBD_SHORT_TRANSFER_OK | USBD_START_ISO_TRANSFER_ASAP;
216
 
      (*urb)->UrbIsochronousTransfer.TransferBufferLength = size;
217
 
      (*urb)->UrbIsochronousTransfer.TransferBufferMDL = buffer;
218
 
      (*urb)->UrbIsochronousTransfer.NumberOfPackets = num_packets;
219
 
      
220
 
      for(i = 0; i < num_packets; i++)
221
 
        {
222
 
          (*urb)->UrbIsochronousTransfer.IsoPacket[i].Offset = i * packet_size;
223
 
          (*urb)->UrbIsochronousTransfer.IsoPacket[i].Length = packet_size;
224
 
        }
225
 
    }
226
 
  /* bulk or interrupt transfer */
227
 
  else
228
 
    {
229
 
      (*urb)->UrbBulkOrInterruptTransfer.PipeHandle = pipe_handle;
230
 
      (*urb)->UrbBulkOrInterruptTransfer.TransferFlags 
231
 
        = direction | USBD_SHORT_TRANSFER_OK;
232
 
      (*urb)->UrbBulkOrInterruptTransfer.TransferBufferLength = size;
233
 
      (*urb)->UrbBulkOrInterruptTransfer.TransferBufferMDL = buffer;
234
 
    }
235
 
 
236
 
  return STATUS_SUCCESS;
237
 
}
238