xref: /openbsd/sys/dev/usb/usbdi.c (revision 78b63d65)
1 /*	$OpenBSD: usbdi.c,v 1.14 2001/05/03 02:20:34 aaron Exp $ */
2 /*	$NetBSD: usbdi.c,v 1.81 2001/04/17 00:05:33 augustss Exp $	*/
3 /*	$FreeBSD: src/sys/dev/usb/usbdi.c,v 1.28 1999/11/17 22:33:49 n_hibma Exp $	*/
4 
5 /*
6  * Copyright (c) 1998 The NetBSD Foundation, Inc.
7  * All rights reserved.
8  *
9  * This code is derived from software contributed to The NetBSD Foundation
10  * by Lennart Augustsson (lennart@augustsson.net) at
11  * Carlstedt Research & Technology.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. All advertising materials mentioning features or use of this software
22  *    must display the following acknowledgement:
23  *        This product includes software developed by the NetBSD
24  *        Foundation, Inc. and its contributors.
25  * 4. Neither the name of The NetBSD Foundation nor the names of its
26  *    contributors may be used to endorse or promote products derived
27  *    from this software without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
30  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
31  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
33  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39  * POSSIBILITY OF SUCH DAMAGE.
40  */
41 
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #if defined(__NetBSD__) || defined(__OpenBSD__)
45 #include <sys/kernel.h>
46 #include <sys/device.h>
47 #elif defined(__FreeBSD__)
48 #include <sys/module.h>
49 #include <sys/bus.h>
50 #include <sys/conf.h>
51 #include "usb_if.h"
52 #if defined(DIAGNOSTIC) && defined(__i386__)
53 #include <machine/cpu.h>
54 #endif
55 #endif
56 #include <sys/malloc.h>
57 #include <sys/proc.h>
58 
59 #include <machine/bus.h>
60 
61 #include <dev/usb/usb.h>
62 #include <dev/usb/usbdi.h>
63 #include <dev/usb/usbdi_util.h>
64 #include <dev/usb/usbdivar.h>
65 #include <dev/usb/usb_mem.h>
66 
67 #if defined(__FreeBSD__)
68 #include "usb_if.h"
69 #endif
70 
71 #ifdef USB_DEBUG
72 #define DPRINTF(x)	if (usbdebug) logprintf x
73 #define DPRINTFN(n,x)	if (usbdebug>(n)) logprintf x
74 extern int usbdebug;
75 #else
76 #define DPRINTF(x)
77 #define DPRINTFN(n,x)
78 #endif
79 
80 Static usbd_status usbd_ar_pipe(usbd_pipe_handle pipe);
81 Static void usbd_do_request_async_cb
82 (usbd_xfer_handle, usbd_private_handle, usbd_status);
83 Static void usbd_start_next(usbd_pipe_handle pipe);
84 Static usbd_status usbd_open_pipe_ival
85 (usbd_interface_handle, u_int8_t, u_int8_t, usbd_pipe_handle *, int);
86 
87 Static int usbd_nbuses = 0;
88 
89 void
90 usbd_init(void)
91 {
92 	usbd_nbuses++;
93 }
94 
95 void
96 usbd_finish(void)
97 {
98 	--usbd_nbuses;
99 }
100 
101 static __inline int
102 usbd_xfer_isread(usbd_xfer_handle xfer)
103 {
104 	if (xfer->rqflags & URQ_REQUEST)
105 		return (xfer->request.bmRequestType & UT_READ);
106 	else
107 		return (xfer->pipe->endpoint->edesc->bEndpointAddress &
108 			UE_DIR_IN);
109 }
110 
111 #ifdef USB_DEBUG
112 void usbd_dump_queue(usbd_pipe_handle pipe);
113 void
114 usbd_dump_queue(usbd_pipe_handle pipe)
115 {
116 	usbd_xfer_handle xfer;
117 
118 	printf("usbd_dump_queue: pipe=%p\n", pipe);
119 	for (xfer = SIMPLEQ_FIRST(&pipe->queue);
120 	     xfer;
121 	     xfer = SIMPLEQ_NEXT(xfer, next)) {
122 		printf("  xfer=%p\n", xfer);
123 	}
124 }
125 #endif
126 
127 usbd_status
128 usbd_open_pipe(usbd_interface_handle iface, u_int8_t address,
129 	       u_int8_t flags, usbd_pipe_handle *pipe)
130 {
131 	return (usbd_open_pipe_ival(iface, address, flags, pipe,
132 				    USBD_DEFAULT_INTERVAL));
133 }
134 
135 usbd_status
136 usbd_open_pipe_ival(usbd_interface_handle iface, u_int8_t address,
137 		    u_int8_t flags, usbd_pipe_handle *pipe, int ival)
138 {
139 	usbd_pipe_handle p;
140 	struct usbd_endpoint *ep;
141 	usbd_status err;
142 	int i;
143 
144 	DPRINTFN(3,("usbd_open_pipe: iface=%p address=0x%x flags=0x%x\n",
145 		    iface, address, flags));
146 
147 	for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
148 		ep = &iface->endpoints[i];
149 		if (ep->edesc == NULL)
150 			return (USBD_IOERROR);
151 		if (ep->edesc->bEndpointAddress == address)
152 			goto found;
153 	}
154 	return (USBD_BAD_ADDRESS);
155  found:
156 	if ((flags & USBD_EXCLUSIVE_USE) && ep->refcnt != 0)
157 		return (USBD_IN_USE);
158 	err = usbd_setup_pipe(iface->device, iface, ep, ival, &p);
159 	if (err)
160 		return (err);
161 	LIST_INSERT_HEAD(&iface->pipes, p, next);
162 	*pipe = p;
163 	return (USBD_NORMAL_COMPLETION);
164 }
165 
166 usbd_status
167 usbd_open_pipe_intr(usbd_interface_handle iface, u_int8_t address,
168 		    u_int8_t flags, usbd_pipe_handle *pipe,
169 		    usbd_private_handle priv, void *buffer, u_int32_t len,
170 		    usbd_callback cb, int ival)
171 {
172 	usbd_status err;
173 	usbd_xfer_handle xfer;
174 	usbd_pipe_handle ipipe;
175 
176 	DPRINTFN(3,("usbd_open_pipe_intr: address=0x%x flags=0x%x len=%d\n",
177 		    address, flags, len));
178 
179 	err = usbd_open_pipe_ival(iface, address, USBD_EXCLUSIVE_USE,
180 				  &ipipe, ival);
181 	if (err)
182 		return (err);
183 	xfer = usbd_alloc_xfer(iface->device);
184 	if (xfer == NULL) {
185 		err = USBD_NOMEM;
186 		goto bad1;
187 	}
188 	usbd_setup_xfer(xfer, ipipe, priv, buffer, len, flags,
189 	    USBD_NO_TIMEOUT, cb);
190 	ipipe->intrxfer = xfer;
191 	ipipe->repeat = 1;
192 	err = usbd_transfer(xfer);
193 	*pipe = ipipe;
194 	if (err != USBD_IN_PROGRESS)
195 		goto bad2;
196 	return (USBD_NORMAL_COMPLETION);
197 
198  bad2:
199 	ipipe->intrxfer = NULL;
200 	ipipe->repeat = 0;
201 	usbd_free_xfer(xfer);
202  bad1:
203 	usbd_close_pipe(ipipe);
204 	return (err);
205 }
206 
207 usbd_status
208 usbd_close_pipe(usbd_pipe_handle pipe)
209 {
210 #ifdef DIAGNOSTIC
211 	if (pipe == NULL) {
212 		printf("usbd_close_pipe: pipe==NULL\n");
213 		return (USBD_NORMAL_COMPLETION);
214 	}
215 #endif
216 
217 	if (--pipe->refcnt != 0)
218 		return (USBD_NORMAL_COMPLETION);
219 	if (SIMPLEQ_FIRST(&pipe->queue) != 0)
220 		return (USBD_PENDING_REQUESTS);
221 	LIST_REMOVE(pipe, next);
222 	pipe->endpoint->refcnt--;
223 	pipe->methods->close(pipe);
224 #if defined(__NetBSD__) && defined(DIAGNOSTIC)
225 	if (callout_pending(&pipe->abort_handle)) {
226 		callout_stop(&pipe->abort_handle);
227 		printf("usbd_close_pipe: abort_handle pending");
228 	}
229 #endif
230 	if (pipe->intrxfer != NULL)
231 		usbd_free_xfer(pipe->intrxfer);
232 	free(pipe, M_USB);
233 	return (USBD_NORMAL_COMPLETION);
234 }
235 
236 usbd_status
237 usbd_transfer(usbd_xfer_handle xfer)
238 {
239 	usbd_pipe_handle pipe = xfer->pipe;
240 	usb_dma_t *dmap = &xfer->dmabuf;
241 	usbd_status err;
242 	u_int size;
243 	int s;
244 
245 	DPRINTFN(5,("usbd_transfer: xfer=%p, flags=%d, pipe=%p, running=%d\n",
246 		    xfer, xfer->flags, pipe, pipe->running));
247 #ifdef USB_DEBUG
248 	if (usbdebug > 5)
249 		usbd_dump_queue(pipe);
250 #endif
251 	xfer->done = 0;
252 
253 	if (pipe->aborting)
254 		return (USBD_CANCELLED);
255 
256 	size = xfer->length;
257 	/* If there is no buffer, allocate one. */
258 	if (!(xfer->rqflags & URQ_DEV_DMABUF) && size != 0) {
259 		struct usbd_bus *bus = pipe->device->bus;
260 
261 #ifdef DIAGNOSTIC
262 		if (xfer->rqflags & URQ_AUTO_DMABUF)
263 			printf("usbd_transfer: has old buffer!\n");
264 #endif
265 		err = bus->methods->allocm(bus, dmap, size);
266 		if (err)
267 			return (err);
268 		xfer->rqflags |= URQ_AUTO_DMABUF;
269 	}
270 
271 	/* Copy data if going out. */
272 	if (!(xfer->flags & USBD_NO_COPY) && size != 0 &&
273 	    !usbd_xfer_isread(xfer))
274 		memcpy(KERNADDR(dmap), xfer->buffer, size);
275 
276 	err = pipe->methods->transfer(xfer);
277 
278 	if (err != USBD_IN_PROGRESS && err) {
279 		/* The transfer has not been queued, so free buffer. */
280 		if (xfer->rqflags & URQ_AUTO_DMABUF) {
281 			struct usbd_bus *bus = pipe->device->bus;
282 
283 			bus->methods->freem(bus, &xfer->dmabuf);
284 			xfer->rqflags &= ~URQ_AUTO_DMABUF;
285 		}
286 	}
287 
288 	if (!(xfer->flags & USBD_SYNCHRONOUS))
289 		return (err);
290 
291 	/* Sync transfer, wait for completion. */
292 	if (err != USBD_IN_PROGRESS)
293 		return (err);
294 	s = splusb();
295 	if (!xfer->done) {
296 		if (pipe->device->bus->use_polling)
297 			panic("usbd_transfer: not done\n");
298 		tsleep(xfer, PRIBIO, "usbsyn", 0);
299 	}
300 	splx(s);
301 	return (xfer->status);
302 }
303 
304 /* Like usbd_transfer(), but waits for completion. */
305 usbd_status
306 usbd_sync_transfer(usbd_xfer_handle xfer)
307 {
308 	xfer->flags |= USBD_SYNCHRONOUS;
309 	return (usbd_transfer(xfer));
310 }
311 
312 void *
313 usbd_alloc_buffer(usbd_xfer_handle xfer, u_int32_t size)
314 {
315 	struct usbd_bus *bus = xfer->device->bus;
316 	usbd_status err;
317 
318 	err = bus->methods->allocm(bus, &xfer->dmabuf, size);
319 	if (err)
320 		return (0);
321 	xfer->rqflags |= URQ_DEV_DMABUF;
322 	return (KERNADDR(&xfer->dmabuf));
323 }
324 
325 void
326 usbd_free_buffer(usbd_xfer_handle xfer)
327 {
328 #ifdef DIAGNOSTIC
329 	if (!(xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))) {
330 		printf("usbd_free_buffer: no buffer\n");
331 		return;
332 	}
333 #endif
334 	xfer->rqflags &= ~(URQ_DEV_DMABUF | URQ_AUTO_DMABUF);
335 	xfer->device->bus->methods->freem(xfer->device->bus, &xfer->dmabuf);
336 }
337 
338 void *
339 usbd_get_buffer(usbd_xfer_handle xfer)
340 {
341 	if (!(xfer->rqflags & URQ_DEV_DMABUF))
342 		return (0);
343 	return (KERNADDR(&xfer->dmabuf));
344 }
345 
346 usbd_xfer_handle
347 usbd_alloc_xfer(usbd_device_handle dev)
348 {
349 	usbd_xfer_handle xfer;
350 
351 	xfer = dev->bus->methods->allocx(dev->bus);
352 	if (xfer == NULL)
353 		return (NULL);
354 	xfer->device = dev;
355 	usb_callout_init(xfer->timeout_handle);
356 	DPRINTFN(5,("usbd_alloc_xfer() = %p\n", xfer));
357 	return (xfer);
358 }
359 
360 usbd_status
361 usbd_free_xfer(usbd_xfer_handle xfer)
362 {
363 	DPRINTFN(5,("usbd_free_xfer: %p\n", xfer));
364 	if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))
365 		usbd_free_buffer(xfer);
366 #if defined(__NetBSD__) && defined(DIAGNOSTIC)
367 	if (callout_pending(&xfer->timeout_handle)) {
368 		callout_stop(&xfer->timeout_handle);
369 		printf("usbd_free_xfer: timout_handle pending");
370 	}
371 #endif
372 	xfer->device->bus->methods->freex(xfer->device->bus, xfer);
373 	return (USBD_NORMAL_COMPLETION);
374 }
375 
376 void
377 usbd_setup_xfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
378 		usbd_private_handle priv, void *buffer, u_int32_t length,
379 		u_int16_t flags, u_int32_t timeout,
380 		usbd_callback callback)
381 {
382 	xfer->pipe = pipe;
383 	xfer->priv = priv;
384 	xfer->buffer = buffer;
385 	xfer->length = length;
386 	xfer->actlen = 0;
387 	xfer->flags = flags;
388 	xfer->timeout = timeout;
389 	xfer->status = USBD_NOT_STARTED;
390 	xfer->callback = callback;
391 	xfer->rqflags &= ~URQ_REQUEST;
392 	xfer->nframes = 0;
393 }
394 
395 void
396 usbd_setup_default_xfer(usbd_xfer_handle xfer, usbd_device_handle dev,
397 			usbd_private_handle priv, u_int32_t timeout,
398 			usb_device_request_t *req, void *buffer,
399 			u_int32_t length, u_int16_t flags,
400 			usbd_callback callback)
401 {
402 	xfer->pipe = dev->default_pipe;
403 	xfer->priv = priv;
404 	xfer->buffer = buffer;
405 	xfer->length = length;
406 	xfer->actlen = 0;
407 	xfer->flags = flags;
408 	xfer->timeout = timeout;
409 	xfer->status = USBD_NOT_STARTED;
410 	xfer->callback = callback;
411 	xfer->request = *req;
412 	xfer->rqflags |= URQ_REQUEST;
413 	xfer->nframes = 0;
414 }
415 
416 void
417 usbd_setup_isoc_xfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
418 		     usbd_private_handle priv, u_int16_t *frlengths,
419 		     u_int32_t nframes, u_int16_t flags, usbd_callback callback)
420 {
421 	xfer->pipe = pipe;
422 	xfer->priv = priv;
423 	xfer->buffer = 0;
424 	xfer->length = 0;
425 	xfer->actlen = 0;
426 	xfer->flags = flags;
427 	xfer->timeout = USBD_NO_TIMEOUT;
428 	xfer->status = USBD_NOT_STARTED;
429 	xfer->callback = callback;
430 	xfer->rqflags &= ~URQ_REQUEST;
431 	xfer->frlengths = frlengths;
432 	xfer->nframes = nframes;
433 }
434 
435 void
436 usbd_get_xfer_status(usbd_xfer_handle xfer, usbd_private_handle *priv,
437 		     void **buffer, u_int32_t *count, usbd_status *status)
438 {
439 	if (priv != NULL)
440 		*priv = xfer->priv;
441 	if (buffer != NULL)
442 		*buffer = xfer->buffer;
443 	if (count != NULL)
444 		*count = xfer->actlen;
445 	if (status != NULL)
446 		*status = xfer->status;
447 }
448 
449 usb_config_descriptor_t *
450 usbd_get_config_descriptor(usbd_device_handle dev)
451 {
452 #ifdef DIAGNOSTIC
453 	if (dev == NULL) {
454 		printf("usbd_get_config_descriptor: dev == NULL\n");
455 		return (NULL);
456 	}
457 #endif
458 	return (dev->cdesc);
459 }
460 
461 usb_interface_descriptor_t *
462 usbd_get_interface_descriptor(usbd_interface_handle iface)
463 {
464 #ifdef DIAGNOSTIC
465 	if (iface == NULL) {
466 		printf("usbd_get_interface_descriptor: dev == NULL\n");
467 		return (NULL);
468 	}
469 #endif
470 	return (iface->idesc);
471 }
472 
473 usb_device_descriptor_t *
474 usbd_get_device_descriptor(usbd_device_handle dev)
475 {
476 	return (&dev->ddesc);
477 }
478 
479 usb_endpoint_descriptor_t *
480 usbd_interface2endpoint_descriptor(usbd_interface_handle iface, u_int8_t index)
481 {
482 	if (index >= iface->idesc->bNumEndpoints)
483 		return (0);
484 	return (iface->endpoints[index].edesc);
485 }
486 
487 usbd_status
488 usbd_abort_pipe(usbd_pipe_handle pipe)
489 {
490 	usbd_status err;
491 	int s;
492 
493 #ifdef DIAGNOSTIC
494 	if (pipe == NULL) {
495 		printf("usbd_close_pipe: pipe==NULL\n");
496 		return (USBD_NORMAL_COMPLETION);
497 	}
498 #endif
499 	s = splusb();
500 	err = usbd_ar_pipe(pipe);
501 	splx(s);
502 	return (err);
503 }
504 
505 usbd_status
506 usbd_clear_endpoint_stall(usbd_pipe_handle pipe)
507 {
508 	usbd_device_handle dev = pipe->device;
509 	usb_device_request_t req;
510 	usbd_status err;
511 
512 	DPRINTFN(8, ("usbd_clear_endpoint_stall\n"));
513 
514 	/*
515 	 * Clearing en endpoint stall resets the enpoint toggle, so
516 	 * do the same to the HC toggle.
517 	 */
518 	pipe->methods->cleartoggle(pipe);
519 
520 	req.bmRequestType = UT_WRITE_ENDPOINT;
521 	req.bRequest = UR_CLEAR_FEATURE;
522 	USETW(req.wValue, UF_ENDPOINT_HALT);
523 	USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
524 	USETW(req.wLength, 0);
525 	err = usbd_do_request(dev, &req, 0);
526 #if 0
527 XXX should we do this?
528 	if (!err) {
529 		pipe->state = USBD_PIPE_ACTIVE;
530 		/* XXX activate pipe */
531 	}
532 #endif
533 	return (err);
534 }
535 
536 usbd_status
537 usbd_clear_endpoint_stall_async(usbd_pipe_handle pipe)
538 {
539 	usbd_device_handle dev = pipe->device;
540 	usb_device_request_t req;
541 	usbd_status err;
542 
543 	pipe->methods->cleartoggle(pipe);
544 
545 	req.bmRequestType = UT_WRITE_ENDPOINT;
546 	req.bRequest = UR_CLEAR_FEATURE;
547 	USETW(req.wValue, UF_ENDPOINT_HALT);
548 	USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
549 	USETW(req.wLength, 0);
550 	err = usbd_do_request_async(dev, &req, 0);
551 	return (err);
552 }
553 
554 void usbd_clear_endpoint_toggle(usbd_pipe_handle pipe); /* XXXXX */
555 void
556 usbd_clear_endpoint_toggle(usbd_pipe_handle pipe)
557 {
558 	pipe->methods->cleartoggle(pipe);
559 }
560 
561 usbd_status
562 usbd_endpoint_count(usbd_interface_handle iface, u_int8_t *count)
563 {
564 #ifdef DIAGNOSTIC
565 	if (iface == NULL || iface->idesc == NULL) {
566 		printf("usbd_endpoint_count: NULL pointer\n");
567 		return (USBD_INVAL);
568 	}
569 #endif
570 	*count = iface->idesc->bNumEndpoints;
571 	return (USBD_NORMAL_COMPLETION);
572 }
573 
574 usbd_status
575 usbd_interface_count(usbd_device_handle dev, u_int8_t *count)
576 {
577 	if (dev->cdesc == NULL)
578 		return (USBD_NOT_CONFIGURED);
579 	*count = dev->cdesc->bNumInterface;
580 	return (USBD_NORMAL_COMPLETION);
581 }
582 
583 usbd_status
584 usbd_interface2device_handle(usbd_interface_handle iface,
585 			     usbd_device_handle *dev)
586 {
587 	*dev = iface->device;
588 	return (USBD_NORMAL_COMPLETION);
589 }
590 
591 usbd_status
592 usbd_device2interface_handle(usbd_device_handle dev,
593 			     u_int8_t ifaceno, usbd_interface_handle *iface)
594 {
595 	if (dev->cdesc == NULL)
596 		return (USBD_NOT_CONFIGURED);
597 	if (ifaceno >= dev->cdesc->bNumInterface)
598 		return (USBD_INVAL);
599 	*iface = &dev->ifaces[ifaceno];
600 	return (USBD_NORMAL_COMPLETION);
601 }
602 
603 usbd_device_handle
604 usbd_pipe2device_handle(usbd_pipe_handle pipe)
605 {
606 	return (pipe->device);
607 }
608 
609 /* XXXX use altno */
610 usbd_status
611 usbd_set_interface(usbd_interface_handle iface, int altidx)
612 {
613 	usb_device_request_t req;
614 	usbd_status err;
615 	void *endpoints;
616 
617 	if (LIST_FIRST(&iface->pipes) != 0)
618 		return (USBD_IN_USE);
619 
620 	endpoints = iface->endpoints;
621 	err = usbd_fill_iface_data(iface->device, iface->index, altidx);
622 	if (err)
623 		return (err);
624 
625 	/* new setting works, we can free old endpoints */
626 	if (endpoints != NULL)
627 		free(endpoints, M_USB);
628 
629 #ifdef DIAGNOSTIC
630 	if (iface->idesc == NULL) {
631 		printf("usbd_set_interface: NULL pointer\n");
632 		return (USBD_INVAL);
633 	}
634 #endif
635 
636 	req.bmRequestType = UT_WRITE_INTERFACE;
637 	req.bRequest = UR_SET_INTERFACE;
638 	USETW(req.wValue, iface->idesc->bAlternateSetting);
639 	USETW(req.wIndex, iface->idesc->bInterfaceNumber);
640 	USETW(req.wLength, 0);
641 	return (usbd_do_request(iface->device, &req, 0));
642 }
643 
644 int
645 usbd_get_no_alts(usb_config_descriptor_t *cdesc, int ifaceno)
646 {
647 	char *p = (char *)cdesc;
648 	char *end = p + UGETW(cdesc->wTotalLength);
649 	usb_interface_descriptor_t *d;
650 	int n;
651 
652 	for (n = 0; p < end; p += d->bLength) {
653 		d = (usb_interface_descriptor_t *)p;
654 		if (p + d->bLength <= end &&
655 		    d->bDescriptorType == UDESC_INTERFACE &&
656 		    d->bInterfaceNumber == ifaceno)
657 			n++;
658 	}
659 	return (n);
660 }
661 
662 int
663 usbd_get_interface_altindex(usbd_interface_handle iface)
664 {
665 	return (iface->altindex);
666 }
667 
668 usbd_status
669 usbd_get_interface(usbd_interface_handle iface, u_int8_t *aiface)
670 {
671 	usb_device_request_t req;
672 
673 	req.bmRequestType = UT_READ_INTERFACE;
674 	req.bRequest = UR_GET_INTERFACE;
675 	USETW(req.wValue, 0);
676 	USETW(req.wIndex, iface->idesc->bInterfaceNumber);
677 	USETW(req.wLength, 1);
678 	return (usbd_do_request(iface->device, &req, aiface));
679 }
680 
681 /*** Internal routines ***/
682 
683 /* Dequeue all pipe operations, called at splusb(). */
684 Static usbd_status
685 usbd_ar_pipe(usbd_pipe_handle pipe)
686 {
687 	usbd_xfer_handle xfer;
688 
689 	SPLUSBCHECK;
690 
691 	DPRINTFN(2,("usbd_ar_pipe: pipe=%p\n", pipe));
692 #ifdef USB_DEBUG
693 	if (usbdebug > 5)
694 		usbd_dump_queue(pipe);
695 #endif
696 	pipe->repeat = 0;
697 	pipe->aborting = 1;
698 	while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL) {
699 		DPRINTFN(2,("usbd_ar_pipe: pipe=%p xfer=%p (methods=%p)\n",
700 			    pipe, xfer, pipe->methods));
701 		/* Make the HC abort it (and invoke the callback). */
702 		pipe->methods->abort(xfer);
703 		/* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */
704 	}
705 	pipe->aborting = 0;
706 	return (USBD_NORMAL_COMPLETION);
707 }
708 
709 /* Called at splusb() */
710 void
711 usb_transfer_complete(usbd_xfer_handle xfer)
712 {
713 	usbd_pipe_handle pipe = xfer->pipe;
714 	usb_dma_t *dmap = &xfer->dmabuf;
715 	int repeat = pipe->repeat;
716 	int polling;
717 
718 	SPLUSBCHECK;
719 
720 	DPRINTFN(5, ("usb_transfer_complete: pipe=%p xfer=%p status=%d "
721 		     "actlen=%d\n", pipe, xfer, xfer->status, xfer->actlen));
722 
723 #ifdef DIAGNOSTIC
724 	if (pipe == NULL) {
725 		printf("usbd_transfer_cb: pipe==0, xfer=%p\n", xfer);
726 		return;
727 	}
728 #endif
729 	polling = pipe->device->bus->use_polling;
730 	/* XXXX */
731 	if (polling)
732 		pipe->running = 0;
733 
734 	if (!(xfer->flags & USBD_NO_COPY) && xfer->actlen != 0 &&
735 	    usbd_xfer_isread(xfer)) {
736 #ifdef DIAGNOSTIC
737 		if (xfer->actlen > xfer->length) {
738 			printf("usb_transfer_complete: actlen > len %d > %d\n",
739 			       xfer->actlen, xfer->length);
740 			xfer->actlen = xfer->length;
741 		}
742 #endif
743 		memcpy(xfer->buffer, KERNADDR(dmap), xfer->actlen);
744 	}
745 
746 	/* if we allocated the buffer in usbd_transfer() we free it here. */
747 	if (xfer->rqflags & URQ_AUTO_DMABUF) {
748 		if (!repeat) {
749 			struct usbd_bus *bus = pipe->device->bus;
750 			bus->methods->freem(bus, dmap);
751 			xfer->rqflags &= ~URQ_AUTO_DMABUF;
752 		}
753 	}
754 
755 	if (!repeat) {
756 		/* Remove request from queue. */
757 #ifdef DIAGNOSTIC
758 		if (xfer != SIMPLEQ_FIRST(&pipe->queue))
759 			printf("usb_transfer_complete: bad dequeue %p != %p\n",
760 			       xfer, SIMPLEQ_FIRST(&pipe->queue));
761 #endif
762 		SIMPLEQ_REMOVE_HEAD(&pipe->queue, xfer, next);
763 	}
764 	DPRINTFN(5,("usb_transfer_complete: repeat=%d new head=%p\n",
765 		    repeat, SIMPLEQ_FIRST(&pipe->queue)));
766 
767 	/* Count completed transfers. */
768 	++pipe->device->bus->stats.requests
769 		[pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE];
770 
771 	xfer->done = 1;
772 	if (!xfer->status && xfer->actlen < xfer->length &&
773 	    !(xfer->flags & USBD_SHORT_XFER_OK)) {
774 		DPRINTFN(-1,("usbd_transfer_cb: short transfer %d<%d\n",
775 			     xfer->actlen, xfer->length));
776 		xfer->status = USBD_SHORT_XFER;
777 	}
778 
779 	if (xfer->callback)
780 		xfer->callback(xfer, xfer->priv, xfer->status);
781 
782 #ifdef DIAGNOSTIC
783 	if (pipe->methods->done != NULL)
784 		pipe->methods->done(xfer);
785 	else
786 		printf("usb_transfer_complete: pipe->methods->done == NULL\n");
787 #else
788 	pipe->methods->done(xfer);
789 #endif
790 
791 	if ((xfer->flags & USBD_SYNCHRONOUS) && !polling)
792 		wakeup(xfer);
793 
794 	if (!repeat) {
795 		/* XXX should we stop the queue on all errors? */
796 		if ((xfer->status == USBD_CANCELLED ||
797 		     xfer->status == USBD_TIMEOUT) &&
798 		    pipe->iface != NULL)		/* not control pipe */
799 			pipe->running = 0;
800 		else
801 			usbd_start_next(pipe);
802 	}
803 }
804 
805 usbd_status
806 usb_insert_transfer(usbd_xfer_handle xfer)
807 {
808 	usbd_pipe_handle pipe = xfer->pipe;
809 	usbd_status err;
810 	int s;
811 
812 	DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d timeout=%d\n",
813 		    pipe, pipe->running, xfer->timeout));
814 	s = splusb();
815 	SIMPLEQ_INSERT_TAIL(&pipe->queue, xfer, next);
816 	if (pipe->running)
817 		err = USBD_IN_PROGRESS;
818 	else {
819 		pipe->running = 1;
820 		err = USBD_NORMAL_COMPLETION;
821 	}
822 	splx(s);
823 	return (err);
824 }
825 
826 /* Called at splusb() */
827 void
828 usbd_start_next(usbd_pipe_handle pipe)
829 {
830 	usbd_xfer_handle xfer;
831 	usbd_status err;
832 
833 	SPLUSBCHECK;
834 
835 #ifdef DIAGNOSTIC
836 	if (pipe == NULL) {
837 		printf("usbd_start_next: pipe == NULL\n");
838 		return;
839 	}
840 	if (pipe->methods == NULL || pipe->methods->start == NULL) {
841 		printf("usbd_start_next: pipe=%p no start method\n", pipe);
842 		return;
843 	}
844 #endif
845 
846 	/* Get next request in queue. */
847 	xfer = SIMPLEQ_FIRST(&pipe->queue);
848 	DPRINTFN(5, ("usbd_start_next: pipe=%p, xfer=%p\n", pipe, xfer));
849 	if (xfer == NULL) {
850 		pipe->running = 0;
851 	} else {
852 		err = pipe->methods->start(xfer);
853 		if (err != USBD_IN_PROGRESS) {
854 			printf("usbd_start_next: error=%d\n", err);
855 			pipe->running = 0;
856 			/* XXX do what? */
857 		}
858 	}
859 }
860 
861 usbd_status
862 usbd_do_request(usbd_device_handle dev, usb_device_request_t *req, void *data)
863 {
864 	return (usbd_do_request_flags(dev, req, data, 0, 0));
865 }
866 
867 usbd_status
868 usbd_do_request_flags(usbd_device_handle dev, usb_device_request_t *req,
869 		      void *data, u_int16_t flags, int *actlen)
870 {
871 	return (usbd_do_request_flags_pipe(dev, dev->default_pipe, req,
872 					   data, flags, actlen));
873 }
874 
875 usbd_status
876 usbd_do_request_flags_pipe(usbd_device_handle dev, usbd_pipe_handle pipe,
877 	usb_device_request_t *req, void *data, u_int16_t flags, int *actlen)
878 {
879 	usbd_xfer_handle xfer;
880 	usbd_status err;
881 
882 #ifdef DIAGNOSTIC
883 #if defined(__i386__) && defined(__FreeBSD__)
884 	KASSERT(intr_nesting_level == 0,
885 	       	("usbd_do_request: in interrupt context"));
886 #endif
887 	if (dev->bus->intr_context) {
888 		printf("usbd_do_request: not in process context\n");
889 		return (USBD_INVAL);
890 	}
891 #endif
892 
893 	xfer = usbd_alloc_xfer(dev);
894 	if (xfer == NULL)
895 		return (USBD_NOMEM);
896 	usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req,
897 				data, UGETW(req->wLength), flags, 0);
898 	xfer->pipe = pipe;
899 	err = usbd_sync_transfer(xfer);
900 #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
901 	if (xfer->actlen > xfer->length)
902 		DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
903 			 "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
904 			 dev->address, xfer->request.bmRequestType,
905 			 xfer->request.bRequest, UGETW(xfer->request.wValue),
906 			 UGETW(xfer->request.wIndex),
907 			 UGETW(xfer->request.wLength),
908 			 xfer->length, xfer->actlen));
909 #endif
910 	if (actlen != NULL)
911 		*actlen = xfer->actlen;
912 	if (err == USBD_STALLED) {
913 		/*
914 		 * The control endpoint has stalled.  Control endpoints
915 		 * should not halt, but some may do so anyway so clear
916 		 * any halt condition.
917 		 */
918 		usb_device_request_t treq;
919 		usb_status_t status;
920 		u_int16_t s;
921 		usbd_status nerr;
922 
923 		treq.bmRequestType = UT_READ_ENDPOINT;
924 		treq.bRequest = UR_GET_STATUS;
925 		USETW(treq.wValue, 0);
926 		USETW(treq.wIndex, 0);
927 		USETW(treq.wLength, sizeof(usb_status_t));
928 		usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
929 					   &treq, &status,sizeof(usb_status_t),
930 					   0, 0);
931 		nerr = usbd_sync_transfer(xfer);
932 		if (nerr)
933 			goto bad;
934 		s = UGETW(status.wStatus);
935 		DPRINTF(("usbd_do_request: status = 0x%04x\n", s));
936 		if (!(s & UES_HALT))
937 			goto bad;
938 		treq.bmRequestType = UT_WRITE_ENDPOINT;
939 		treq.bRequest = UR_CLEAR_FEATURE;
940 		USETW(treq.wValue, UF_ENDPOINT_HALT);
941 		USETW(treq.wIndex, 0);
942 		USETW(treq.wLength, 0);
943 		usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
944 					   &treq, &status, 0, 0, 0);
945 		nerr = usbd_sync_transfer(xfer);
946 		if (nerr)
947 			goto bad;
948 	}
949 
950  bad:
951 	usbd_free_xfer(xfer);
952 	return (err);
953 }
954 
955 void
956 usbd_do_request_async_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
957 			 usbd_status status)
958 {
959 #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
960 	if (xfer->actlen > xfer->length)
961 		DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
962 			 "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
963 			 xfer->pipe->device->address,
964 			 xfer->request.bmRequestType,
965 			 xfer->request.bRequest, UGETW(xfer->request.wValue),
966 			 UGETW(xfer->request.wIndex),
967 			 UGETW(xfer->request.wLength),
968 			 xfer->length, xfer->actlen));
969 #endif
970 	usbd_free_xfer(xfer);
971 }
972 
973 /*
974  * Execute a request without waiting for completion.
975  * Can be used from interrupt context.
976  */
977 usbd_status
978 usbd_do_request_async(usbd_device_handle dev, usb_device_request_t *req,
979 		      void *data)
980 {
981 	usbd_xfer_handle xfer;
982 	usbd_status err;
983 
984 	xfer = usbd_alloc_xfer(dev);
985 	if (xfer == NULL)
986 		return (USBD_NOMEM);
987 	usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req,
988 	    data, UGETW(req->wLength), 0, usbd_do_request_async_cb);
989 	err = usbd_transfer(xfer);
990 	if (err != USBD_IN_PROGRESS) {
991 		usbd_free_xfer(xfer);
992 		return (err);
993 	}
994 	return (USBD_NORMAL_COMPLETION);
995 }
996 
997 const struct usbd_quirks *
998 usbd_get_quirks(usbd_device_handle dev)
999 {
1000 #ifdef DIAGNOSTIC
1001 	if (dev == NULL) {
1002 		printf("usbd_get_quirks: dev == NULL\n");
1003 		return 0;
1004 	}
1005 #endif
1006 	return (dev->quirks);
1007 }
1008 
1009 /* XXX do periodic free() of free list */
1010 
1011 /*
1012  * Called from keyboard driver when in polling mode.
1013  */
1014 void
1015 usbd_dopoll(usbd_interface_handle iface)
1016 {
1017 	iface->device->bus->methods->do_poll(iface->device->bus);
1018 }
1019 
1020 void
1021 usbd_set_polling(usbd_device_handle dev, int on)
1022 {
1023 	if (on)
1024 		dev->bus->use_polling++;
1025 	else
1026 		dev->bus->use_polling--;
1027 }
1028 
1029 
1030 usb_endpoint_descriptor_t *
1031 usbd_get_endpoint_descriptor(usbd_interface_handle iface, u_int8_t address)
1032 {
1033 	struct usbd_endpoint *ep;
1034 	int i;
1035 
1036 	for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
1037 		ep = &iface->endpoints[i];
1038 		if (ep->edesc->bEndpointAddress == address)
1039 			return (iface->endpoints[i].edesc);
1040 	}
1041 	return (0);
1042 }
1043 
1044 /*
1045  * usbd_ratecheck() can limit the number of error messages that occurs.
1046  * When a device is unplugged it may take up to 0.25s for the hub driver
1047  * to notice it.  If the driver continuosly tries to do I/O operations
1048  * this can generate a large number of messages.
1049  */
1050 int
1051 usbd_ratecheck(struct timeval *last)
1052 {
1053 	static struct timeval errinterval = { 0, 250000 }; /* 0.25 s*/
1054 
1055 	return (ratecheck(last, &errinterval));
1056 }
1057 
1058 #if defined(__FreeBSD__)
1059 int
1060 usbd_driver_load(module_t mod, int what, void *arg)
1061 {
1062 	/* XXX should implement something like a function that removes all generic devices */
1063 
1064  	return (0);
1065 }
1066 
1067 #endif
1068