1 /* $NetBSD: usbdi.c,v 1.20 1999/01/08 11:58:26 augustss Exp $ */
5 * Copyright (c) 1998 The NetBSD Foundation, Inc.
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Lennart Augustsson (augustss@carlstedt.se) at
10 * Carlstedt Research & Technology.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the NetBSD
23 * Foundation, Inc. and its contributors.
24 * 4. Neither the name of The NetBSD Foundation nor the names of its
25 * contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #if defined(__NetBSD__)
45 #include <sys/device.h>
47 #include <sys/module.h>
51 #include <sys/malloc.h>
54 #include <dev/usb/usb.h>
56 #include <dev/usb/usbdi.h>
57 #include <dev/usb/usbdi_util.h>
58 #include <dev/usb/usbdivar.h>
60 #if defined(__FreeBSD__)
65 #define DPRINTF(x) if (usbdebug) logprintf x
66 #define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x
73 static usbd_status usbd_ar_pipe __P((usbd_pipe_handle pipe));
74 static usbd_status usbd_ar_iface __P((usbd_interface_handle iface));
75 static void usbd_transfer_cb __P((usbd_request_handle reqh));
76 static void usbd_sync_transfer_cb __P((usbd_request_handle reqh));
77 static usbd_status usbd_do_transfer __P((usbd_request_handle reqh));
78 void usbd_do_request_async_cb
79 __P((usbd_request_handle, usbd_private_handle, usbd_status));
81 static SIMPLEQ_HEAD(, usbd_request) usbd_free_requests;
83 #if defined(__FreeBSD__)
84 #define USB_CDEV_MAJOR 108
86 extern struct cdevsw usb_cdevsw;
90 char *usbd_error_strs[USBD_ERROR_MAX] = {
101 "INTERFACE_NOT_ACTIVE",
117 usbd_open_pipe(iface, address, flags, pipe)
118 usbd_interface_handle iface;
121 usbd_pipe_handle *pipe;
124 struct usbd_endpoint *ep;
128 if (iface->state != USBD_INTERFACE_ACTIVE)
129 return (USBD_INTERFACE_NOT_ACTIVE);
130 for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
131 ep = &iface->endpoints[i];
132 if (ep->edesc->bEndpointAddress == address)
135 return (USBD_BAD_ADDRESS);
137 if ((flags & USBD_EXCLUSIVE_USE) &&
139 return (USBD_IN_USE);
140 r = usbd_setup_pipe(iface->device, iface, ep, &p);
141 if (r != USBD_NORMAL_COMPLETION)
143 LIST_INSERT_HEAD(&iface->pipes, p, next);
145 return (USBD_NORMAL_COMPLETION);
149 usbd_open_pipe_intr(iface, address, flags, pipe, priv, buffer, length, cb)
150 usbd_interface_handle iface;
153 usbd_pipe_handle *pipe;
154 usbd_private_handle priv;
160 usbd_request_handle reqh;
161 usbd_pipe_handle ipipe;
163 reqh = usbd_alloc_request();
166 r = usbd_open_pipe(iface, address, USBD_EXCLUSIVE_USE, &ipipe);
167 if (r != USBD_NORMAL_COMPLETION)
169 r = usbd_setup_request(reqh, ipipe, priv, buffer, length,
170 USBD_XFER_IN | flags, USBD_NO_TIMEOUT, cb);
171 if (r != USBD_NORMAL_COMPLETION)
173 ipipe->intrreqh = reqh;
174 r = usbd_transfer(reqh);
176 if (r != USBD_IN_PROGRESS)
178 return (USBD_NORMAL_COMPLETION);
183 usbd_close_pipe(ipipe);
185 usbd_free_request(reqh);
190 usbd_open_pipe_iso(iface, address, flags, pipe, priv, bufsize, nbuf, cb)
191 usbd_interface_handle iface;
194 usbd_pipe_handle *pipe;
195 usbd_private_handle priv;
203 r = usbd_open_pipe(iface, address, USBD_EXCLUSIVE_USE, &p);
204 if (r != USBD_NORMAL_COMPLETION)
206 if (!p->methods->isobuf) {
210 r = p->methods->isobuf(p, bufsize, nbuf);
211 if (r != USBD_NORMAL_COMPLETION) {
220 usbd_close_pipe(pipe)
221 usbd_pipe_handle pipe;
223 if (pipe->iface->state != USBD_INTERFACE_ACTIVE)
224 return (USBD_INTERFACE_NOT_ACTIVE);
225 if (--pipe->refcnt != 0)
226 return (USBD_NORMAL_COMPLETION);
227 if (SIMPLEQ_FIRST(&pipe->queue) != 0)
228 return (USBD_PENDING_REQUESTS);
229 LIST_REMOVE(pipe, next);
230 pipe->endpoint->refcnt--;
231 pipe->methods->close(pipe);
233 usbd_free_request(pipe->intrreqh);
235 return (USBD_NORMAL_COMPLETION);
240 usbd_request_handle reqh;
242 reqh->xfercb = usbd_transfer_cb;
243 return (usbd_do_transfer(reqh));
247 usbd_do_transfer(reqh)
248 usbd_request_handle reqh;
250 usbd_pipe_handle pipe = reqh->pipe;
252 DPRINTFN(10,("usbd_do_transfer: reqh=%p\n", reqh));
254 return (pipe->methods->transfer(reqh));
260 usbd_request_handle reqh;
262 reqh = SIMPLEQ_FIRST(&usbd_free_requests);
264 #if defined(__NetBSD__)
265 SIMPLEQ_REMOVE_HEAD(&usbd_free_requests, reqh, next);
266 #elif defined(__FreeBSD__)
267 SIMPLEQ_REMOVE_HEAD(&usbd_free_requests, next);
270 reqh = malloc(sizeof(*reqh), M_USB, M_NOWAIT);
273 memset(reqh, 0, sizeof *reqh);
278 usbd_free_request(reqh)
279 usbd_request_handle reqh;
281 SIMPLEQ_INSERT_HEAD(&usbd_free_requests, reqh, next);
282 return (USBD_NORMAL_COMPLETION);
286 usbd_setup_request(reqh, pipe, priv, buffer, length, flags, timeout, callback)
287 usbd_request_handle reqh;
288 usbd_pipe_handle pipe;
289 usbd_private_handle priv;
294 void (*callback) __P((usbd_request_handle,
300 reqh->buffer = buffer;
301 reqh->length = length;
304 reqh->timeout = timeout;
305 reqh->status = USBD_NOT_STARTED;
306 reqh->callback = callback;
309 return (USBD_NORMAL_COMPLETION);
313 usbd_setup_device_request(reqh, req)
314 usbd_request_handle reqh;
315 usb_device_request_t *req;
318 reqh->request = *req;
319 return (USBD_NORMAL_COMPLETION);
323 usbd_setup_default_request(reqh, dev, priv, timeout, req, buffer,
324 length, flags, callback)
325 usbd_request_handle reqh;
326 usbd_device_handle dev;
327 usbd_private_handle priv;
329 usb_device_request_t *req;
333 void (*callback) __P((usbd_request_handle,
337 reqh->pipe = dev->default_pipe;
339 reqh->buffer = buffer;
340 reqh->length = length;
343 reqh->timeout = timeout;
344 reqh->status = USBD_NOT_STARTED;
345 reqh->callback = callback;
346 reqh->request = *req;
349 return (USBD_NORMAL_COMPLETION);
353 usbd_set_request_timeout(reqh, timeout)
354 usbd_request_handle reqh;
357 reqh->timeout = timeout;
358 return (USBD_NORMAL_COMPLETION);
362 usbd_get_request_status(reqh, priv, buffer, count, status)
363 usbd_request_handle reqh;
364 usbd_private_handle *priv;
370 *buffer = reqh->buffer;
371 *count = reqh->actlen;
372 *status = reqh->status;
373 return (USBD_NORMAL_COMPLETION);
377 usbd_request_device_data(reqh, req)
378 usbd_request_handle reqh;
379 usb_device_request_t *req;
383 *req = reqh->request;
384 return (USBD_NORMAL_COMPLETION);
389 usbd_get_descriptor(iface, desc_type)
390 usbd_interface_handle *iface;
395 usb_config_descriptor_t *
396 usbd_get_config_descriptor(dev)
397 usbd_device_handle dev;
402 usb_interface_descriptor_t *
403 usbd_get_interface_descriptor(iface)
404 usbd_interface_handle iface;
406 return (iface->idesc);
409 usb_device_descriptor_t *
410 usbd_get_device_descriptor(dev)
411 usbd_device_handle dev;
413 return (&dev->ddesc);
416 usb_endpoint_descriptor_t *
417 usbd_interface2endpoint_descriptor(iface, index)
418 usbd_interface_handle iface;
421 if (index >= iface->idesc->bNumEndpoints)
423 return (iface->endpoints[index].edesc);
427 usbd_set_configuration(dev, conf)
428 usbd_device_handle dev;
431 return usbd_set_config_no(dev, conf, 0);
435 usbd_retry_request(reqh, retry_count)
436 usbd_request_handle reqh;
437 u_int32_t retry_count;
441 r = usbd_set_pipe_state(reqh->pipe, USBD_PIPE_ACTIVE);
442 if (r != USBD_NORMAL_COMPLETION)
444 reqh->retries = retry_count;
445 return (usbd_transfer(reqh));
449 usbd_abort_pipe(pipe)
450 usbd_pipe_handle pipe;
455 if (pipe->iface->state != USBD_INTERFACE_ACTIVE)
456 return (USBD_INTERFACE_NOT_ACTIVE);
459 r = usbd_ar_pipe(pipe);
466 usbd_abort_interface(iface)
467 usbd_interface_handle iface;
474 r = usbd_ar_iface(iface);
481 usbd_reset_pipe(pipe)
482 usbd_pipe_handle pipe;
487 if (pipe->iface->state != USBD_INTERFACE_ACTIVE)
488 return (USBD_INTERFACE_NOT_ACTIVE);
490 r = usbd_ar_pipe(pipe);
491 /* XXX anything else */
492 pipe->state = USBD_PIPE_ACTIVE;
498 usbd_reset_interface(iface)
499 usbd_interface_handle iface;
505 r = usbd_ar_iface(iface);
506 /* XXX anything else */
507 iface->state = USBD_INTERFACE_ACTIVE;
513 usbd_clear_endpoint_stall(pipe)
514 usbd_pipe_handle pipe;
516 usbd_device_handle dev = pipe->device;
517 usb_device_request_t req;
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 r = usbd_do_request(dev, &req, 0);
527 XXX should we do this?
528 if (r == USBD_NORMAL_COMPLETION) {
529 pipe->state = USBD_PIPE_ACTIVE;
530 /* XXX activate pipe */
537 usbd_clear_endpoint_stall_async(pipe)
538 usbd_pipe_handle pipe;
540 usbd_device_handle dev = pipe->device;
541 usb_device_request_t req;
544 req.bmRequestType = UT_WRITE_ENDPOINT;
545 req.bRequest = UR_CLEAR_FEATURE;
546 USETW(req.wValue, UF_ENDPOINT_HALT);
547 USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
548 USETW(req.wLength, 0);
549 r = usbd_do_request_async(dev, &req, 0);
554 usbd_set_pipe_state(pipe, state)
555 usbd_pipe_handle pipe;
556 usbd_pipe_state state;
560 usbd_request_handle reqh;
562 if (pipe->iface->state != USBD_INTERFACE_ACTIVE)
563 return (USBD_INTERFACE_NOT_ACTIVE);
564 if (state != USBD_PIPE_ACTIVE &&
565 state != USBD_PIPE_STALLED &&
566 state != USBD_PIPE_IDLE)
569 r = USBD_NORMAL_COMPLETION;
570 if (state == USBD_PIPE_ACTIVE) {
572 if (!pipe->running) {
573 reqh = SIMPLEQ_FIRST(&pipe->queue);
577 r = pipe->methods->start(reqh);
587 usbd_get_pipe_state(pipe, state, endpoint_state, request_count)
588 usbd_pipe_handle pipe;
589 usbd_pipe_state *state;
590 u_int32_t *endpoint_state;
591 u_int32_t *request_count;
594 usbd_request_handle r;
596 *state = pipe->state;
597 *endpoint_state = pipe->endpoint->state;
598 for (r = SIMPLEQ_FIRST(&pipe->queue), n = 0;
600 r = SIMPLEQ_NEXT(r, next), n++)
603 return (USBD_NORMAL_COMPLETION);
607 usbd_set_interface_state(iface, state)
608 usbd_interface_handle iface;
609 usbd_interface_state state;
614 if (state == USBD_INTERFACE_ACTIVE)
615 ps = USBD_PIPE_ACTIVE;
616 else if (state == USBD_INTERFACE_STALLED)
617 ps = USBD_PIPE_STALLED;
618 else if (state == USBD_INTERFACE_IDLE)
622 iface->state = USBD_INTERFACE_ACTIVE; /* to allow setting the pipe */
623 for (p = LIST_FIRST(&iface->pipes); p != 0; p = LIST_NEXT(p, next))
624 usbd_set_pipe_state(p, ps);
625 iface->state = state;
626 return (USBD_NORMAL_COMPLETION);
630 usbd_get_interface_state(iface, state)
631 usbd_interface_handle iface;
632 usbd_interface_state *state;
634 *state = iface->state;
635 return (USBD_NORMAL_COMPLETION);
639 usbd_get_device_state(dev, state)
640 usbd_device_handle dev;
641 usbd_device_state *state;
644 return (USBD_NORMAL_COMPLETION);
649 usbd_set_device_state(dev, state)
650 usbd_device_handle dev;
651 usbd_device_state state;
656 usbd_device_address(dev, address)
657 usbd_device_handle dev;
660 *address = dev->address;
661 return (USBD_NORMAL_COMPLETION);
665 usbd_endpoint_address(pipe, address)
666 usbd_pipe_handle pipe;
669 *address = pipe->endpoint->edesc->bEndpointAddress;
670 return (USBD_NORMAL_COMPLETION);
674 usbd_endpoint_count(iface, count)
675 usbd_interface_handle iface;
678 *count = iface->idesc->bNumEndpoints;
679 return (USBD_NORMAL_COMPLETION);
683 usbd_interface_count(dev, count)
684 usbd_device_handle dev;
688 return (USBD_NOT_CONFIGURED);
689 *count = dev->cdesc->bNumInterface;
690 return (USBD_NORMAL_COMPLETION);
697 return (usb_bus_count());
701 usbd_get_bus_handle(index, bus)
703 usbd_bus_handle *bus;
705 return (usb_get_bus_handle(index, bus));
709 usbd_get_root_hub(bus, dev)
711 usbd_device_handle *dev;
713 *dev = bus->root_hub;
714 return (USBD_NORMAL_COMPLETION);
718 usbd_port_count(dev, nports)
719 usbd_device_handle dev;
724 *nports = dev->hub->hubdesc.bNbrPorts;
725 return (USBD_NORMAL_COMPLETION);
729 usbd_hub2device_handle(dev, port, devp)
730 usbd_device_handle dev;
732 usbd_device_handle *devp;
734 if (dev->hub == 0 || port >= dev->hub->hubdesc.bNbrPorts ||
735 dev->hub->ports[port].device == 0)
737 *devp = dev->hub->ports[port].device;
738 return (USBD_NORMAL_COMPLETION);
743 usbd_request2pipe_handle(reqh, pipe)
744 usbd_request_handle reqh;
745 usbd_pipe_handle *pipe;
748 return (USBD_NORMAL_COMPLETION);
752 usbd_pipe2interface_handle(pipe, iface)
753 usbd_pipe_handle pipe;
754 usbd_interface_handle *iface;
756 *iface = pipe->iface;
757 return (USBD_NORMAL_COMPLETION);
761 usbd_interface2device_handle(iface, dev)
762 usbd_interface_handle iface;
763 usbd_device_handle *dev;
765 *dev = iface->device;
766 return (USBD_NORMAL_COMPLETION);
770 usbd_device2bus_handle(dev, bus)
771 usbd_device_handle dev;
772 usbd_bus_handle *bus;
775 return (USBD_NORMAL_COMPLETION);
779 usbd_device2interface_handle(dev, ifaceno, iface)
780 usbd_device_handle dev;
782 usbd_interface_handle *iface;
785 return (USBD_NOT_CONFIGURED);
786 if (ifaceno >= dev->cdesc->bNumInterface)
788 *iface = &dev->ifaces[ifaceno];
789 return (USBD_NORMAL_COMPLETION);
793 usbd_set_interface_private_handle(iface, priv)
794 usbd_interface_handle iface;
795 usbd_private_handle priv;
798 return (USBD_NORMAL_COMPLETION);
802 usbd_get_interface_private_handle(iface, priv)
803 usbd_interface_handle iface;
804 usbd_private_handle *priv;
807 return (USBD_NORMAL_COMPLETION);
811 usbd_reference_pipe(pipe)
812 usbd_pipe_handle pipe;
815 return (USBD_NORMAL_COMPLETION);
819 usbd_dereference_pipe(pipe)
820 usbd_pipe_handle pipe;
823 return (USBD_NORMAL_COMPLETION);
841 usbd_set_interface(iface, altidx)
842 usbd_interface_handle iface;
845 usb_device_request_t req;
848 if (LIST_FIRST(&iface->pipes) != 0)
849 return (USBD_IN_USE);
851 if (iface->endpoints)
852 free(iface->endpoints, M_USB);
853 iface->endpoints = 0;
855 iface->state = USBD_INTERFACE_IDLE;
857 r = usbd_fill_iface_data(iface->device, iface->index, altidx);
858 if (r != USBD_NORMAL_COMPLETION)
861 req.bmRequestType = UT_WRITE_INTERFACE;
862 req.bRequest = UR_SET_INTERFACE;
863 USETW(req.wValue, iface->idesc->bAlternateSetting);
864 USETW(req.wIndex, iface->idesc->bInterfaceNumber);
865 USETW(req.wLength, 0);
866 return usbd_do_request(iface->device, &req, 0);
870 usbd_get_no_alts(cdesc, ifaceno)
871 usb_config_descriptor_t *cdesc;
874 char *p = (char *)cdesc;
875 char *end = p + UGETW(cdesc->wTotalLength);
876 usb_interface_descriptor_t *d;
879 for (n = 0; p < end; p += d->bLength) {
880 d = (usb_interface_descriptor_t *)p;
881 if (p + d->bLength <= end &&
882 d->bDescriptorType == UDESC_INTERFACE &&
883 d->bInterfaceNumber == ifaceno)
890 usbd_get_interface_altindex(iface)
891 usbd_interface_handle iface;
893 return (iface->altindex);
897 usbd_get_interface(iface, aiface)
898 usbd_interface_handle iface;
901 usb_device_request_t req;
903 req.bmRequestType = UT_READ_INTERFACE;
904 req.bRequest = UR_GET_INTERFACE;
905 USETW(req.wValue, 0);
906 USETW(req.wIndex, iface->idesc->bInterfaceNumber);
907 USETW(req.wLength, 1);
908 return usbd_do_request(iface->device, &req, aiface);
911 /*** Internal routines ***/
913 /* Dequeue all pipe operations, called at splusb(). */
916 usbd_pipe_handle pipe;
918 usbd_request_handle reqh;
922 reqh = SIMPLEQ_FIRST(&pipe->queue);
925 #if defined(__NetBSD__)
926 SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next);
927 #elif defined(__FreeBSD__)
928 SIMPLEQ_REMOVE_HEAD(&pipe->queue, next);
930 reqh->status = USBD_CANCELLED;
932 reqh->callback(reqh, reqh->priv, reqh->status);
935 while ((reqh = SIMPLEQ_FIRST(&pipe->queue))) {
936 pipe->methods->abort(reqh);
937 #if defined(__NetBSD__)
938 SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next);
939 #elif defined(__FreeBSD__)
940 SIMPLEQ_REMOVE_HEAD(&pipe->queue, next);
944 return (USBD_NORMAL_COMPLETION);
947 /* Dequeue all interface operations, called at splusb(). */
950 usbd_interface_handle iface;
953 usbd_status r, ret = USBD_NORMAL_COMPLETION;
955 for (p = LIST_FIRST(&iface->pipes); p != 0; p = LIST_NEXT(p, next)) {
957 if (r != USBD_NORMAL_COMPLETION)
963 static int usbd_global_init_done = 0;
968 #if defined(__FreeBSD__)
972 if (!usbd_global_init_done) {
973 usbd_global_init_done = 1;
974 SIMPLEQ_INIT(&usbd_free_requests);
976 #if defined(__FreeBSD__)
977 dev = makedev(USB_CDEV_MAJOR, 0);
978 cdevsw_add(&dev, &usb_cdevsw, NULL);
984 usbd_transfer_cb(reqh)
985 usbd_request_handle reqh;
987 usbd_pipe_handle pipe = reqh->pipe;
989 /* Count completed transfers. */
990 ++pipe->device->bus->stats.requests
991 [pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE];
993 /* XXX check retry count */
995 if (reqh->status == USBD_NORMAL_COMPLETION &&
996 reqh->actlen < reqh->length &&
997 !(reqh->flags & USBD_SHORT_XFER_OK)) {
998 DPRINTFN(-1, ("usbd_transfer_cb: short xfer %d<%d (bytes)\n",
999 reqh->actlen, reqh->length));
1000 reqh->status = USBD_SHORT_XFER;
1003 reqh->callback(reqh, reqh->priv, reqh->status);
1007 usbd_sync_transfer_cb(reqh)
1008 usbd_request_handle reqh;
1010 usbd_transfer_cb(reqh);
1011 if (!reqh->pipe->device->bus->use_polling)
1015 /* Like usbd_transfer(), but waits for completion. */
1017 usbd_sync_transfer(reqh)
1018 usbd_request_handle reqh;
1023 reqh->xfercb = usbd_sync_transfer_cb;
1024 r = usbd_do_transfer(reqh);
1025 if (r != USBD_IN_PROGRESS)
1029 if (reqh->pipe->device->bus->use_polling)
1030 panic("usbd_sync_transfer: not done\n");
1031 tsleep(reqh, PRIBIO, "usbsyn", 0);
1034 return (reqh->status);
1038 usbd_do_request(dev, req, data)
1039 usbd_device_handle dev;
1040 usb_device_request_t *req;
1043 return (usbd_do_request_flags(dev, req, data, 0, 0));
1047 usbd_do_request_flags(dev, req, data, flags, actlen)
1048 usbd_device_handle dev;
1049 usb_device_request_t *req;
1054 usbd_request_handle reqh;
1059 printf("usbd_do_request: not in process context\n");
1064 reqh = usbd_alloc_request();
1066 return (USBD_NOMEM);
1067 r = usbd_setup_default_request(
1068 reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req, data,
1069 UGETW(req->wLength), flags, 0);
1070 if (r != USBD_NORMAL_COMPLETION)
1072 r = usbd_sync_transfer(reqh);
1073 #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
1074 if (reqh->actlen > reqh->length)
1075 printf("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
1076 "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
1077 dev->address, reqh->request.bmRequestType,
1078 reqh->request.bRequest, UGETW(reqh->request.wValue),
1079 UGETW(reqh->request.wIndex),
1080 UGETW(reqh->request.wLength),
1081 reqh->length, reqh->actlen);
1084 *actlen = reqh->actlen;
1085 if (r == USBD_STALLED) {
1087 * The control endpoint has stalled. Control endpoints
1088 * should not halt, but some may do so anyway so clear
1089 * any halt condition.
1091 usb_device_request_t treq;
1092 usb_status_t status;
1096 treq.bmRequestType = UT_READ_ENDPOINT;
1097 treq.bRequest = UR_GET_STATUS;
1098 USETW(treq.wValue, 0);
1099 USETW(treq.wIndex, 0);
1100 USETW(treq.wLength, sizeof(usb_status_t));
1101 nr = usbd_setup_default_request(
1102 reqh, dev, 0, USBD_DEFAULT_TIMEOUT, &treq, &status,
1103 sizeof(usb_status_t), 0, 0);
1104 if (nr != USBD_NORMAL_COMPLETION)
1106 nr = usbd_sync_transfer(reqh);
1107 if (nr != USBD_NORMAL_COMPLETION)
1109 s = UGETW(status.wStatus);
1110 DPRINTF(("usbd_do_request: status = 0x%04x\n", s));
1111 if (!(s & UES_HALT))
1113 treq.bmRequestType = UT_WRITE_ENDPOINT;
1114 treq.bRequest = UR_CLEAR_FEATURE;
1115 USETW(treq.wValue, UF_ENDPOINT_HALT);
1116 USETW(treq.wIndex, 0);
1117 USETW(treq.wLength, 0);
1118 nr = usbd_setup_default_request(
1119 reqh, dev, 0, USBD_DEFAULT_TIMEOUT, &treq, &status,
1121 if (nr != USBD_NORMAL_COMPLETION)
1123 nr = usbd_sync_transfer(reqh);
1124 if (nr != USBD_NORMAL_COMPLETION)
1129 usbd_free_request(reqh);
1134 usbd_do_request_async_cb(reqh, priv, status)
1135 usbd_request_handle reqh;
1136 usbd_private_handle priv;
1139 #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
1140 if (reqh->actlen > reqh->length)
1141 printf("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
1142 "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
1143 reqh->pipe->device->address,
1144 reqh->request.bmRequestType,
1145 reqh->request.bRequest, UGETW(reqh->request.wValue),
1146 UGETW(reqh->request.wIndex),
1147 UGETW(reqh->request.wLength),
1148 reqh->length, reqh->actlen);
1150 usbd_free_request(reqh);
1154 * Execute a request without waiting for completion.
1155 * Can be used from interrupt context.
1158 usbd_do_request_async(dev, req, data)
1159 usbd_device_handle dev;
1160 usb_device_request_t *req;
1163 usbd_request_handle reqh;
1166 reqh = usbd_alloc_request();
1168 return (USBD_NOMEM);
1169 r = usbd_setup_default_request(
1170 reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req, data,
1171 UGETW(req->wLength), 0, usbd_do_request_async_cb);
1172 if (r != USBD_NORMAL_COMPLETION) {
1173 usbd_free_request(reqh);
1176 r = usbd_transfer(reqh);
1177 if (r != USBD_IN_PROGRESS)
1179 return (USBD_NORMAL_COMPLETION);
1182 struct usbd_quirks *
1183 usbd_get_quirks(dev)
1184 usbd_device_handle dev;
1186 return (dev->quirks);
1190 usbd_set_disco(p, hdl, data)
1192 void (*hdl) __P((void *));
1199 /* XXX do periodic free() of free list */
1202 * Called from keyboard driver when in polling mode.
1206 usbd_interface_handle iface;
1208 iface->device->bus->do_poll(iface->device->bus);
1212 usbd_set_polling(iface, on)
1213 usbd_interface_handle iface;
1216 iface->device->bus->use_polling = on;
1220 usb_endpoint_descriptor_t *
1221 usbd_get_endpoint_descriptor(iface, address)
1222 usbd_interface_handle iface;
1225 struct usbd_endpoint *ep;
1228 for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
1229 ep = &iface->endpoints[i];
1230 if (ep->edesc->bEndpointAddress == address)
1231 return (iface->endpoints[i].edesc);
1236 #if defined(__FreeBSD__)
1238 usbd_print_child(device_t parent, device_t child)
1241 struct usb_softc *sc = device_get_softc(child);
1244 printf(" at %s%d", device_get_name(parent), device_get_unit(parent));
1246 /* XXX How do we get to the usbd_device_handle???
1247 usbd_device_handle dev = invalidadosch;
1249 printf(" addr %d", dev->addr);
1253 printf(", lowspeed");
1254 if (dev->self_powered)
1255 printf(", self powered");
1257 printf(", %dmA", dev->power);
1258 printf(", config %d", dev->config);
1263 /* Reconfigure all the USB busses in the system. */
1265 usbd_driver_load(module_t mod, int what, void *arg)
1270 devclass_t usb_devclass = devclass_find("usb");
1271 devclass_t ugen_devclass = devclass_find("ugen");
1276 if ( what == MOD_LOAD || what == MOD_UNLOAD ) {
1278 return 0; /* just ignore call */
1280 /* Detach all the generic devices and do a reconfigure
1281 * of the bus. This should attach the new driver to anything
1282 * that is already connected and it can handle.
1283 * XXX For the moment disabled. The detach does not remove
1284 * the device from the list of devices attached to the hub.
1285 * Legacy of converting from NetBSD to FreeBSD.
1287 if (ugen_devclass) {
1288 /* detach devices from generic driver if possible */
1289 error = devclass_get_devices(ugen_devclass, &devlist,
1292 for (devcount--; devcount >= 0; devcount--)
1293 (void)DEVICE_DETACH(devlist[devcount]);
1294 free(devlist, M_TEMP);
1297 /* Reconfigure the busses, possibly attaching something to the
1299 error = devclass_get_devices(usb_devclass, &devlist, &devcount);
1301 return 0; /* XXX maybe transient, or error? */
1303 for (devcount--; devcount >= 0; devcount--)
1304 USB_RECONFIGURE(devlist[devcount]);
1306 free(devlist, M_TEMP);
1309 return 0; /* nothing to do */
1313 /* Set the description of the device including a malloc and copy. */
1315 usbd_device_set_desc(device_t device, char *devinfo)
1317 device_set_desc_copy(device, devinfo);
1323 usbd_errstr(usbd_status err)
1325 static char buffer[5]; /* XXX static buffer */
1328 if ( err < USBD_ERROR_MAX ) {
1329 return usbd_error_strs[err];
1331 snprintf(buffer, 4, "%d", err);
1335 snprintf(buffer, 4, "%d", err);