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