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;
84 char *usbd_error_strs[USBD_ERROR_MAX] = {
95 "INTERFACE_NOT_ACTIVE",
111 usbd_open_pipe(iface, address, flags, pipe)
112 usbd_interface_handle iface;
115 usbd_pipe_handle *pipe;
118 struct usbd_endpoint *ep;
122 if (iface->state != USBD_INTERFACE_ACTIVE)
123 return (USBD_INTERFACE_NOT_ACTIVE);
124 for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
125 ep = &iface->endpoints[i];
126 if (ep->edesc->bEndpointAddress == address)
129 return (USBD_BAD_ADDRESS);
131 if ((flags & USBD_EXCLUSIVE_USE) &&
133 return (USBD_IN_USE);
134 r = usbd_setup_pipe(iface->device, iface, ep, &p);
135 if (r != USBD_NORMAL_COMPLETION)
137 LIST_INSERT_HEAD(&iface->pipes, p, next);
139 return (USBD_NORMAL_COMPLETION);
143 usbd_open_pipe_intr(iface, address, flags, pipe, priv, buffer, length, cb)
144 usbd_interface_handle iface;
147 usbd_pipe_handle *pipe;
148 usbd_private_handle priv;
154 usbd_request_handle reqh;
155 usbd_pipe_handle ipipe;
157 reqh = usbd_alloc_request();
160 r = usbd_open_pipe(iface, address, USBD_EXCLUSIVE_USE, &ipipe);
161 if (r != USBD_NORMAL_COMPLETION)
163 r = usbd_setup_request(reqh, ipipe, priv, buffer, length,
164 USBD_XFER_IN | flags, USBD_NO_TIMEOUT, cb);
165 if (r != USBD_NORMAL_COMPLETION)
167 ipipe->intrreqh = reqh;
168 r = usbd_transfer(reqh);
170 if (r != USBD_IN_PROGRESS)
172 return (USBD_NORMAL_COMPLETION);
177 usbd_close_pipe(ipipe);
179 usbd_free_request(reqh);
184 usbd_open_pipe_iso(iface, address, flags, pipe, priv, bufsize, nbuf, cb)
185 usbd_interface_handle iface;
188 usbd_pipe_handle *pipe;
189 usbd_private_handle priv;
197 r = usbd_open_pipe(iface, address, USBD_EXCLUSIVE_USE, &p);
198 if (r != USBD_NORMAL_COMPLETION)
200 if (!p->methods->isobuf) {
204 r = p->methods->isobuf(p, bufsize, nbuf);
205 if (r != USBD_NORMAL_COMPLETION) {
214 usbd_close_pipe(pipe)
215 usbd_pipe_handle pipe;
217 if (pipe->iface->state != USBD_INTERFACE_ACTIVE)
218 return (USBD_INTERFACE_NOT_ACTIVE);
219 if (--pipe->refcnt != 0)
220 return (USBD_NORMAL_COMPLETION);
221 if (SIMPLEQ_FIRST(&pipe->queue) != 0)
222 return (USBD_PENDING_REQUESTS);
223 LIST_REMOVE(pipe, next);
224 pipe->endpoint->refcnt--;
225 pipe->methods->close(pipe);
227 usbd_free_request(pipe->intrreqh);
229 return (USBD_NORMAL_COMPLETION);
234 usbd_request_handle reqh;
236 reqh->xfercb = usbd_transfer_cb;
237 return (usbd_do_transfer(reqh));
241 usbd_do_transfer(reqh)
242 usbd_request_handle reqh;
244 usbd_pipe_handle pipe = reqh->pipe;
246 DPRINTFN(10,("usbd_do_transfer: reqh=%p\n", reqh));
248 return (pipe->methods->transfer(reqh));
254 usbd_request_handle reqh;
256 reqh = SIMPLEQ_FIRST(&usbd_free_requests);
258 #if defined(__NetBSD__)
259 SIMPLEQ_REMOVE_HEAD(&usbd_free_requests, reqh, next);
260 #elif defined(__FreeBSD__)
261 SIMPLEQ_REMOVE_HEAD(&usbd_free_requests, next);
264 reqh = malloc(sizeof(*reqh), M_USB, M_NOWAIT);
267 memset(reqh, 0, sizeof *reqh);
272 usbd_free_request(reqh)
273 usbd_request_handle reqh;
275 SIMPLEQ_INSERT_HEAD(&usbd_free_requests, reqh, next);
276 return (USBD_NORMAL_COMPLETION);
280 usbd_setup_request(reqh, pipe, priv, buffer, length, flags, timeout, callback)
281 usbd_request_handle reqh;
282 usbd_pipe_handle pipe;
283 usbd_private_handle priv;
288 void (*callback) __P((usbd_request_handle,
294 reqh->buffer = buffer;
295 reqh->length = length;
298 reqh->timeout = timeout;
299 reqh->status = USBD_NOT_STARTED;
300 reqh->callback = callback;
303 return (USBD_NORMAL_COMPLETION);
307 usbd_setup_device_request(reqh, req)
308 usbd_request_handle reqh;
309 usb_device_request_t *req;
312 reqh->request = *req;
313 return (USBD_NORMAL_COMPLETION);
317 usbd_setup_default_request(reqh, dev, priv, timeout, req, buffer,
318 length, flags, callback)
319 usbd_request_handle reqh;
320 usbd_device_handle dev;
321 usbd_private_handle priv;
323 usb_device_request_t *req;
327 void (*callback) __P((usbd_request_handle,
331 reqh->pipe = dev->default_pipe;
333 reqh->buffer = buffer;
334 reqh->length = length;
337 reqh->timeout = timeout;
338 reqh->status = USBD_NOT_STARTED;
339 reqh->callback = callback;
340 reqh->request = *req;
343 return (USBD_NORMAL_COMPLETION);
347 usbd_set_request_timeout(reqh, timeout)
348 usbd_request_handle reqh;
351 reqh->timeout = timeout;
352 return (USBD_NORMAL_COMPLETION);
356 usbd_get_request_status(reqh, priv, buffer, count, status)
357 usbd_request_handle reqh;
358 usbd_private_handle *priv;
366 *buffer = reqh->buffer;
368 *count = reqh->actlen;
370 *status = reqh->status;
372 return (USBD_NORMAL_COMPLETION);
376 usbd_request_device_data(reqh, req)
377 usbd_request_handle reqh;
378 usb_device_request_t *req;
382 *req = reqh->request;
383 return (USBD_NORMAL_COMPLETION);
388 usbd_get_descriptor(iface, desc_type)
389 usbd_interface_handle *iface;
394 usb_config_descriptor_t *
395 usbd_get_config_descriptor(dev)
396 usbd_device_handle dev;
401 usb_interface_descriptor_t *
402 usbd_get_interface_descriptor(iface)
403 usbd_interface_handle iface;
405 return (iface->idesc);
408 usb_device_descriptor_t *
409 usbd_get_device_descriptor(dev)
410 usbd_device_handle dev;
412 return (&dev->ddesc);
415 usb_endpoint_descriptor_t *
416 usbd_interface2endpoint_descriptor(iface, index)
417 usbd_interface_handle iface;
420 if (index >= iface->idesc->bNumEndpoints)
422 return (iface->endpoints[index].edesc);
426 usbd_set_configuration(dev, conf)
427 usbd_device_handle dev;
430 return usbd_set_config_no(dev, conf, 0);
434 usbd_retry_request(reqh, retry_count)
435 usbd_request_handle reqh;
436 u_int32_t retry_count;
440 r = usbd_set_pipe_state(reqh->pipe, USBD_PIPE_ACTIVE);
441 if (r != USBD_NORMAL_COMPLETION)
443 reqh->retries = retry_count;
444 return (usbd_transfer(reqh));
448 usbd_abort_pipe(pipe)
449 usbd_pipe_handle pipe;
454 if (pipe->iface->state != USBD_INTERFACE_ACTIVE)
455 return (USBD_INTERFACE_NOT_ACTIVE);
458 r = usbd_ar_pipe(pipe);
465 usbd_abort_interface(iface)
466 usbd_interface_handle iface;
473 r = usbd_ar_iface(iface);
480 usbd_reset_pipe(pipe)
481 usbd_pipe_handle pipe;
486 if (pipe->iface->state != USBD_INTERFACE_ACTIVE)
487 return (USBD_INTERFACE_NOT_ACTIVE);
489 r = usbd_ar_pipe(pipe);
490 /* XXX anything else */
491 pipe->state = USBD_PIPE_ACTIVE;
497 usbd_reset_interface(iface)
498 usbd_interface_handle iface;
504 r = usbd_ar_iface(iface);
505 /* XXX anything else */
506 iface->state = USBD_INTERFACE_ACTIVE;
512 usbd_clear_endpoint_stall(pipe)
513 usbd_pipe_handle pipe;
515 usbd_device_handle dev = pipe->device;
516 usb_device_request_t req;
519 req.bmRequestType = UT_WRITE_ENDPOINT;
520 req.bRequest = UR_CLEAR_FEATURE;
521 USETW(req.wValue, UF_ENDPOINT_HALT);
522 USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
523 USETW(req.wLength, 0);
524 r = usbd_do_request(dev, &req, 0);
526 XXX should we do this?
527 if (r == USBD_NORMAL_COMPLETION) {
528 pipe->state = USBD_PIPE_ACTIVE;
529 /* XXX activate pipe */
536 usbd_clear_endpoint_stall_async(pipe)
537 usbd_pipe_handle pipe;
539 usbd_device_handle dev = pipe->device;
540 usb_device_request_t req;
543 req.bmRequestType = UT_WRITE_ENDPOINT;
544 req.bRequest = UR_CLEAR_FEATURE;
545 USETW(req.wValue, UF_ENDPOINT_HALT);
546 USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
547 USETW(req.wLength, 0);
548 r = usbd_do_request_async(dev, &req, 0);
553 usbd_set_pipe_state(pipe, state)
554 usbd_pipe_handle pipe;
555 usbd_pipe_state state;
559 usbd_request_handle reqh;
561 if (pipe->iface->state != USBD_INTERFACE_ACTIVE)
562 return (USBD_INTERFACE_NOT_ACTIVE);
563 if (state != USBD_PIPE_ACTIVE &&
564 state != USBD_PIPE_STALLED &&
565 state != USBD_PIPE_IDLE)
568 r = USBD_NORMAL_COMPLETION;
569 if (state == USBD_PIPE_ACTIVE) {
571 if (!pipe->running) {
572 reqh = SIMPLEQ_FIRST(&pipe->queue);
576 r = pipe->methods->start(reqh);
586 usbd_get_pipe_state(pipe, state, endpoint_state, request_count)
587 usbd_pipe_handle pipe;
588 usbd_pipe_state *state;
589 u_int32_t *endpoint_state;
590 u_int32_t *request_count;
593 usbd_request_handle r;
595 *state = pipe->state;
596 *endpoint_state = pipe->endpoint->state;
597 for (r = SIMPLEQ_FIRST(&pipe->queue), n = 0;
599 r = SIMPLEQ_NEXT(r, next), n++)
602 return (USBD_NORMAL_COMPLETION);
606 usbd_set_interface_state(iface, state)
607 usbd_interface_handle iface;
608 usbd_interface_state state;
613 if (state == USBD_INTERFACE_ACTIVE)
614 ps = USBD_PIPE_ACTIVE;
615 else if (state == USBD_INTERFACE_STALLED)
616 ps = USBD_PIPE_STALLED;
617 else if (state == USBD_INTERFACE_IDLE)
621 iface->state = USBD_INTERFACE_ACTIVE; /* to allow setting the pipe */
622 for (p = LIST_FIRST(&iface->pipes); p != 0; p = LIST_NEXT(p, next))
623 usbd_set_pipe_state(p, ps);
624 iface->state = state;
625 return (USBD_NORMAL_COMPLETION);
629 usbd_get_interface_state(iface, state)
630 usbd_interface_handle iface;
631 usbd_interface_state *state;
633 *state = iface->state;
634 return (USBD_NORMAL_COMPLETION);
638 usbd_get_device_state(dev, state)
639 usbd_device_handle dev;
640 usbd_device_state *state;
643 return (USBD_NORMAL_COMPLETION);
648 usbd_set_device_state(dev, state)
649 usbd_device_handle dev;
650 usbd_device_state state;
655 usbd_device_address(dev, address)
656 usbd_device_handle dev;
659 *address = dev->address;
660 return (USBD_NORMAL_COMPLETION);
664 usbd_endpoint_address(pipe, address)
665 usbd_pipe_handle pipe;
668 *address = pipe->endpoint->edesc->bEndpointAddress;
669 return (USBD_NORMAL_COMPLETION);
673 usbd_endpoint_count(iface, count)
674 usbd_interface_handle iface;
677 *count = iface->idesc->bNumEndpoints;
678 return (USBD_NORMAL_COMPLETION);
682 usbd_interface_count(dev, count)
683 usbd_device_handle dev;
687 return (USBD_NOT_CONFIGURED);
688 *count = dev->cdesc->bNumInterface;
689 return (USBD_NORMAL_COMPLETION);
696 return (usb_bus_count());
700 usbd_get_bus_handle(index, bus)
702 usbd_bus_handle *bus;
704 return (usb_get_bus_handle(index, bus));
708 usbd_get_root_hub(bus, dev)
710 usbd_device_handle *dev;
712 *dev = bus->root_hub;
713 return (USBD_NORMAL_COMPLETION);
717 usbd_port_count(dev, nports)
718 usbd_device_handle dev;
723 *nports = dev->hub->hubdesc.bNbrPorts;
724 return (USBD_NORMAL_COMPLETION);
728 usbd_hub2device_handle(dev, port, devp)
729 usbd_device_handle dev;
731 usbd_device_handle *devp;
733 if (dev->hub == 0 || port >= dev->hub->hubdesc.bNbrPorts ||
734 dev->hub->ports[port].device == 0)
736 *devp = dev->hub->ports[port].device;
737 return (USBD_NORMAL_COMPLETION);
742 usbd_request2pipe_handle(reqh, pipe)
743 usbd_request_handle reqh;
744 usbd_pipe_handle *pipe;
747 return (USBD_NORMAL_COMPLETION);
751 usbd_pipe2interface_handle(pipe, iface)
752 usbd_pipe_handle pipe;
753 usbd_interface_handle *iface;
755 *iface = pipe->iface;
756 return (USBD_NORMAL_COMPLETION);
760 usbd_interface2device_handle(iface, dev)
761 usbd_interface_handle iface;
762 usbd_device_handle *dev;
764 *dev = iface->device;
765 return (USBD_NORMAL_COMPLETION);
769 usbd_device2bus_handle(dev, bus)
770 usbd_device_handle dev;
771 usbd_bus_handle *bus;
774 return (USBD_NORMAL_COMPLETION);
778 usbd_device2interface_handle(dev, ifaceno, iface)
779 usbd_device_handle dev;
781 usbd_interface_handle *iface;
784 return (USBD_NOT_CONFIGURED);
785 if (ifaceno >= dev->cdesc->bNumInterface)
787 *iface = &dev->ifaces[ifaceno];
788 return (USBD_NORMAL_COMPLETION);
792 usbd_set_interface_private_handle(iface, priv)
793 usbd_interface_handle iface;
794 usbd_private_handle priv;
797 return (USBD_NORMAL_COMPLETION);
801 usbd_get_interface_private_handle(iface, priv)
802 usbd_interface_handle iface;
803 usbd_private_handle *priv;
806 return (USBD_NORMAL_COMPLETION);
810 usbd_reference_pipe(pipe)
811 usbd_pipe_handle pipe;
814 return (USBD_NORMAL_COMPLETION);
818 usbd_dereference_pipe(pipe)
819 usbd_pipe_handle pipe;
822 return (USBD_NORMAL_COMPLETION);
840 usbd_set_interface(iface, altidx)
841 usbd_interface_handle iface;
844 usb_device_request_t req;
847 if (LIST_FIRST(&iface->pipes) != 0)
848 return (USBD_IN_USE);
850 if (iface->endpoints)
851 free(iface->endpoints, M_USB);
852 iface->endpoints = 0;
854 iface->state = USBD_INTERFACE_IDLE;
856 r = usbd_fill_iface_data(iface->device, iface->index, altidx);
857 if (r != USBD_NORMAL_COMPLETION)
860 req.bmRequestType = UT_WRITE_INTERFACE;
861 req.bRequest = UR_SET_INTERFACE;
862 USETW(req.wValue, iface->idesc->bAlternateSetting);
863 USETW(req.wIndex, iface->idesc->bInterfaceNumber);
864 USETW(req.wLength, 0);
865 return usbd_do_request(iface->device, &req, 0);
869 usbd_get_no_alts(cdesc, ifaceno)
870 usb_config_descriptor_t *cdesc;
873 char *p = (char *)cdesc;
874 char *end = p + UGETW(cdesc->wTotalLength);
875 usb_interface_descriptor_t *d;
878 for (n = 0; p < end; p += d->bLength) {
879 d = (usb_interface_descriptor_t *)p;
880 if (p + d->bLength <= end &&
881 d->bDescriptorType == UDESC_INTERFACE &&
882 d->bInterfaceNumber == ifaceno)
889 usbd_get_interface_altindex(iface)
890 usbd_interface_handle iface;
892 return (iface->altindex);
896 usbd_get_interface(iface, aiface)
897 usbd_interface_handle iface;
900 usb_device_request_t req;
902 req.bmRequestType = UT_READ_INTERFACE;
903 req.bRequest = UR_GET_INTERFACE;
904 USETW(req.wValue, 0);
905 USETW(req.wIndex, iface->idesc->bInterfaceNumber);
906 USETW(req.wLength, 1);
907 return usbd_do_request(iface->device, &req, aiface);
910 /*** Internal routines ***/
912 /* Dequeue all pipe operations, called at splusb(). */
915 usbd_pipe_handle pipe;
917 usbd_request_handle reqh;
921 reqh = SIMPLEQ_FIRST(&pipe->queue);
924 #if defined(__NetBSD__)
925 SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next);
926 #elif defined(__FreeBSD__)
927 SIMPLEQ_REMOVE_HEAD(&pipe->queue, next);
929 reqh->status = USBD_CANCELLED;
931 reqh->callback(reqh, reqh->priv, reqh->status);
934 while ((reqh = SIMPLEQ_FIRST(&pipe->queue))) {
935 pipe->methods->abort(reqh);
936 #if defined(__NetBSD__)
937 SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next);
938 #elif defined(__FreeBSD__)
939 SIMPLEQ_REMOVE_HEAD(&pipe->queue, next);
943 return (USBD_NORMAL_COMPLETION);
946 /* Dequeue all interface operations, called at splusb(). */
949 usbd_interface_handle iface;
952 usbd_status r, ret = USBD_NORMAL_COMPLETION;
954 for (p = LIST_FIRST(&iface->pipes); p != 0; p = LIST_NEXT(p, next)) {
956 if (r != USBD_NORMAL_COMPLETION)
962 static int usbd_global_init_done = 0;
968 if (!usbd_global_init_done) {
969 usbd_global_init_done = 1;
970 SIMPLEQ_INIT(&usbd_free_requests);
972 #if defined(__FreeBSD__)
973 cdevsw_add(&usb_cdevsw);
979 usbd_transfer_cb(reqh)
980 usbd_request_handle reqh;
982 usbd_pipe_handle pipe = reqh->pipe;
984 /* Count completed transfers. */
985 ++pipe->device->bus->stats.requests[pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE];
987 /* XXX check retry count */
989 if (reqh->status == USBD_NORMAL_COMPLETION &&
990 reqh->actlen < reqh->length &&
991 !(reqh->flags & USBD_SHORT_XFER_OK)) {
992 DPRINTFN(-1, ("usbd_transfer_cb: short xfer %d<%d (bytes)\n",
993 reqh->actlen, reqh->length));
994 reqh->status = USBD_SHORT_XFER;
998 reqh->callback(reqh, reqh->priv, reqh->status);
1002 usbd_sync_transfer_cb(reqh)
1003 usbd_request_handle reqh;
1005 usbd_transfer_cb(reqh);
1006 if (!reqh->pipe->device->bus->use_polling)
1010 /* Like usbd_transfer(), but waits for completion. */
1012 usbd_sync_transfer(reqh)
1013 usbd_request_handle reqh;
1018 reqh->xfercb = usbd_sync_transfer_cb;
1019 r = usbd_do_transfer(reqh);
1020 if (r != USBD_IN_PROGRESS)
1024 if (reqh->pipe->device->bus->use_polling)
1025 panic("usbd_sync_transfer: not done\n");
1026 tsleep(reqh, PRIBIO, "usbsyn", 0);
1029 return (reqh->status);
1033 usbd_do_request(dev, req, data)
1034 usbd_device_handle dev;
1035 usb_device_request_t *req;
1038 return (usbd_do_request_flags(dev, req, data, 0, 0));
1042 usbd_do_request_flags(dev, req, data, flags, actlen)
1043 usbd_device_handle dev;
1044 usb_device_request_t *req;
1049 usbd_request_handle reqh;
1054 printf("usbd_do_request: not in process context\n");
1059 reqh = usbd_alloc_request();
1061 return (USBD_NOMEM);
1062 r = usbd_setup_default_request(
1063 reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req, data,
1064 UGETW(req->wLength), flags, 0);
1065 if (r != USBD_NORMAL_COMPLETION)
1067 r = usbd_sync_transfer(reqh);
1069 #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
1070 if (reqh->actlen > reqh->length)
1071 printf("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
1072 "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
1073 dev->address, reqh->request.bmRequestType,
1074 reqh->request.bRequest, UGETW(reqh->request.wValue),
1075 UGETW(reqh->request.wIndex),
1076 UGETW(reqh->request.wLength),
1077 reqh->length, reqh->actlen);
1081 *actlen = reqh->actlen;
1083 if (r == USBD_STALLED) {
1085 * The control endpoint has stalled. Control endpoints
1086 * should not halt, but some may do so anyway so clear
1087 * any halt condition.
1089 usb_device_request_t treq;
1090 usb_status_t status;
1094 treq.bmRequestType = UT_READ_ENDPOINT;
1095 treq.bRequest = UR_GET_STATUS;
1096 USETW(treq.wValue, 0);
1097 USETW(treq.wIndex, 0);
1098 USETW(treq.wLength, sizeof(usb_status_t));
1099 nr = usbd_setup_default_request(
1100 reqh, dev, 0, USBD_DEFAULT_TIMEOUT, &treq, &status,
1101 sizeof(usb_status_t), 0, 0);
1102 if (nr != USBD_NORMAL_COMPLETION)
1104 nr = usbd_sync_transfer(reqh);
1105 if (nr != USBD_NORMAL_COMPLETION)
1107 s = UGETW(status.wStatus);
1108 DPRINTF(("usbd_do_request: status = 0x%04x\n", s));
1109 if (!(s & UES_HALT))
1111 treq.bmRequestType = UT_WRITE_ENDPOINT;
1112 treq.bRequest = UR_CLEAR_FEATURE;
1113 USETW(treq.wValue, UF_ENDPOINT_HALT);
1114 USETW(treq.wIndex, 0);
1115 USETW(treq.wLength, 0);
1116 nr = usbd_setup_default_request(
1117 reqh, dev, 0, USBD_DEFAULT_TIMEOUT, &treq, &status,
1119 if (nr != USBD_NORMAL_COMPLETION)
1121 nr = usbd_sync_transfer(reqh);
1122 if (nr != USBD_NORMAL_COMPLETION)
1127 usbd_free_request(reqh);
1132 usbd_do_request_async_cb(reqh, priv, status)
1133 usbd_request_handle reqh;
1134 usbd_private_handle priv;
1137 #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
1138 if (reqh->actlen > reqh->length)
1139 printf("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
1140 "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
1141 reqh->pipe->device->address,
1142 reqh->request.bmRequestType,
1143 reqh->request.bRequest, UGETW(reqh->request.wValue),
1144 UGETW(reqh->request.wIndex),
1145 UGETW(reqh->request.wLength),
1146 reqh->length, reqh->actlen);
1148 usbd_free_request(reqh);
1152 * Execute a request without waiting for completion.
1153 * Can be used from interrupt context.
1156 usbd_do_request_async(dev, req, data)
1157 usbd_device_handle dev;
1158 usb_device_request_t *req;
1161 usbd_request_handle reqh;
1164 reqh = usbd_alloc_request();
1166 return (USBD_NOMEM);
1167 r = usbd_setup_default_request(
1168 reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req, data,
1169 UGETW(req->wLength), 0, usbd_do_request_async_cb);
1170 if (r != USBD_NORMAL_COMPLETION) {
1171 usbd_free_request(reqh);
1174 r = usbd_transfer(reqh);
1175 if (r != USBD_IN_PROGRESS)
1177 return (USBD_NORMAL_COMPLETION);
1180 struct usbd_quirks *
1181 usbd_get_quirks(dev)
1182 usbd_device_handle dev;
1184 return (dev->quirks);
1188 usbd_set_disco(p, hdl, data)
1190 void (*hdl) __P((void *));
1197 /* XXX do periodic free() of free list */
1200 * Called from keyboard driver when in polling mode.
1204 usbd_interface_handle iface;
1206 iface->device->bus->do_poll(iface->device->bus);
1210 usbd_set_polling(iface, on)
1211 usbd_interface_handle iface;
1214 iface->device->bus->use_polling = on;
1218 usb_endpoint_descriptor_t *
1219 usbd_get_endpoint_descriptor(iface, address)
1220 usbd_interface_handle iface;
1223 struct usbd_endpoint *ep;
1226 for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
1227 ep = &iface->endpoints[i];
1228 if (ep->edesc->bEndpointAddress == address)
1229 return (iface->endpoints[i].edesc);
1234 #if defined(__FreeBSD__)
1236 usbd_print_child(device_t parent, device_t child)
1239 struct usb_softc *sc = device_get_softc(child);
1242 printf(" at %s%d", device_get_name(parent), device_get_unit(parent));
1244 /* XXX How do we get to the usbd_device_handle???
1245 usbd_device_handle dev = invalidadosch;
1247 printf(" addr %d", dev->addr);
1251 printf(", lowspeed");
1252 if (dev->self_powered)
1253 printf(", self powered");
1255 printf(", %dmA", dev->power);
1256 printf(", config %d", dev->config);
1261 /* Reconfigure all the USB busses in the system. */
1263 usbd_driver_load(module_t mod, int what, void *arg)
1268 devclass_t usb_devclass = devclass_find("usb");
1269 devclass_t ugen_devclass = devclass_find("ugen");
1274 if ( what == MOD_LOAD || what == MOD_UNLOAD ) {
1276 return 0; /* just ignore call */
1278 /* Detach all the generic devices and do a reconfigure
1279 * of the bus. This should attach the new driver to anything
1280 * that is already connected and it can handle.
1281 * XXX For the moment disabled. The detach does not remove
1282 * the device from the list of devices attached to the hub.
1283 * Legacy of converting from NetBSD to FreeBSD.
1285 if (ugen_devclass) {
1286 /* detach devices from generic driver if possible */
1287 error = devclass_get_devices(ugen_devclass, &devlist,
1290 for (devcount--; devcount >= 0; devcount--)
1291 (void)DEVICE_DETACH(devlist[devcount]);
1292 free(devlist, M_TEMP);
1295 /* Reconfigure the busses, possibly attaching something to the
1297 error = devclass_get_devices(usb_devclass, &devlist, &devcount);
1299 return 0; /* XXX maybe transient, or error? */
1301 for (devcount--; devcount >= 0; devcount--)
1302 USB_RECONFIGURE(devlist[devcount]);
1304 free(devlist, M_TEMP);
1307 return 0; /* nothing to do */
1313 usbd_errstr(usbd_status err)
1315 static char buffer[5]; /* XXX static buffer */
1318 if ( err < USBD_ERROR_MAX ) {
1319 return usbd_error_strs[err];
1321 snprintf(buffer, 4, "%d", err);
1325 snprintf(buffer, 4, "%d", err);