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