Merge branch 'vendor/LIBPCAP'
[dragonfly.git] / sys / bus / u4b / 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/param.h>
29 #include <sys/queue.h>
30 #include <sys/types.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/bus.h>
34 #include <sys/module.h>
35 #include <sys/lock.h>
36 #include <sys/mutex.h>
37 #include <sys/condvar.h>
38 #include <sys/sysctl.h>
39 #include <sys/unistd.h>
40 #include <sys/callout.h>
41 #include <sys/malloc.h>
42 #include <sys/priv.h>
43
44 #include <bus/u4b/usb.h>
45 #include <bus/u4b/usbdi.h>
46 #include <bus/u4b/usbdi_util.h>
47 #include "usb_if.h"
48
49 #define USB_DEBUG_VAR usb_debug
50
51 #include <bus/u4b/usb_core.h>
52 #include <bus/u4b/usb_process.h>
53 #include <bus/u4b/usb_busdma.h>
54 #include <bus/u4b/usb_transfer.h>
55 #include <bus/u4b/usb_device.h>
56 #include <bus/u4b/usb_debug.h>
57 #include <bus/u4b/usb_dynamic.h>
58 #include <bus/u4b/usb_hub.h>
59
60 #include <bus/u4b/usb_controller.h>
61 #include <bus/u4b/usb_bus.h>
62
63 /* function prototypes */
64
65 static uint8_t usb_handle_get_stall(struct usb_device *, uint8_t);
66 static usb_error_t       usb_handle_remote_wakeup(struct usb_xfer *, uint8_t);
67 static usb_error_t       usb_handle_request(struct usb_xfer *);
68 static usb_error_t       usb_handle_set_config(struct usb_xfer *, uint8_t);
69 static usb_error_t       usb_handle_set_stall(struct usb_xfer *, uint8_t,
70                             uint8_t);
71 static usb_error_t       usb_handle_iface_request(struct usb_xfer *, void **,
72                             uint16_t *, struct usb_device_request, uint16_t,
73                             uint8_t);
74
75 /*------------------------------------------------------------------------*
76  *      usb_handle_request_callback
77  *
78  * This function is the USB callback for generic USB Device control
79  * transfers.
80  *------------------------------------------------------------------------*/
81 void
82 usb_handle_request_callback(struct usb_xfer *xfer, usb_error_t error)
83 {
84         usb_error_t err;
85
86         /* check the current transfer state */
87
88         switch (USB_GET_STATE(xfer)) {
89         case USB_ST_SETUP:
90         case USB_ST_TRANSFERRED:
91
92                 /* handle the request */
93                 err = usb_handle_request(xfer);
94
95                 if (err) {
96
97                         if (err == USB_ERR_BAD_CONTEXT) {
98                                 /* we need to re-setup the control transfer */
99                                 usb_needs_explore(xfer->xroot->bus, 0);
100                                 break;
101                         }
102                         goto tr_restart;
103                 }
104                 usbd_transfer_submit(xfer);
105                 break;
106
107         default:
108                 /* check if a control transfer is active */
109                 if (xfer->flags_int.control_rem != 0xFFFF) {
110                         /* handle the request */
111                         err = usb_handle_request(xfer);
112                 }
113                 if (xfer->error != USB_ERR_CANCELLED) {
114                         /* should not happen - try stalling */
115                         goto tr_restart;
116                 }
117                 break;
118         }
119         return;
120
121 tr_restart:
122         /*
123          * If a control transfer is active, stall it, and wait for the
124          * next control transfer.
125          */
126         usbd_xfer_set_frame_len(xfer, 0, sizeof(struct usb_device_request));
127         xfer->nframes = 1;
128         xfer->flags.manual_status = 1;
129         xfer->flags.force_short_xfer = 0;
130         usbd_xfer_set_stall(xfer);      /* cancel previous transfer, if any */
131         usbd_transfer_submit(xfer);
132 }
133
134 /*------------------------------------------------------------------------*
135  *      usb_handle_set_config
136  *
137  * Returns:
138  *    0: Success
139  * Else: Failure
140  *------------------------------------------------------------------------*/
141 static usb_error_t
142 usb_handle_set_config(struct usb_xfer *xfer, uint8_t conf_no)
143 {
144         struct usb_device *udev = xfer->xroot->udev;
145         usb_error_t err = 0;
146         uint8_t do_unlock;
147
148         /*
149          * We need to protect against other threads doing probe and
150          * attach:
151          */
152         USB_XFER_UNLOCK(xfer);
153
154         /* Prevent re-enumeration */
155         do_unlock = usbd_enum_lock(udev);
156
157         if (conf_no == USB_UNCONFIG_NO) {
158                 conf_no = USB_UNCONFIG_INDEX;
159         } else {
160                 /*
161                  * The relationship between config number and config index
162                  * is very simple in our case:
163                  */
164                 conf_no--;
165         }
166
167         if (usbd_set_config_index(udev, conf_no)) {
168                 DPRINTF("set config %d failed\n", conf_no);
169                 err = USB_ERR_STALLED;
170                 goto done;
171         }
172         if (usb_probe_and_attach(udev, USB_IFACE_INDEX_ANY)) {
173                 DPRINTF("probe and attach failed\n");
174                 err = USB_ERR_STALLED;
175                 goto done;
176         }
177 done:
178         if (do_unlock)
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         /* Prevent re-enumeration */
192         do_unlock = usbd_enum_lock(udev);
193
194         if (alt_index >= usbd_get_no_alts(udev->cdesc, iface->idesc))
195                 err = USB_ERR_INVAL;
196
197         if (do_unlock)
198                 usbd_enum_unlock(udev);
199
200         return (err);
201 }
202
203 /*------------------------------------------------------------------------*
204  *      usb_handle_iface_request
205  *
206  * Returns:
207  *    0: Success
208  * Else: Failure
209  *------------------------------------------------------------------------*/
210 static usb_error_t
211 usb_handle_iface_request(struct usb_xfer *xfer,
212     void **ppdata, uint16_t *plen,
213     struct usb_device_request req, uint16_t off, uint8_t state)
214 {
215         struct usb_interface *iface;
216         struct usb_interface *iface_parent;     /* parent interface */
217         struct usb_device *udev = xfer->xroot->udev;
218         int error;
219         uint8_t iface_index;
220         uint8_t temp_state;
221         uint8_t do_unlock;
222
223         if ((req.bmRequestType & 0x1F) == UT_INTERFACE) {
224                 iface_index = req.wIndex[0];    /* unicast */
225         } else {
226                 iface_index = 0;        /* broadcast */
227         }
228
229         /*
230          * We need to protect against other threads doing probe and
231          * attach:
232          */
233         USB_XFER_UNLOCK(xfer);
234
235         /* Prevent re-enumeration */
236         do_unlock = usbd_enum_lock(udev);
237
238         error = ENXIO;
239
240 tr_repeat:
241         iface = usbd_get_iface(udev, iface_index);
242         if ((iface == NULL) ||
243             (iface->idesc == NULL)) {
244                 /* end of interfaces non-existing interface */
245                 goto tr_stalled;
246         }
247         /* set initial state */
248
249         temp_state = state;
250
251         /* forward request to interface, if any */
252
253         if ((error != 0) &&
254             (error != ENOTTY) &&
255             (iface->subdev != NULL) &&
256             device_is_attached(iface->subdev)) {
257 #if 0
258                 DEVMETHOD(usb_handle_request, NULL);    /* dummy */
259 #endif
260                 error = USB_HANDLE_REQUEST(iface->subdev,
261                     &req, ppdata, plen,
262                     off, &temp_state);
263         }
264         iface_parent = usbd_get_iface(udev, iface->parent_iface_index);
265
266         if ((iface_parent == NULL) ||
267             (iface_parent->idesc == NULL)) {
268                 /* non-existing interface */
269                 iface_parent = NULL;
270         }
271         /* forward request to parent interface, if any */
272
273         if ((error != 0) &&
274             (error != ENOTTY) &&
275             (iface_parent != NULL) &&
276             (iface_parent->subdev != NULL) &&
277             ((req.bmRequestType & 0x1F) == UT_INTERFACE) &&
278             (iface_parent->subdev != iface->subdev) &&
279             device_is_attached(iface_parent->subdev)) {
280                 error = USB_HANDLE_REQUEST(iface_parent->subdev,
281                     &req, ppdata, plen, off, &temp_state);
282         }
283         if (error == 0) {
284                 /* negativly adjust pointer and length */
285                 *ppdata = ((uint8_t *)(*ppdata)) - off;
286                 *plen += off;
287
288                 if ((state == USB_HR_NOT_COMPLETE) &&
289                     (temp_state == USB_HR_COMPLETE_OK))
290                         goto tr_short;
291                 else
292                         goto tr_valid;
293         } else if (error == ENOTTY) {
294                 goto tr_stalled;
295         }
296         if ((req.bmRequestType & 0x1F) != UT_INTERFACE) {
297                 iface_index++;          /* iterate */
298                 goto tr_repeat;
299         }
300         if (state != USB_HR_NOT_COMPLETE) {
301                 /* we are complete */
302                 goto tr_valid;
303         }
304         switch (req.bmRequestType) {
305         case UT_WRITE_INTERFACE:
306                 switch (req.bRequest) {
307                 case UR_SET_INTERFACE:
308                         /*
309                          * We assume that the endpoints are the same
310                          * accross the alternate settings.
311                          *
312                          * Reset the endpoints, because re-attaching
313                          * only a part of the device is not possible.
314                          */
315                         error = usb_check_alt_setting(udev,
316                             iface, req.wValue[0]);
317                         if (error) {
318                                 DPRINTF("alt setting does not exist %s\n",
319                                     usbd_errstr(error));
320                                 goto tr_stalled;
321                         }
322                         error = usb_reset_iface_endpoints(udev, iface_index);
323                         if (error) {
324                                 DPRINTF("alt setting failed %s\n",
325                                     usbd_errstr(error));
326                                 goto tr_stalled;
327                         }
328                         /* update the current alternate setting */
329                         iface->alt_index = req.wValue[0];
330                         break;
331
332                 default:
333                         goto tr_stalled;
334                 }
335                 break;
336
337         case UT_READ_INTERFACE:
338                 switch (req.bRequest) {
339                 case UR_GET_INTERFACE:
340                         *ppdata = &iface->alt_index;
341                         *plen = 1;
342                         break;
343
344                 default:
345                         goto tr_stalled;
346                 }
347                 break;
348         default:
349                 goto tr_stalled;
350         }
351 tr_valid:
352         if (do_unlock)
353                 usbd_enum_unlock(udev);
354         USB_XFER_LOCK(xfer);
355         return (0);
356
357 tr_short:
358         if (do_unlock)
359                 usbd_enum_unlock(udev);
360         USB_XFER_LOCK(xfer);
361         return (USB_ERR_SHORT_XFER);
362
363 tr_stalled:
364         if (do_unlock)
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 #if USB_HAVE_POWERD
442         /* In case we are out of sync, update the power state. */
443         usb_bus_power_update(udev->bus);
444 #endif
445         return (0);                     /* success */
446 }
447
448 /*------------------------------------------------------------------------*
449  *      usb_handle_request
450  *
451  * Internal state sequence:
452  *
453  * USB_HR_NOT_COMPLETE -> USB_HR_COMPLETE_OK v USB_HR_COMPLETE_ERR
454  *
455  * Returns:
456  * 0: Ready to start hardware
457  * Else: Stall current transfer, if any
458  *------------------------------------------------------------------------*/
459 static usb_error_t
460 usb_handle_request(struct usb_xfer *xfer)
461 {
462         struct usb_device_request req;
463         struct usb_device *udev;
464         const void *src_zcopy;          /* zero-copy source pointer */
465         const void *src_mcopy;          /* non zero-copy source pointer */
466         uint16_t off;                   /* data offset */
467         uint16_t rem;                   /* data remainder */
468         uint16_t max_len;               /* max fragment length */
469         uint16_t wValue;
470         uint8_t state;
471         uint8_t is_complete = 1;
472         usb_error_t err;
473         union {
474                 uWord   wStatus;
475                 uint8_t buf[2];
476         }     temp;
477
478         /*
479          * Filter the USB transfer state into
480          * something which we understand:
481          */
482
483         switch (USB_GET_STATE(xfer)) {
484         case USB_ST_SETUP:
485                 state = USB_HR_NOT_COMPLETE;
486
487                 if (!xfer->flags_int.control_act) {
488                         /* nothing to do */
489                         goto tr_stalled;
490                 }
491                 break;
492         case USB_ST_TRANSFERRED:
493                 if (!xfer->flags_int.control_act) {
494                         state = USB_HR_COMPLETE_OK;
495                 } else {
496                         state = USB_HR_NOT_COMPLETE;
497                 }
498                 break;
499         default:
500                 state = USB_HR_COMPLETE_ERR;
501                 break;
502         }
503
504         /* reset frame stuff */
505
506         usbd_xfer_set_frame_len(xfer, 0, 0);
507
508         usbd_xfer_set_frame_offset(xfer, 0, 0);
509         usbd_xfer_set_frame_offset(xfer, sizeof(req), 1);
510
511         /* get the current request, if any */
512
513         usbd_copy_out(xfer->frbuffers, 0, &req, sizeof(req));
514
515         if (xfer->flags_int.control_rem == 0xFFFF) {
516                 /* first time - not initialised */
517                 rem = UGETW(req.wLength);
518                 off = 0;
519         } else {
520                 /* not first time - initialised */
521                 rem = xfer->flags_int.control_rem;
522                 off = UGETW(req.wLength) - rem;
523         }
524
525         /* set some defaults */
526
527         max_len = 0;
528         src_zcopy = NULL;
529         src_mcopy = NULL;
530         udev = xfer->xroot->udev;
531
532         /* get some request fields decoded */
533
534         wValue = UGETW(req.wValue);
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, UGETW(req.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 }