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