Merge branch 'vendor/FILE'
[dragonfly.git] / sys / emulation / ndis / subr_u4bd.c
1 /*-
2  * Copyright (c) 2005
3  *      Bill Paul <wpaul@windriver.com>.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Bill Paul.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30  * THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * $FreeBSD: src/sys/compat/ndis/subr_usbd.c,v 1.22 2012/11/17 01:51:26 svnexp Exp $
33  */
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/unistd.h>
38 #include <sys/types.h>
39
40 #include <sys/kernel.h>
41 #include <sys/malloc.h>
42 #include <sys/lock.h>
43 #include <sys/condvar.h>
44 #include <sys/module.h>
45 #include <sys/conf.h>
46 #include <sys/mbuf.h>
47 #include <sys/socket.h>
48 #include <sys/bus.h>
49
50 #include <sys/queue.h>
51
52 #include <net/if.h>
53 #include <net/if_media.h>
54 #include <netproto/802_11/ieee80211_var.h>
55 #include <netproto/802_11/ieee80211_ioctl.h>
56
57 #include <bus/u4b/usb.h>
58 #include <bus/u4b/usbdi.h>
59 #include <bus/u4b/usbdi_util.h>
60 #include <bus/u4b/usb_busdma.h>
61 #include <bus/u4b/usb_device.h>
62 #include <bus/u4b/usb_request.h>
63
64 #include <emulation/ndis/pe_var.h>
65 #include <emulation/ndis/cfg_var.h>
66 #include <emulation/ndis/resource_var.h>
67 #include <emulation/ndis/ntoskrnl_var.h>
68 #include <emulation/ndis/ndis_var.h>
69 #include <emulation/ndis/hal_var.h>
70 #include <emulation/ndis/u4bd_var.h>
71 #include <dev/netif/ndis/if_ndisvar.h>
72
73 static driver_object usbd_driver;
74 static usb_callback_t usbd_non_isoc_callback;
75 static usb_callback_t usbd_ctrl_callback;
76
77 #define USBD_CTRL_READ_PIPE             0
78 #define USBD_CTRL_WRITE_PIPE            1
79 #define USBD_CTRL_MAX_PIPE              2
80 #define USBD_CTRL_READ_BUFFER_SP        256
81 #define USBD_CTRL_WRITE_BUFFER_SP       256
82 #define USBD_CTRL_READ_BUFFER_SIZE      \
83         (sizeof(struct usb_device_request) + USBD_CTRL_READ_BUFFER_SP)
84 #define USBD_CTRL_WRITE_BUFFER_SIZE     \
85         (sizeof(struct usb_device_request) + USBD_CTRL_WRITE_BUFFER_SP)
86 static struct usb_config usbd_default_epconfig[USBD_CTRL_MAX_PIPE] = {
87         [USBD_CTRL_READ_PIPE] = {
88                 .type =         UE_CONTROL,
89                 .endpoint =     0x00,   /* control pipe */
90                 .direction =    UE_DIR_ANY,
91                 .if_index =     0,
92                 .bufsize =      USBD_CTRL_READ_BUFFER_SIZE,
93                 .flags =        { .short_xfer_ok = 1, },
94                 .callback =     &usbd_ctrl_callback,
95                 .timeout =      5000,   /* 5 seconds */
96         },
97         [USBD_CTRL_WRITE_PIPE] = {
98                 .type =         UE_CONTROL,
99                 .endpoint =     0x00,   /* control pipe */
100                 .direction =    UE_DIR_ANY,
101                 .if_index =     0,
102                 .bufsize =      USBD_CTRL_WRITE_BUFFER_SIZE,
103                 .flags =        { .proxy_buffer = 1, },
104                 .callback =     &usbd_ctrl_callback,
105                 .timeout =      5000,   /* 5 seconds */
106         }
107 };
108
109 static int32_t           usbd_func_bulkintr(irp *);
110 static int32_t           usbd_func_vendorclass(irp *);
111 static int32_t           usbd_func_selconf(irp *);
112 static int32_t           usbd_func_abort_pipe(irp *);
113 static usb_error_t       usbd_setup_endpoint(irp *, uint8_t,
114                             struct usb_endpoint_descriptor      *);
115 static usb_error_t       usbd_setup_endpoint_default(irp *, uint8_t);
116 static usb_error_t       usbd_setup_endpoint_one(irp *, uint8_t,
117                             struct ndisusb_ep *, struct usb_config *);
118 static int32_t           usbd_func_getdesc(irp *);
119 static union usbd_urb   *usbd_geturb(irp *);
120 static struct ndisusb_ep*usbd_get_ndisep(irp *, usb_endpoint_descriptor_t *);
121 static int32_t           usbd_iodispatch(device_object *, irp *);
122 static int32_t           usbd_ioinvalid(device_object *, irp *);
123 static int32_t           usbd_pnp(device_object *, irp *);
124 static int32_t           usbd_power(device_object *, irp *);
125 static void              usbd_irpcancel(device_object *, irp *);
126 static int32_t           usbd_submit_urb(irp *);
127 static int32_t           usbd_urb2nt(int32_t);
128 static void              usbd_task(device_object *, void *);
129 static int32_t           usbd_taskadd(irp *, unsigned);
130 static void              usbd_xfertask(device_object *, void *);
131 static void              dummy(void);
132
133 static union usbd_urb   *USBD_CreateConfigurationRequestEx(
134                             usb_config_descriptor_t *,
135                             struct usbd_interface_list_entry *);
136 static union usbd_urb   *USBD_CreateConfigurationRequest(
137                             usb_config_descriptor_t *,
138                             uint16_t *);
139 static void              USBD_GetUSBDIVersion(usbd_version_info *);
140 static usb_interface_descriptor_t *USBD_ParseConfigurationDescriptorEx(
141                             usb_config_descriptor_t *, void *, int32_t, int32_t,
142                             int32_t, int32_t, int32_t);
143 static usb_interface_descriptor_t *USBD_ParseConfigurationDescriptor(
144                     usb_config_descriptor_t *, uint8_t, uint8_t);
145
146 /*
147  * We need to wrap these functions because these need `context switch' from
148  * Windows to UNIX before it's called.
149  */
150 static funcptr usbd_iodispatch_wrap;
151 static funcptr usbd_ioinvalid_wrap;
152 static funcptr usbd_pnp_wrap;
153 static funcptr usbd_power_wrap;
154 static funcptr usbd_irpcancel_wrap;
155 static funcptr usbd_task_wrap;
156 static funcptr usbd_xfertask_wrap;
157
158 int
159 usbd_libinit(void)
160 {
161         image_patch_table       *patch;
162         int i;
163
164         patch = usbd_functbl;
165         while (patch->ipt_func != NULL) {
166                 windrv_wrap((funcptr)patch->ipt_func,
167                     (funcptr *)&patch->ipt_wrap,
168                     patch->ipt_argcnt, patch->ipt_ftype);
169                 patch++;
170         }
171
172         windrv_wrap((funcptr)usbd_ioinvalid,
173             (funcptr *)&usbd_ioinvalid_wrap, 2, WINDRV_WRAP_STDCALL);
174         windrv_wrap((funcptr)usbd_iodispatch,
175             (funcptr *)&usbd_iodispatch_wrap, 2, WINDRV_WRAP_STDCALL);
176         windrv_wrap((funcptr)usbd_pnp,
177             (funcptr *)&usbd_pnp_wrap, 2, WINDRV_WRAP_STDCALL);
178         windrv_wrap((funcptr)usbd_power,
179             (funcptr *)&usbd_power_wrap, 2, WINDRV_WRAP_STDCALL);
180         windrv_wrap((funcptr)usbd_irpcancel,
181             (funcptr *)&usbd_irpcancel_wrap, 2, WINDRV_WRAP_STDCALL);
182         windrv_wrap((funcptr)usbd_task,
183             (funcptr *)&usbd_task_wrap, 2, WINDRV_WRAP_STDCALL);
184         windrv_wrap((funcptr)usbd_xfertask,
185             (funcptr *)&usbd_xfertask_wrap, 2, WINDRV_WRAP_STDCALL);
186
187         /* Create a fake USB driver instance. */
188
189         windrv_bus_attach(&usbd_driver, "USB Bus");
190
191         /* Set up our dipatch routine. */
192         for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
193                 usbd_driver.dro_dispatch[i] =
194                         (driver_dispatch)usbd_ioinvalid_wrap;
195
196         usbd_driver.dro_dispatch[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
197             (driver_dispatch)usbd_iodispatch_wrap;
198         usbd_driver.dro_dispatch[IRP_MJ_DEVICE_CONTROL] =
199             (driver_dispatch)usbd_iodispatch_wrap;
200         usbd_driver.dro_dispatch[IRP_MJ_POWER] =
201             (driver_dispatch)usbd_power_wrap;
202         usbd_driver.dro_dispatch[IRP_MJ_PNP] =
203             (driver_dispatch)usbd_pnp_wrap;
204
205         return (0);
206 }
207
208 int
209 usbd_libfini(void)
210 {
211         image_patch_table       *patch;
212
213         patch = usbd_functbl;
214         while (patch->ipt_func != NULL) {
215                 windrv_unwrap(patch->ipt_wrap);
216                 patch++;
217         }
218
219         windrv_unwrap(usbd_ioinvalid_wrap);
220         windrv_unwrap(usbd_iodispatch_wrap);
221         windrv_unwrap(usbd_pnp_wrap);
222         windrv_unwrap(usbd_power_wrap);
223         windrv_unwrap(usbd_irpcancel_wrap);
224         windrv_unwrap(usbd_task_wrap);
225         windrv_unwrap(usbd_xfertask_wrap);
226
227         kfree(usbd_driver.dro_drivername.us_buf, M_DEVBUF);
228
229         return (0);
230 }
231
232 static int32_t
233 usbd_iodispatch(device_object *dobj, irp *ip)
234 {
235         device_t dev = dobj->do_devext;
236         int32_t status;
237         struct io_stack_location *irp_sl;
238
239         irp_sl = IoGetCurrentIrpStackLocation(ip);
240         switch (irp_sl->isl_parameters.isl_ioctl.isl_iocode) {
241         case IOCTL_INTERNAL_USB_SUBMIT_URB:
242                 IRP_NDIS_DEV(ip) = dev;
243
244                 status = usbd_submit_urb(ip);
245                 break;
246         default:
247                 device_printf(dev, "ioctl 0x%x isn't supported\n",
248                     irp_sl->isl_parameters.isl_ioctl.isl_iocode);
249                 status = USBD_STATUS_NOT_SUPPORTED;
250                 break;
251         }
252
253         if (status == USBD_STATUS_PENDING)
254                 return (STATUS_PENDING);
255
256         ip->irp_iostat.isb_status = usbd_urb2nt(status);
257         if (status != USBD_STATUS_SUCCESS)
258                 ip->irp_iostat.isb_info = 0;
259         return (ip->irp_iostat.isb_status);
260 }
261
262 static int32_t
263 usbd_ioinvalid(device_object *dobj, irp *ip)
264 {
265         device_t dev = dobj->do_devext;
266         struct io_stack_location *irp_sl;
267
268         irp_sl = IoGetCurrentIrpStackLocation(ip);
269         device_printf(dev, "invalid I/O dispatch %d:%d\n", irp_sl->isl_major,
270             irp_sl->isl_minor);
271
272         ip->irp_iostat.isb_status = STATUS_FAILURE;
273         ip->irp_iostat.isb_info = 0;
274
275         IoCompleteRequest(ip, IO_NO_INCREMENT);
276
277         return (STATUS_FAILURE);
278 }
279
280 static int32_t
281 usbd_pnp(device_object *dobj, irp *ip)
282 {
283         device_t dev = dobj->do_devext;
284         struct io_stack_location *irp_sl;
285
286         irp_sl = IoGetCurrentIrpStackLocation(ip);
287         device_printf(dev, "%s: unsupported I/O dispatch %d:%d\n",
288             __func__, irp_sl->isl_major, irp_sl->isl_minor);
289
290         ip->irp_iostat.isb_status = STATUS_FAILURE;
291         ip->irp_iostat.isb_info = 0;
292
293         IoCompleteRequest(ip, IO_NO_INCREMENT);
294
295         return (STATUS_FAILURE);
296 }
297
298 static int32_t
299 usbd_power(device_object *dobj, irp *ip)
300 {
301         device_t dev = dobj->do_devext;
302         struct io_stack_location *irp_sl;
303
304         irp_sl = IoGetCurrentIrpStackLocation(ip);
305         device_printf(dev, "%s: unsupported I/O dispatch %d:%d\n",
306             __func__, irp_sl->isl_major, irp_sl->isl_minor);
307
308         ip->irp_iostat.isb_status = STATUS_FAILURE;
309         ip->irp_iostat.isb_info = 0;
310
311         IoCompleteRequest(ip, IO_NO_INCREMENT);
312
313         return (STATUS_FAILURE);
314 }
315
316 /* Convert USBD_STATUS to NTSTATUS  */
317 static int32_t
318 usbd_urb2nt(int32_t status)
319 {
320
321         switch (status) {
322         case USBD_STATUS_SUCCESS:
323                 return (STATUS_SUCCESS);
324         case USBD_STATUS_DEVICE_GONE:
325                 return (STATUS_DEVICE_NOT_CONNECTED);
326         case USBD_STATUS_PENDING:
327                 return (STATUS_PENDING);
328         case USBD_STATUS_NOT_SUPPORTED:
329                 return (STATUS_NOT_IMPLEMENTED);
330         case USBD_STATUS_NO_MEMORY:
331                 return (STATUS_NO_MEMORY);
332         case USBD_STATUS_REQUEST_FAILED:
333                 return (STATUS_NOT_SUPPORTED);
334         case USBD_STATUS_CANCELED:
335                 return (STATUS_CANCELLED);
336         default:
337                 break;
338         }
339
340         return (STATUS_FAILURE);
341 }
342
343 /* Convert FreeBSD's usb_error_t to USBD_STATUS  */
344 static int32_t
345 usbd_usb2urb(int status)
346 {
347
348         switch (status) {
349         case USB_ERR_NORMAL_COMPLETION:
350                 return (USBD_STATUS_SUCCESS);
351         case USB_ERR_PENDING_REQUESTS:
352                 return (USBD_STATUS_PENDING);
353         case USB_ERR_TIMEOUT:
354                 return (USBD_STATUS_TIMEOUT);
355         case USB_ERR_SHORT_XFER:
356                 return (USBD_STATUS_ERROR_SHORT_TRANSFER);
357         case USB_ERR_IOERROR:
358                 return (USBD_STATUS_XACT_ERROR);
359         case USB_ERR_NOMEM:
360                 return (USBD_STATUS_NO_MEMORY);
361         case USB_ERR_INVAL:
362                 return (USBD_STATUS_REQUEST_FAILED);
363         case USB_ERR_NOT_STARTED:
364         case USB_ERR_TOO_DEEP:
365         case USB_ERR_NO_POWER:
366                 return (USBD_STATUS_DEVICE_GONE);
367         case USB_ERR_CANCELLED:
368                 return (USBD_STATUS_CANCELED);
369         default:
370                 break;
371         }
372
373         return (USBD_STATUS_NOT_SUPPORTED);
374 }
375
376 static union usbd_urb *
377 usbd_geturb(irp *ip)
378 {
379         struct io_stack_location *irp_sl;
380
381         irp_sl = IoGetCurrentIrpStackLocation(ip);
382
383         return (irp_sl->isl_parameters.isl_others.isl_arg1);
384 }
385
386 static int32_t
387 usbd_submit_urb(irp *ip)
388 {
389         device_t dev = IRP_NDIS_DEV(ip);
390         int32_t status;
391         union usbd_urb *urb;
392
393         urb = usbd_geturb(ip);
394         /*
395          * In a case of URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER,
396          * USBD_URB_STATUS(urb) would be set at callback functions like
397          * usbd_intr() or usbd_xfereof().
398          */
399         switch (urb->uu_hdr.uuh_func) {
400         case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
401                 status = usbd_func_bulkintr(ip);
402                 if (status != USBD_STATUS_SUCCESS &&
403                     status != USBD_STATUS_PENDING)
404                         USBD_URB_STATUS(urb) = status;
405                 break;
406         case URB_FUNCTION_VENDOR_DEVICE:
407         case URB_FUNCTION_VENDOR_INTERFACE:
408         case URB_FUNCTION_VENDOR_ENDPOINT:
409         case URB_FUNCTION_VENDOR_OTHER:
410         case URB_FUNCTION_CLASS_DEVICE:
411         case URB_FUNCTION_CLASS_INTERFACE:
412         case URB_FUNCTION_CLASS_ENDPOINT:
413         case URB_FUNCTION_CLASS_OTHER:
414                 status = usbd_func_vendorclass(ip);
415                 USBD_URB_STATUS(urb) = status;
416                 break;
417         case URB_FUNCTION_SELECT_CONFIGURATION:
418                 status = usbd_func_selconf(ip);
419                 USBD_URB_STATUS(urb) = status;
420                 break;
421         case URB_FUNCTION_ABORT_PIPE:
422                 status = usbd_func_abort_pipe(ip);
423                 USBD_URB_STATUS(urb) = status;
424                 break;
425         case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
426                 status = usbd_func_getdesc(ip);
427                 USBD_URB_STATUS(urb) = status;
428                 break;
429         default:
430                 device_printf(dev, "func 0x%x isn't supported\n",
431                     urb->uu_hdr.uuh_func);
432                 USBD_URB_STATUS(urb) = status = USBD_STATUS_NOT_SUPPORTED;
433                 break;
434         }
435
436         return (status);
437 }
438
439 static int32_t
440 usbd_func_getdesc(irp *ip)
441 {
442 #define NDISUSB_GETDESC_MAXRETRIES              3
443         device_t dev = IRP_NDIS_DEV(ip);
444         struct ndis_softc *sc = device_get_softc(dev);
445         struct usbd_urb_control_descriptor_request *ctldesc;
446         uint16_t actlen;
447         uint32_t len;
448         union usbd_urb *urb;
449         usb_config_descriptor_t *cdp;
450         usb_error_t status;
451
452         urb = usbd_geturb(ip);
453         ctldesc = &urb->uu_ctldesc;
454         if (ctldesc->ucd_desctype == UDESC_CONFIG) {
455                 /*
456                  * The NDIS driver is not allowed to change the
457                  * config! There is only one choice!
458                  */
459                 cdp = usbd_get_config_descriptor(sc->ndisusb_dev);
460                 if (cdp == NULL) {
461                         status = USB_ERR_INVAL;
462                         goto exit;
463                 }
464                 if (cdp->bDescriptorType != UDESC_CONFIG) {
465                         device_printf(dev, "bad desc %d\n",
466                             cdp->bDescriptorType);
467                         status = USB_ERR_INVAL;
468                         goto exit;
469                 }
470                 /* get minimum length */
471                 len = MIN(UGETW(cdp->wTotalLength), ctldesc->ucd_trans_buflen);
472                 /* copy out config descriptor */
473                 memcpy(ctldesc->ucd_trans_buf, cdp, len);
474                 /* set actual length */
475                 actlen = len;
476                 status = USB_ERR_NORMAL_COMPLETION;
477         } else {
478                 NDISUSB_LOCK(sc);
479                 status = usbd_req_get_desc(sc->ndisusb_dev, &sc->ndisusb_lock,
480                     &actlen, ctldesc->ucd_trans_buf, 2,
481                     ctldesc->ucd_trans_buflen, ctldesc->ucd_langid,
482                     ctldesc->ucd_desctype, ctldesc->ucd_idx,
483                     NDISUSB_GETDESC_MAXRETRIES);
484                 NDISUSB_UNLOCK(sc);
485         }
486 exit:
487         if (status != USB_ERR_NORMAL_COMPLETION) {
488                 ctldesc->ucd_trans_buflen = 0;
489                 return usbd_usb2urb(status);
490         }
491
492         ctldesc->ucd_trans_buflen = actlen;
493         ip->irp_iostat.isb_info = actlen;
494
495         return (USBD_STATUS_SUCCESS);
496 #undef NDISUSB_GETDESC_MAXRETRIES
497 }
498
499 static int32_t
500 usbd_func_selconf(irp *ip)
501 {
502         device_t dev = IRP_NDIS_DEV(ip);
503         int i, j;
504         struct ndis_softc *sc = device_get_softc(dev);
505         struct usb_device *udev = sc->ndisusb_dev;
506         struct usb_endpoint *ep = NULL;
507         struct usbd_interface_information *intf;
508         struct usbd_pipe_information *pipe;
509         struct usbd_urb_select_configuration *selconf;
510         union usbd_urb *urb;
511         usb_config_descriptor_t *conf;
512         usb_endpoint_descriptor_t *edesc;
513         usb_error_t ret;
514
515         urb = usbd_geturb(ip);
516
517         selconf = &urb->uu_selconf;
518         conf = selconf->usc_conf;
519         if (conf == NULL) {
520                 device_printf(dev, "select configuration is NULL\n");
521                 return usbd_usb2urb(USB_ERR_NORMAL_COMPLETION);
522         }
523
524         intf = &selconf->usc_intf;
525         for (i = 0; i < conf->bNumInterface && intf->uii_len > 0; i++) {
526                 ret = usbd_set_alt_interface_index(udev,
527                     intf->uii_intfnum, intf->uii_altset);
528                 if (ret != USB_ERR_NORMAL_COMPLETION && ret != USB_ERR_IN_USE) {
529                         device_printf(dev,
530                             "setting alternate interface failed: %s\n",
531                             usbd_errstr(ret));
532                         return usbd_usb2urb(ret);
533                 }
534
535                 for (j = 0; (ep = usb_endpoint_foreach(udev, ep)); j++) {
536                         if (j >= intf->uii_numeps) {
537                                 device_printf(dev,
538                                     "endpoint %d and above are ignored",
539                                     intf->uii_numeps);
540                                 break;
541                         }
542                         edesc = ep->edesc;
543                         pipe = &intf->uii_pipes[j];
544                         pipe->upi_handle = edesc;
545                         pipe->upi_epaddr = edesc->bEndpointAddress;
546                         pipe->upi_maxpktsize = UGETW(edesc->wMaxPacketSize);
547                         pipe->upi_type = UE_GET_XFERTYPE(edesc->bmAttributes);
548
549                         ret = usbd_setup_endpoint(ip, intf->uii_intfnum, edesc);
550                         if (ret != USB_ERR_NORMAL_COMPLETION)
551                                 return usbd_usb2urb(ret);
552
553                         if (pipe->upi_type != UE_INTERRUPT)
554                                 continue;
555
556                         /* XXX we're following linux USB's interval policy.  */
557                         if (udev->speed == USB_SPEED_LOW)
558                                 pipe->upi_interval = edesc->bInterval + 5;
559                         else if (udev->speed == USB_SPEED_FULL)
560                                 pipe->upi_interval = edesc->bInterval;
561                         else {
562                                 int k0 = 0, k1 = 1;
563                                 do {
564                                         k1 = k1 * 2;
565                                         k0 = k0 + 1;
566                                 } while (k1 < edesc->bInterval);
567                                 pipe->upi_interval = k0;
568                         }
569                 }
570
571                 intf = (struct usbd_interface_information *)(((char *)intf) +
572                     intf->uii_len);
573         }
574
575         return (USBD_STATUS_SUCCESS);
576 }
577
578 static usb_error_t
579 usbd_setup_endpoint_one(irp *ip, uint8_t ifidx, struct ndisusb_ep *ne,
580     struct usb_config *epconf)
581 {
582         device_t dev = IRP_NDIS_DEV(ip);
583         struct ndis_softc *sc = device_get_softc(dev);
584         struct usb_xfer *xfer;
585         usb_error_t status;
586
587         InitializeListHead(&ne->ne_active);
588         InitializeListHead(&ne->ne_pending);
589         KeInitializeSpinLock(&ne->ne_lock);
590
591         status = usbd_transfer_setup(sc->ndisusb_dev, &ifidx, ne->ne_xfer,
592             epconf, 1, sc, &sc->ndisusb_lock);
593         if (status != USB_ERR_NORMAL_COMPLETION) {
594                 device_printf(dev, "couldn't setup xfer: %s\n",
595                     usbd_errstr(status));
596                 return (status);
597         }
598         xfer = ne->ne_xfer[0];
599         usbd_xfer_set_priv(xfer, ne);
600
601         return (status);
602 }
603
604 static usb_error_t
605 usbd_setup_endpoint_default(irp *ip, uint8_t ifidx)
606 {
607         device_t dev = IRP_NDIS_DEV(ip);
608         struct ndis_softc *sc = device_get_softc(dev);
609         usb_error_t status;
610
611         if (ifidx > 0)
612                 device_printf(dev, "warning: ifidx > 0 isn't supported.\n");
613
614         status = usbd_setup_endpoint_one(ip, ifidx, &sc->ndisusb_dread_ep,
615             &usbd_default_epconfig[USBD_CTRL_READ_PIPE]);
616         if (status != USB_ERR_NORMAL_COMPLETION)
617                 return (status);
618
619         status = usbd_setup_endpoint_one(ip, ifidx, &sc->ndisusb_dwrite_ep,
620             &usbd_default_epconfig[USBD_CTRL_WRITE_PIPE]);
621         return (status);
622 }
623
624 static usb_error_t
625 usbd_setup_endpoint(irp *ip, uint8_t ifidx,
626     struct usb_endpoint_descriptor *ep)
627 {
628         device_t dev = IRP_NDIS_DEV(ip);
629         struct ndis_softc *sc = device_get_softc(dev);
630         struct ndisusb_ep *ne;
631         struct usb_config cfg;
632         struct usb_xfer *xfer;
633         usb_error_t status;
634
635         /* check for non-supported transfer types */
636         if (UE_GET_XFERTYPE(ep->bmAttributes) == UE_CONTROL ||
637             UE_GET_XFERTYPE(ep->bmAttributes) == UE_ISOCHRONOUS) {
638                 device_printf(dev, "%s: unsuppotted transfer types %#x\n",
639                     __func__, UE_GET_XFERTYPE(ep->bmAttributes));
640                 return (USB_ERR_INVAL);
641         }
642
643         ne = &sc->ndisusb_ep[NDISUSB_GET_ENDPT(ep->bEndpointAddress)];
644         InitializeListHead(&ne->ne_active);
645         InitializeListHead(&ne->ne_pending);
646         KeInitializeSpinLock(&ne->ne_lock);
647         ne->ne_dirin = UE_GET_DIR(ep->bEndpointAddress) >> 7;
648
649         memset(&cfg, 0, sizeof(struct usb_config));
650         cfg.type        = UE_GET_XFERTYPE(ep->bmAttributes);
651         cfg.endpoint    = UE_GET_ADDR(ep->bEndpointAddress);
652         cfg.direction   = UE_GET_DIR(ep->bEndpointAddress);
653         cfg.callback    = &usbd_non_isoc_callback;
654         cfg.bufsize     = UGETW(ep->wMaxPacketSize);
655         cfg.flags.proxy_buffer = 1;
656         if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN)
657                 cfg.flags.short_xfer_ok = 1;
658
659         status = usbd_transfer_setup(sc->ndisusb_dev, &ifidx, ne->ne_xfer,
660             &cfg, 1, sc, &sc->ndisusb_lock);
661         if (status != USB_ERR_NORMAL_COMPLETION) {
662                 device_printf(dev, "couldn't setup xfer: %s\n",
663                     usbd_errstr(status));
664                 return (status);
665         }
666         xfer = ne->ne_xfer[0];
667         usbd_xfer_set_priv(xfer, ne);
668         if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN)
669                 usbd_xfer_set_timeout(xfer, NDISUSB_NO_TIMEOUT);
670         else {
671                 if (UE_GET_XFERTYPE(ep->bmAttributes) == UE_BULK)
672                         usbd_xfer_set_timeout(xfer, NDISUSB_TX_TIMEOUT);
673                 else
674                         usbd_xfer_set_timeout(xfer, NDISUSB_INTR_TIMEOUT);
675         }
676
677         return (status);
678 }
679
680 static int32_t
681 usbd_func_abort_pipe(irp *ip)
682 {
683         device_t dev = IRP_NDIS_DEV(ip);
684         struct ndis_softc *sc = device_get_softc(dev);
685         struct ndisusb_ep *ne;
686         union usbd_urb *urb;
687
688         urb = usbd_geturb(ip);
689         ne = usbd_get_ndisep(ip, urb->uu_pipe.upr_handle);
690         if (ne == NULL) {
691                 device_printf(IRP_NDIS_DEV(ip), "get NULL endpoint info.\n");
692                 return (USBD_STATUS_INVALID_PIPE_HANDLE);
693         }
694
695         NDISUSB_LOCK(sc);
696         usbd_transfer_stop(ne->ne_xfer[0]);
697         usbd_transfer_start(ne->ne_xfer[0]);
698         NDISUSB_UNLOCK(sc);
699
700         return (USBD_STATUS_SUCCESS);
701 }
702
703 static int32_t
704 usbd_func_vendorclass(irp *ip)
705 {
706         device_t dev = IRP_NDIS_DEV(ip);
707         int32_t error;
708         struct ndis_softc *sc = device_get_softc(dev);
709         struct ndisusb_ep *ne;
710         struct ndisusb_xfer *nx;
711         struct usbd_urb_vendor_or_class_request *vcreq;
712         union usbd_urb *urb;
713
714         if (!(sc->ndisusb_status & NDISUSB_STATUS_SETUP_EP)) {
715                 /*
716                  * XXX In some cases the interface number isn't 0.  However
717                  * some driver (eg. RTL8187L NDIS driver) calls this function
718                  * before calling URB_FUNCTION_SELECT_CONFIGURATION.
719                  */
720                 error = usbd_setup_endpoint_default(ip, 0);
721                 if (error != USB_ERR_NORMAL_COMPLETION)
722                         return usbd_usb2urb(error);
723                 sc->ndisusb_status |= NDISUSB_STATUS_SETUP_EP;
724         }
725
726         urb = usbd_geturb(ip);
727         vcreq = &urb->uu_vcreq;
728         ne = (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) ?
729             &sc->ndisusb_dread_ep : &sc->ndisusb_dwrite_ep;
730         IRP_NDISUSB_EP(ip) = ne;
731         ip->irp_cancelfunc = (cancel_func)usbd_irpcancel_wrap;
732
733         nx = kmalloc(sizeof(struct ndisusb_xfer), M_USBDEV, M_NOWAIT | M_ZERO);
734         if (nx == NULL) {
735                 device_printf(IRP_NDIS_DEV(ip), "out of memory\n");
736                 return (USBD_STATUS_NO_MEMORY);
737         }
738         nx->nx_ep = ne;
739         nx->nx_priv = ip;
740         KeAcquireSpinLockAtDpcLevel(&ne->ne_lock);
741         InsertTailList((&ne->ne_pending), (&nx->nx_next));
742         KeReleaseSpinLockFromDpcLevel(&ne->ne_lock);
743
744         /* we've done to setup xfer.  Let's transfer it.  */
745         ip->irp_iostat.isb_status = STATUS_PENDING;
746         ip->irp_iostat.isb_info = 0;
747         USBD_URB_STATUS(urb) = USBD_STATUS_PENDING;
748         IoMarkIrpPending(ip);
749
750         error = usbd_taskadd(ip, NDISUSB_TASK_VENDOR);
751         if (error != USBD_STATUS_SUCCESS)
752                 return (error);
753
754         return (USBD_STATUS_PENDING);
755 }
756
757 static void
758 usbd_irpcancel(device_object *dobj, irp *ip)
759 {
760         device_t dev = IRP_NDIS_DEV(ip);
761         struct ndis_softc *sc = device_get_softc(dev);
762         struct ndisusb_ep *ne = IRP_NDISUSB_EP(ip);
763
764         if (ne == NULL) {
765                 ip->irp_cancel = TRUE;
766                 IoReleaseCancelSpinLock(ip->irp_cancelirql);
767                 return;
768         }
769
770         /*
771          * Make sure that the current USB transfer proxy is
772          * cancelled and then restarted.
773          */
774         NDISUSB_LOCK(sc);
775         usbd_transfer_stop(ne->ne_xfer[0]);
776         usbd_transfer_start(ne->ne_xfer[0]);
777         NDISUSB_UNLOCK(sc);
778
779         ip->irp_cancel = TRUE;
780         IoReleaseCancelSpinLock(ip->irp_cancelirql);
781 }
782
783 static void
784 usbd_xfer_complete(struct ndis_softc *sc, struct ndisusb_ep *ne,
785     struct ndisusb_xfer *nx, usb_error_t status)
786 {
787         struct ndisusb_xferdone *nd;
788         uint8_t irql;
789
790         nd = kmalloc(sizeof(struct ndisusb_xferdone), M_USBDEV,
791             M_NOWAIT | M_ZERO);
792         if (nd == NULL) {
793                 device_printf(sc->ndis_dev, "out of memory");
794                 return;
795         }
796         nd->nd_xfer = nx;
797         nd->nd_status = status;
798
799         KeAcquireSpinLock(&sc->ndisusb_xferdonelock, &irql);
800         InsertTailList((&sc->ndisusb_xferdonelist), (&nd->nd_donelist));
801         KeReleaseSpinLock(&sc->ndisusb_xferdonelock, irql);
802
803         IoQueueWorkItem(sc->ndisusb_xferdoneitem,
804             (io_workitem_func)usbd_xfertask_wrap, WORKQUEUE_CRITICAL, sc);
805 }
806
807 static struct ndisusb_xfer *
808 usbd_aq_getfirst(struct ndis_softc *sc, struct ndisusb_ep *ne)
809 {
810         struct ndisusb_xfer *nx;
811
812         KeAcquireSpinLockAtDpcLevel(&ne->ne_lock);
813         if (IsListEmpty(&ne->ne_active)) {
814                 device_printf(sc->ndis_dev,
815                     "%s: the active queue can't be empty.\n", __func__);
816                 KeReleaseSpinLockFromDpcLevel(&ne->ne_lock);
817                 return (NULL);
818         }
819         nx = CONTAINING_RECORD(ne->ne_active.nle_flink, struct ndisusb_xfer,
820             nx_next);
821         RemoveEntryList(&nx->nx_next);
822         KeReleaseSpinLockFromDpcLevel(&ne->ne_lock);
823
824         return (nx);
825 }
826
827 static void
828 usbd_non_isoc_callback(struct usb_xfer *xfer, usb_error_t error)
829 {
830         irp *ip;
831         struct ndis_softc *sc = usbd_xfer_softc(xfer);
832         struct ndisusb_ep *ne = usbd_xfer_get_priv(xfer);
833         struct ndisusb_xfer *nx;
834         struct usbd_urb_bulk_or_intr_transfer *ubi;
835         struct usb_page_cache *pc;
836         uint8_t irql;
837         uint32_t len;
838         union usbd_urb *urb;
839         usb_endpoint_descriptor_t *ep;
840         int actlen, sumlen;
841
842         usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
843
844         switch (USB_GET_STATE(xfer)) {
845         case USB_ST_TRANSFERRED:
846                 nx = usbd_aq_getfirst(sc, ne);
847                 pc = usbd_xfer_get_frame(xfer, 0);
848                 if (nx == NULL)
849                         return;
850
851                 /* copy in data with regard to the URB */
852                 if (ne->ne_dirin != 0)
853                         usbd_copy_out(pc, 0, nx->nx_urbbuf, actlen);
854                 nx->nx_urbbuf += actlen;
855                 nx->nx_urbactlen += actlen;
856                 nx->nx_urblen -= actlen;
857
858                 /* check for short transfer */
859                 if (actlen < sumlen)
860                         nx->nx_urblen = 0;
861                 else {
862                         /* check remainder */
863                         if (nx->nx_urblen > 0) {
864                                 KeAcquireSpinLock(&ne->ne_lock, &irql);
865                                 InsertHeadList((&ne->ne_active), (&nx->nx_next));
866                                 KeReleaseSpinLock(&ne->ne_lock, irql);
867
868                                 ip = nx->nx_priv;
869                                 urb = usbd_geturb(ip);
870                                 ubi = &urb->uu_bulkintr;
871                                 ep = ubi->ubi_epdesc;
872                                 goto extra;
873                         }
874                 }
875                 usbd_xfer_complete(sc, ne, nx,
876                     ((actlen < sumlen) && (nx->nx_shortxfer == 0)) ?
877                     USB_ERR_SHORT_XFER : USB_ERR_NORMAL_COMPLETION);
878
879                 /* fall through */
880         case USB_ST_SETUP:
881 next:
882                 /* get next transfer */
883                 KeAcquireSpinLock(&ne->ne_lock, &irql);
884                 if (IsListEmpty(&ne->ne_pending)) {
885                         KeReleaseSpinLock(&ne->ne_lock, irql);
886                         return;
887                 }
888                 nx = CONTAINING_RECORD(ne->ne_pending.nle_flink,
889                     struct ndisusb_xfer, nx_next);
890                 RemoveEntryList(&nx->nx_next);
891                 /* add a entry to the active queue's tail.  */
892                 InsertTailList((&ne->ne_active), (&nx->nx_next));
893                 KeReleaseSpinLock(&ne->ne_lock, irql);
894
895                 ip = nx->nx_priv;
896                 urb = usbd_geturb(ip);
897                 ubi = &urb->uu_bulkintr;
898                 ep = ubi->ubi_epdesc;
899
900                 nx->nx_urbbuf           = ubi->ubi_trans_buf;
901                 nx->nx_urbactlen        = 0;
902                 nx->nx_urblen           = ubi->ubi_trans_buflen;
903                 nx->nx_shortxfer        = (ubi->ubi_trans_flags &
904                     USBD_SHORT_TRANSFER_OK) ? 1 : 0;
905 extra:
906                 len = MIN(usbd_xfer_max_len(xfer), nx->nx_urblen);
907                 pc = usbd_xfer_get_frame(xfer, 0);
908                 if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_OUT)
909                         usbd_copy_in(pc, 0, nx->nx_urbbuf, len);
910                 usbd_xfer_set_frame_len(xfer, 0, len);
911                 usbd_xfer_set_frames(xfer, 1);
912                 usbd_transfer_submit(xfer);
913                 break;
914         default:
915                 nx = usbd_aq_getfirst(sc, ne);
916                 if (nx == NULL)
917                         return;
918                 if (error != USB_ERR_CANCELLED) {
919                         usbd_xfer_set_stall(xfer);
920                         device_printf(sc->ndis_dev, "usb xfer warning (%s)\n",
921                             usbd_errstr(error));
922                 }
923                 usbd_xfer_complete(sc, ne, nx, error);
924                 if (error != USB_ERR_CANCELLED)
925                         goto next;
926                 break;
927         }
928 }
929
930 static void
931 usbd_ctrl_callback(struct usb_xfer *xfer, usb_error_t error)
932 {
933         irp *ip;
934         struct ndis_softc *sc = usbd_xfer_softc(xfer);
935         struct ndisusb_ep *ne = usbd_xfer_get_priv(xfer);
936         struct ndisusb_xfer *nx;
937         uint8_t irql;
938         union usbd_urb *urb;
939         struct usbd_urb_vendor_or_class_request *vcreq;
940         struct usb_page_cache *pc;
941         uint8_t type = 0;
942         struct usb_device_request req;
943         int len;
944
945         switch (USB_GET_STATE(xfer)) {
946         case USB_ST_TRANSFERRED:
947                 nx = usbd_aq_getfirst(sc, ne);
948                 if (nx == NULL)
949                         return;
950
951                 ip = nx->nx_priv;
952                 urb = usbd_geturb(ip);
953                 vcreq = &urb->uu_vcreq;
954
955                 if (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) {
956                         pc = usbd_xfer_get_frame(xfer, 1);
957                         len = usbd_xfer_frame_len(xfer, 1);
958                         usbd_copy_out(pc, 0, vcreq->uvc_trans_buf, len);
959                         nx->nx_urbactlen += len;
960                 }
961
962                 usbd_xfer_complete(sc, ne, nx, USB_ERR_NORMAL_COMPLETION);
963                 /* fall through */
964         case USB_ST_SETUP:
965 next:
966                 /* get next transfer */
967                 KeAcquireSpinLock(&ne->ne_lock, &irql);
968                 if (IsListEmpty(&ne->ne_pending)) {
969                         KeReleaseSpinLock(&ne->ne_lock, irql);
970                         return;
971                 }
972                 nx = CONTAINING_RECORD(ne->ne_pending.nle_flink,
973                     struct ndisusb_xfer, nx_next);
974                 RemoveEntryList(&nx->nx_next);
975                 /* add a entry to the active queue's tail.  */
976                 InsertTailList((&ne->ne_active), (&nx->nx_next));
977                 KeReleaseSpinLock(&ne->ne_lock, irql);
978
979                 ip = nx->nx_priv;
980                 urb = usbd_geturb(ip);
981                 vcreq = &urb->uu_vcreq;
982
983                 switch (urb->uu_hdr.uuh_func) {
984                 case URB_FUNCTION_CLASS_DEVICE:
985                         type = UT_CLASS | UT_DEVICE;
986                         break;
987                 case URB_FUNCTION_CLASS_INTERFACE:
988                         type = UT_CLASS | UT_INTERFACE;
989                         break;
990                 case URB_FUNCTION_CLASS_OTHER:
991                         type = UT_CLASS | UT_OTHER;
992                         break;
993                 case URB_FUNCTION_CLASS_ENDPOINT:
994                         type = UT_CLASS | UT_ENDPOINT;
995                         break;
996                 case URB_FUNCTION_VENDOR_DEVICE:
997                         type = UT_VENDOR | UT_DEVICE;
998                         break;
999                 case URB_FUNCTION_VENDOR_INTERFACE:
1000                         type = UT_VENDOR | UT_INTERFACE;
1001                         break;
1002                 case URB_FUNCTION_VENDOR_OTHER:
1003                         type = UT_VENDOR | UT_OTHER;
1004                         break;
1005                 case URB_FUNCTION_VENDOR_ENDPOINT:
1006                         type = UT_VENDOR | UT_ENDPOINT;
1007                         break;
1008                 default:
1009                         /* never reached.  */
1010                         break;
1011                 }
1012
1013                 type |= (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) ?
1014                     UT_READ : UT_WRITE;
1015                 type |= vcreq->uvc_reserved1;
1016
1017                 req.bmRequestType = type;
1018                 req.bRequest = vcreq->uvc_req;
1019                 USETW(req.wIndex, vcreq->uvc_idx);
1020                 USETW(req.wValue, vcreq->uvc_value);
1021                 USETW(req.wLength, vcreq->uvc_trans_buflen);
1022
1023                 nx->nx_urbbuf           = vcreq->uvc_trans_buf;
1024                 nx->nx_urblen           = vcreq->uvc_trans_buflen;
1025                 nx->nx_urbactlen        = 0;
1026
1027                 pc = usbd_xfer_get_frame(xfer, 0);
1028                 usbd_copy_in(pc, 0, &req, sizeof(req));
1029                 usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
1030                 usbd_xfer_set_frames(xfer, 1);
1031                 if (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) {
1032                         if (vcreq->uvc_trans_buflen >= USBD_CTRL_READ_BUFFER_SP)
1033                                 device_printf(sc->ndis_dev,
1034                                     "warning: not enough buffer space (%d).\n",
1035                                     vcreq->uvc_trans_buflen);
1036                         usbd_xfer_set_frame_len(xfer, 1,
1037                             MIN(usbd_xfer_max_len(xfer),
1038                                     vcreq->uvc_trans_buflen));
1039                         usbd_xfer_set_frames(xfer, 2);
1040                 } else {
1041                         if (nx->nx_urblen > USBD_CTRL_WRITE_BUFFER_SP)
1042                                 device_printf(sc->ndis_dev,
1043                                     "warning: not enough write buffer space"
1044                                     " (%d).\n", nx->nx_urblen);
1045                         /*
1046                          * XXX with my local tests there was no cases to require
1047                          * a extra buffer until now but it'd need to update in
1048                          * the future if it needs to be.
1049                          */
1050                         if (nx->nx_urblen > 0) {
1051                                 pc = usbd_xfer_get_frame(xfer, 1);
1052                                 usbd_copy_in(pc, 0, nx->nx_urbbuf,
1053                                     nx->nx_urblen);
1054                                 usbd_xfer_set_frame_len(xfer, 1, nx->nx_urblen);
1055                                 usbd_xfer_set_frames(xfer, 2);
1056                         }
1057                 }
1058                 usbd_transfer_submit(xfer);
1059                 break;
1060         default:
1061                 nx = usbd_aq_getfirst(sc, ne);
1062                 if (nx == NULL)
1063                         return;
1064                 if (error != USB_ERR_CANCELLED) {
1065                         usbd_xfer_set_stall(xfer);
1066                         device_printf(sc->ndis_dev, "usb xfer warning (%s)\n",
1067                             usbd_errstr(error));
1068                 }
1069                 usbd_xfer_complete(sc, ne, nx, error);
1070                 if (error != USB_ERR_CANCELLED)
1071                         goto next;
1072                 break;
1073         }
1074 }
1075
1076 static struct ndisusb_ep *
1077 usbd_get_ndisep(irp *ip, usb_endpoint_descriptor_t *ep)
1078 {
1079         device_t dev = IRP_NDIS_DEV(ip);
1080         struct ndis_softc *sc = device_get_softc(dev);
1081         struct ndisusb_ep *ne;
1082
1083         ne = &sc->ndisusb_ep[NDISUSB_GET_ENDPT(ep->bEndpointAddress)];
1084
1085         IRP_NDISUSB_EP(ip) = ne;
1086         ip->irp_cancelfunc = (cancel_func)usbd_irpcancel_wrap;
1087
1088         return (ne);
1089 }
1090
1091 static void
1092 usbd_xfertask(device_object *dobj, void *arg)
1093 {
1094         int error;
1095         irp *ip;
1096         list_entry *l;
1097         struct ndis_softc *sc = arg;
1098         struct ndisusb_xferdone *nd;
1099         struct ndisusb_xfer *nq;
1100         struct usbd_urb_bulk_or_intr_transfer *ubi;
1101         struct usbd_urb_vendor_or_class_request *vcreq;
1102         union usbd_urb *urb;
1103         usb_error_t status;
1104         void *priv;
1105
1106         if (IsListEmpty(&sc->ndisusb_xferdonelist))
1107                 return;
1108
1109         KeAcquireSpinLockAtDpcLevel(&sc->ndisusb_xferdonelock);
1110         l = sc->ndisusb_xferdonelist.nle_flink;
1111         while (l != &sc->ndisusb_xferdonelist) {
1112                 nd = CONTAINING_RECORD(l, struct ndisusb_xferdone, nd_donelist);
1113                 nq = nd->nd_xfer;
1114                 priv = nq->nx_priv;
1115                 status = nd->nd_status;
1116                 error = 0;
1117                 ip = priv;
1118                 urb = usbd_geturb(ip);
1119
1120                 ip->irp_cancelfunc = NULL;
1121                 IRP_NDISUSB_EP(ip) = NULL;
1122
1123                 switch (status) {
1124                 case USB_ERR_NORMAL_COMPLETION:
1125                         if (urb->uu_hdr.uuh_func ==
1126                             URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER) {
1127                                 ubi = &urb->uu_bulkintr;
1128                                 ubi->ubi_trans_buflen = nq->nx_urbactlen;
1129                         } else {
1130                                 vcreq = &urb->uu_vcreq;
1131                                 vcreq->uvc_trans_buflen = nq->nx_urbactlen;
1132                         }
1133                         ip->irp_iostat.isb_info = nq->nx_urbactlen;
1134                         ip->irp_iostat.isb_status = STATUS_SUCCESS;
1135                         USBD_URB_STATUS(urb) = USBD_STATUS_SUCCESS;
1136                         break;
1137                 case USB_ERR_CANCELLED:
1138                         ip->irp_iostat.isb_info = 0;
1139                         ip->irp_iostat.isb_status = STATUS_CANCELLED;
1140                         USBD_URB_STATUS(urb) = USBD_STATUS_CANCELED;
1141                         break;
1142                 default:
1143                         ip->irp_iostat.isb_info = 0;
1144                         USBD_URB_STATUS(urb) = usbd_usb2urb(status);
1145                         ip->irp_iostat.isb_status =
1146                             usbd_urb2nt(USBD_URB_STATUS(urb));
1147                         break;
1148                 }
1149
1150                 l = l->nle_flink;
1151                 RemoveEntryList(&nd->nd_donelist);
1152                 kfree(nq, M_USBDEV);
1153                 kfree(nd, M_USBDEV);
1154                 if (error)
1155                         continue;
1156                 KeReleaseSpinLockFromDpcLevel(&sc->ndisusb_xferdonelock);
1157                 /* NB: call after cleaning  */
1158                 IoCompleteRequest(ip, IO_NO_INCREMENT);
1159                 KeAcquireSpinLockAtDpcLevel(&sc->ndisusb_xferdonelock);
1160         }
1161         KeReleaseSpinLockFromDpcLevel(&sc->ndisusb_xferdonelock);
1162 }
1163
1164 /*
1165  * this function is for mainly deferring a task to the another thread because
1166  * we don't want to be in the scope of HAL lock.
1167  */
1168 static int32_t
1169 usbd_taskadd(irp *ip, unsigned type)
1170 {
1171         device_t dev = IRP_NDIS_DEV(ip);
1172         struct ndis_softc *sc = device_get_softc(dev);
1173         struct ndisusb_task *nt;
1174
1175         nt = kmalloc(sizeof(struct ndisusb_task), M_USBDEV, M_NOWAIT | M_ZERO);
1176         if (nt == NULL)
1177                 return (USBD_STATUS_NO_MEMORY);
1178         nt->nt_type = type;
1179         nt->nt_ctx = ip;
1180
1181         KeAcquireSpinLockAtDpcLevel(&sc->ndisusb_tasklock);
1182         InsertTailList((&sc->ndisusb_tasklist), (&nt->nt_tasklist));
1183         KeReleaseSpinLockFromDpcLevel(&sc->ndisusb_tasklock);
1184
1185         IoQueueWorkItem(sc->ndisusb_taskitem,
1186             (io_workitem_func)usbd_task_wrap, WORKQUEUE_CRITICAL, sc);
1187
1188         return (USBD_STATUS_SUCCESS);
1189 }
1190
1191 static void
1192 usbd_task(device_object *dobj, void *arg)
1193 {
1194         irp *ip;
1195         list_entry *l;
1196         struct ndis_softc *sc = arg;
1197         struct ndisusb_ep *ne;
1198         struct ndisusb_task *nt;
1199         union usbd_urb *urb;
1200
1201         if (IsListEmpty(&sc->ndisusb_tasklist))
1202                 return;
1203
1204         KeAcquireSpinLockAtDpcLevel(&sc->ndisusb_tasklock);
1205         l = sc->ndisusb_tasklist.nle_flink;
1206         while (l != &sc->ndisusb_tasklist) {
1207                 nt = CONTAINING_RECORD(l, struct ndisusb_task, nt_tasklist);
1208
1209                 ip = nt->nt_ctx;
1210                 urb = usbd_geturb(ip);
1211
1212                 KeReleaseSpinLockFromDpcLevel(&sc->ndisusb_tasklock);
1213                 NDISUSB_LOCK(sc);
1214                 switch (nt->nt_type) {
1215                 case NDISUSB_TASK_TSTART:
1216                         ne = usbd_get_ndisep(ip, urb->uu_bulkintr.ubi_epdesc);
1217                         if (ne == NULL)
1218                                 goto exit;
1219                         usbd_transfer_start(ne->ne_xfer[0]);
1220                         break;
1221                 case NDISUSB_TASK_IRPCANCEL:
1222                         ne = usbd_get_ndisep(ip,
1223                             (nt->nt_type == NDISUSB_TASK_IRPCANCEL) ?
1224                             urb->uu_bulkintr.ubi_epdesc :
1225                             urb->uu_pipe.upr_handle);
1226                         if (ne == NULL)
1227                                 goto exit;
1228                         
1229                         usbd_transfer_stop(ne->ne_xfer[0]);
1230                         usbd_transfer_start(ne->ne_xfer[0]);
1231                         break;
1232                 case NDISUSB_TASK_VENDOR:
1233                         ne = (urb->uu_vcreq.uvc_trans_flags &
1234                             USBD_TRANSFER_DIRECTION_IN) ?
1235                             &sc->ndisusb_dread_ep : &sc->ndisusb_dwrite_ep;
1236                         usbd_transfer_start(ne->ne_xfer[0]);
1237                         break;
1238                 default:
1239                         break;
1240                 }
1241 exit:
1242                 NDISUSB_UNLOCK(sc);
1243                 KeAcquireSpinLockAtDpcLevel(&sc->ndisusb_tasklock);
1244
1245                 l = l->nle_flink;
1246                 RemoveEntryList(&nt->nt_tasklist);
1247                 kfree(nt, M_USBDEV);
1248         }
1249         KeReleaseSpinLockFromDpcLevel(&sc->ndisusb_tasklock);
1250 }
1251
1252 static int32_t
1253 usbd_func_bulkintr(irp *ip)
1254 {
1255         int32_t error;
1256         struct ndisusb_ep *ne;
1257         struct ndisusb_xfer *nx;
1258         struct usbd_urb_bulk_or_intr_transfer *ubi;
1259         union usbd_urb *urb;
1260         usb_endpoint_descriptor_t *ep;
1261
1262         urb = usbd_geturb(ip);
1263         ubi = &urb->uu_bulkintr;
1264         ep = ubi->ubi_epdesc;
1265         if (ep == NULL)
1266                 return (USBD_STATUS_INVALID_PIPE_HANDLE);
1267
1268         ne = usbd_get_ndisep(ip, ep);
1269         if (ne == NULL) {
1270                 device_printf(IRP_NDIS_DEV(ip), "get NULL endpoint info.\n");
1271                 return (USBD_STATUS_INVALID_PIPE_HANDLE);
1272         }
1273
1274         nx = kmalloc(sizeof(struct ndisusb_xfer), M_USBDEV, M_NOWAIT | M_ZERO);
1275         if (nx == NULL) {
1276                 device_printf(IRP_NDIS_DEV(ip), "out of memory\n");
1277                 return (USBD_STATUS_NO_MEMORY);
1278         }
1279         nx->nx_ep = ne;
1280         nx->nx_priv = ip;
1281         KeAcquireSpinLockAtDpcLevel(&ne->ne_lock);
1282         InsertTailList((&ne->ne_pending), (&nx->nx_next));
1283         KeReleaseSpinLockFromDpcLevel(&ne->ne_lock);
1284
1285         /* we've done to setup xfer.  Let's transfer it.  */
1286         ip->irp_iostat.isb_status = STATUS_PENDING;
1287         ip->irp_iostat.isb_info = 0;
1288         USBD_URB_STATUS(urb) = USBD_STATUS_PENDING;
1289         IoMarkIrpPending(ip);
1290
1291         error = usbd_taskadd(ip, NDISUSB_TASK_TSTART);
1292         if (error != USBD_STATUS_SUCCESS)
1293                 return (error);
1294
1295         return (USBD_STATUS_PENDING);
1296 }
1297
1298 static union usbd_urb *
1299 USBD_CreateConfigurationRequest(usb_config_descriptor_t *conf, uint16_t *len)
1300 {
1301         struct usbd_interface_list_entry list[2];
1302         union usbd_urb *urb;
1303
1304         bzero(list, sizeof(struct usbd_interface_list_entry) * 2);
1305         list[0].uil_intfdesc = USBD_ParseConfigurationDescriptorEx(conf, conf,
1306             -1, -1, -1, -1, -1);
1307         urb = USBD_CreateConfigurationRequestEx(conf, list);
1308         if (urb == NULL)
1309                 return (NULL);
1310
1311         *len = urb->uu_selconf.usc_hdr.uuh_len;
1312         return (urb);
1313 }
1314
1315 static union usbd_urb *
1316 USBD_CreateConfigurationRequestEx(usb_config_descriptor_t *conf,
1317     struct usbd_interface_list_entry *list)
1318 {
1319         int i, j, size;
1320         struct usbd_interface_information *intf;
1321         struct usbd_pipe_information *pipe;
1322         struct usbd_urb_select_configuration *selconf;
1323         usb_interface_descriptor_t *desc;
1324
1325         for (i = 0, size = 0; i < conf->bNumInterface; i++) {
1326                 j = list[i].uil_intfdesc->bNumEndpoints;
1327                 size = size + sizeof(struct usbd_interface_information) +
1328                     sizeof(struct usbd_pipe_information) * (j - 1);
1329         }
1330         size += sizeof(struct usbd_urb_select_configuration) -
1331             sizeof(struct usbd_interface_information);
1332
1333         selconf = ExAllocatePoolWithTag(NonPagedPool, size, 0);
1334         if (selconf == NULL)
1335                 return (NULL);
1336         selconf->usc_hdr.uuh_func = URB_FUNCTION_SELECT_CONFIGURATION;
1337         selconf->usc_hdr.uuh_len = size;
1338         selconf->usc_handle = conf;
1339         selconf->usc_conf = conf;
1340
1341         intf = &selconf->usc_intf;
1342         for (i = 0; i < conf->bNumInterface; i++) {
1343                 if (list[i].uil_intfdesc == NULL)
1344                         break;
1345
1346                 list[i].uil_intf = intf;
1347                 desc = list[i].uil_intfdesc;
1348
1349                 intf->uii_len = sizeof(struct usbd_interface_information) +
1350                     (desc->bNumEndpoints - 1) *
1351                     sizeof(struct usbd_pipe_information);
1352                 intf->uii_intfnum = desc->bInterfaceNumber;
1353                 intf->uii_altset = desc->bAlternateSetting;
1354                 intf->uii_intfclass = desc->bInterfaceClass;
1355                 intf->uii_intfsubclass = desc->bInterfaceSubClass;
1356                 intf->uii_intfproto = desc->bInterfaceProtocol;
1357                 intf->uii_handle = desc;
1358                 intf->uii_numeps = desc->bNumEndpoints;
1359
1360                 pipe = &intf->uii_pipes[0];
1361                 for (j = 0; j < intf->uii_numeps; j++)
1362                         pipe[j].upi_maxtxsize =
1363                             USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;
1364
1365                 intf = (struct usbd_interface_information *)((char *)intf +
1366                     intf->uii_len);
1367         }
1368
1369         return ((union usbd_urb *)selconf);
1370 }
1371
1372 static void
1373 USBD_GetUSBDIVersion(usbd_version_info *ui)
1374 {
1375
1376         /* Pretend to be Windows XP. */
1377
1378         ui->uvi_usbdi_vers = USBDI_VERSION;
1379         ui->uvi_supported_vers = USB_VER_2_0;
1380 }
1381
1382 static usb_interface_descriptor_t *
1383 USBD_ParseConfigurationDescriptor(usb_config_descriptor_t *conf,
1384         uint8_t intfnum, uint8_t altset)
1385 {
1386
1387         return USBD_ParseConfigurationDescriptorEx(conf, conf, intfnum, altset,
1388             -1, -1, -1);
1389 }
1390
1391 static usb_interface_descriptor_t *
1392 USBD_ParseConfigurationDescriptorEx(usb_config_descriptor_t *conf,
1393     void *start, int32_t intfnum, int32_t altset, int32_t intfclass,
1394     int32_t intfsubclass, int32_t intfproto)
1395 {
1396         struct usb_descriptor *next = NULL;
1397         usb_interface_descriptor_t *desc;
1398
1399         while ((next = usb_desc_foreach(conf, next)) != NULL) {
1400                 desc = (usb_interface_descriptor_t *)next;
1401                 if (desc->bDescriptorType != UDESC_INTERFACE)
1402                         continue;
1403                 if (!(intfnum == -1 || desc->bInterfaceNumber == intfnum))
1404                         continue;
1405                 if (!(altset == -1 || desc->bAlternateSetting == altset))
1406                         continue;
1407                 if (!(intfclass == -1 || desc->bInterfaceClass == intfclass))
1408                         continue;
1409                 if (!(intfsubclass == -1 ||
1410                     desc->bInterfaceSubClass == intfsubclass))
1411                         continue;
1412                 if (!(intfproto == -1 || desc->bInterfaceProtocol == intfproto))
1413                         continue;
1414                 return (desc);
1415         }
1416
1417         return (NULL);
1418 }
1419
1420 static void
1421 dummy(void)
1422 {
1423         kprintf("USBD dummy called\n");
1424 }
1425
1426 image_patch_table usbd_functbl[] = {
1427         IMPORT_SFUNC(USBD_CreateConfigurationRequest, 2),
1428         IMPORT_SFUNC(USBD_CreateConfigurationRequestEx, 2),
1429         IMPORT_SFUNC_MAP(_USBD_CreateConfigurationRequestEx@8,
1430             USBD_CreateConfigurationRequestEx, 2),
1431         IMPORT_SFUNC(USBD_GetUSBDIVersion, 1),
1432         IMPORT_SFUNC(USBD_ParseConfigurationDescriptor, 3),
1433         IMPORT_SFUNC(USBD_ParseConfigurationDescriptorEx, 7),
1434         IMPORT_SFUNC_MAP(_USBD_ParseConfigurationDescriptorEx@28,
1435             USBD_ParseConfigurationDescriptorEx, 7),
1436
1437         /*
1438          * This last entry is a catch-all for any function we haven't
1439          * implemented yet. The PE import list patching routine will
1440          * use it for any function that doesn't have an explicit match
1441          * in this table.
1442          */
1443
1444         { NULL, (FUNC)dummy, NULL, 0, WINDRV_WRAP_STDCALL },
1445
1446         /* End of list. */
1447
1448         { NULL, NULL, NULL }
1449 };
1450
1451 MODULE_DEPEND(ndis, usb, 1, 1, 1);