]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/dev/usb/usb_handle_request.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.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
156         usbd_enum_lock(udev);
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         usbd_enum_unlock(udev);
180         USB_XFER_LOCK(xfer);
181         return (err);
182 }
183
184 static usb_error_t
185 usb_check_alt_setting(struct usb_device *udev, 
186      struct usb_interface *iface, uint8_t alt_index)
187 {
188         uint8_t do_unlock;
189         usb_error_t err = 0;
190
191         /* automatic locking */
192         if (usbd_enum_is_locked(udev)) {
193                 do_unlock = 0;
194         } else {
195                 do_unlock = 1;
196                 usbd_enum_lock(udev);
197         }
198
199         if (alt_index >= usbd_get_no_alts(udev->cdesc, iface->idesc))
200                 err = USB_ERR_INVAL;
201
202         if (do_unlock)
203                 usbd_enum_unlock(udev);
204
205         return (err);
206 }
207
208 /*------------------------------------------------------------------------*
209  *      usb_handle_iface_request
210  *
211  * Returns:
212  *    0: Success
213  * Else: Failure
214  *------------------------------------------------------------------------*/
215 static usb_error_t
216 usb_handle_iface_request(struct usb_xfer *xfer,
217     void **ppdata, uint16_t *plen,
218     struct usb_device_request req, uint16_t off, uint8_t state)
219 {
220         struct usb_interface *iface;
221         struct usb_interface *iface_parent;     /* parent interface */
222         struct usb_device *udev = xfer->xroot->udev;
223         int error;
224         uint8_t iface_index;
225         uint8_t temp_state;
226
227         if ((req.bmRequestType & 0x1F) == UT_INTERFACE) {
228                 iface_index = req.wIndex[0];    /* unicast */
229         } else {
230                 iface_index = 0;        /* broadcast */
231         }
232
233         /*
234          * We need to protect against other threads doing probe and
235          * attach:
236          */
237         USB_XFER_UNLOCK(xfer);
238
239         usbd_enum_lock(udev);
240
241         error = ENXIO;
242
243 tr_repeat:
244         iface = usbd_get_iface(udev, iface_index);
245         if ((iface == NULL) ||
246             (iface->idesc == NULL)) {
247                 /* end of interfaces non-existing interface */
248                 goto tr_stalled;
249         }
250         /* set initial state */
251
252         temp_state = state;
253
254         /* forward request to interface, if any */
255
256         if ((error != 0) &&
257             (error != ENOTTY) &&
258             (iface->subdev != NULL) &&
259             device_is_attached(iface->subdev)) {
260 #if 0
261                 DEVMETHOD(usb_handle_request, NULL);    /* dummy */
262 #endif
263                 error = USB_HANDLE_REQUEST(iface->subdev,
264                     &req, ppdata, plen,
265                     off, &temp_state);
266         }
267         iface_parent = usbd_get_iface(udev, iface->parent_iface_index);
268
269         if ((iface_parent == NULL) ||
270             (iface_parent->idesc == NULL)) {
271                 /* non-existing interface */
272                 iface_parent = NULL;
273         }
274         /* forward request to parent interface, if any */
275
276         if ((error != 0) &&
277             (error != ENOTTY) &&
278             (iface_parent != NULL) &&
279             (iface_parent->subdev != NULL) &&
280             ((req.bmRequestType & 0x1F) == UT_INTERFACE) &&
281             (iface_parent->subdev != iface->subdev) &&
282             device_is_attached(iface_parent->subdev)) {
283                 error = USB_HANDLE_REQUEST(iface_parent->subdev,
284                     &req, ppdata, plen, off, &temp_state);
285         }
286         if (error == 0) {
287                 /* negativly adjust pointer and length */
288                 *ppdata = ((uint8_t *)(*ppdata)) - off;
289                 *plen += off;
290
291                 if ((state == USB_HR_NOT_COMPLETE) &&
292                     (temp_state == USB_HR_COMPLETE_OK))
293                         goto tr_short;
294                 else
295                         goto tr_valid;
296         } else if (error == ENOTTY) {
297                 goto tr_stalled;
298         }
299         if ((req.bmRequestType & 0x1F) != UT_INTERFACE) {
300                 iface_index++;          /* iterate */
301                 goto tr_repeat;
302         }
303         if (state != USB_HR_NOT_COMPLETE) {
304                 /* we are complete */
305                 goto tr_valid;
306         }
307         switch (req.bmRequestType) {
308         case UT_WRITE_INTERFACE:
309                 switch (req.bRequest) {
310                 case UR_SET_INTERFACE:
311                         /*
312                          * We assume that the endpoints are the same
313                          * accross the alternate settings.
314                          *
315                          * Reset the endpoints, because re-attaching
316                          * only a part of the device is not possible.
317                          */
318                         error = usb_check_alt_setting(udev,
319                             iface, req.wValue[0]);
320                         if (error) {
321                                 DPRINTF("alt setting does not exist %s\n",
322                                     usbd_errstr(error));
323                                 goto tr_stalled;
324                         }
325                         error = usb_reset_iface_endpoints(udev, iface_index);
326                         if (error) {
327                                 DPRINTF("alt setting failed %s\n",
328                                     usbd_errstr(error));
329                                 goto tr_stalled;
330                         }
331                         /* update the current alternate setting */
332                         iface->alt_index = req.wValue[0];
333                         break;
334
335                 default:
336                         goto tr_stalled;
337                 }
338                 break;
339
340         case UT_READ_INTERFACE:
341                 switch (req.bRequest) {
342                 case UR_GET_INTERFACE:
343                         *ppdata = &iface->alt_index;
344                         *plen = 1;
345                         break;
346
347                 default:
348                         goto tr_stalled;
349                 }
350                 break;
351         default:
352                 goto tr_stalled;
353         }
354 tr_valid:
355         usbd_enum_unlock(udev);
356         USB_XFER_LOCK(xfer);
357         return (0);
358
359 tr_short:
360         usbd_enum_unlock(udev);
361         USB_XFER_LOCK(xfer);
362         return (USB_ERR_SHORT_XFER);
363
364 tr_stalled:
365         usbd_enum_unlock(udev);
366         USB_XFER_LOCK(xfer);
367         return (USB_ERR_STALLED);
368 }
369
370 /*------------------------------------------------------------------------*
371  *      usb_handle_stall
372  *
373  * Returns:
374  *    0: Success
375  * Else: Failure
376  *------------------------------------------------------------------------*/
377 static usb_error_t
378 usb_handle_set_stall(struct usb_xfer *xfer, uint8_t ep, uint8_t do_stall)
379 {
380         struct usb_device *udev = xfer->xroot->udev;
381         usb_error_t err;
382
383         USB_XFER_UNLOCK(xfer);
384         err = usbd_set_endpoint_stall(udev,
385             usbd_get_ep_by_addr(udev, ep), do_stall);
386         USB_XFER_LOCK(xfer);
387         return (err);
388 }
389
390 /*------------------------------------------------------------------------*
391  *      usb_handle_get_stall
392  *
393  * Returns:
394  *    0: Success
395  * Else: Failure
396  *------------------------------------------------------------------------*/
397 static uint8_t
398 usb_handle_get_stall(struct usb_device *udev, uint8_t ea_val)
399 {
400         struct usb_endpoint *ep;
401         uint8_t halted;
402
403         ep = usbd_get_ep_by_addr(udev, ea_val);
404         if (ep == NULL) {
405                 /* nothing to do */
406                 return (0);
407         }
408         USB_BUS_LOCK(udev->bus);
409         halted = ep->is_stalled;
410         USB_BUS_UNLOCK(udev->bus);
411
412         return (halted);
413 }
414
415 /*------------------------------------------------------------------------*
416  *      usb_handle_remote_wakeup
417  *
418  * Returns:
419  *    0: Success
420  * Else: Failure
421  *------------------------------------------------------------------------*/
422 static usb_error_t
423 usb_handle_remote_wakeup(struct usb_xfer *xfer, uint8_t is_on)
424 {
425         struct usb_device *udev;
426         struct usb_bus *bus;
427
428         udev = xfer->xroot->udev;
429         bus = udev->bus;
430
431         USB_BUS_LOCK(bus);
432
433         if (is_on) {
434                 udev->flags.remote_wakeup = 1;
435         } else {
436                 udev->flags.remote_wakeup = 0;
437         }
438
439         USB_BUS_UNLOCK(bus);
440
441         /* In case we are out of sync, update the power state. */
442         usb_bus_power_update(udev->bus);
443         return (0);                     /* success */
444 }
445
446 /*------------------------------------------------------------------------*
447  *      usb_handle_request
448  *
449  * Internal state sequence:
450  *
451  * USB_HR_NOT_COMPLETE -> USB_HR_COMPLETE_OK v USB_HR_COMPLETE_ERR
452  *
453  * Returns:
454  * 0: Ready to start hardware
455  * Else: Stall current transfer, if any
456  *------------------------------------------------------------------------*/
457 static usb_error_t
458 usb_handle_request(struct usb_xfer *xfer)
459 {
460         struct usb_device_request req;
461         struct usb_device *udev;
462         const void *src_zcopy;          /* zero-copy source pointer */
463         const void *src_mcopy;          /* non zero-copy source pointer */
464         uint16_t off;                   /* data offset */
465         uint16_t rem;                   /* data remainder */
466         uint16_t max_len;               /* max fragment length */
467         uint16_t wValue;
468         uint16_t wIndex;
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         wIndex = UGETW(req.wIndex);
535
536         DPRINTF("req 0x%02x 0x%02x 0x%04x 0x%04x "
537             "off=0x%x rem=0x%x, state=%d\n", req.bmRequestType,
538             req.bRequest, wValue, wIndex, off, rem, state);
539
540         /* demultiplex the control request */
541
542         switch (req.bmRequestType) {
543         case UT_READ_DEVICE:
544                 if (state != USB_HR_NOT_COMPLETE) {
545                         break;
546                 }
547                 switch (req.bRequest) {
548                 case UR_GET_DESCRIPTOR:
549                         goto tr_handle_get_descriptor;
550                 case UR_GET_CONFIG:
551                         goto tr_handle_get_config;
552                 case UR_GET_STATUS:
553                         goto tr_handle_get_status;
554                 default:
555                         goto tr_stalled;
556                 }
557                 break;
558
559         case UT_WRITE_DEVICE:
560                 switch (req.bRequest) {
561                 case UR_SET_ADDRESS:
562                         goto tr_handle_set_address;
563                 case UR_SET_CONFIG:
564                         goto tr_handle_set_config;
565                 case UR_CLEAR_FEATURE:
566                         switch (wValue) {
567                         case UF_DEVICE_REMOTE_WAKEUP:
568                                 goto tr_handle_clear_wakeup;
569                         default:
570                                 goto tr_stalled;
571                         }
572                         break;
573                 case UR_SET_FEATURE:
574                         switch (wValue) {
575                         case UF_DEVICE_REMOTE_WAKEUP:
576                                 goto tr_handle_set_wakeup;
577                         default:
578                                 goto tr_stalled;
579                         }
580                         break;
581                 default:
582                         goto tr_stalled;
583                 }
584                 break;
585
586         case UT_WRITE_ENDPOINT:
587                 switch (req.bRequest) {
588                 case UR_CLEAR_FEATURE:
589                         switch (wValue) {
590                         case UF_ENDPOINT_HALT:
591                                 goto tr_handle_clear_halt;
592                         default:
593                                 goto tr_stalled;
594                         }
595                         break;
596                 case UR_SET_FEATURE:
597                         switch (wValue) {
598                         case UF_ENDPOINT_HALT:
599                                 goto tr_handle_set_halt;
600                         default:
601                                 goto tr_stalled;
602                         }
603                         break;
604                 default:
605                         goto tr_stalled;
606                 }
607                 break;
608
609         case UT_READ_ENDPOINT:
610                 switch (req.bRequest) {
611                 case UR_GET_STATUS:
612                         goto tr_handle_get_ep_status;
613                 default:
614                         goto tr_stalled;
615                 }
616                 break;
617         default:
618                 /* we use "USB_ADD_BYTES" to de-const the src_zcopy */
619                 err = usb_handle_iface_request(xfer,
620                     USB_ADD_BYTES(&src_zcopy, 0),
621                     &max_len, req, off, state);
622                 if (err == 0) {
623                         is_complete = 0;
624                         goto tr_valid;
625                 } else if (err == USB_ERR_SHORT_XFER) {
626                         goto tr_valid;
627                 }
628                 /*
629                  * Reset zero-copy pointer and max length
630                  * variable in case they were unintentionally
631                  * set:
632                  */
633                 src_zcopy = NULL;
634                 max_len = 0;
635
636                 /*
637                  * Check if we have a vendor specific
638                  * descriptor:
639                  */
640                 goto tr_handle_get_descriptor;
641         }
642         goto tr_valid;
643
644 tr_handle_get_descriptor:
645         err = (usb_temp_get_desc_p) (udev, &req, &src_zcopy, &max_len);
646         if (err)
647                 goto tr_stalled;
648         if (src_zcopy == NULL)
649                 goto tr_stalled;
650         goto tr_valid;
651
652 tr_handle_get_config:
653         temp.buf[0] = udev->curr_config_no;
654         src_mcopy = temp.buf;
655         max_len = 1;
656         goto tr_valid;
657
658 tr_handle_get_status:
659
660         wValue = 0;
661
662         USB_BUS_LOCK(udev->bus);
663         if (udev->flags.remote_wakeup) {
664                 wValue |= UDS_REMOTE_WAKEUP;
665         }
666         if (udev->flags.self_powered) {
667                 wValue |= UDS_SELF_POWERED;
668         }
669         USB_BUS_UNLOCK(udev->bus);
670
671         USETW(temp.wStatus, wValue);
672         src_mcopy = temp.wStatus;
673         max_len = sizeof(temp.wStatus);
674         goto tr_valid;
675
676 tr_handle_set_address:
677         if (state == USB_HR_NOT_COMPLETE) {
678                 if (wValue >= 0x80) {
679                         /* invalid value */
680                         goto tr_stalled;
681                 } else if (udev->curr_config_no != 0) {
682                         /* we are configured ! */
683                         goto tr_stalled;
684                 }
685         } else if (state != USB_HR_NOT_COMPLETE) {
686                 udev->address = (wValue & 0x7F);
687                 goto tr_bad_context;
688         }
689         goto tr_valid;
690
691 tr_handle_set_config:
692         if (state == USB_HR_NOT_COMPLETE) {
693                 if (usb_handle_set_config(xfer, req.wValue[0])) {
694                         goto tr_stalled;
695                 }
696         }
697         goto tr_valid;
698
699 tr_handle_clear_halt:
700         if (state == USB_HR_NOT_COMPLETE) {
701                 if (usb_handle_set_stall(xfer, req.wIndex[0], 0)) {
702                         goto tr_stalled;
703                 }
704         }
705         goto tr_valid;
706
707 tr_handle_clear_wakeup:
708         if (state == USB_HR_NOT_COMPLETE) {
709                 if (usb_handle_remote_wakeup(xfer, 0)) {
710                         goto tr_stalled;
711                 }
712         }
713         goto tr_valid;
714
715 tr_handle_set_halt:
716         if (state == USB_HR_NOT_COMPLETE) {
717                 if (usb_handle_set_stall(xfer, req.wIndex[0], 1)) {
718                         goto tr_stalled;
719                 }
720         }
721         goto tr_valid;
722
723 tr_handle_set_wakeup:
724         if (state == USB_HR_NOT_COMPLETE) {
725                 if (usb_handle_remote_wakeup(xfer, 1)) {
726                         goto tr_stalled;
727                 }
728         }
729         goto tr_valid;
730
731 tr_handle_get_ep_status:
732         if (state == USB_HR_NOT_COMPLETE) {
733                 temp.wStatus[0] =
734                     usb_handle_get_stall(udev, req.wIndex[0]);
735                 temp.wStatus[1] = 0;
736                 src_mcopy = temp.wStatus;
737                 max_len = sizeof(temp.wStatus);
738         }
739         goto tr_valid;
740
741 tr_valid:
742         if (state != USB_HR_NOT_COMPLETE) {
743                 goto tr_stalled;
744         }
745         /* subtract offset from length */
746
747         max_len -= off;
748
749         /* Compute the real maximum data length */
750
751         if (max_len > xfer->max_data_length) {
752                 max_len = usbd_xfer_max_len(xfer);
753         }
754         if (max_len > rem) {
755                 max_len = rem;
756         }
757         /*
758          * If the remainder is greater than the maximum data length,
759          * we need to truncate the value for the sake of the
760          * comparison below:
761          */
762         if (rem > xfer->max_data_length) {
763                 rem = usbd_xfer_max_len(xfer);
764         }
765         if ((rem != max_len) && (is_complete != 0)) {
766                 /*
767                  * If we don't transfer the data we can transfer, then
768                  * the transfer is short !
769                  */
770                 xfer->flags.force_short_xfer = 1;
771                 xfer->nframes = 2;
772         } else {
773                 /*
774                  * Default case
775                  */
776                 xfer->flags.force_short_xfer = 0;
777                 xfer->nframes = max_len ? 2 : 1;
778         }
779         if (max_len > 0) {
780                 if (src_mcopy) {
781                         src_mcopy = USB_ADD_BYTES(src_mcopy, off);
782                         usbd_copy_in(xfer->frbuffers + 1, 0,
783                             src_mcopy, max_len);
784                         usbd_xfer_set_frame_len(xfer, 1, max_len);
785                 } else {
786                         usbd_xfer_set_frame_data(xfer, 1,
787                             USB_ADD_BYTES(src_zcopy, off), max_len);
788                 }
789         } else {
790                 /* the end is reached, send status */
791                 xfer->flags.manual_status = 0;
792                 usbd_xfer_set_frame_len(xfer, 1, 0);
793         }
794         DPRINTF("success\n");
795         return (0);                     /* success */
796
797 tr_stalled:
798         DPRINTF("%s\n", (state != USB_HR_NOT_COMPLETE) ?
799             "complete" : "stalled");
800         return (USB_ERR_STALLED);
801
802 tr_bad_context:
803         DPRINTF("bad context\n");
804         return (USB_ERR_BAD_CONTEXT);
805 }