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