xref: /dragonfly/sys/bus/u4b/usb_handle_request.c (revision 2b3f93ea6d1f70880f3e87f3c2cbe0dc0bfc9332)
1 /* $FreeBSD: head/sys/dev/usb/usb_handle_request.c 246759 2013-02-13 12:35:17Z hselasky $ */
2 /*-
3  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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
24  * SUCH DAMAGE.
25  */
26 
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>
33 #include <sys/bus.h>
34 #include <sys/module.h>
35 #include <sys/lock.h>
36 #include <sys/condvar.h>
37 #include <sys/sysctl.h>
38 #include <sys/unistd.h>
39 #include <sys/callout.h>
40 #include <sys/malloc.h>
41 #include <sys/caps.h>
42 
43 #include <bus/u4b/usb.h>
44 #include <bus/u4b/usbdi.h>
45 #include <bus/u4b/usbdi_util.h>
46 #include "usb_if.h"
47 
48 #define   USB_DEBUG_VAR usb_debug
49 
50 #include <bus/u4b/usb_core.h>
51 #include <bus/u4b/usb_process.h>
52 #include <bus/u4b/usb_busdma.h>
53 #include <bus/u4b/usb_transfer.h>
54 #include <bus/u4b/usb_device.h>
55 #include <bus/u4b/usb_debug.h>
56 #include <bus/u4b/usb_dynamic.h>
57 #include <bus/u4b/usb_hub.h>
58 
59 #include <bus/u4b/usb_controller.h>
60 #include <bus/u4b/usb_bus.h>
61 
62 /* function prototypes */
63 
64 static uint8_t usb_handle_get_stall(struct usb_device *, uint8_t);
65 static usb_error_t   usb_handle_remote_wakeup(struct usb_xfer *, uint8_t);
66 static usb_error_t   usb_handle_request(struct usb_xfer *);
67 static usb_error_t   usb_handle_set_config(struct usb_xfer *, uint8_t);
68 static usb_error_t   usb_handle_set_stall(struct usb_xfer *, uint8_t,
69                                   uint8_t);
70 static usb_error_t   usb_handle_iface_request(struct usb_xfer *, void **,
71                                   uint16_t *, struct usb_device_request, uint16_t,
72                                   uint8_t);
73 
74 /*------------------------------------------------------------------------*
75  *        usb_handle_request_callback
76  *
77  * This function is the USB callback for generic USB Device control
78  * transfers.
79  *------------------------------------------------------------------------*/
80 void
usb_handle_request_callback(struct usb_xfer * xfer,usb_error_t error)81 usb_handle_request_callback(struct usb_xfer *xfer, usb_error_t error)
82 {
83           usb_error_t err;
84 
85           /* check the current transfer state */
86 
87           switch (USB_GET_STATE(xfer)) {
88           case USB_ST_SETUP:
89           case USB_ST_TRANSFERRED:
90 
91                     /* handle the request */
92                     err = usb_handle_request(xfer);
93 
94                     if (err) {
95 
96                               if (err == USB_ERR_BAD_CONTEXT) {
97                                         /* we need to re-setup the control transfer */
98                                         usb_needs_explore(xfer->xroot->bus, 0);
99                                         break;
100                               }
101                               goto tr_restart;
102                     }
103                     usbd_transfer_submit(xfer);
104                     break;
105 
106           default:
107                     /* check if a control transfer is active */
108                     if (xfer->flags_int.control_rem != 0xFFFF) {
109                               /* handle the request */
110                               err = usb_handle_request(xfer);
111                     }
112                     if (xfer->error != USB_ERR_CANCELLED) {
113                               /* should not happen - try stalling */
114                               goto tr_restart;
115                     }
116                     break;
117           }
118           return;
119 
120 tr_restart:
121           /*
122            * If a control transfer is active, stall it, and wait for the
123            * next control transfer.
124            */
125           usbd_xfer_set_frame_len(xfer, 0, sizeof(struct usb_device_request));
126           xfer->nframes = 1;
127           xfer->flags.manual_status = 1;
128           xfer->flags.force_short_xfer = 0;
129           usbd_xfer_set_stall(xfer);    /* cancel previous transfer, if any */
130           usbd_transfer_submit(xfer);
131 }
132 
133 /*------------------------------------------------------------------------*
134  *        usb_handle_set_config
135  *
136  * Returns:
137  *    0: Success
138  * Else: Failure
139  *------------------------------------------------------------------------*/
140 static usb_error_t
usb_handle_set_config(struct usb_xfer * xfer,uint8_t conf_no)141 usb_handle_set_config(struct usb_xfer *xfer, uint8_t conf_no)
142 {
143           struct usb_device *udev = xfer->xroot->udev;
144           usb_error_t err = 0;
145           uint8_t do_unlock;
146 
147           /*
148            * We need to protect against other threads doing probe and
149            * attach:
150            */
151           USB_XFER_UNLOCK(xfer);
152 
153           /* Prevent re-enumeration */
154           do_unlock = usbd_enum_lock(udev);
155 
156           if (conf_no == USB_UNCONFIG_NO) {
157                     conf_no = USB_UNCONFIG_INDEX;
158           } else {
159                     /*
160                      * The relationship between config number and config index
161                      * is very simple in our case:
162                      */
163                     conf_no--;
164           }
165 
166           if (usbd_set_config_index(udev, conf_no)) {
167                     DPRINTF("set config %d failed\n", conf_no);
168                     err = USB_ERR_STALLED;
169                     goto done;
170           }
171           if (usb_probe_and_attach(udev, USB_IFACE_INDEX_ANY)) {
172                     DPRINTF("probe and attach failed\n");
173                     err = USB_ERR_STALLED;
174                     goto done;
175           }
176 done:
177           if (do_unlock)
178                     usbd_enum_unlock(udev);
179           USB_XFER_LOCK(xfer);
180           return (err);
181 }
182 
183 static usb_error_t
usb_check_alt_setting(struct usb_device * udev,struct usb_interface * iface,uint8_t alt_index)184 usb_check_alt_setting(struct usb_device *udev,
185      struct usb_interface *iface, uint8_t alt_index)
186 {
187           uint8_t do_unlock;
188           usb_error_t err = 0;
189 
190           /* Prevent re-enumeration */
191           do_unlock = usbd_enum_lock(udev);
192 
193           if (alt_index >= usbd_get_no_alts(udev->cdesc, iface->idesc))
194                     err = USB_ERR_INVAL;
195 
196           if (do_unlock)
197                     usbd_enum_unlock(udev);
198 
199           return (err);
200 }
201 
202 /*------------------------------------------------------------------------*
203  *        usb_handle_iface_request
204  *
205  * Returns:
206  *    0: Success
207  * Else: Failure
208  *------------------------------------------------------------------------*/
209 static usb_error_t
usb_handle_iface_request(struct usb_xfer * xfer,void ** ppdata,uint16_t * plen,struct usb_device_request req,uint16_t off,uint8_t state)210 usb_handle_iface_request(struct usb_xfer *xfer,
211     void **ppdata, uint16_t *plen,
212     struct usb_device_request req, uint16_t off, uint8_t state)
213 {
214           struct usb_interface *iface;
215           struct usb_interface *iface_parent;     /* parent interface */
216           struct usb_device *udev = xfer->xroot->udev;
217           int error;
218           uint8_t iface_index;
219           uint8_t temp_state;
220           uint8_t do_unlock;
221 
222           if ((req.bmRequestType & 0x1F) == UT_INTERFACE) {
223                     iface_index = req.wIndex[0];  /* unicast */
224           } else {
225                     iface_index = 0;    /* broadcast */
226           }
227 
228           /*
229            * We need to protect against other threads doing probe and
230            * attach:
231            */
232           USB_XFER_UNLOCK(xfer);
233 
234           /* Prevent re-enumeration */
235           do_unlock = usbd_enum_lock(udev);
236 
237           error = ENXIO;
238 
239 tr_repeat:
240           iface = usbd_get_iface(udev, iface_index);
241           if ((iface == NULL) ||
242               (iface->idesc == NULL)) {
243                     /* end of interfaces non-existing interface */
244                     goto tr_stalled;
245           }
246           /* set initial state */
247 
248           temp_state = state;
249 
250           /* forward request to interface, if any */
251 
252           if ((error != 0) &&
253               (error != ENOTTY) &&
254               (iface->subdev != NULL) &&
255               device_is_attached(iface->subdev)) {
256 #if 0
257                     DEVMETHOD(usb_handle_request, NULL);    /* dummy */
258 #endif
259                     error = USB_HANDLE_REQUEST(iface->subdev,
260                         &req, ppdata, plen,
261                         off, &temp_state);
262           }
263           iface_parent = usbd_get_iface(udev, iface->parent_iface_index);
264 
265           if ((iface_parent == NULL) ||
266               (iface_parent->idesc == NULL)) {
267                     /* non-existing interface */
268                     iface_parent = NULL;
269           }
270           /* forward request to parent interface, if any */
271 
272           if ((error != 0) &&
273               (error != ENOTTY) &&
274               (iface_parent != NULL) &&
275               (iface_parent->subdev != NULL) &&
276               ((req.bmRequestType & 0x1F) == UT_INTERFACE) &&
277               (iface_parent->subdev != iface->subdev) &&
278               device_is_attached(iface_parent->subdev)) {
279                     error = USB_HANDLE_REQUEST(iface_parent->subdev,
280                         &req, ppdata, plen, off, &temp_state);
281           }
282           if (error == 0) {
283                     /* negativly adjust pointer and length */
284                     *ppdata = ((uint8_t *)(*ppdata)) - off;
285                     *plen += off;
286 
287                     if ((state == USB_HR_NOT_COMPLETE) &&
288                         (temp_state == USB_HR_COMPLETE_OK))
289                               goto tr_short;
290                     else
291                               goto tr_valid;
292           } else if (error == ENOTTY) {
293                     goto tr_stalled;
294           }
295           if ((req.bmRequestType & 0x1F) != UT_INTERFACE) {
296                     iface_index++;                /* iterate */
297                     goto tr_repeat;
298           }
299           if (state != USB_HR_NOT_COMPLETE) {
300                     /* we are complete */
301                     goto tr_valid;
302           }
303           switch (req.bmRequestType) {
304           case UT_WRITE_INTERFACE:
305                     switch (req.bRequest) {
306                     case UR_SET_INTERFACE:
307                               /*
308                                * We assume that the endpoints are the same
309                                * accross the alternate settings.
310                                *
311                                * Reset the endpoints, because re-attaching
312                                * only a part of the device is not possible.
313                                */
314                               error = usb_check_alt_setting(udev,
315                                   iface, req.wValue[0]);
316                               if (error) {
317                                         DPRINTF("alt setting does not exist %s\n",
318                                             usbd_errstr(error));
319                                         goto tr_stalled;
320                               }
321                               error = usb_reset_iface_endpoints(udev, iface_index);
322                               if (error) {
323                                         DPRINTF("alt setting failed %s\n",
324                                             usbd_errstr(error));
325                                         goto tr_stalled;
326                               }
327                               /* update the current alternate setting */
328                               iface->alt_index = req.wValue[0];
329                               break;
330 
331                     default:
332                               goto tr_stalled;
333                     }
334                     break;
335 
336           case UT_READ_INTERFACE:
337                     switch (req.bRequest) {
338                     case UR_GET_INTERFACE:
339                               *ppdata = &iface->alt_index;
340                               *plen = 1;
341                               break;
342 
343                     default:
344                               goto tr_stalled;
345                     }
346                     break;
347           default:
348                     goto tr_stalled;
349           }
350 tr_valid:
351           if (do_unlock)
352                     usbd_enum_unlock(udev);
353           USB_XFER_LOCK(xfer);
354           return (0);
355 
356 tr_short:
357           if (do_unlock)
358                     usbd_enum_unlock(udev);
359           USB_XFER_LOCK(xfer);
360           return (USB_ERR_SHORT_XFER);
361 
362 tr_stalled:
363           if (do_unlock)
364                     usbd_enum_unlock(udev);
365           USB_XFER_LOCK(xfer);
366           return (USB_ERR_STALLED);
367 }
368 
369 /*------------------------------------------------------------------------*
370  *        usb_handle_stall
371  *
372  * Returns:
373  *    0: Success
374  * Else: Failure
375  *------------------------------------------------------------------------*/
376 static usb_error_t
usb_handle_set_stall(struct usb_xfer * xfer,uint8_t ep,uint8_t do_stall)377 usb_handle_set_stall(struct usb_xfer *xfer, uint8_t ep, uint8_t do_stall)
378 {
379           struct usb_device *udev = xfer->xroot->udev;
380           usb_error_t err;
381 
382           USB_XFER_UNLOCK(xfer);
383           err = usbd_set_endpoint_stall(udev,
384               usbd_get_ep_by_addr(udev, ep), do_stall);
385           USB_XFER_LOCK(xfer);
386           return (err);
387 }
388 
389 /*------------------------------------------------------------------------*
390  *        usb_handle_get_stall
391  *
392  * Returns:
393  *    0: Success
394  * Else: Failure
395  *------------------------------------------------------------------------*/
396 static uint8_t
usb_handle_get_stall(struct usb_device * udev,uint8_t ea_val)397 usb_handle_get_stall(struct usb_device *udev, uint8_t ea_val)
398 {
399           struct usb_endpoint *ep;
400           uint8_t halted;
401 
402           ep = usbd_get_ep_by_addr(udev, ea_val);
403           if (ep == NULL) {
404                     /* nothing to do */
405                     return (0);
406           }
407           USB_BUS_LOCK(udev->bus);
408           halted = ep->is_stalled;
409           USB_BUS_UNLOCK(udev->bus);
410 
411           return (halted);
412 }
413 
414 /*------------------------------------------------------------------------*
415  *        usb_handle_remote_wakeup
416  *
417  * Returns:
418  *    0: Success
419  * Else: Failure
420  *------------------------------------------------------------------------*/
421 static usb_error_t
usb_handle_remote_wakeup(struct usb_xfer * xfer,uint8_t is_on)422 usb_handle_remote_wakeup(struct usb_xfer *xfer, uint8_t is_on)
423 {
424           struct usb_device *udev;
425           struct usb_bus *bus;
426 
427           udev = xfer->xroot->udev;
428           bus = udev->bus;
429 
430           USB_BUS_LOCK(bus);
431 
432           if (is_on) {
433                     udev->flags.remote_wakeup = 1;
434           } else {
435                     udev->flags.remote_wakeup = 0;
436           }
437 
438           USB_BUS_UNLOCK(bus);
439 
440 #if USB_HAVE_POWERD
441           /* In case we are out of sync, update the power state. */
442           usb_bus_power_update(udev->bus);
443 #endif
444           return (0);                             /* success */
445 }
446 
447 /*------------------------------------------------------------------------*
448  *        usb_handle_request
449  *
450  * Internal state sequence:
451  *
452  * USB_HR_NOT_COMPLETE -> USB_HR_COMPLETE_OK v USB_HR_COMPLETE_ERR
453  *
454  * Returns:
455  * 0: Ready to start hardware
456  * Else: Stall current transfer, if any
457  *------------------------------------------------------------------------*/
458 static usb_error_t
usb_handle_request(struct usb_xfer * xfer)459 usb_handle_request(struct usb_xfer *xfer)
460 {
461           struct usb_device_request req;
462           struct usb_device *udev;
463           const void *src_zcopy;                  /* zero-copy source pointer */
464           const void *src_mcopy;                  /* non zero-copy source pointer */
465           uint16_t off;                           /* data offset */
466           uint16_t rem;                           /* data remainder */
467           uint16_t max_len;             /* max fragment length */
468           uint16_t wValue;
469           uint8_t state;
470           uint8_t is_complete = 1;
471           usb_error_t err;
472           union {
473                     uWord     wStatus;
474                     uint8_t   buf[2];
475           }     temp;
476 
477           /*
478            * Filter the USB transfer state into
479            * something which we understand:
480            */
481 
482           switch (USB_GET_STATE(xfer)) {
483           case USB_ST_SETUP:
484                     state = USB_HR_NOT_COMPLETE;
485 
486                     if (!xfer->flags_int.control_act) {
487                               /* nothing to do */
488                               goto tr_stalled;
489                     }
490                     break;
491           case USB_ST_TRANSFERRED:
492                     if (!xfer->flags_int.control_act) {
493                               state = USB_HR_COMPLETE_OK;
494                     } else {
495                               state = USB_HR_NOT_COMPLETE;
496                     }
497                     break;
498           default:
499                     state = USB_HR_COMPLETE_ERR;
500                     break;
501           }
502 
503           /* reset frame stuff */
504 
505           usbd_xfer_set_frame_len(xfer, 0, 0);
506 
507           usbd_xfer_set_frame_offset(xfer, 0, 0);
508           usbd_xfer_set_frame_offset(xfer, sizeof(req), 1);
509 
510           /* get the current request, if any */
511 
512           usbd_copy_out(xfer->frbuffers, 0, &req, sizeof(req));
513 
514           if (xfer->flags_int.control_rem == 0xFFFF) {
515                     /* first time - not initialised */
516                     rem = UGETW(req.wLength);
517                     off = 0;
518           } else {
519                     /* not first time - initialised */
520                     rem = xfer->flags_int.control_rem;
521                     off = UGETW(req.wLength) - rem;
522           }
523 
524           /* set some defaults */
525 
526           max_len = 0;
527           src_zcopy = NULL;
528           src_mcopy = NULL;
529           udev = xfer->xroot->udev;
530 
531           /* get some request fields decoded */
532 
533           wValue = UGETW(req.wValue);
534 
535           DPRINTF("req 0x%02x 0x%02x 0x%04x 0x%04x "
536               "off=0x%x rem=0x%x, state=%d\n", req.bmRequestType,
537               req.bRequest, wValue, UGETW(req.wIndex), off, rem, state);
538 
539           /* demultiplex the control request */
540 
541           switch (req.bmRequestType) {
542           case UT_READ_DEVICE:
543                     if (state != USB_HR_NOT_COMPLETE) {
544                               break;
545                     }
546                     switch (req.bRequest) {
547                     case UR_GET_DESCRIPTOR:
548                               goto tr_handle_get_descriptor;
549                     case UR_GET_CONFIG:
550                               goto tr_handle_get_config;
551                     case UR_GET_STATUS:
552                               goto tr_handle_get_status;
553                     default:
554                               goto tr_stalled;
555                     }
556                     break;
557 
558           case UT_WRITE_DEVICE:
559                     switch (req.bRequest) {
560                     case UR_SET_ADDRESS:
561                               goto tr_handle_set_address;
562                     case UR_SET_CONFIG:
563                               goto tr_handle_set_config;
564                     case UR_CLEAR_FEATURE:
565                               switch (wValue) {
566                               case UF_DEVICE_REMOTE_WAKEUP:
567                                         goto tr_handle_clear_wakeup;
568                               default:
569                                         goto tr_stalled;
570                               }
571                               break;
572                     case UR_SET_FEATURE:
573                               switch (wValue) {
574                               case UF_DEVICE_REMOTE_WAKEUP:
575                                         goto tr_handle_set_wakeup;
576                               default:
577                                         goto tr_stalled;
578                               }
579                               break;
580                     default:
581                               goto tr_stalled;
582                     }
583                     break;
584 
585           case UT_WRITE_ENDPOINT:
586                     switch (req.bRequest) {
587                     case UR_CLEAR_FEATURE:
588                               switch (wValue) {
589                               case UF_ENDPOINT_HALT:
590                                         goto tr_handle_clear_halt;
591                               default:
592                                         goto tr_stalled;
593                               }
594                               break;
595                     case UR_SET_FEATURE:
596                               switch (wValue) {
597                               case UF_ENDPOINT_HALT:
598                                         goto tr_handle_set_halt;
599                               default:
600                                         goto tr_stalled;
601                               }
602                               break;
603                     default:
604                               goto tr_stalled;
605                     }
606                     break;
607 
608           case UT_READ_ENDPOINT:
609                     switch (req.bRequest) {
610                     case UR_GET_STATUS:
611                               goto tr_handle_get_ep_status;
612                     default:
613                               goto tr_stalled;
614                     }
615                     break;
616           default:
617                     /* we use "USB_ADD_BYTES" to de-const the src_zcopy */
618                     err = usb_handle_iface_request(xfer,
619                         USB_ADD_BYTES(&src_zcopy, 0),
620                         &max_len, req, off, state);
621                     if (err == 0) {
622                               is_complete = 0;
623                               goto tr_valid;
624                     } else if (err == USB_ERR_SHORT_XFER) {
625                               goto tr_valid;
626                     }
627                     /*
628                      * Reset zero-copy pointer and max length
629                      * variable in case they were unintentionally
630                      * set:
631                      */
632                     src_zcopy = NULL;
633                     max_len = 0;
634 
635                     /*
636                      * Check if we have a vendor specific
637                      * descriptor:
638                      */
639                     goto tr_handle_get_descriptor;
640           }
641           goto tr_valid;
642 
643 tr_handle_get_descriptor:
644           err = (usb_temp_get_desc_p) (udev, &req, &src_zcopy, &max_len);
645           if (err)
646                     goto tr_stalled;
647           if (src_zcopy == NULL)
648                     goto tr_stalled;
649           goto tr_valid;
650 
651 tr_handle_get_config:
652           temp.buf[0] = udev->curr_config_no;
653           src_mcopy = temp.buf;
654           max_len = 1;
655           goto tr_valid;
656 
657 tr_handle_get_status:
658 
659           wValue = 0;
660 
661           USB_BUS_LOCK(udev->bus);
662           if (udev->flags.remote_wakeup) {
663                     wValue |= UDS_REMOTE_WAKEUP;
664           }
665           if (udev->flags.self_powered) {
666                     wValue |= UDS_SELF_POWERED;
667           }
668           USB_BUS_UNLOCK(udev->bus);
669 
670           USETW(temp.wStatus, wValue);
671           src_mcopy = temp.wStatus;
672           max_len = sizeof(temp.wStatus);
673           goto tr_valid;
674 
675 tr_handle_set_address:
676           if (state == USB_HR_NOT_COMPLETE) {
677                     if (wValue >= 0x80) {
678                               /* invalid value */
679                               goto tr_stalled;
680                     } else if (udev->curr_config_no != 0) {
681                               /* we are configured ! */
682                               goto tr_stalled;
683                     }
684           } else if (state != USB_HR_NOT_COMPLETE) {
685                     udev->address = (wValue & 0x7F);
686                     goto tr_bad_context;
687           }
688           goto tr_valid;
689 
690 tr_handle_set_config:
691           if (state == USB_HR_NOT_COMPLETE) {
692                     if (usb_handle_set_config(xfer, req.wValue[0])) {
693                               goto tr_stalled;
694                     }
695           }
696           goto tr_valid;
697 
698 tr_handle_clear_halt:
699           if (state == USB_HR_NOT_COMPLETE) {
700                     if (usb_handle_set_stall(xfer, req.wIndex[0], 0)) {
701                               goto tr_stalled;
702                     }
703           }
704           goto tr_valid;
705 
706 tr_handle_clear_wakeup:
707           if (state == USB_HR_NOT_COMPLETE) {
708                     if (usb_handle_remote_wakeup(xfer, 0)) {
709                               goto tr_stalled;
710                     }
711           }
712           goto tr_valid;
713 
714 tr_handle_set_halt:
715           if (state == USB_HR_NOT_COMPLETE) {
716                     if (usb_handle_set_stall(xfer, req.wIndex[0], 1)) {
717                               goto tr_stalled;
718                     }
719           }
720           goto tr_valid;
721 
722 tr_handle_set_wakeup:
723           if (state == USB_HR_NOT_COMPLETE) {
724                     if (usb_handle_remote_wakeup(xfer, 1)) {
725                               goto tr_stalled;
726                     }
727           }
728           goto tr_valid;
729 
730 tr_handle_get_ep_status:
731           if (state == USB_HR_NOT_COMPLETE) {
732                     temp.wStatus[0] =
733                         usb_handle_get_stall(udev, req.wIndex[0]);
734                     temp.wStatus[1] = 0;
735                     src_mcopy = temp.wStatus;
736                     max_len = sizeof(temp.wStatus);
737           }
738           goto tr_valid;
739 
740 tr_valid:
741           if (state != USB_HR_NOT_COMPLETE) {
742                     goto tr_stalled;
743           }
744           /* subtract offset from length */
745 
746           max_len -= off;
747 
748           /* Compute the real maximum data length */
749 
750           if (max_len > xfer->max_data_length) {
751                     max_len = usbd_xfer_max_len(xfer);
752           }
753           if (max_len > rem) {
754                     max_len = rem;
755           }
756           /*
757            * If the remainder is greater than the maximum data length,
758            * we need to truncate the value for the sake of the
759            * comparison below:
760            */
761           if (rem > xfer->max_data_length) {
762                     rem = usbd_xfer_max_len(xfer);
763           }
764           if ((rem != max_len) && (is_complete != 0)) {
765                     /*
766                    * If we don't transfer the data we can transfer, then
767                    * the transfer is short !
768                    */
769                     xfer->flags.force_short_xfer = 1;
770                     xfer->nframes = 2;
771           } else {
772                     /*
773                      * Default case
774                      */
775                     xfer->flags.force_short_xfer = 0;
776                     xfer->nframes = max_len ? 2 : 1;
777           }
778           if (max_len > 0) {
779                     if (src_mcopy) {
780                               src_mcopy = USB_ADD_BYTES(src_mcopy, off);
781                               usbd_copy_in(xfer->frbuffers + 1, 0,
782                                   src_mcopy, max_len);
783                               usbd_xfer_set_frame_len(xfer, 1, max_len);
784                     } else {
785                               usbd_xfer_set_frame_data(xfer, 1,
786                                   USB_ADD_BYTES(src_zcopy, off), max_len);
787                     }
788           } else {
789                     /* the end is reached, send status */
790                     xfer->flags.manual_status = 0;
791                     usbd_xfer_set_frame_len(xfer, 1, 0);
792           }
793           DPRINTF("success\n");
794           return (0);                             /* success */
795 
796 tr_stalled:
797           DPRINTF("%s\n", (state != USB_HR_NOT_COMPLETE) ?
798               "complete" : "stalled");
799           return (USB_ERR_STALLED);
800 
801 tr_bad_context:
802           DPRINTF("bad context\n");
803           return (USB_ERR_BAD_CONTEXT);
804 }
805