1 /* $FreeBSD: head/sys/dev/usb/usb_handle_request.c 246759 2013-02-13 12:35:17Z hselasky $ */
3 * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/stdint.h>
28 #include <sys/param.h>
29 #include <sys/queue.h>
30 #include <sys/types.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
34 #include <sys/module.h>
36 #include <sys/mutex.h>
37 #include <sys/condvar.h>
38 #include <sys/sysctl.h>
39 #include <sys/unistd.h>
40 #include <sys/callout.h>
41 #include <sys/malloc.h>
44 #include <bus/u4b/usb.h>
45 #include <bus/u4b/usbdi.h>
46 #include <bus/u4b/usbdi_util.h>
49 #define USB_DEBUG_VAR usb_debug
51 #include <bus/u4b/usb_core.h>
52 #include <bus/u4b/usb_process.h>
53 #include <bus/u4b/usb_busdma.h>
54 #include <bus/u4b/usb_transfer.h>
55 #include <bus/u4b/usb_device.h>
56 #include <bus/u4b/usb_debug.h>
57 #include <bus/u4b/usb_dynamic.h>
58 #include <bus/u4b/usb_hub.h>
60 #include <bus/u4b/usb_controller.h>
61 #include <bus/u4b/usb_bus.h>
63 /* function prototypes */
65 static uint8_t usb_handle_get_stall(struct usb_device
*, uint8_t);
66 static usb_error_t
usb_handle_remote_wakeup(struct usb_xfer
*, uint8_t);
67 static usb_error_t
usb_handle_request(struct usb_xfer
*);
68 static usb_error_t
usb_handle_set_config(struct usb_xfer
*, uint8_t);
69 static usb_error_t
usb_handle_set_stall(struct usb_xfer
*, uint8_t,
71 static usb_error_t
usb_handle_iface_request(struct usb_xfer
*, void **,
72 uint16_t *, struct usb_device_request
, uint16_t,
75 /*------------------------------------------------------------------------*
76 * usb_handle_request_callback
78 * This function is the USB callback for generic USB Device control
80 *------------------------------------------------------------------------*/
82 usb_handle_request_callback(struct usb_xfer
*xfer
, usb_error_t error
)
86 /* check the current transfer state */
88 switch (USB_GET_STATE(xfer
)) {
90 case USB_ST_TRANSFERRED
:
92 /* handle the request */
93 err
= usb_handle_request(xfer
);
97 if (err
== USB_ERR_BAD_CONTEXT
) {
98 /* we need to re-setup the control transfer */
99 usb_needs_explore(xfer
->xroot
->bus
, 0);
104 usbd_transfer_submit(xfer
);
108 /* check if a control transfer is active */
109 if (xfer
->flags_int
.control_rem
!= 0xFFFF) {
110 /* handle the request */
111 err
= usb_handle_request(xfer
);
113 if (xfer
->error
!= USB_ERR_CANCELLED
) {
114 /* should not happen - try stalling */
123 * If a control transfer is active, stall it, and wait for the
124 * next control transfer.
126 usbd_xfer_set_frame_len(xfer
, 0, sizeof(struct usb_device_request
));
128 xfer
->flags
.manual_status
= 1;
129 xfer
->flags
.force_short_xfer
= 0;
130 usbd_xfer_set_stall(xfer
); /* cancel previous transfer, if any */
131 usbd_transfer_submit(xfer
);
134 /*------------------------------------------------------------------------*
135 * usb_handle_set_config
140 *------------------------------------------------------------------------*/
142 usb_handle_set_config(struct usb_xfer
*xfer
, uint8_t conf_no
)
144 struct usb_device
*udev
= xfer
->xroot
->udev
;
149 * We need to protect against other threads doing probe and
152 USB_XFER_UNLOCK(xfer
);
154 /* Prevent re-enumeration */
155 do_unlock
= usbd_enum_lock(udev
);
157 if (conf_no
== USB_UNCONFIG_NO
) {
158 conf_no
= USB_UNCONFIG_INDEX
;
161 * The relationship between config number and config index
162 * is very simple in our case:
167 if (usbd_set_config_index(udev
, conf_no
)) {
168 DPRINTF("set config %d failed\n", conf_no
);
169 err
= USB_ERR_STALLED
;
172 if (usb_probe_and_attach(udev
, USB_IFACE_INDEX_ANY
)) {
173 DPRINTF("probe and attach failed\n");
174 err
= USB_ERR_STALLED
;
179 usbd_enum_unlock(udev
);
185 usb_check_alt_setting(struct usb_device
*udev
,
186 struct usb_interface
*iface
, uint8_t alt_index
)
191 /* Prevent re-enumeration */
192 do_unlock
= usbd_enum_lock(udev
);
194 if (alt_index
>= usbd_get_no_alts(udev
->cdesc
, iface
->idesc
))
198 usbd_enum_unlock(udev
);
203 /*------------------------------------------------------------------------*
204 * usb_handle_iface_request
209 *------------------------------------------------------------------------*/
211 usb_handle_iface_request(struct usb_xfer
*xfer
,
212 void **ppdata
, uint16_t *plen
,
213 struct usb_device_request req
, uint16_t off
, uint8_t state
)
215 struct usb_interface
*iface
;
216 struct usb_interface
*iface_parent
; /* parent interface */
217 struct usb_device
*udev
= xfer
->xroot
->udev
;
223 if ((req
.bmRequestType
& 0x1F) == UT_INTERFACE
) {
224 iface_index
= req
.wIndex
[0]; /* unicast */
226 iface_index
= 0; /* broadcast */
230 * We need to protect against other threads doing probe and
233 USB_XFER_UNLOCK(xfer
);
235 /* Prevent re-enumeration */
236 do_unlock
= usbd_enum_lock(udev
);
241 iface
= usbd_get_iface(udev
, iface_index
);
242 if ((iface
== NULL
) ||
243 (iface
->idesc
== NULL
)) {
244 /* end of interfaces non-existing interface */
247 /* set initial state */
251 /* forward request to interface, if any */
255 (iface
->subdev
!= NULL
) &&
256 device_is_attached(iface
->subdev
)) {
258 DEVMETHOD(usb_handle_request
, NULL
); /* dummy */
260 error
= USB_HANDLE_REQUEST(iface
->subdev
,
264 iface_parent
= usbd_get_iface(udev
, iface
->parent_iface_index
);
266 if ((iface_parent
== NULL
) ||
267 (iface_parent
->idesc
== NULL
)) {
268 /* non-existing interface */
271 /* forward request to parent interface, if any */
275 (iface_parent
!= NULL
) &&
276 (iface_parent
->subdev
!= NULL
) &&
277 ((req
.bmRequestType
& 0x1F) == UT_INTERFACE
) &&
278 (iface_parent
->subdev
!= iface
->subdev
) &&
279 device_is_attached(iface_parent
->subdev
)) {
280 error
= USB_HANDLE_REQUEST(iface_parent
->subdev
,
281 &req
, ppdata
, plen
, off
, &temp_state
);
284 /* negativly adjust pointer and length */
285 *ppdata
= ((uint8_t *)(*ppdata
)) - off
;
288 if ((state
== USB_HR_NOT_COMPLETE
) &&
289 (temp_state
== USB_HR_COMPLETE_OK
))
293 } else if (error
== ENOTTY
) {
296 if ((req
.bmRequestType
& 0x1F) != UT_INTERFACE
) {
297 iface_index
++; /* iterate */
300 if (state
!= USB_HR_NOT_COMPLETE
) {
301 /* we are complete */
304 switch (req
.bmRequestType
) {
305 case UT_WRITE_INTERFACE
:
306 switch (req
.bRequest
) {
307 case UR_SET_INTERFACE
:
309 * We assume that the endpoints are the same
310 * accross the alternate settings.
312 * Reset the endpoints, because re-attaching
313 * only a part of the device is not possible.
315 error
= usb_check_alt_setting(udev
,
316 iface
, req
.wValue
[0]);
318 DPRINTF("alt setting does not exist %s\n",
322 error
= usb_reset_iface_endpoints(udev
, iface_index
);
324 DPRINTF("alt setting failed %s\n",
328 /* update the current alternate setting */
329 iface
->alt_index
= req
.wValue
[0];
337 case UT_READ_INTERFACE
:
338 switch (req
.bRequest
) {
339 case UR_GET_INTERFACE
:
340 *ppdata
= &iface
->alt_index
;
353 usbd_enum_unlock(udev
);
359 usbd_enum_unlock(udev
);
361 return (USB_ERR_SHORT_XFER
);
365 usbd_enum_unlock(udev
);
367 return (USB_ERR_STALLED
);
370 /*------------------------------------------------------------------------*
376 *------------------------------------------------------------------------*/
378 usb_handle_set_stall(struct usb_xfer
*xfer
, uint8_t ep
, uint8_t do_stall
)
380 struct usb_device
*udev
= xfer
->xroot
->udev
;
383 USB_XFER_UNLOCK(xfer
);
384 err
= usbd_set_endpoint_stall(udev
,
385 usbd_get_ep_by_addr(udev
, ep
), do_stall
);
390 /*------------------------------------------------------------------------*
391 * usb_handle_get_stall
396 *------------------------------------------------------------------------*/
398 usb_handle_get_stall(struct usb_device
*udev
, uint8_t ea_val
)
400 struct usb_endpoint
*ep
;
403 ep
= usbd_get_ep_by_addr(udev
, ea_val
);
408 USB_BUS_LOCK(udev
->bus
);
409 halted
= ep
->is_stalled
;
410 USB_BUS_UNLOCK(udev
->bus
);
415 /*------------------------------------------------------------------------*
416 * usb_handle_remote_wakeup
421 *------------------------------------------------------------------------*/
423 usb_handle_remote_wakeup(struct usb_xfer
*xfer
, uint8_t is_on
)
425 struct usb_device
*udev
;
428 udev
= xfer
->xroot
->udev
;
434 udev
->flags
.remote_wakeup
= 1;
436 udev
->flags
.remote_wakeup
= 0;
442 /* In case we are out of sync, update the power state. */
443 usb_bus_power_update(udev
->bus
);
445 return (0); /* success */
448 /*------------------------------------------------------------------------*
451 * Internal state sequence:
453 * USB_HR_NOT_COMPLETE -> USB_HR_COMPLETE_OK v USB_HR_COMPLETE_ERR
456 * 0: Ready to start hardware
457 * Else: Stall current transfer, if any
458 *------------------------------------------------------------------------*/
460 usb_handle_request(struct usb_xfer
*xfer
)
462 struct usb_device_request req
;
463 struct usb_device
*udev
;
464 const void *src_zcopy
; /* zero-copy source pointer */
465 const void *src_mcopy
; /* non zero-copy source pointer */
466 uint16_t off
; /* data offset */
467 uint16_t rem
; /* data remainder */
468 uint16_t max_len
; /* max fragment length */
471 uint8_t is_complete
= 1;
479 * Filter the USB transfer state into
480 * something which we understand:
483 switch (USB_GET_STATE(xfer
)) {
485 state
= USB_HR_NOT_COMPLETE
;
487 if (!xfer
->flags_int
.control_act
) {
492 case USB_ST_TRANSFERRED
:
493 if (!xfer
->flags_int
.control_act
) {
494 state
= USB_HR_COMPLETE_OK
;
496 state
= USB_HR_NOT_COMPLETE
;
500 state
= USB_HR_COMPLETE_ERR
;
504 /* reset frame stuff */
506 usbd_xfer_set_frame_len(xfer
, 0, 0);
508 usbd_xfer_set_frame_offset(xfer
, 0, 0);
509 usbd_xfer_set_frame_offset(xfer
, sizeof(req
), 1);
511 /* get the current request, if any */
513 usbd_copy_out(xfer
->frbuffers
, 0, &req
, sizeof(req
));
515 if (xfer
->flags_int
.control_rem
== 0xFFFF) {
516 /* first time - not initialised */
517 rem
= UGETW(req
.wLength
);
520 /* not first time - initialised */
521 rem
= xfer
->flags_int
.control_rem
;
522 off
= UGETW(req
.wLength
) - rem
;
525 /* set some defaults */
530 udev
= xfer
->xroot
->udev
;
532 /* get some request fields decoded */
534 wValue
= UGETW(req
.wValue
);
536 DPRINTF("req 0x%02x 0x%02x 0x%04x 0x%04x "
537 "off=0x%x rem=0x%x, state=%d\n", req
.bmRequestType
,
538 req
.bRequest
, wValue
, UGETW(req
.wIndex
), off
, rem
, state
);
540 /* demultiplex the control request */
542 switch (req
.bmRequestType
) {
544 if (state
!= USB_HR_NOT_COMPLETE
) {
547 switch (req
.bRequest
) {
548 case UR_GET_DESCRIPTOR
:
549 goto tr_handle_get_descriptor
;
551 goto tr_handle_get_config
;
553 goto tr_handle_get_status
;
559 case UT_WRITE_DEVICE
:
560 switch (req
.bRequest
) {
562 goto tr_handle_set_address
;
564 goto tr_handle_set_config
;
565 case UR_CLEAR_FEATURE
:
567 case UF_DEVICE_REMOTE_WAKEUP
:
568 goto tr_handle_clear_wakeup
;
575 case UF_DEVICE_REMOTE_WAKEUP
:
576 goto tr_handle_set_wakeup
;
586 case UT_WRITE_ENDPOINT
:
587 switch (req
.bRequest
) {
588 case UR_CLEAR_FEATURE
:
590 case UF_ENDPOINT_HALT
:
591 goto tr_handle_clear_halt
;
598 case UF_ENDPOINT_HALT
:
599 goto tr_handle_set_halt
;
609 case UT_READ_ENDPOINT
:
610 switch (req
.bRequest
) {
612 goto tr_handle_get_ep_status
;
618 /* we use "USB_ADD_BYTES" to de-const the src_zcopy */
619 err
= usb_handle_iface_request(xfer
,
620 USB_ADD_BYTES(&src_zcopy
, 0),
621 &max_len
, req
, off
, state
);
625 } else if (err
== USB_ERR_SHORT_XFER
) {
629 * Reset zero-copy pointer and max length
630 * variable in case they were unintentionally
637 * Check if we have a vendor specific
640 goto tr_handle_get_descriptor
;
644 tr_handle_get_descriptor
:
645 err
= (usb_temp_get_desc_p
) (udev
, &req
, &src_zcopy
, &max_len
);
648 if (src_zcopy
== NULL
)
652 tr_handle_get_config
:
653 temp
.buf
[0] = udev
->curr_config_no
;
654 src_mcopy
= temp
.buf
;
658 tr_handle_get_status
:
662 USB_BUS_LOCK(udev
->bus
);
663 if (udev
->flags
.remote_wakeup
) {
664 wValue
|= UDS_REMOTE_WAKEUP
;
666 if (udev
->flags
.self_powered
) {
667 wValue
|= UDS_SELF_POWERED
;
669 USB_BUS_UNLOCK(udev
->bus
);
671 USETW(temp
.wStatus
, wValue
);
672 src_mcopy
= temp
.wStatus
;
673 max_len
= sizeof(temp
.wStatus
);
676 tr_handle_set_address
:
677 if (state
== USB_HR_NOT_COMPLETE
) {
678 if (wValue
>= 0x80) {
681 } else if (udev
->curr_config_no
!= 0) {
682 /* we are configured ! */
685 } else if (state
!= USB_HR_NOT_COMPLETE
) {
686 udev
->address
= (wValue
& 0x7F);
691 tr_handle_set_config
:
692 if (state
== USB_HR_NOT_COMPLETE
) {
693 if (usb_handle_set_config(xfer
, req
.wValue
[0])) {
699 tr_handle_clear_halt
:
700 if (state
== USB_HR_NOT_COMPLETE
) {
701 if (usb_handle_set_stall(xfer
, req
.wIndex
[0], 0)) {
707 tr_handle_clear_wakeup
:
708 if (state
== USB_HR_NOT_COMPLETE
) {
709 if (usb_handle_remote_wakeup(xfer
, 0)) {
716 if (state
== USB_HR_NOT_COMPLETE
) {
717 if (usb_handle_set_stall(xfer
, req
.wIndex
[0], 1)) {
723 tr_handle_set_wakeup
:
724 if (state
== USB_HR_NOT_COMPLETE
) {
725 if (usb_handle_remote_wakeup(xfer
, 1)) {
731 tr_handle_get_ep_status
:
732 if (state
== USB_HR_NOT_COMPLETE
) {
734 usb_handle_get_stall(udev
, req
.wIndex
[0]);
736 src_mcopy
= temp
.wStatus
;
737 max_len
= sizeof(temp
.wStatus
);
742 if (state
!= USB_HR_NOT_COMPLETE
) {
745 /* subtract offset from length */
749 /* Compute the real maximum data length */
751 if (max_len
> xfer
->max_data_length
) {
752 max_len
= usbd_xfer_max_len(xfer
);
758 * If the remainder is greater than the maximum data length,
759 * we need to truncate the value for the sake of the
762 if (rem
> xfer
->max_data_length
) {
763 rem
= usbd_xfer_max_len(xfer
);
765 if ((rem
!= max_len
) && (is_complete
!= 0)) {
767 * If we don't transfer the data we can transfer, then
768 * the transfer is short !
770 xfer
->flags
.force_short_xfer
= 1;
776 xfer
->flags
.force_short_xfer
= 0;
777 xfer
->nframes
= max_len
? 2 : 1;
781 src_mcopy
= USB_ADD_BYTES(src_mcopy
, off
);
782 usbd_copy_in(xfer
->frbuffers
+ 1, 0,
784 usbd_xfer_set_frame_len(xfer
, 1, max_len
);
786 usbd_xfer_set_frame_data(xfer
, 1,
787 USB_ADD_BYTES(src_zcopy
, off
), max_len
);
790 /* the end is reached, send status */
791 xfer
->flags
.manual_status
= 0;
792 usbd_xfer_set_frame_len(xfer
, 1, 0);
794 DPRINTF("success\n");
795 return (0); /* success */
798 DPRINTF("%s\n", (state
!= USB_HR_NOT_COMPLETE
) ?
799 "complete" : "stalled");
800 return (USB_ERR_STALLED
);
803 DPRINTF("bad context\n");
804 return (USB_ERR_BAD_CONTEXT
);