~ubuntu-branches/ubuntu/lucid/ndiswrapper/lucid

« back to all changes in this revision

Viewing changes to driver/usb.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott James Remnant
  • Date: 2005-11-16 23:39:48 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051116233948-00yddqygl6w65vzg
Tags: 1.5-1ubuntu1
Resynchronise with Debian.  (Totally me!)

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
#include "ndis.h"
17
17
#include "usb.h"
18
18
 
19
 
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
20
 
 
21
 
#define WRAP_ALLOC_URB(a, b)  usb_alloc_urb(a)
22
 
#define WRAP_SUBMIT_URB(a, b) usb_submit_urb(a)
23
 
 
24
 
#else
25
 
 
26
 
#define WRAP_ALLOC_URB(a, b)  usb_alloc_urb(a, b)
27
 
#define WRAP_SUBMIT_URB(a, b) usb_submit_urb(a, b)
28
 
 
 
19
#ifdef USB_DEBUG
 
20
static unsigned int urb_id = 0;
29
21
#endif
30
22
 
 
23
#define DUMP_WRAP_URB(wrap_urb, dir)                                    \
 
24
        USBTRACE("urb %p (%d) %s: buf: %p, len: %d, pipe: %u",  \
 
25
                 (wrap_urb)->urb, (wrap_urb)->id,                       \
 
26
                 (dir == 0) ? "going down" : "coming back",             \
 
27
                 (wrap_urb)->urb->transfer_buffer,                      \
 
28
                 (wrap_urb)->urb->transfer_buffer_length,               \
 
29
                 (wrap_urb)->urb->pipe)
 
30
 
 
31
#define DUMP_BUFFER(buf, len)                                           \
 
32
        while (debug >= 2) {                                            \
 
33
                int __i;                                                \
 
34
                char __msg[100], *__t;                                  \
 
35
                if (!buf)                                               \
 
36
                        break;                                          \
 
37
                __t = __msg;                                            \
 
38
                for (__i = 0; __i < len &&                              \
 
39
                             __t < &__msg[sizeof(__msg) - 4]; __i++) {  \
 
40
                        __t += sprintf(__t, "%02X ",                    \
 
41
                                       (((UCHAR *)buf)[__i]));          \
 
42
                }                                                       \
 
43
                USBTRACE("%s", __msg);                                  \
 
44
                break;                                                  \
 
45
        }
 
46
 
31
47
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,5)
32
48
#define CUR_ALT_SETTING(intf) (intf)->cur_altsetting
33
49
#else
34
50
#define CUR_ALT_SETTING(intf) (intf)->altsetting[(intf)->act_altsetting]
35
51
#endif
36
52
 
37
 
static struct list_head completed_irps;
38
 
static KIRQL completed_irps_lock;
39
 
void usb_transfer_complete_tasklet(unsigned long dummy);
40
 
DECLARE_TASKLET(completed_irps_tasklet, usb_transfer_complete_tasklet, 0);
41
 
 
42
 
static struct list_head canceled_irps;
43
 
void usb_cancel_worker(void *dummy);
44
 
static struct work_struct cancel_usb_irp_work;
 
53
#ifndef USB_CTRL_SET_TIMEOUT
 
54
#define USB_CTRL_SET_TIMEOUT 5000
 
55
#endif
 
56
 
 
57
static int inline wrap_cancel_urb(struct urb *urb)
 
58
{
 
59
        int ret;
 
60
        ret = usb_unlink_urb(urb);
 
61
        if (ret != -EINPROGRESS) {
 
62
                WARNING("unlink failed: %d", ret);
 
63
                return ret;
 
64
        } else
 
65
                return 0;
 
66
}
 
67
 
 
68
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
 
69
 
 
70
#define URB_NO_TRANSFER_DMA_MAP         0x0004
 
71
#define URB_STATUS(wrap_urb) (wrap_urb->urb_status)
 
72
 
 
73
static void *usb_buffer_alloc(struct usb_device *udev, size_t size,
 
74
                              unsigned mem_flags, dma_addr_t *dma)
 
75
{
 
76
        return kmalloc(size, mem_flags);
 
77
}
 
78
 
 
79
static void usb_buffer_free(struct usb_device *udev, size_t size, void *addr,
 
80
                            dma_addr_t dma)
 
81
{
 
82
        kfree(addr);
 
83
}
 
84
 
 
85
static void usb_init_urb(struct urb *urb)
 
86
{
 
87
        memset(urb, 0, sizeof(*urb));
 
88
}
 
89
 
 
90
#else
 
91
 
 
92
#define URB_STATUS(wrap_urb) (wrap_urb->urb->status)
 
93
 
 
94
#endif
 
95
 
45
96
extern KSPIN_LOCK irp_cancel_lock;
46
97
 
47
 
#ifdef DUMPURBS
48
 
#define DUMP_URB(urb) do {                                              \
49
 
                int i;                                                  \
50
 
                char dbg[40], *t;                                       \
51
 
                if ((urb)->pipe & USB_DIR_IN)                           \
52
 
                        USBTRACE("URB coming back");                    \
53
 
                else                                                    \
54
 
                        USBTRACE("URB going down");                     \
55
 
                printk(KERN_DEBUG "length: %x",                         \
56
 
                       urb->transfer_buffer_length);                    \
57
 
                t = dbg;                                                \
58
 
                for (i = 0; i < urb->transfer_buffer_length &&          \
59
 
                             t < &dbg[sizeof(dbg) - 2]; i++)            \
60
 
                        t += sprintf(t, "%02X ",                        \
61
 
                                     *(((UCHAR *)urb->transfer_buffer)+i)); \
62
 
                dbg[sizeof(dbg)-1] = 0;                                 \
63
 
                printk(KERN_DEBUG "%s\n", dbg);                         \
64
 
        } while (0)
65
 
#else
66
 
#define DUMP_URB(urb)
67
 
#endif /* DUMPURBS */
68
 
 
69
 
static inline int wrap_submit_urb(struct urb *urb, int flags)
70
 
{
71
 
        int ret;
72
 
        struct irp *irp = urb->context;
73
 
 
74
 
        ret = WRAP_SUBMIT_URB(urb, flags);
75
 
        if (ret) {
76
 
                ERROR("usb_submit_urb() = %d", ret);
77
 
                usb_free_urb(urb);
78
 
                if (IRP_DRIVER_CONTEXT(irp)[2])
79
 
                        kfree(IRP_DRIVER_CONTEXT(irp)[2]);
80
 
        }
81
 
        return ret;
82
 
}
 
98
/* TODO: using a worker instead of tasklet is probably preferable,
 
99
 * since we don't know if IoCompleteRequest can be called from atomic
 
100
 * context, but with ZyDas driver the worker never gets executed, even
 
101
 * though it gets scheduled */
 
102
static struct tasklet_struct irp_complete_work;
 
103
static struct nt_list irp_complete_list;
 
104
 
 
105
static STDCALL void wrap_cancel_irp(struct device_object *dev_obj,
 
106
                                    struct irp *irp);
 
107
static void irp_complete_worker(unsigned long data);
83
108
 
84
109
int usb_init(void)
85
110
{
86
 
        kspin_lock_init(&completed_irps_lock);
87
 
        INIT_LIST_HEAD(&canceled_irps);
88
 
        INIT_LIST_HEAD(&completed_irps);
89
 
        INIT_WORK(&cancel_usb_irp_work, usb_cancel_worker, NULL);
 
111
        InitializeListHead(&irp_complete_list);
 
112
        tasklet_init(&irp_complete_work, irp_complete_worker, 0);
 
113
#ifdef USB_DEBUG
 
114
        urb_id = 0;
 
115
#endif
90
116
        return 0;
91
117
}
92
118
 
93
119
void usb_exit(void)
94
120
{
95
 
        return;
96
 
}
97
 
 
98
 
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
99
 
void usb_transfer_complete(struct urb *urb, struct pt_regs *regs)
100
 
#else
101
 
void usb_transfer_complete(struct urb *urb)
102
 
#endif
103
 
{
104
 
        struct irp *irp = urb->context;
105
 
        int cancel;
106
 
 
107
 
        USBTRACEENTER("urb = %p", urb);
108
 
 
109
 
        /* canceled via usb_unlink_urb? */
110
 
        if ((urb->status == -ENOENT) || (urb->status == -ECONNRESET))
111
 
                USBTRACEEXIT(return);
112
 
 
113
 
        /* canceled but not yet unlinked? */
114
 
        kspin_lock(&irp_cancel_lock);
115
 
        irp->cancel_routine = NULL;
116
 
        cancel = irp->cancel;
117
 
        kspin_unlock(&irp_cancel_lock);
118
 
 
119
 
        if (cancel)
120
 
                USBTRACEEXIT(return);
121
 
 
122
 
        kspin_lock(&completed_irps_lock);
123
 
        list_add_tail(&irp->completed_list, &completed_irps);
124
 
        kspin_unlock(&completed_irps_lock);
125
 
 
126
 
        tasklet_schedule(&completed_irps_tasklet);
127
 
        USBTRACEEXIT(return);
128
 
}
129
 
 
130
 
void usb_transfer_complete_tasklet(unsigned long dummy)
131
 
{
132
 
        struct irp *irp;
133
 
        struct urb *urb;
134
 
        struct io_stack_location *stack;
135
 
        union nt_urb *nt_urb;
136
 
        unsigned long flags;
137
 
 
138
 
        while (1) {
139
 
                kspin_lock_irqsave(&completed_irps_lock, flags);
140
 
 
141
 
                if (list_empty(&completed_irps)) {
142
 
                        kspin_unlock_irqrestore(&completed_irps_lock, flags);
143
 
                        USBTRACEEXIT(return);
144
 
                }
145
 
                irp = list_entry(completed_irps.next, struct irp,
146
 
                                 completed_list);
147
 
                list_del(&irp->completed_list);
148
 
 
149
 
                kspin_unlock_irqrestore(&completed_irps_lock, flags);
150
 
 
151
 
                urb = IRP_DRIVER_CONTEXT(irp)[3];
152
 
                stack = IRP_CUR_STACK_LOC(irp) - 1;
153
 
                nt_urb = stack->params.generic.arg1;
154
 
 
155
 
                USBTRACE("irp = %p, urb = %p, status = %d", irp, urb,
156
 
                          urb->status);
157
 
 
158
 
                if (urb->setup_packet)
159
 
                        kfree(urb->setup_packet);
160
 
 
161
 
                irp->pending_returned = 1;
162
 
 
163
 
                if (urb->status)
164
 
                        irp->io_status.status = STATUS_FAILURE;
165
 
                else
 
121
        tasklet_kill(&irp_complete_work);
 
122
        TRACEEXIT1(return);
 
123
}
 
124
 
 
125
int usb_init_device(struct wrapper_dev *wd)
 
126
{
 
127
        InitializeListHead(&wd->dev.usb.wrap_urb_list);
 
128
        wd->dev.usb.num_alloc_urbs = 0;
 
129
        return 0;
 
130
}
 
131
 
 
132
void usb_exit_device(struct wrapper_dev *wd)
 
133
{
 
134
        struct nt_list *ent;
 
135
        struct wrap_urb *wrap_urb;
 
136
        KIRQL irql;
 
137
 
 
138
        while (1) {
 
139
                IoAcquireCancelSpinLock(&irql);
 
140
                ent = RemoveHeadList(&wd->dev.usb.wrap_urb_list);
 
141
                IoReleaseCancelSpinLock(irql);
 
142
                if (!ent)
 
143
                        break;
 
144
                wrap_urb = container_of(ent, struct wrap_urb, list);
 
145
                if (wrap_urb->state == URB_SUBMITTED) {
 
146
                        WARNING("Windows driver %s didn't free urb: %p",
 
147
                                wd->driver->name, wrap_urb->urb);
 
148
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
 
149
                        wrap_cancel_urb(wrap_urb->urb);
 
150
#else
 
151
                        usb_kill_urb(wrap_urb->urb);
 
152
#endif
 
153
                        wrap_urb->state = URB_FREE;
 
154
                }
 
155
                usb_free_urb(wrap_urb->urb);
 
156
                kfree(wrap_urb);
 
157
        }
 
158
        wd->dev.usb.num_alloc_urbs = 0;
 
159
        return;
 
160
}
 
161
 
 
162
/* for a given Linux urb status code, return corresponding NT urb status */
 
163
static USBD_STATUS wrap_urb_status(int urb_status)
 
164
{
 
165
        switch (urb_status) {
 
166
        case 0:
 
167
                return USBD_STATUS_SUCCESS;
 
168
        case -EPROTO:
 
169
                return USBD_STATUS_BTSTUFF;
 
170
        case -EILSEQ:
 
171
                return USBD_STATUS_CRC;
 
172
        case -EPIPE:
 
173
                return USBD_STATUS_INVALID_PIPE_HANDLE;
 
174
        case -ECOMM:
 
175
                return USBD_STATUS_DATA_OVERRUN;
 
176
        case -ENOSR:
 
177
                return USBD_STATUS_DATA_UNDERRUN;
 
178
        case -EOVERFLOW:
 
179
                return USBD_STATUS_BABBLE_DETECTED;
 
180
        case -EREMOTEIO:
 
181
                return USBD_STATUS_ERROR_SHORT_TRANSFER;;
 
182
        case -ENODEV:
 
183
        case -ESHUTDOWN:
 
184
                return USBD_STATUS_DEVICE_GONE;
 
185
        case -ENOMEM:
 
186
                return USBD_STATUS_NO_MEMORY;
 
187
        default:
 
188
                return USBD_STATUS_NOT_SUPPORTED;
 
189
        }
 
190
}
 
191
 
 
192
/* for a given USBD_STATUS, return its corresponding NTSTATUS (for irp) */
 
193
static NTSTATUS nt_urb_irp_status(USBD_STATUS nt_urb_status)
 
194
{
 
195
        switch (nt_urb_status) {
 
196
        case USBD_STATUS_SUCCESS:
 
197
                return STATUS_SUCCESS;
 
198
        case USBD_STATUS_DEVICE_GONE:
 
199
                return STATUS_DEVICE_REMOVED;
 
200
        case USBD_STATUS_PENDING:
 
201
                return STATUS_PENDING;
 
202
        case USBD_STATUS_NOT_SUPPORTED:
 
203
                return STATUS_NOT_IMPLEMENTED;
 
204
        case USBD_STATUS_NO_MEMORY:
 
205
                return STATUS_NO_MEMORY;
 
206
        default:
 
207
                return STATUS_FAILURE;
 
208
        }
 
209
}
 
210
 
 
211
static void wrap_free_urb(struct urb *urb)
 
212
{
 
213
        struct irp *irp;
 
214
        struct wrap_urb *wrap_urb;
 
215
        struct wrapper_dev *wd;
 
216
 
 
217
        USBTRACE("freeing urb: %p", urb);
 
218
        wrap_urb = urb->context;
 
219
        irp = wrap_urb->irp;
 
220
        IoAcquireCancelSpinLock(&irp->cancel_irql);
 
221
        wd = irp->wd;
 
222
        irp->cancel_routine = NULL;
 
223
        irp->wrap_urb = NULL;
 
224
        if (urb->transfer_buffer &&
 
225
            (wrap_urb->alloc_flags & URB_NO_TRANSFER_DMA_MAP)) {
 
226
                USBTRACE("freeing DMA buffer for URB: %p %p",
 
227
                         urb, urb->transfer_buffer);
 
228
                usb_buffer_free(irp->wd->dev.usb.udev,
 
229
                                urb->transfer_buffer_length, 
 
230
                                urb->transfer_buffer, urb->transfer_dma);
 
231
        }
 
232
        if (urb->setup_packet)
 
233
                kfree(urb->setup_packet);
 
234
        if (wd->dev.usb.num_alloc_urbs > MAX_ALLOCATED_URBS) {
 
235
                RemoveEntryList(&wrap_urb->list);
 
236
                wd->dev.usb.num_alloc_urbs--;
 
237
                usb_free_urb(urb);
 
238
                kfree(wrap_urb);
 
239
        } else {
 
240
                wrap_urb->state = URB_FREE;
 
241
                wrap_urb->alloc_flags = 0;
 
242
                wrap_urb->irp = NULL;
 
243
        }
 
244
        if (wd->dev.usb.num_alloc_urbs < 0)
 
245
                WARNING("num_allocated_urbs: %d",
 
246
                        wd->dev.usb.num_alloc_urbs);
 
247
        IoReleaseCancelSpinLock(irp->cancel_irql);
 
248
        return;
 
249
}
 
250
 
 
251
void wrap_suspend_urbs(struct wrapper_dev *wd)
 
252
{
 
253
        /* TODO: do we need to cancel urbs? */
 
254
}
 
255
 
 
256
void wrap_resume_urbs(struct wrapper_dev *wd)
 
257
{
 
258
        /* TODO: do we need to resubmit urbs? */
 
259
}
 
260
 
 
261
static struct urb *wrap_alloc_urb(struct irp *irp, unsigned int pipe,
 
262
                                  void *buf, unsigned int buf_len)
 
263
{
 
264
        struct urb *urb;
 
265
        unsigned int alloc_flags;
 
266
        struct wrap_urb *wrap_urb;
 
267
        struct wrapper_dev *wd;
 
268
 
 
269
        if (current_irql() < DISPATCH_LEVEL)
 
270
                alloc_flags = GFP_KERNEL;
 
271
        else
 
272
                alloc_flags = GFP_ATOMIC;
 
273
        wd = irp->wd;
 
274
        IoAcquireCancelSpinLock(&irp->cancel_irql);
 
275
        urb = NULL;
 
276
        nt_list_for_each_entry(wrap_urb, &wd->dev.usb.wrap_urb_list, list) {
 
277
                if (wrap_urb->state == URB_FREE) {
 
278
                        wrap_urb->state = URB_ALLOCATED;
 
279
                        urb = wrap_urb->urb;
 
280
                        usb_init_urb(urb);
 
281
                        break;
 
282
                }
 
283
        }
 
284
 
 
285
        if (!urb) {
 
286
                IoReleaseCancelSpinLock(irp->cancel_irql);
 
287
                wrap_urb = kmalloc(sizeof(*wrap_urb), alloc_flags);
 
288
                if (!wrap_urb) {
 
289
                        WARNING("couldn't allocate memory");
 
290
                        return NULL;
 
291
                }
 
292
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 
293
                urb = usb_alloc_urb(0, alloc_flags);
 
294
#else
 
295
                urb = usb_alloc_urb(0);
 
296
#endif
 
297
                if (!urb) {
 
298
                        WARNING("couldn't allocate urb");
 
299
                        kfree(wrap_urb);
 
300
                        return NULL;
 
301
                }
 
302
                IoAcquireCancelSpinLock(&irp->cancel_irql);
 
303
                memset(wrap_urb, 0, sizeof(*wrap_urb));
 
304
                wrap_urb->urb = urb;
 
305
                wrap_urb->state = URB_ALLOCATED;
 
306
                InsertTailList(&wd->dev.usb.wrap_urb_list, &wrap_urb->list);
 
307
                wd->dev.usb.num_alloc_urbs++;
 
308
        }
 
309
 
 
310
#ifdef USB_ASYNC_UNLINK
 
311
        urb->transfer_flags |= URB_ASYNC_UNLINK;
 
312
#endif
 
313
        urb->context = wrap_urb;
 
314
        wrap_urb->irp = irp;
 
315
        wrap_urb->state = URB_ALLOCATED;
 
316
        wrap_urb->pipe = pipe;
 
317
        irp->wrap_urb = wrap_urb;
 
318
        irp->cancel_routine = wrap_cancel_irp;
 
319
        IoReleaseCancelSpinLock(irp->cancel_irql);
 
320
        USBTRACE("allocated urb: %p", urb);
 
321
        if (buf_len && buf) {
 
322
                if (virt_addr_valid(buf))
 
323
                        urb->transfer_buffer = buf;
 
324
                else {
 
325
                        urb->transfer_buffer =
 
326
                                usb_buffer_alloc(irp->wd->dev.usb.udev,
 
327
                                                 buf_len, alloc_flags,
 
328
                                                 &urb->transfer_dma);
 
329
                        if (!urb->transfer_buffer) {
 
330
                                WARNING("couldn't allocate dma buf");
 
331
                                IoAcquireCancelSpinLock(&irp->cancel_irql);
 
332
                                wrap_urb->state = URB_FREE;
 
333
                                wrap_urb->irp = NULL;
 
334
                                irp->wrap_urb = NULL;
 
335
                                IoReleaseCancelSpinLock(irp->cancel_irql);
 
336
                                return NULL;
 
337
                        }
 
338
                        urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
339
                        wrap_urb->alloc_flags |= URB_NO_TRANSFER_DMA_MAP;
 
340
                        if (usb_pipeout(pipe))
 
341
                                memcpy(urb->transfer_buffer, buf, buf_len);
 
342
                        USBTRACE("DMA buffer for urb %p is %p",
 
343
                                 urb, urb->transfer_buffer);
 
344
                }
 
345
        } else
 
346
                urb->transfer_buffer = NULL;
 
347
        urb->transfer_buffer_length = buf_len;
 
348
        return urb;
 
349
}
 
350
 
 
351
NTSTATUS wrap_submit_urb(struct irp *irp)
 
352
{
 
353
        int ret;
 
354
        struct urb *urb;
 
355
        unsigned int alloc_flags;
 
356
        NTSTATUS status;
 
357
        union nt_urb *nt_urb;
 
358
 
 
359
        if (current_irql() < DISPATCH_LEVEL)
 
360
                alloc_flags = GFP_KERNEL;
 
361
        else
 
362
                alloc_flags = GFP_ATOMIC;
 
363
        IoAcquireCancelSpinLock(&irp->cancel_irql);
 
364
        urb = irp->wrap_urb->urb;
 
365
        nt_urb = URB_FROM_IRP(irp);
 
366
        if (irp->wrap_urb->state != URB_ALLOCATED) {
 
367
                ERROR("urb %p is in wrong state: %d",
 
368
                      urb, irp->wrap_urb->state);
 
369
                status = NT_URB_STATUS(nt_urb) = USBD_STATUS_REQUEST_FAILED;
 
370
                irp->io_status.status = STATUS_NOT_SUPPORTED;
 
371
                irp->io_status.status_info = 0;
 
372
                IoReleaseCancelSpinLock(irp->cancel_irql);
 
373
                return status;
 
374
        }
 
375
        irp->wrap_urb->state = URB_SUBMITTED;
 
376
#ifdef USB_DEBUG
 
377
        irp->wrap_urb->id = urb_id++;
 
378
#endif
 
379
        IoReleaseCancelSpinLock(irp->cancel_irql);
 
380
        DUMP_WRAP_URB(irp->wrap_urb, 0);
 
381
        irp->io_status.status = STATUS_PENDING;
 
382
        irp->io_status.status_info = 0;
 
383
        NT_URB_STATUS(nt_urb) = USBD_STATUS_PENDING;
 
384
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 
385
        ret = usb_submit_urb(urb, alloc_flags);
 
386
#else
 
387
        ret = usb_submit_urb(urb);
 
388
#endif
 
389
        if (ret) {
 
390
                USBTRACE("ret: %d", ret);
 
391
                wrap_free_urb(urb);
 
392
                irp->io_status.status = STATUS_NOT_SUPPORTED;
 
393
                irp->io_status.status_info = 0;
 
394
                NT_URB_STATUS(nt_urb) = USBD_STATUS_REQUEST_FAILED;
 
395
                USBEXIT(return irp->io_status.status);
 
396
        } else
 
397
                USBEXIT(return STATUS_PENDING);
 
398
}
 
399
 
 
400
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 
401
static void wrap_urb_complete(struct urb *urb, struct pt_regs *regs)
 
402
#else
 
403
static void wrap_urb_complete(struct urb *urb)
 
404
#endif
 
405
{
 
406
        struct irp *irp;
 
407
        struct wrap_urb *wrap_urb;
 
408
 
 
409
        wrap_urb = urb->context;
 
410
        irp = wrap_urb->irp;
 
411
        IoAcquireCancelSpinLock(&irp->cancel_irql);
 
412
        DUMP_WRAP_URB(wrap_urb, 1);
 
413
        irp->cancel_routine = NULL;
 
414
        if (wrap_urb->state != URB_SUBMITTED &&
 
415
            wrap_urb->state != URB_CANCELED)
 
416
                WARNING("urb %p in wrong state: %d", urb, wrap_urb->state);
 
417
        wrap_urb->state = URB_COMPLETED;
 
418
        /* To prevent 2.4 kernels from resubmiting interrupt URBs
 
419
         * (Windows driver also resubmits them); UHCI doesn't resubmit
 
420
         * URB if status == -ENOENT */
 
421
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
 
422
        if (usb_pipeint(urb->pipe)) {
 
423
                wrap_urb->urb_status = urb->status;
 
424
                urb->status = -ENOENT;
 
425
        }
 
426
#endif
 
427
        InsertTailList(&irp_complete_list, &irp->complete_list);
 
428
        IoReleaseCancelSpinLock(irp->cancel_irql);
 
429
        USBTRACE("urb %p (irp: %p) completed", urb, irp);
 
430
        tasklet_schedule(&irp_complete_work);
 
431
}
 
432
 
 
433
/* one worker for all devices */
 
434
static void irp_complete_worker(unsigned long data)
 
435
{
 
436
        struct irp *irp;
 
437
        struct urb *urb;
 
438
        struct usbd_bulk_or_intr_transfer *bulk_int_tx;
 
439
        struct usbd_vendor_or_class_request *vc_req;
 
440
        union nt_urb *nt_urb;
 
441
        struct wrap_urb *wrap_urb;
 
442
        struct nt_list *ent;
 
443
        KIRQL irql;
 
444
 
 
445
        while (1) {
 
446
                IoAcquireCancelSpinLock(&irql);
 
447
                ent = RemoveHeadList(&irp_complete_list);
 
448
                IoReleaseCancelSpinLock(irql);
 
449
                if (!ent)
 
450
                        break;
 
451
                irp = container_of(ent, struct irp, complete_list);
 
452
                DUMP_IRP(irp);
 
453
                wrap_urb = irp->wrap_urb;
 
454
                urb = wrap_urb->urb;
 
455
                if (wrap_urb->state != URB_COMPLETED)
 
456
                        WARNING("urb %p in wrong state: %d",
 
457
                                urb, wrap_urb->state);
 
458
                nt_urb = URB_FROM_IRP(irp);
 
459
                USBTRACE("urb: %p, nt_urb: %p, status: %d",
 
460
                         urb, nt_urb, URB_STATUS(wrap_urb));
 
461
                switch (URB_STATUS(wrap_urb)) {
 
462
                case 0:
 
463
                        /* succesfully transferred */
 
464
                        NT_URB_STATUS(nt_urb) =
 
465
                                wrap_urb_status(URB_STATUS(wrap_urb));
166
466
                        irp->io_status.status = STATUS_SUCCESS;
167
 
                irp->io_status.status_info = urb->actual_length;
168
 
 
169
 
                /* also applies to ctrlDescReq or venClsReq */
170
 
                nt_urb->bulkIntrTrans.transferBufLen = urb->actual_length;
171
 
 
172
 
                DUMP_URB(urb);
173
 
 
174
 
                if (IRP_DRIVER_CONTEXT(irp)[2]) {
175
 
                        if (urb->pipe & USB_DIR_IN) {
176
 
                                /* also applies to ctrlDescReq or venClsReq */
177
 
                                memcpy(nt_urb->bulkIntrTrans.transferBuf,
178
 
                                       IRP_DRIVER_CONTEXT(irp)[2],
179
 
                                       nt_urb->bulkIntrTrans.transferBufLen);
 
467
                        irp->io_status.status_info = urb->actual_length;
 
468
 
 
469
                        /* from WDM examples, it seems we don't need
 
470
                         * to update MDL's byte count if MDL is used */
 
471
                        switch (nt_urb->header.function) {
 
472
                        case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
 
473
                                bulk_int_tx = &nt_urb->bulk_int_transfer;
 
474
                                bulk_int_tx->transfer_buffer_length =
 
475
                                        urb->actual_length;
 
476
                                DUMP_BUFFER(urb->transfer_buffer,
 
477
                                            urb->actual_length);
 
478
                                if ((wrap_urb->alloc_flags &
 
479
                                     URB_NO_TRANSFER_DMA_MAP) &&
 
480
                                    usb_pipein(urb->pipe))
 
481
                                        memcpy(bulk_int_tx->transfer_buffer,
 
482
                                               urb->transfer_buffer,
 
483
                                               urb->actual_length);
 
484
                                break;
 
485
                        case URB_FUNCTION_VENDOR_DEVICE:
 
486
                        case URB_FUNCTION_VENDOR_INTERFACE:
 
487
                        case URB_FUNCTION_VENDOR_ENDPOINT:
 
488
                        case URB_FUNCTION_VENDOR_OTHER:
 
489
                        case URB_FUNCTION_CLASS_DEVICE:
 
490
                        case URB_FUNCTION_CLASS_INTERFACE:
 
491
                        case URB_FUNCTION_CLASS_ENDPOINT:
 
492
                        case URB_FUNCTION_CLASS_OTHER:
 
493
                                vc_req = &nt_urb->vendor_class_request;
 
494
                                vc_req->transfer_buffer_length =
 
495
                                        urb->actual_length;
 
496
                                DUMP_BUFFER(urb->transfer_buffer,
 
497
                                            urb->actual_length);
 
498
                                DUMP_BUFFER(urb->setup_packet,
 
499
                                            sizeof(struct usb_ctrlrequest));
 
500
                                if ((wrap_urb->alloc_flags &
 
501
                                     URB_NO_TRANSFER_DMA_MAP) &&
 
502
                                    usb_pipein(urb->pipe))
 
503
                                        memcpy(vc_req->transfer_buffer,
 
504
                                               urb->transfer_buffer,
 
505
                                               urb->actual_length);
 
506
                                break;
 
507
                        default:
 
508
                                ERROR("nt_urb type: %d unknown",
 
509
                                      nt_urb->header.function);
 
510
                                break;
180
511
                        }
181
 
                        kfree(IRP_DRIVER_CONTEXT(irp)[2]);
 
512
                        break;
 
513
                case -ENOENT:
 
514
                case -ECONNRESET:
 
515
                        /* irp canceled */
 
516
                        if (wrap_urb->state == URB_SUSPEND)
 
517
                                continue;
 
518
                        NT_URB_STATUS(nt_urb) = USBD_STATUS_CANCELLED;
 
519
                        irp->io_status.status = STATUS_CANCELLED;
 
520
                        irp->io_status.status_info = 0;
 
521
                        USBTRACE("irp %p canceled", irp);
 
522
                        break;
 
523
                default:
 
524
                        NT_URB_STATUS(nt_urb) =
 
525
                                wrap_urb_status(URB_STATUS(wrap_urb));
 
526
                        irp->io_status.status =
 
527
                                nt_urb_irp_status(NT_URB_STATUS(nt_urb));
 
528
                        irp->io_status.status_info = 0;
 
529
                        USBTRACE("irp: %p, status: %d", irp,
 
530
                                 URB_STATUS(wrap_urb));
 
531
                        break;
182
532
                }
183
 
 
184
 
                IofCompleteRequest(FASTCALL_ARGS_2(irp, 0));
185
 
 
186
 
                USBTRACE("freeing urb %p", urb);
187
 
                usb_free_urb(urb);
 
533
                wrap_free_urb(urb);
 
534
                IoCompleteRequest(irp, IO_NO_INCREMENT);
188
535
        }
189
 
}
190
 
 
191
 
/* this is called holding irp_cancel_lock */
192
 
STDCALL void usb_cancel_transfer(struct device_object *dev_obj,
193
 
                                 struct irp *irp)
194
 
{
195
 
        struct urb *urb;
196
 
 
197
 
        USBTRACEENTER("irp = %p", irp);
198
 
        urb = IRP_DRIVER_CONTEXT(irp)[3];
199
 
        USBTRACE("adding urb %p to cancel", urb);
200
 
 
201
 
        /* while this function can run at DISPATCH_LEVEL,
202
 
         * usb_unlink/kill_urb will only work successfully in
203
 
         * schedulable context */
204
 
        list_add_tail(&irp->cancel_list, &canceled_irps);
205
 
 
206
 
        schedule_work(&cancel_usb_irp_work);
207
 
}
208
 
 
209
 
void usb_cancel_worker(void *dummy)
210
 
{
211
 
        struct irp *irp;
212
 
        struct urb *urb;
213
 
 
214
 
        USBTRACEENTER("%s", "");
215
 
 
216
 
        while (1) {
217
 
                kspin_lock(&irp_cancel_lock);
218
 
 
219
 
                if (list_empty(&canceled_irps)) {
220
 
                        kspin_unlock(&irp_cancel_lock);
221
 
                        USBTRACEEXIT(return);
222
 
                }
223
 
                irp = list_entry(canceled_irps.next, struct irp, cancel_list);
224
 
                list_del(&irp->cancel_list);
225
 
 
226
 
                kspin_unlock(&irp_cancel_lock);
227
 
 
228
 
                urb = IRP_DRIVER_CONTEXT(irp)[3];
229
 
 
230
 
                USBTRACE("freeing urb = %p", urb);
231
 
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,8)
232
 
                usb_kill_urb(urb);
233
 
#else
234
 
                if (usb_unlink_urb(urb) < 0)
235
 
                        USBTRACEEXIT(return);
236
 
#endif
237
 
                if (urb->setup_packet)
238
 
                        kfree(urb->setup_packet);
239
 
 
240
 
                usb_free_urb(urb);
241
 
                if (IRP_DRIVER_CONTEXT(irp)[2])
242
 
                        kfree(IRP_DRIVER_CONTEXT(irp)[2]);
243
 
 
244
 
                irp->io_status.status = STATUS_CANCELLED;
 
536
        return;
 
537
}
 
538
 
 
539
static STDCALL void wrap_cancel_irp(struct device_object *dev_obj,
 
540
                                    struct irp *irp)
 
541
{
 
542
        struct urb *urb;
 
543
 
 
544
        /* NB: this function is called holding Cancel spinlock */
 
545
        USBENTER("irp: %p", irp);
 
546
        urb = irp->wrap_urb->urb;
 
547
        USBTRACE("canceling urb %p", urb);
 
548
        if (irp->wrap_urb->state == URB_SUBMITTED &&
 
549
            wrap_cancel_urb(urb) == 0) {
 
550
                USBTRACE("urb %p canceled", urb);
 
551
                irp->wrap_urb->state = URB_CANCELED;
 
552
                /* this IRP will be returned in urb's completion function */
 
553
                IoReleaseCancelSpinLock(irp->cancel_irql);
 
554
        } else {
 
555
                union nt_urb *nt_urb;
 
556
                nt_urb = URB_FROM_IRP(irp);
 
557
                ERROR("urb %p not canceld: %d", urb, irp->wrap_urb->state);
 
558
                NT_URB_STATUS(nt_urb) = USBD_STATUS_REQUEST_FAILED;
 
559
                irp->io_status.status = STATUS_INVALID_PARAMETER;
245
560
                irp->io_status.status_info = 0;
246
 
                IofCompleteRequest(FASTCALL_ARGS_2(irp, 0));
 
561
                IoReleaseCancelSpinLock(irp->cancel_irql);
 
562
                wrap_free_urb(urb);
 
563
                IoCompleteRequest(irp, IO_NO_INCREMENT);
247
564
        }
248
565
}
249
566
 
250
 
unsigned long usb_bulk_or_intr_trans(struct usb_device *dev,
251
 
                                     union nt_urb *nt_urb, struct irp *irp)
 
567
static USBD_STATUS wrap_bulk_or_intr_trans(struct irp *irp)
252
568
{
253
 
        union pipe_handle pipe_handle;
 
569
        usbd_pipe_handle pipe_handle;
254
570
        struct urb *urb;
255
571
        unsigned int pipe;
256
 
        int ret;
257
 
        UCHAR endpoint;
258
 
 
259
 
        ASSERT(!nt_urb->bulkIntrTrans.transferBufMdl);
260
 
        ASSERT(!nt_urb->bulkIntrTrans.urbLink);
261
 
        USBTRACE("flags = %lX, length = %lu, buffer = %p",
262
 
                  nt_urb->bulkIntrTrans.transferFlags,
263
 
                  nt_urb->bulkIntrTrans.transferBufLen,
264
 
                  nt_urb->bulkIntrTrans.transferBuf);
265
 
 
266
 
        /* FIXME: we should better check what GFP_ is required */
267
 
        urb = WRAP_ALLOC_URB(0, GFP_ATOMIC);
268
 
        if (!urb)
269
 
                return -ENOMEM;
270
 
 
271
 
        /* store the linux-urb in the nt-irp and set the cancel routine */
272
 
        IRP_DRIVER_CONTEXT(irp)[3] = urb;
273
 
        irp->cancel_routine = usb_cancel_transfer;
274
 
 
275
 
        pipe_handle = nt_urb->bulkIntrTrans.pipeHandle;
276
 
 
277
 
        endpoint = pipe_handle.encoded.endpointAddr;
278
 
        switch(pipe_handle.encoded.pipeType) {
279
 
        case USB_ENDPOINT_XFER_CONTROL:
280
 
                if (nt_urb->bulkIntrTrans.transferFlags &
281
 
                    USBD_TRANSFER_DIRECTION_IN)
282
 
                        pipe = usb_rcvctrlpipe(dev, endpoint);
283
 
                else
284
 
                        pipe = usb_sndctrlpipe(dev, endpoint);
285
 
 
286
 
                usb_fill_control_urb(urb, dev, pipe, urb->setup_packet,
287
 
                                     nt_urb->bulkIntrTrans.transferBuf,
288
 
                                     nt_urb->bulkIntrTrans.transferBufLen,
289
 
                                     usb_transfer_complete, irp);
290
 
                break;
291
 
        case USB_ENDPOINT_XFER_ISOC:
292
 
                if (nt_urb->bulkIntrTrans.transferFlags &
293
 
                    USBD_TRANSFER_DIRECTION_IN)
294
 
                        pipe = usb_rcvisocpipe(dev, endpoint);
295
 
                else
296
 
                        pipe = usb_sndisocpipe(dev, endpoint);
297
 
                break;
 
572
        struct usbd_bulk_or_intr_transfer *bulk_int_tx;
 
573
        USBD_STATUS status;
 
574
        struct usb_device *udev;
 
575
        union nt_urb *nt_urb;
 
576
 
 
577
        nt_urb = URB_FROM_IRP(irp);
 
578
        udev = irp->wd->dev.usb.udev;
 
579
        bulk_int_tx = &nt_urb->bulk_int_transfer;
 
580
        USBTRACE("flags = %X, length = %u, buffer = %p",
 
581
                  bulk_int_tx->transfer_flags,
 
582
                  bulk_int_tx->transfer_buffer_length,
 
583
                  bulk_int_tx->transfer_buffer);
 
584
 
 
585
        DUMP_IRP(irp);
 
586
        pipe_handle = bulk_int_tx->pipe_handle;
 
587
        if (bulk_int_tx->transfer_flags & USBD_TRANSFER_DIRECTION_IN)
 
588
                pipe = usb_rcvbulkpipe(udev, pipe_handle->bEndpointAddress);
 
589
        else
 
590
                pipe = usb_sndbulkpipe(udev, pipe_handle->bEndpointAddress);
 
591
 
 
592
        if (unlikely(bulk_int_tx->transfer_buffer == NULL &&
 
593
                     bulk_int_tx->transfer_buffer_length > 0)) {
 
594
                if (MmGetMdlByteCount(bulk_int_tx->mdl) !=
 
595
                    bulk_int_tx->transfer_buffer_length)
 
596
                        WARNING("mdl size %d != %d",
 
597
                                MmGetMdlByteCount(bulk_int_tx->mdl),
 
598
                                bulk_int_tx->transfer_buffer_length);
 
599
                bulk_int_tx->transfer_buffer =
 
600
                        MmGetMdlVirtualAddress(bulk_int_tx->mdl);
 
601
        }
 
602
 
 
603
        urb = wrap_alloc_urb(irp, pipe, bulk_int_tx->transfer_buffer,
 
604
                             bulk_int_tx->transfer_buffer_length);
 
605
        if (!urb) {
 
606
                ERROR("couldn't allocate urb");
 
607
                return USBD_STATUS_NO_MEMORY;
 
608
        }
 
609
        if (usb_pipein(pipe) &&
 
610
            (!(bulk_int_tx->transfer_flags & USBD_SHORT_TRANSFER_OK))) {
 
611
                USBTRACE("short not ok");
 
612
                urb->transfer_flags |= URB_SHORT_NOT_OK;
 
613
        }
 
614
 
 
615
        switch(usb_pipetype(pipe)) {
298
616
        case USB_ENDPOINT_XFER_BULK:
299
 
                if (nt_urb->bulkIntrTrans.transferFlags &
300
 
                    USBD_TRANSFER_DIRECTION_IN)
301
 
                        pipe = usb_rcvbulkpipe(dev, endpoint);
302
 
                else
303
 
                        pipe = usb_sndbulkpipe(dev, endpoint);
304
 
 
305
 
                usb_fill_bulk_urb(urb, dev, pipe,
306
 
                                  nt_urb->bulkIntrTrans.transferBuf,
307
 
                                  nt_urb->bulkIntrTrans.transferBufLen,
308
 
                                  usb_transfer_complete, irp);
 
617
                usb_fill_bulk_urb(urb, udev, pipe, urb->transfer_buffer,
 
618
                                  bulk_int_tx->transfer_buffer_length,
 
619
                                  wrap_urb_complete, urb->context);
 
620
                USBTRACE("submitting bulk urb %p on pipe %u",
 
621
                         urb, pipe_handle->bEndpointAddress);
 
622
                status = USBD_STATUS_PENDING;
309
623
                break;
310
624
        case USB_ENDPOINT_XFER_INT:
311
 
                if (nt_urb->bulkIntrTrans.transferFlags &
312
 
                    USBD_TRANSFER_DIRECTION_IN)
313
 
                        pipe = usb_rcvintpipe(dev, endpoint);
314
 
                else
315
 
                        pipe = usb_sndintpipe(dev, endpoint);
316
 
 
317
 
                usb_fill_int_urb(urb, dev, pipe,
318
 
                                 nt_urb->bulkIntrTrans.transferBuf,
319
 
                                 nt_urb->bulkIntrTrans.transferBufLen,
320
 
                                 usb_transfer_complete, irp,
321
 
                                 pipe_handle.encoded.interval);
 
625
                usb_fill_int_urb(urb, udev, pipe, urb->transfer_buffer,
 
626
                                 bulk_int_tx->transfer_buffer_length,
 
627
                                 wrap_urb_complete, urb->context,
 
628
                                 pipe_handle->bInterval);
 
629
                USBTRACE("submitting interrupt urb %p on pipe %u, intvl: %d",
 
630
                         urb, pipe_handle->bEndpointAddress,
 
631
                         pipe_handle->bInterval);
 
632
                status = USBD_STATUS_PENDING;
322
633
                break;
323
634
        default:
324
 
                ERROR("unknown pipe type: %d", pipe_handle.encoded.pipeType);
325
 
                return -EINVAL;
326
 
        }
327
 
 
328
 
        if ((nt_urb->venClsReq.transferFlags &
329
 
             (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK)) ==
330
 
            USBD_TRANSFER_DIRECTION_IN)
331
 
                urb->transfer_flags |= URB_SHORT_NOT_OK;
332
 
 
333
 
        DUMP_URB(urb);
334
 
 
335
 
        /* non-DMA-capable buffers have to be mirrored */
336
 
        IRP_DRIVER_CONTEXT(irp)[2] = NULL;
337
 
        if (!virt_addr_valid(nt_urb->bulkIntrTrans.transferBuf)) {
338
 
                IRP_DRIVER_CONTEXT(irp)[2] =
339
 
                        kmalloc(nt_urb->bulkIntrTrans.transferBufLen,
340
 
                                GFP_ATOMIC);
341
 
                if (!IRP_DRIVER_CONTEXT(irp)[2]) {
342
 
                        ERROR("%s", "kmalloc failed!");
343
 
                        usb_free_urb(urb);
344
 
                        return -ENOMEM;
345
 
                }
346
 
 
347
 
                if (!(pipe & USB_DIR_IN))
348
 
                        memcpy(IRP_DRIVER_CONTEXT(irp)[2],
349
 
                               nt_urb->bulkIntrTrans.transferBuf,
350
 
                               nt_urb->bulkIntrTrans.transferBufLen);
351
 
                urb->transfer_buffer = IRP_DRIVER_CONTEXT(irp)[2];
352
 
                USBTRACE("mirroring non-DMA buffer");
353
 
        }
354
 
 
355
 
        /* mark setup_packet as unused for cleanup procedure */
356
 
        urb->setup_packet = NULL;
357
 
 
358
 
        USBTRACE("submitting urb %p on pipe %p", urb, pipe_handle.handle);
359
 
        /* FIXME: we should better check what GFP_ is required */
360
 
        ret = wrap_submit_urb(urb, GFP_ATOMIC);
361
 
        return ret;
 
635
                ERROR("unknown pipe type: %u", pipe_handle->bEndpointAddress);
 
636
                status = USBD_STATUS_NOT_SUPPORTED;
 
637
                break;
 
638
        }
 
639
        USBEXIT(return status);
362
640
}
363
641
 
364
 
unsigned long usb_vendor_or_class_intf(struct usb_device *dev,
365
 
                                       union nt_urb *nt_urb, struct irp *irp)
 
642
static USBD_STATUS wrap_vendor_or_class_req(struct irp *irp)
366
643
{
367
644
        struct urb *urb;
368
645
        struct usb_ctrlrequest *dr;
369
646
        char req_type;
370
647
        unsigned int pipe;
371
 
        int ret;
372
 
 
373
 
        ASSERT(!nt_urb->venClsReq.transferBufMdl);
374
 
        ASSERT(!nt_urb->venClsReq.urbLink);
375
 
        USBTRACE("reservedBits = %x, request = %x, "
376
 
                  "value = %d, index = %d, transferFlags = %lx, "
377
 
                  "transferBuf = %p, transferBufLen = %ld",
378
 
                  nt_urb->venClsReq.reservedBits,
379
 
                  nt_urb->venClsReq.request, nt_urb->venClsReq.value,
380
 
                  nt_urb->venClsReq.index, nt_urb->venClsReq.transferFlags,
381
 
                  nt_urb->venClsReq.transferBuf,
382
 
                  nt_urb->venClsReq.transferBufLen);
383
 
 
384
 
        /* FIXME: we should better check what GFP_ is required */
385
 
        urb = WRAP_ALLOC_URB(0, GFP_ATOMIC);
386
 
        if (!urb) {
387
 
                ERROR("%s", "usb_alloc_urb failed!");
388
 
                return -ENOMEM;
389
 
        }
390
 
 
391
 
        req_type = USB_TYPE_VENDOR | USB_RECIP_DEVICE |
392
 
                nt_urb->venClsReq.reservedBits;
393
 
 
394
 
        if (nt_urb->venClsReq.transferFlags & USBD_TRANSFER_DIRECTION_IN) {
395
 
                pipe = usb_rcvctrlpipe(dev, 0);
 
648
        struct usbd_vendor_or_class_request *vc_req;
 
649
        struct usb_device *udev;
 
650
        union nt_urb *nt_urb;
 
651
        USBD_STATUS status;
 
652
 
 
653
        nt_urb = URB_FROM_IRP(irp);
 
654
        udev = irp->wd->dev.usb.udev;
 
655
        vc_req = &nt_urb->vendor_class_request;
 
656
        USBTRACE("bits = %x, req = %x, val = %08x, index = %08x, flags = %x,"
 
657
                 "tx_buf = %p, tx_buf_len = %d", vc_req->reserved_bits,
 
658
                 vc_req->request, vc_req->value, vc_req->index,
 
659
                 vc_req->transfer_flags, vc_req->transfer_buffer,
 
660
                 vc_req->transfer_buffer_length);
 
661
 
 
662
        switch (nt_urb->header.function) {
 
663
        case URB_FUNCTION_VENDOR_DEVICE:
 
664
                req_type = USB_TYPE_VENDOR | USB_RECIP_DEVICE;
 
665
                break;
 
666
        case URB_FUNCTION_VENDOR_INTERFACE:
 
667
                req_type = USB_TYPE_VENDOR | USB_RECIP_INTERFACE;
 
668
                break;
 
669
        case URB_FUNCTION_VENDOR_ENDPOINT:
 
670
                req_type = USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;
 
671
                break;
 
672
        case URB_FUNCTION_VENDOR_OTHER:
 
673
                req_type = USB_TYPE_VENDOR | USB_RECIP_OTHER;
 
674
                break;
 
675
        case URB_FUNCTION_CLASS_DEVICE:
 
676
                req_type = USB_TYPE_CLASS | USB_RECIP_DEVICE;
 
677
                break;
 
678
        case URB_FUNCTION_CLASS_INTERFACE:
 
679
                req_type = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
 
680
                break;
 
681
        case URB_FUNCTION_CLASS_ENDPOINT:
 
682
                req_type = USB_TYPE_CLASS | USB_RECIP_ENDPOINT;
 
683
                break;
 
684
        case URB_FUNCTION_CLASS_OTHER:
 
685
                req_type = USB_TYPE_CLASS | USB_RECIP_OTHER;
 
686
                break;
 
687
        default:
 
688
                ERROR("unknown request type: %x", nt_urb->header.function);
 
689
                req_type = 0;
 
690
                break;
 
691
        }
 
692
 
 
693
        req_type |= vc_req->reserved_bits;
 
694
        USBTRACE("req type: %08x", req_type);
 
695
 
 
696
        if (unlikely(vc_req->transfer_buffer == NULL &&
 
697
                     vc_req->transfer_buffer_length > 0)) {
 
698
                if (MmGetMdlByteCount(vc_req->mdl) !=
 
699
                    vc_req->transfer_buffer_length)
 
700
                        WARNING("mdl size %d != %d",
 
701
                                MmGetMdlByteCount(vc_req->mdl),
 
702
                                vc_req->transfer_buffer_length);
 
703
                vc_req->transfer_buffer = MmGetMdlVirtualAddress(vc_req->mdl);
 
704
        }
 
705
 
 
706
        if (vc_req->transfer_flags & USBD_TRANSFER_DIRECTION_IN) {
 
707
                pipe = usb_rcvctrlpipe(udev, 0);
396
708
                req_type |= USB_DIR_IN;
 
709
                USBTRACE("pipe: %u, dir in", pipe);
397
710
        } else {
398
 
                pipe = usb_sndctrlpipe(dev, 0);
 
711
                pipe = usb_sndctrlpipe(udev, 0);
399
712
                req_type |= USB_DIR_OUT;
400
 
        }
401
 
 
402
 
        dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
 
713
                USBTRACE("pipe: %u, dir out", pipe);
 
714
        }
 
715
 
 
716
        urb = wrap_alloc_urb(irp, pipe, vc_req->transfer_buffer,
 
717
                             vc_req->transfer_buffer_length);
 
718
        if (!urb) {
 
719
                ERROR("couldn't allocate urb");
 
720
                return USBD_STATUS_NO_MEMORY;
 
721
        }
 
722
 
 
723
        if (usb_pipein(pipe) &&
 
724
            (!(vc_req->transfer_flags & USBD_SHORT_TRANSFER_OK))) {
 
725
                USBTRACE("short not ok");
 
726
                urb->transfer_flags |= URB_SHORT_NOT_OK;
 
727
        }
 
728
 
 
729
        dr = kmalloc(sizeof(*dr), GFP_ATOMIC);
403
730
        if (!dr) {
404
 
                ERROR("%s", "kmalloc failed!");
405
 
                usb_free_urb(urb);
406
 
                return -ENOMEM;
 
731
                ERROR("couldn't allocate memory");
 
732
                wrap_free_urb(urb);
 
733
                return USBD_STATUS_NO_MEMORY;
407
734
        }
408
 
 
 
735
        memset(dr, 0, sizeof(*dr));
409
736
        dr->bRequestType = req_type;
410
 
        dr->bRequest = nt_urb->venClsReq.request;
411
 
        dr->wValue = nt_urb->venClsReq.value;
412
 
        dr->wIndex = nt_urb->venClsReq.index;
413
 
        dr->wLength = nt_urb->venClsReq.transferBufLen;
414
 
 
415
 
        usb_fill_control_urb(urb, dev, pipe, (unsigned char *)dr,
416
 
                             nt_urb->venClsReq.transferBuf,
417
 
                             nt_urb->venClsReq.transferBufLen,
418
 
                             usb_transfer_complete, irp);
419
 
 
420
 
        if ((nt_urb->venClsReq.transferFlags &
421
 
             (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK)) ==
422
 
            USBD_TRANSFER_DIRECTION_IN)
423
 
                urb->transfer_flags |= URB_SHORT_NOT_OK;
424
 
 
425
 
        DUMP_URB(urb);
426
 
 
427
 
        /* non-DMA-capable buffers have to be mirrored */
428
 
        IRP_DRIVER_CONTEXT(irp)[2] = NULL;
429
 
        if ((nt_urb->venClsReq.transferBufLen > 0) &&
430
 
            !virt_addr_valid(nt_urb->venClsReq.transferBuf)) {
431
 
                IRP_DRIVER_CONTEXT(irp)[2] =
432
 
                        kmalloc(nt_urb->venClsReq.transferBufLen, GFP_KERNEL);
433
 
                if (!IRP_DRIVER_CONTEXT(irp)[2]) {
434
 
                        ERROR("%s", "kmalloc failed!");
435
 
                        kfree(dr);
436
 
                        usb_free_urb(urb);
437
 
                        return -ENOMEM;
438
 
                }
439
 
 
440
 
                if (!(pipe & USB_DIR_IN))
441
 
                        memcpy(IRP_DRIVER_CONTEXT(irp)[2],
442
 
                               nt_urb->venClsReq.transferBuf,
443
 
                               nt_urb->venClsReq.transferBufLen);
444
 
                urb->transfer_buffer = IRP_DRIVER_CONTEXT(irp)[2];
445
 
                USBTRACE("mirroring non-DMA buffer");
 
737
        dr->bRequest = vc_req->request;
 
738
        dr->wValue = cpu_to_le16(vc_req->value);
 
739
        dr->wIndex = cpu_to_le16(vc_req->index);
 
740
        dr->wLength = cpu_to_le16(vc_req->transfer_buffer_length);
 
741
 
 
742
        usb_fill_control_urb(urb, udev, pipe, (unsigned char *)dr,
 
743
                             urb->transfer_buffer,
 
744
                             vc_req->transfer_buffer_length,
 
745
                             wrap_urb_complete, urb->context);
 
746
 
 
747
        status = USBD_STATUS_PENDING;
 
748
        USBEXIT(return status);
 
749
}
 
750
 
 
751
static USBD_STATUS wrap_reset_pipe(struct usb_device *udev, struct irp *irp)
 
752
{
 
753
        unsigned int pipe1, pipe2;
 
754
        int ret;
 
755
        union nt_urb *nt_urb;
 
756
        usbd_pipe_handle pipe_handle;
 
757
        enum pipe_type pipe_type;
 
758
 
 
759
        USBTRACE("irp = %p", irp);
 
760
        nt_urb = URB_FROM_IRP(irp);
 
761
 
 
762
        pipe_handle = nt_urb->pipe_req.pipe_handle;
 
763
        pipe_type = pipe_handle->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
 
764
        /* TODO: not clear if both directions should be cleared? */
 
765
        if (pipe_type == USB_ENDPOINT_XFER_BULK) {
 
766
                pipe1 = usb_rcvbulkpipe(udev, pipe_handle->bEndpointAddress);
 
767
                pipe2 = usb_sndbulkpipe(udev, pipe_handle->bEndpointAddress);
 
768
        } else if (pipe_type == USB_ENDPOINT_XFER_INT) {
 
769
                pipe1 = usb_rcvintpipe(udev, pipe_handle->bEndpointAddress);
 
770
                /* no outgoing interrupt pipes */
 
771
                pipe2 = pipe1;
 
772
        } else if (pipe_type == USB_ENDPOINT_XFER_CONTROL) {
 
773
                pipe1 = usb_rcvctrlpipe(udev, pipe_handle->bEndpointAddress);
 
774
                pipe2 = usb_sndctrlpipe(udev, pipe_handle->bEndpointAddress);
 
775
        } else {
 
776
                WARNING("pipe type %d not handled", pipe_type);
 
777
                return USBD_STATUS_SUCCESS;
446
778
        }
447
 
 
448
 
        /* store the linux-urb in the nt-irp and set the cancel routine */
449
 
        IRP_DRIVER_CONTEXT(irp)[3] = urb;
450
 
        irp->cancel_routine = usb_cancel_transfer;
451
 
 
452
 
        USBTRACE("submitting urb %p on control pipe", urb);
453
 
        /* FIXME: we should better check what GFP_ is required */
454
 
        ret = wrap_submit_urb(urb, GFP_ATOMIC);
 
779
        ret = usb_clear_halt(udev, pipe1);
455
780
        if (ret)
456
 
                kfree(dr);
457
 
        return ret;
458
 
}
459
 
 
460
 
unsigned long usb_reset_pipe(struct usb_device *dev,
461
 
                             union pipe_handle pipe_handle)
462
 
{
463
 
        int pipe;
464
 
        UCHAR endpoint;
465
 
 
466
 
        USBTRACE("pipe = %p", pipe_handle.handle);
467
 
        endpoint = pipe_handle.encoded.endpointAddr;
468
 
        switch (pipe_handle.encoded.pipeType) {
469
 
        case USB_ENDPOINT_XFER_CONTROL:
470
 
                if (pipe_handle.encoded.endpointAddr & USB_ENDPOINT_DIR_MASK)
471
 
                        pipe = usb_rcvctrlpipe(dev, endpoint);
472
 
                else
473
 
                        pipe = usb_sndctrlpipe(dev, endpoint);
474
 
                break;
475
 
 
476
 
        case USB_ENDPOINT_XFER_ISOC:
477
 
                if (pipe_handle.encoded.endpointAddr & USB_ENDPOINT_DIR_MASK)
478
 
                        pipe = usb_rcvisocpipe(dev, endpoint);
479
 
                else
480
 
                        pipe = usb_sndisocpipe(dev, endpoint);
481
 
                break;
482
 
 
483
 
        case USB_ENDPOINT_XFER_BULK:
484
 
                if (pipe_handle.encoded.endpointAddr & USB_ENDPOINT_DIR_MASK)
485
 
                        pipe = usb_rcvbulkpipe(dev, endpoint);
486
 
                else
487
 
                        pipe = usb_sndbulkpipe(dev, endpoint);
488
 
                break;
489
 
 
490
 
        default: /* USB_ENDPOINT_XFER_INT */
491
 
                if (pipe_handle.encoded.endpointAddr & USB_ENDPOINT_DIR_MASK)
492
 
                        pipe = usb_rcvbulkpipe(dev, endpoint);
493
 
                else
494
 
                        pipe = usb_sndbulkpipe(dev, endpoint);
495
 
                break;
496
 
        }
497
 
 
498
 
        return usb_clear_halt(dev, pipe);
499
 
}
500
 
 
501
 
unsigned long usb_select_configuration(struct usb_device *dev,
502
 
                                       union nt_urb *nt_urb, struct irp *irp)
503
 
{
504
 
        struct usb_interface *intf;
505
 
        struct usbd_pipe_information *pipe_info;
506
 
        int i, ret;
507
 
        struct usb_endpoint_descriptor *desc;
508
 
 
509
 
        ASSERT(nt_urb->selConf.config->bNumInterfaces == 1);
510
 
        USBTRACE("intf.intfNum = %d, intf.altSet = %d",
511
 
                  nt_urb->selConf.intf.intfNum, nt_urb->selConf.intf.altSet);
512
 
 
513
 
        ret = usb_set_interface(dev, nt_urb->selConf.intf.intfNum,
514
 
                                nt_urb->selConf.intf.altSet);
 
781
                WARNING("resetting pipe %d failed: %d", pipe_type, ret);
 
782
        if (pipe2 != pipe1) {
 
783
                ret = usb_clear_halt(udev, pipe2);
 
784
                if (ret)
 
785
                        WARNING("resetting pipe %d failed: %d",
 
786
                                pipe_type, ret);
 
787
        }
 
788
        return USBD_STATUS_SUCCESS;
 
789
}
 
790
 
 
791
static USBD_STATUS wrap_abort_pipe(struct usb_device *udev, struct irp *irp)
 
792
{
 
793
        union nt_urb *nt_urb;
 
794
        usbd_pipe_handle pipe_handle;
 
795
        unsigned long flags;
 
796
        struct urb *urb;
 
797
        struct wrap_urb *wrap_urb;
 
798
        struct wrapper_dev *wd;
 
799
 
 
800
        USBENTER("irp = %p", irp);
 
801
        wd = irp->wd;
 
802
        nt_urb = URB_FROM_IRP(irp);
 
803
        pipe_handle = nt_urb->pipe_req.pipe_handle;
 
804
 
 
805
        nt_urb = URB_FROM_IRP(irp);
 
806
        while (1) {
 
807
                kspin_lock_irqsave(&irp_cancel_lock, flags);
 
808
                urb = NULL;
 
809
                nt_list_for_each_entry(wrap_urb, &wd->dev.usb.wrap_urb_list,
 
810
                                       list) {
 
811
                        if (wrap_urb->state == URB_SUBMITTED &&
 
812
                            (usb_pipeendpoint(wrap_urb->pipe) ==
 
813
                             pipe_handle->bEndpointAddress)) {
 
814
                                wrap_urb->state = URB_CANCELED;
 
815
                                urb = wrap_urb->urb;
 
816
                                break;
 
817
                        }
 
818
                }
 
819
                kspin_unlock_irqrestore(&irp_cancel_lock, flags);
 
820
                if (urb) {
 
821
                        wrap_cancel_urb(urb);
 
822
                        USBTRACE("canceled urb: %p", urb);
 
823
                } else
 
824
                        break;
 
825
        }
 
826
        USBEXIT(return USBD_STATUS_SUCCESS);
 
827
}
 
828
 
 
829
static USBD_STATUS wrap_select_configuration(struct wrapper_dev *wd,
 
830
                                             union nt_urb *nt_urb,
 
831
                                             struct irp *irp)
 
832
{
 
833
        struct usbd_pipe_information *pipe;
 
834
        int i, n, ret, pipe_num;
 
835
        struct usb_endpoint_descriptor *ep;
 
836
        struct usbd_select_configuration *sel_conf;
 
837
        struct usb_device *udev;
 
838
        struct usbd_interface_information *intf;
 
839
        struct usb_config_descriptor *config;
 
840
        struct usb_interface *usb_intf;
 
841
 
 
842
        udev = wd->dev.usb.udev;
 
843
        sel_conf = &nt_urb->select_conf;
 
844
        config = sel_conf->config;
 
845
        if (config == NULL) {
 
846
                /* TODO: set to unconfigured state (configuration 0):
 
847
                 * is this correctt? */
 
848
                ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 
849
                                      USB_REQ_SET_CONFIGURATION, 0,
 
850
                                      0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
 
851
                return wrap_urb_status(ret);
 
852
        }
 
853
 
 
854
        USBTRACE("conf: %d, type: %d, length: %d, numif: %d, attr: %08x",
 
855
                 config->bConfigurationValue, config->bDescriptorType,
 
856
                 config->wTotalLength, config->bNumInterfaces,
 
857
                 config->bmAttributes);
 
858
 
 
859
        ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 
860
                              USB_REQ_SET_CONFIGURATION, 0,
 
861
                              config->bConfigurationValue, 0,
 
862
                              NULL, 0, USB_CTRL_SET_TIMEOUT);
515
863
        if (ret < 0) {
516
 
                ERROR("usb_set_interface() = %d", ret);
517
 
                USBTRACEEXIT(return ret);
518
 
        }
519
 
 
520
 
        intf = usb_ifnum_to_if(dev, nt_urb->selConf.intf.intfNum);
521
 
        if (!intf) {
522
 
                ERROR("usb_ifnum_to_if() = %d", ret);
523
 
                USBTRACEEXIT(return ret);
524
 
        }
 
864
                ERROR("ret: %d", ret);
 
865
                return wrap_urb_status(ret);
 
866
        }
 
867
 
 
868
        pipe_num = 0;
 
869
        intf = &sel_conf->intf;
 
870
        for (n = 0; n < config->bNumInterfaces && intf->bLength > 0;
 
871
             n++, intf = (((void *)intf) + intf->bLength)) {
 
872
 
 
873
                USBTRACE("intf: %d, alt setting: %d",
 
874
                         intf->bInterfaceNumber, intf->bAlternateSetting);
 
875
                ret = usb_set_interface(udev, intf->bInterfaceNumber,
 
876
                                        intf->bAlternateSetting);
 
877
                if (ret < 0) {
 
878
                        ERROR("failed with %d", ret);
 
879
                        return wrap_urb_status(ret);
 
880
                }
 
881
                usb_intf = usb_ifnum_to_if(udev, intf->bInterfaceNumber);
 
882
                if (!usb_intf) {
 
883
                        ERROR("couldn't obtain ifnum");
 
884
                        return USBD_STATUS_REQUEST_FAILED;
 
885
                }
 
886
                USBTRACE("intf: %p, num ep: %d", intf, intf->bNumEndpoints);
525
887
 
526
888
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
527
 
        for (i = 0; i < CUR_ALT_SETTING(intf)->desc.bNumEndpoints; i++) {
528
 
                desc = &(CUR_ALT_SETTING(intf)->endpoint + i)->desc;
 
889
                for (i = 0; i < CUR_ALT_SETTING(usb_intf)->desc.bNumEndpoints;
 
890
                     i++, pipe_num++) {
 
891
                        ep = &(CUR_ALT_SETTING(usb_intf)->endpoint + i)->desc;
529
892
#else
530
 
        for (i = 0; i < CUR_ALT_SETTING(intf).bNumEndpoints; i++) {
531
 
                desc = &((CUR_ALT_SETTING(intf)).endpoint[i]);
 
893
                for (i = 0; i < CUR_ALT_SETTING(usb_intf).bNumEndpoints;
 
894
                     i++, pipe_num++) {
 
895
                        ep = &((CUR_ALT_SETTING(usb_intf)).endpoint[i]);
532
896
#endif
533
 
                pipe_info = &nt_urb->selConf.intf.pipes[i];
534
 
 
535
 
                pipe_info->maxPacketSize = desc->wMaxPacketSize;
536
 
                pipe_info->endpointAddr = desc->bEndpointAddress;
537
 
                pipe_info->interval = desc->bInterval;
538
 
                pipe_info->pipeType = desc->bmAttributes;
539
 
 
540
 
                pipe_info->pipeHandle.encoded.endpointAddr =
541
 
                        desc->bEndpointAddress;
542
 
                pipe_info->pipeHandle.encoded.pipeType =
543
 
                        desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
544
 
                pipe_info->pipeHandle.encoded.interval =
545
 
                        (dev->speed == USB_SPEED_HIGH) ?
546
 
                        desc->bInterval + 3 : desc->bInterval;
547
 
                pipe_info->pipeHandle.encoded.fill = 0;
548
 
 
549
 
                USBTRACE("%i: Addr %X, Type %d, PkSz %d, "
550
 
                          "Intv %d, Handle %p", i, desc->bEndpointAddress,
551
 
                          desc->bmAttributes, desc->wMaxPacketSize,
552
 
                          desc->bInterval, pipe_info->pipeHandle.handle);
553
 
        }
554
 
        USBTRACEEXIT(return 0);
555
 
}
556
 
 
557
 
unsigned long usb_submit_nt_urb(struct usb_device *dev, union nt_urb *nt_urb,
558
 
                                struct irp *irp)
559
 
{
560
 
        int ret;
561
 
 
562
 
        USBTRACEENTER("nt_urb = %p, irp = %p, length = %d, function = %x",
563
 
                    nt_urb, irp, nt_urb->header.length,
564
 
                    nt_urb->header.function);
565
 
 
566
 
        nt_urb->header.status = USB_STATUS_SUCCESS;
567
 
 
 
897
                        if (i >= intf->bNumEndpoints) {
 
898
                                ERROR("intf %p has only %d endpoints, "
 
899
                                      "ignoring endpoints above %d",
 
900
                                      intf, intf->bNumEndpoints, i);
 
901
                                break;
 
902
                        }
 
903
                        pipe = &intf->pipes[i];
 
904
 
 
905
                        if (pipe->flags & USBD_PF_CHANGE_MAX_PACKET)
 
906
                                WARNING("pkt_sz: %d: %d", pipe->wMaxPacketSize,
 
907
                                        pipe->max_tx_size);
 
908
                        USBTRACE("driver wants max_tx_size to %d",
 
909
                                 pipe->max_tx_size);
 
910
 
 
911
                        pipe->wMaxPacketSize = ep->wMaxPacketSize;
 
912
                        pipe->bEndpointAddress = ep->bEndpointAddress;
 
913
                        pipe->bInterval = ep->bInterval;
 
914
                        pipe->type =
 
915
                                ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
 
916
 
 
917
                        pipe->handle = ep;
 
918
                        USBTRACE("%d: addr %X, type %d, pkt_sz %d, intv %d,"
 
919
                                 "handle %p", i, ep->bEndpointAddress,
 
920
                                 ep->bmAttributes, ep->wMaxPacketSize,
 
921
                                 ep->bInterval, pipe->handle);
 
922
                }
 
923
        }
 
924
        return USBD_STATUS_SUCCESS;
 
925
}
 
926
 
 
927
static USBD_STATUS wrap_get_descriptor(struct wrapper_dev *wd,
 
928
                                       union nt_urb *nt_urb, struct irp *irp)
 
929
{
 
930
        struct usbd_control_descriptor_request *ctrl_req;
 
931
        int ret = 0;
 
932
        struct usb_device *udev;
 
933
 
 
934
        udev = wd->dev.usb.udev;
 
935
        ctrl_req = &nt_urb->control_request;
 
936
        USBTRACE("desctype = %d, descindex = %d, transfer_buffer = %p,"
 
937
                 "transfer_buffer_length = %d", ctrl_req->desc_type,
 
938
                 ctrl_req->index, ctrl_req->transfer_buffer,
 
939
                 ctrl_req->transfer_buffer_length);
 
940
 
 
941
        if (ctrl_req->desc_type == USB_DT_STRING) {
 
942
                USBTRACE("langid: %d", ctrl_req->language_id);
 
943
                ret = usb_get_string(udev, ctrl_req->language_id,
 
944
                                     ctrl_req->index,
 
945
                                     ctrl_req->transfer_buffer,
 
946
                                     ctrl_req->transfer_buffer_length);
 
947
        } else {
 
948
                ret = usb_get_descriptor(udev, ctrl_req->desc_type,
 
949
                                         ctrl_req->index,
 
950
                                         ctrl_req->transfer_buffer,
 
951
                                         ctrl_req->transfer_buffer_length);
 
952
        }
 
953
        if (ret < 0) {
 
954
                WARNING("request %d failed with %d", ctrl_req->desc_type, ret);
 
955
                ctrl_req->transfer_buffer_length = 0;
 
956
                return USBD_STATUS_REQUEST_FAILED;
 
957
        } else {
 
958
                USBTRACE("ret: %08x", ret);
 
959
                DUMP_BUFFER(ctrl_req->transfer_buffer, ret);
 
960
                ctrl_req->transfer_buffer_length = ret;
 
961
                irp->io_status.status_info = ret;
 
962
                return USBD_STATUS_SUCCESS;
 
963
        }
 
964
}
 
965
 
 
966
static USBD_STATUS wrap_process_nt_urb(struct irp *irp)
 
967
{
 
968
        union nt_urb *nt_urb;
 
969
        struct usb_device *udev;
 
970
        USBD_STATUS status;
 
971
        struct wrapper_dev *wd;
 
972
 
 
973
        wd = irp->wd;
 
974
        udev = wd->dev.usb.udev;
 
975
        nt_urb = URB_FROM_IRP(irp);
 
976
        USBENTER("nt_urb = %p, irp = %p, length = %d, function = %x",
 
977
                 nt_urb, irp, nt_urb->header.length, nt_urb->header.function);
 
978
 
 
979
        DUMP_IRP(irp);
568
980
        switch (nt_urb->header.function) {
 
981
                /* bulk/int and vendor/class urbs are submitted
 
982
                 * asynchronously later by pdoDispatchDeviceControl */
 
983
        case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
 
984
                USBTRACE("submitting bulk/int irp: %p", irp);
 
985
                status = wrap_bulk_or_intr_trans(irp);
 
986
                break;
 
987
 
 
988
        case URB_FUNCTION_VENDOR_DEVICE:
 
989
        case URB_FUNCTION_VENDOR_INTERFACE:
 
990
        case URB_FUNCTION_VENDOR_ENDPOINT:
 
991
        case URB_FUNCTION_VENDOR_OTHER:
 
992
        case URB_FUNCTION_CLASS_DEVICE:
 
993
        case URB_FUNCTION_CLASS_INTERFACE:
 
994
        case URB_FUNCTION_CLASS_ENDPOINT:
 
995
        case URB_FUNCTION_CLASS_OTHER:
 
996
                USBTRACE("submitting vendor/class irp: %p", irp);
 
997
                status = wrap_vendor_or_class_req(irp);
 
998
                break;
 
999
 
 
1000
                /* rest are synchronous */
569
1001
        case URB_FUNCTION_SELECT_CONFIGURATION:
570
 
                usb_select_configuration(dev, nt_urb, irp);
571
 
                USBTRACEEXIT(return STATUS_SUCCESS);
572
 
 
573
 
        case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
574
 
                ret = usb_bulk_or_intr_trans(dev, nt_urb, irp);
575
 
                if (ret < 0)
576
 
                        break;
577
 
                USBTRACEEXIT(return STATUS_PENDING);
 
1002
                status = wrap_select_configuration(wd, nt_urb, irp);
 
1003
                NT_URB_STATUS(nt_urb) = status;
 
1004
                break;
578
1005
 
579
1006
        case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
580
 
                ASSERT(!nt_urb->ctrlDescReq.transferBufMdl);
581
 
                ASSERT(!nt_urb->ctrlDescReq.urbLink);
582
 
                USBTRACE("desctype = %d, descindex = %d, "
583
 
                          "transferBuf = %p, transferBufLen = %ld",
584
 
                          nt_urb->ctrlDescReq.desctype,
585
 
                          nt_urb->ctrlDescReq.descindex,
586
 
                          nt_urb->ctrlDescReq.transferBuf,
587
 
                          nt_urb->ctrlDescReq.transferBufLen);
588
 
 
589
 
                ret = usb_get_descriptor(dev, nt_urb->ctrlDescReq.desctype,
590
 
                                         nt_urb->ctrlDescReq.descindex,
591
 
                                         nt_urb->ctrlDescReq.transferBuf,
592
 
                                         nt_urb->ctrlDescReq.transferBufLen);
593
 
                if (ret < 0) {
594
 
                        ERROR("usb_get_descriptor() = %d", ret);
595
 
                        break;
596
 
                }
597
 
                nt_urb->ctrlDescReq.transferBufLen = ret;
598
 
                USBTRACEEXIT(return STATUS_SUCCESS);
599
 
 
600
 
        case URB_FUNCTION_VENDOR_DEVICE:
601
 
        case URB_FUNCTION_VENDOR_INTERFACE:
602
 
        case URB_FUNCTION_CLASS_INTERFACE:
603
 
                USBTRACE("func: %d", nt_urb->header.function);
604
 
                ret = usb_vendor_or_class_intf(dev, nt_urb, irp);
605
 
                if (ret < 0)
606
 
                        break;
607
 
                USBTRACEEXIT(return STATUS_PENDING);
 
1007
                status = wrap_get_descriptor(wd, nt_urb, irp);
 
1008
                NT_URB_STATUS(nt_urb) = status;
 
1009
                break;
608
1010
 
609
1011
        case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
610
 
                ret = usb_reset_pipe(dev, nt_urb->pipeReq.pipeHandle);
611
 
                if (ret < 0) {
612
 
                        ERROR("usb_reset_pipe() = %d", ret);
613
 
                        break;
614
 
                }
615
 
                USBTRACEEXIT(return STATUS_SUCCESS);
 
1012
                status = wrap_reset_pipe(udev, irp);
 
1013
                NT_URB_STATUS(nt_urb) = status;
 
1014
                break;
 
1015
 
 
1016
        case URB_FUNCTION_ABORT_PIPE:
 
1017
                status = wrap_abort_pipe(udev, irp);
 
1018
                NT_URB_STATUS(nt_urb) = status;
 
1019
                break;
616
1020
 
617
1021
        default:
618
 
                ERROR("function %X NOT IMPLEMENTED!\n",
619
 
                      nt_urb->header.function);
 
1022
                ERROR("function %x not implemented", nt_urb->header.function);
 
1023
                status = NT_URB_STATUS(nt_urb) = USBD_STATUS_NOT_SUPPORTED;
 
1024
                break;
620
1025
        }
621
 
        nt_urb->header.status = USB_STATUS_ERROR;
622
 
        USBTRACEEXIT(return STATUS_FAILURE);
 
1026
        USBTRACE("status: %08X", status);
 
1027
        return status;
623
1028
}
624
1029
 
625
 
unsigned long usb_reset_port(struct usb_device *dev)
 
1030
static USBD_STATUS wrap_reset_port(struct irp *irp)
626
1031
{
627
1032
        int ret;
628
 
 
629
 
        USBTRACEENTER("%s", "");
630
 
 
631
 
        ret = usb_reset_device(dev);
632
 
        if (ret < 0) {
633
 
                ERROR("usb_reset_device() = %d", ret);
634
 
                USBTRACEEXIT(return STATUS_FAILURE);
635
 
        }
636
 
 
637
 
        USBTRACEEXIT(return STATUS_SUCCESS);
638
 
}
639
 
 
640
 
STDCALL union nt_urb *WRAP_EXPORT(USBD_CreateConfigurationRequest)
641
 
        (struct usb_config_descriptor *config, unsigned short *urb_size)
642
 
{
643
 
        union nt_urb *urb;
644
 
        struct usb_interface_descriptor *intf_desc;
645
 
        struct usbd_interface_information *intf_info;
646
 
        char *pos = (char *)config;
647
 
        int cfg_size = config->wTotalLength;
648
 
        int found = 0;
649
 
 
650
 
        USBTRACEENTER("config = %p, urb_size = %p", config, urb_size);
651
 
        ASSERT(config->bNumInterfaces < 2);
652
 
 
653
 
        while ((char *)pos - (char *)config < cfg_size) {
654
 
                intf_desc = (struct usb_interface_descriptor *)pos;
655
 
                pos = pos + intf_desc->bLength;
656
 
 
657
 
                if (intf_desc->bDescriptorType != USB_DT_INTERFACE)
658
 
                        continue;
659
 
 
660
 
                USBTRACE("selected interface = %p", intf_desc);
661
 
                found = 1;
662
 
                break;
663
 
        }
664
 
        if (!found)
665
 
                USBTRACEEXIT(return NULL);
666
 
 
667
 
        *urb_size = sizeof(union nt_urb) +
668
 
                sizeof(struct usbd_pipe_information) *
669
 
                (intf_desc->bNumEndpoints - 1);
670
 
        /* FIXME: we should better check what GFP_ is required */
671
 
        urb = kmalloc(*urb_size, GFP_ATOMIC);
672
 
 
673
 
        if (urb) {
674
 
                urb->selConf.header.length = *urb_size;
675
 
                urb->selConf.header.function =
676
 
                        URB_FUNCTION_SELECT_CONFIGURATION;
677
 
                urb->selConf.config = config;
678
 
 
679
 
                intf_info = &urb->selConf.intf;
680
 
                intf_info->length = sizeof(struct usbd_interface_information)+
681
 
                        sizeof(struct usbd_pipe_information) *
682
 
                        (intf_desc->bNumEndpoints - 1);
683
 
                intf_info->intfNum = intf_desc->bInterfaceNumber;
684
 
                intf_info->altSet = intf_desc->bAlternateSetting;
685
 
                intf_info->class = intf_desc->bInterfaceClass;
686
 
                intf_info->subClass = intf_desc->bInterfaceSubClass;
687
 
                intf_info->proto = intf_desc->bInterfaceProtocol;
688
 
                intf_info->pipeNum = intf_desc->bNumEndpoints;
689
 
        }
690
 
 
691
 
        USBTRACEEXIT(return urb);
692
 
}
693
 
 
694
 
STDCALL union nt_urb * WRAP_EXPORT(USBD_CreateConfigurationRequestEx)
 
1033
        struct wrapper_dev *wd;
 
1034
 
 
1035
        wd = irp->wd;
 
1036
        USBENTER("%p, %p", wd, wd->dev.usb.udev);
 
1037
 
 
1038
        ret = usb_reset_device(wd->dev.usb.udev);
 
1039
        if (ret < 0)
 
1040
                WARNING("reset failed: %d", ret);
 
1041
        return USBD_STATUS_SUCCESS;
 
1042
}
 
1043
 
 
1044
static USBD_STATUS wrap_get_port_status(struct irp *irp)
 
1045
{
 
1046
        struct wrapper_dev *wd;
 
1047
        ULONG *status;
 
1048
 
 
1049
        wd = irp->wd;
 
1050
        USBENTER("%p, %p", wd, wd->dev.usb.udev);
 
1051
        status = IoGetCurrentIrpStackLocation(irp)->params.others.arg1;
 
1052
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 
1053
        {
 
1054
                enum usb_device_state state;
 
1055
                state = wd->dev.usb.udev->state;
 
1056
                if (state != USB_STATE_NOTATTACHED &&
 
1057
                    state != USB_STATE_SUSPENDED) {
 
1058
                        *status |= USBD_PORT_CONNECTED;
 
1059
                        if (state == USB_STATE_CONFIGURED)
 
1060
                                *status |= USBD_PORT_ENABLED;
 
1061
                }
 
1062
        }
 
1063
#else
 
1064
        {
 
1065
                /* TODO: how to get current status? */
 
1066
                *status = USBD_PORT_CONNECTED | USBD_PORT_ENABLED;
 
1067
        }
 
1068
#endif
 
1069
        return USBD_STATUS_SUCCESS;
 
1070
}
 
1071
 
 
1072
NTSTATUS wrap_submit_irp(struct device_object *pdo, struct irp *irp)
 
1073
{
 
1074
        struct io_stack_location *irp_sl;
 
1075
        struct wrapper_dev *wd;
 
1076
        USBD_STATUS status;
 
1077
 
 
1078
        irp_sl = IoGetCurrentIrpStackLocation(irp);
 
1079
        wd = pdo->reserved;
 
1080
 
 
1081
        if (unlikely(wd->dev.usb.intf == NULL)) {
 
1082
                irp->io_status.status = STATUS_DEVICE_REMOVED;
 
1083
                irp->io_status.status_info = 0;
 
1084
                return irp->io_status.status;
 
1085
        }
 
1086
 
 
1087
        irp->wd = wd;
 
1088
        switch (irp_sl->params.ioctl.code) {
 
1089
        case IOCTL_INTERNAL_USB_SUBMIT_URB:
 
1090
                status = wrap_process_nt_urb(irp);
 
1091
                break;
 
1092
        case IOCTL_INTERNAL_USB_RESET_PORT:
 
1093
                status = wrap_reset_port(irp);
 
1094
                break;
 
1095
        case IOCTL_INTERNAL_USB_GET_PORT_STATUS:
 
1096
                status = wrap_get_port_status(irp);
 
1097
                break;
 
1098
        default:
 
1099
                ERROR("ioctl %08X NOT IMPLEMENTED", irp_sl->params.ioctl.code);
 
1100
                status = USBD_STATUS_NOT_SUPPORTED;
 
1101
                break;
 
1102
        }
 
1103
 
 
1104
        USBTRACE("status: %08X", status);
 
1105
        if (status == USBD_STATUS_PENDING)
 
1106
                return STATUS_PENDING;
 
1107
        irp->io_status.status = nt_urb_irp_status(status);
 
1108
        if (status != USBD_STATUS_SUCCESS)
 
1109
                irp->io_status.status_info = 0;
 
1110
        USBEXIT(return irp->io_status.status);
 
1111
}
 
1112
 
 
1113
/* TODO: The example on msdn in reference section suggests that second
 
1114
 * argument should be an array of usbd_interface_information, but
 
1115
 * description and examples elsewhere suggest that it should be
 
1116
 * usbd_interface_list_entry structre. Which is correct? */
 
1117
 
 
1118
STDCALL union nt_urb *WRAP_EXPORT(USBD_CreateConfigurationRequestEx)
695
1119
        (struct usb_config_descriptor *config,
696
 
         struct usbd_interface_list_entry *intfList)
 
1120
         struct usbd_interface_list_entry *intf_list)
697
1121
{
698
 
        union nt_urb *urb;
699
 
        int urb_size;
 
1122
        int size, i, n;
 
1123
        struct usbd_interface_information *intf;
 
1124
        struct usbd_pipe_information *pipe;
700
1125
        struct usb_interface_descriptor *intf_desc;
701
 
        struct usbd_interface_information *intf_info;
702
 
 
703
 
        /*
704
 
         * Note: This function is more or less a hack - due to a lack
705
 
         * of understanding of the underlying USB details. It only
706
 
         * sets up an URB with one interface inside. This is what the
707
 
         * WUSB54G driver requests or what the WUSB54G device
708
 
         * provides. However, this function warns if the assumption is
709
 
         * incorrect.
710
 
         */
711
 
 
712
 
        USBTRACEENTER("config = %p, intfList = %p", config, intfList);
713
 
        ASSERT(config->bNumInterfaces < 2);
714
 
 
715
 
        intf_desc = intfList->intfDesc;
716
 
        urb_size = sizeof(union nt_urb) +
717
 
                sizeof(struct usbd_pipe_information) *
718
 
                (intf_desc->bNumEndpoints - 1);
719
 
        /* FIXME: we should better check what GFP_ is required */
720
 
        urb = kmalloc(urb_size, GFP_ATOMIC);
721
 
 
722
 
        if (urb) {
723
 
                urb->selConf.header.length = urb_size;
724
 
                urb->selConf.header.function =
725
 
                        URB_FUNCTION_SELECT_CONFIGURATION;
726
 
                urb->selConf.config = config;
727
 
 
728
 
                intf_info = &urb->selConf.intf;
729
 
                intfList->intf = intf_info;
730
 
                intf_info->length = sizeof(struct usbd_interface_information)+
731
 
                        sizeof(struct usbd_pipe_information) *
732
 
                        (intf_desc->bNumEndpoints - 1);
733
 
                intf_info->intfNum = intf_desc->bInterfaceNumber;
734
 
                intf_info->altSet = intf_desc->bAlternateSetting;
735
 
                intf_info->class = intf_desc->bInterfaceClass;
736
 
                intf_info->subClass = intf_desc->bInterfaceSubClass;
737
 
                intf_info->proto = intf_desc->bInterfaceProtocol;
738
 
                intf_info->pipeNum = intf_desc->bNumEndpoints;
739
 
 
740
 
                ASSERT(!(intfList+1)->intfDesc);
741
 
        }
742
 
 
743
 
        USBTRACEEXIT(return urb);
 
1126
        struct usbd_select_configuration *select_conf;
 
1127
 
 
1128
        USBENTER("config = %p, intf_list = %p", config, intf_list);
 
1129
 
 
1130
        /* calculate size required; select_conf already has space for
 
1131
         * one intf structure */
 
1132
        size = sizeof(*select_conf) - sizeof(*intf);
 
1133
        for (n = 0; n < config->bNumInterfaces; n++) {
 
1134
                i = intf_list[n].intf_desc->bNumEndpoints;
 
1135
                /* intf already has space for one pipe */
 
1136
                size += sizeof(*intf) + (i - 1) * sizeof(*pipe);
 
1137
        }
 
1138
        /* don't use kmalloc - driver frees it with ExFreePool */
 
1139
        select_conf = ExAllocatePoolWithTag(NonPagedPool, size,
 
1140
                                            POOL_TAG('L', 'U', 'S', 'B'));
 
1141
        if (!select_conf) {
 
1142
                WARNING("couldn't allocate memory");
 
1143
                return NULL;
 
1144
        }
 
1145
        memset(select_conf, 0, size);
 
1146
        intf = &select_conf->intf;
 
1147
        /* handle points to beginning of interface information */
 
1148
        select_conf->handle = intf;
 
1149
        for (n = 0; n < config->bNumInterfaces && intf_list[n].intf_desc;
 
1150
             n++) {
 
1151
                /* initialize 'intf' fields in intf_list so they point
 
1152
                 * to appropriate entry; these may be read/written by
 
1153
                 * driver after this function returns */
 
1154
                intf_list[n].intf = intf;
 
1155
                intf_desc = intf_list[n].intf_desc;
 
1156
 
 
1157
                i = intf_desc->bNumEndpoints;
 
1158
                intf->bLength = sizeof(*intf) + (i - 1) * sizeof(*pipe);
 
1159
 
 
1160
                intf->bInterfaceNumber = intf_desc->bInterfaceNumber;
 
1161
                intf->bAlternateSetting = intf_desc->bAlternateSetting;
 
1162
                intf->bInterfaceClass = intf_desc->bInterfaceClass;
 
1163
                intf->bInterfaceSubClass = intf_desc->bInterfaceSubClass;
 
1164
                intf->bInterfaceProtocol = intf_desc->bInterfaceProtocol;
 
1165
                intf->bNumEndpoints = intf_desc->bNumEndpoints;
 
1166
 
 
1167
                pipe = &intf->pipes[0];
 
1168
                for (i = 0; i < intf->bNumEndpoints; i++) {
 
1169
                        memset(&pipe[i], 0, sizeof(*pipe));
 
1170
                        pipe[i].max_tx_size =
 
1171
                                USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;
 
1172
                }
 
1173
                intf = (((void *)intf) + intf->bLength);
 
1174
        }
 
1175
        select_conf->header.function = URB_FUNCTION_SELECT_CONFIGURATION;
 
1176
        select_conf->header.length = size;
 
1177
        select_conf->config = config;
 
1178
        USBEXIT(return (union nt_urb *)select_conf);
744
1179
}
 
1180
 
745
1181
WRAP_EXPORT_MAP("_USBD_CreateConfigurationRequestEx@8", USBD_CreateConfigurationRequestEx);
746
1182
 
747
1183
STDCALL struct usb_interface_descriptor *
748
 
        WRAP_EXPORT(USBD_ParseConfigurationDescriptorEx)
749
 
        (struct usb_config_descriptor *config,
750
 
         void *startPos, LONG intfNum, LONG altSet,
751
 
         LONG intfClass, LONG intfSubClass, LONG intfProto)
 
1184
WRAP_EXPORT(USBD_ParseConfigurationDescriptorEx)
 
1185
        (struct usb_config_descriptor *config, void *start,
 
1186
         LONG bInterfaceNumber, LONG bAlternateSetting, LONG bInterfaceClass,
 
1187
         LONG bInterfaceSubClass, LONG bInterfaceProtocol)
752
1188
{
753
 
        int size = config->wTotalLength;
754
 
        char *pos = startPos;
 
1189
        void *pos;
755
1190
        struct usb_interface_descriptor *intf;
756
1191
 
757
 
        USBTRACEENTER("config = %p, startPos = %p, intfNum = %d, altSet = %d,"
758
 
                    " intfClass = %d, intfSubClass = %d, intfProto = %d",
759
 
                    config, startPos, intfNum, altSet, intfClass, intfSubClass,
760
 
                    intfProto);
761
 
 
762
 
        while ((char *)pos - (char *)config < size) {
763
 
                intf = (struct usb_interface_descriptor *)pos;
764
 
                pos = pos + intf->bLength;
765
 
 
766
 
                if (intf->bDescriptorType != USB_DT_INTERFACE)
767
 
                        continue;
768
 
                if ((intfNum != -1) && (intf->bInterfaceNumber != intfNum))
769
 
                        continue;
770
 
                if ((altSet != -1) && (intf->bAlternateSetting != altSet))
771
 
                        continue;
772
 
                if ((intfClass != -1) && (intf->bInterfaceClass != intfClass))
773
 
                        continue;
774
 
                if ((intfSubClass != -1) &&
775
 
                    (intf->bInterfaceSubClass != intfSubClass))
776
 
                        continue;
777
 
                if ((intfProto != -1) &&
778
 
                    (intf->bInterfaceProtocol != intfProto))
779
 
                        continue;
780
 
 
781
 
                USBTRACE("selected interface = %p", intf);
782
 
                USBTRACEEXIT(return intf);
 
1192
        USBENTER("config = %p, start = %p, ifnum = %d, alt_setting = %d,"
 
1193
                      " class = %d, subclass = %d, proto = %d", config, start,
 
1194
                      bInterfaceNumber, bAlternateSetting,
 
1195
                      bInterfaceClass, bInterfaceSubClass, bInterfaceProtocol);
 
1196
 
 
1197
        for (pos = start; pos < ((void *)config + config->wTotalLength);
 
1198
             pos += intf->bLength) {
 
1199
 
 
1200
                intf = pos;
 
1201
 
 
1202
                if ((intf->bDescriptorType == USB_DT_INTERFACE) &&
 
1203
                    ((bInterfaceNumber == -1) ||
 
1204
                     (intf->bInterfaceNumber == bInterfaceNumber)) &&
 
1205
                    ((bAlternateSetting == -1) ||
 
1206
                     (intf->bAlternateSetting == bAlternateSetting)) &&
 
1207
                    ((bInterfaceClass == -1) ||
 
1208
                     (intf->bInterfaceClass == bInterfaceClass)) &&
 
1209
                    ((bInterfaceSubClass == -1) ||
 
1210
                     (intf->bInterfaceSubClass == bInterfaceSubClass)) &&
 
1211
                    ((bInterfaceProtocol == -1) ||
 
1212
                     (intf->bInterfaceProtocol == bInterfaceProtocol))) {
 
1213
                        USBTRACE("selected interface = %p", intf);
 
1214
                        USBEXIT(return intf);
 
1215
                }
783
1216
        }
784
 
 
785
 
        USBTRACEEXIT(return NULL);
 
1217
        USBEXIT(return NULL);
786
1218
}
 
1219
 
787
1220
WRAP_EXPORT_MAP("_USBD_ParseConfigurationDescriptorEx@28", USBD_ParseConfigurationDescriptorEx);
788
1221
 
 
1222
STDCALL union nt_urb *WRAP_EXPORT(USBD_CreateConfigurationRequest)
 
1223
        (struct usb_config_descriptor *config, USHORT *size)
 
1224
{
 
1225
        union nt_urb *nt_urb;
 
1226
        struct usbd_interface_list_entry intf_list[2];
 
1227
        struct usb_interface_descriptor *intf_desc;
 
1228
 
 
1229
        USBENTER("config = %p, urb_size = %p", config, size);
 
1230
 
 
1231
        intf_desc = USBD_ParseConfigurationDescriptorEx(config, config, -1, -1,
 
1232
                                                        -1, -1, -1);
 
1233
        intf_list[0].intf_desc = intf_desc;
 
1234
        intf_list[0].intf = NULL;
 
1235
        intf_list[1].intf_desc = NULL;
 
1236
        intf_list[1].intf = NULL;
 
1237
        nt_urb = USBD_CreateConfigurationRequestEx(config, intf_list);
 
1238
        if (!nt_urb)
 
1239
                return NULL;
 
1240
 
 
1241
        *size = nt_urb->select_conf.header.length;
 
1242
        USBEXIT(return nt_urb);
 
1243
}
 
1244
 
789
1245
STDCALL struct usb_interface_descriptor *
790
 
        WRAP_EXPORT(USBD_ParseConfigurationDescriptor)
791
 
        (struct usb_config_descriptor *config,
792
 
         unsigned char intfNum, unsigned char altSet)
 
1246
WRAP_EXPORT(USBD_ParseConfigurationDescriptor)
 
1247
        (struct usb_config_descriptor *config, UCHAR bInterfaceNumber,
 
1248
         UCHAR bAlternateSetting)
793
1249
{
794
1250
        return USBD_ParseConfigurationDescriptorEx(config, config,
795
 
                                                   intfNum, altSet,
 
1251
                                                   bInterfaceNumber,
 
1252
                                                   bAlternateSetting,
796
1253
                                                   -1, -1, -1);
797
1254
}
798
1255