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