Merge branch 'vendor/LIBARCHIVE'
[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
147         /*
148          * We need to protect against other threads doing probe and
149          * attach:
150          */
151         USB_XFER_UNLOCK(xfer);
152
153         usbd_enum_lock(udev);
154
155         if (conf_no == USB_UNCONFIG_NO) {
156                 conf_no = USB_UNCONFIG_INDEX;
157         } else {
158                 /*
159                  * The relationship between config number and config index
160                  * is very simple in our case:
161                  */
162                 conf_no--;
163         }
164
165         if (usbd_set_config_index(udev, conf_no)) {
166                 DPRINTF("set config %d failed\n", conf_no);
167                 err = USB_ERR_STALLED;
168                 goto done;
169         }
170         if (usb_probe_and_attach(udev, USB_IFACE_INDEX_ANY)) {
171                 DPRINTF("probe and attach failed\n");
172                 err = USB_ERR_STALLED;
173                 goto done;
174         }
175 done:
176         usbd_enum_unlock(udev);
177         USB_XFER_LOCK(xfer);
178         return (err);
179 }
180
181 static usb_error_t
182 usb_check_alt_setting(struct usb_device *udev, 
183      struct usb_interface *iface, uint8_t alt_index)
184 {
185         uint8_t do_unlock;
186         usb_error_t err = 0;
187
188         /* automatic locking */
189         if (usbd_enum_is_locked(udev)) {
190                 do_unlock = 0;
191         } else {
192                 do_unlock = 1;
193                 usbd_enum_lock(udev);
194         }
195
196         if (alt_index >= usbd_get_no_alts(udev->cdesc, iface->idesc))
197                 err = USB_ERR_INVAL;
198
199         if (do_unlock)
200                 usbd_enum_unlock(udev);
201
202         return (err);
203 }
204
205 /*------------------------------------------------------------------------*
206  *      usb_handle_iface_request
207  *
208  * Returns:
209  *    0: Success
210  * Else: Failure
211  *------------------------------------------------------------------------*/
212 static usb_error_t
213 usb_handle_iface_request(struct usb_xfer *xfer,
214     void **ppdata, uint16_t *plen,
215     struct usb_device_request req, uint16_t off, uint8_t state)
216 {
217         struct usb_interface *iface;
218         struct usb_interface *iface_parent;     /* parent interface */
219         struct usb_device *udev = xfer->xroot->udev;
220         int error;
221         uint8_t iface_index;
222         uint8_t temp_state;
223
224         if ((req.bmRequestType & 0x1F) == UT_INTERFACE) {
225                 iface_index = req.wIndex[0];    /* unicast */
226         } else {
227                 iface_index = 0;        /* broadcast */
228         }
229
230         /*
231          * We need to protect against other threads doing probe and
232          * attach:
233          */
234         USB_XFER_UNLOCK(xfer);
235
236         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         usbd_enum_unlock(udev);
353         USB_XFER_LOCK(xfer);
354         return (0);
355
356 tr_short:
357         usbd_enum_unlock(udev);
358         USB_XFER_LOCK(xfer);
359         return (USB_ERR_SHORT_XFER);
360
361 tr_stalled:
362         usbd_enum_unlock(udev);
363         USB_XFER_LOCK(xfer);
364         return (USB_ERR_STALLED);
365 }
366
367 /*------------------------------------------------------------------------*
368  *      usb_handle_stall
369  *
370  * Returns:
371  *    0: Success
372  * Else: Failure
373  *------------------------------------------------------------------------*/
374 static usb_error_t
375 usb_handle_set_stall(struct usb_xfer *xfer, uint8_t ep, uint8_t do_stall)
376 {
377         struct usb_device *udev = xfer->xroot->udev;
378         usb_error_t err;
379
380         USB_XFER_UNLOCK(xfer);
381         err = usbd_set_endpoint_stall(udev,
382             usbd_get_ep_by_addr(udev, ep), do_stall);
383         USB_XFER_LOCK(xfer);
384         return (err);
385 }
386
387 /*------------------------------------------------------------------------*
388  *      usb_handle_get_stall
389  *
390  * Returns:
391  *    0: Success
392  * Else: Failure
393  *------------------------------------------------------------------------*/
394 static uint8_t
395 usb_handle_get_stall(struct usb_device *udev, uint8_t ea_val)
396 {
397         struct usb_endpoint *ep;
398         uint8_t halted;
399
400         ep = usbd_get_ep_by_addr(udev, ea_val);
401         if (ep == NULL) {
402                 /* nothing to do */
403                 return (0);
404         }
405         USB_BUS_LOCK(udev->bus);
406         halted = ep->is_stalled;
407         USB_BUS_UNLOCK(udev->bus);
408
409         return (halted);
410 }
411
412 /*------------------------------------------------------------------------*
413  *      usb_handle_remote_wakeup
414  *
415  * Returns:
416  *    0: Success
417  * Else: Failure
418  *------------------------------------------------------------------------*/
419 static usb_error_t
420 usb_handle_remote_wakeup(struct usb_xfer *xfer, uint8_t is_on)
421 {
422         struct usb_device *udev;
423         struct usb_bus *bus;
424
425         udev = xfer->xroot->udev;
426         bus = udev->bus;
427
428         USB_BUS_LOCK(bus);
429
430         if (is_on) {
431                 udev->flags.remote_wakeup = 1;
432         } else {
433                 udev->flags.remote_wakeup = 0;
434         }
435
436         USB_BUS_UNLOCK(bus);
437
438 #if USB_HAVE_POWERD
439         /* In case we are out of sync, update the power state. */
440         usb_bus_power_update(udev->bus);
441 #endif
442         return (0);                     /* success */
443 }
444
445 /*------------------------------------------------------------------------*
446  *      usb_handle_request
447  *
448  * Internal state sequence:
449  *
450  * USB_HR_NOT_COMPLETE -> USB_HR_COMPLETE_OK v USB_HR_COMPLETE_ERR
451  *
452  * Returns:
453  * 0: Ready to start hardware
454  * Else: Stall current transfer, if any
455  *------------------------------------------------------------------------*/
456 static usb_error_t
457 usb_handle_request(struct usb_xfer *xfer)
458 {
459         struct usb_device_request req;
460         struct usb_device *udev;
461         const void *src_zcopy;          /* zero-copy source pointer */
462         const void *src_mcopy;          /* non zero-copy source pointer */
463         uint16_t off;                   /* data offset */
464         uint16_t rem;                   /* data remainder */
465         uint16_t max_len;               /* max fragment length */
466         uint16_t wValue;
467         uint16_t wIndex;
468         uint8_t state;
469         uint8_t is_complete = 1;
470         usb_error_t err;
471         union {
472                 uWord   wStatus;
473                 uint8_t buf[2];
474         }     temp;
475
476         /*
477          * Filter the USB transfer state into
478          * something which we understand:
479          */
480
481         switch (USB_GET_STATE(xfer)) {
482         case USB_ST_SETUP:
483                 state = USB_HR_NOT_COMPLETE;
484
485                 if (!xfer->flags_int.control_act) {
486                         /* nothing to do */
487                         goto tr_stalled;
488                 }
489                 break;
490         case USB_ST_TRANSFERRED:
491                 if (!xfer->flags_int.control_act) {
492                         state = USB_HR_COMPLETE_OK;
493                 } else {
494                         state = USB_HR_NOT_COMPLETE;
495                 }
496                 break;
497         default:
498                 state = USB_HR_COMPLETE_ERR;
499                 break;
500         }
501
502         /* reset frame stuff */
503
504         usbd_xfer_set_frame_len(xfer, 0, 0);
505
506         usbd_xfer_set_frame_offset(xfer, 0, 0);
507         usbd_xfer_set_frame_offset(xfer, sizeof(req), 1);
508
509         /* get the current request, if any */
510
511         usbd_copy_out(xfer->frbuffers, 0, &req, sizeof(req));
512
513         if (xfer->flags_int.control_rem == 0xFFFF) {
514                 /* first time - not initialised */
515                 rem = UGETW(req.wLength);
516                 off = 0;
517         } else {
518                 /* not first time - initialised */
519                 rem = xfer->flags_int.control_rem;
520                 off = UGETW(req.wLength) - rem;
521         }
522
523         /* set some defaults */
524
525         max_len = 0;
526         src_zcopy = NULL;
527         src_mcopy = NULL;
528         udev = xfer->xroot->udev;
529
530         /* get some request fields decoded */
531
532         wValue = UGETW(req.wValue);
533         wIndex = UGETW(req.wIndex);
534
535         DPRINTF("req 0x%02x 0x%02x 0x%04x 0x%04x "
536             "off=0x%x rem=0x%x, state=%d\n", req.bmRequestType,
537             req.bRequest, wValue, wIndex, off, rem, state);
538
539         /* demultiplex the control request */
540
541         switch (req.bmRequestType) {
542         case UT_READ_DEVICE:
543                 if (state != USB_HR_NOT_COMPLETE) {
544                         break;
545                 }
546                 switch (req.bRequest) {
547                 case UR_GET_DESCRIPTOR:
548                         goto tr_handle_get_descriptor;
549                 case UR_GET_CONFIG:
550                         goto tr_handle_get_config;
551                 case UR_GET_STATUS:
552                         goto tr_handle_get_status;
553                 default:
554                         goto tr_stalled;
555                 }
556                 break;
557
558         case UT_WRITE_DEVICE:
559                 switch (req.bRequest) {
560                 case UR_SET_ADDRESS:
561                         goto tr_handle_set_address;
562                 case UR_SET_CONFIG:
563                         goto tr_handle_set_config;
564                 case UR_CLEAR_FEATURE:
565                         switch (wValue) {
566                         case UF_DEVICE_REMOTE_WAKEUP:
567                                 goto tr_handle_clear_wakeup;
568                         default:
569                                 goto tr_stalled;
570                         }
571                         break;
572                 case UR_SET_FEATURE:
573                         switch (wValue) {
574                         case UF_DEVICE_REMOTE_WAKEUP:
575                                 goto tr_handle_set_wakeup;
576                         default:
577                                 goto tr_stalled;
578                         }
579                         break;
580                 default:
581                         goto tr_stalled;
582                 }
583                 break;
584
585         case UT_WRITE_ENDPOINT:
586                 switch (req.bRequest) {
587                 case UR_CLEAR_FEATURE:
588                         switch (wValue) {
589                         case UF_ENDPOINT_HALT:
590                                 goto tr_handle_clear_halt;
591                         default:
592                                 goto tr_stalled;
593                         }
594                         break;
595                 case UR_SET_FEATURE:
596                         switch (wValue) {
597                         case UF_ENDPOINT_HALT:
598                                 goto tr_handle_set_halt;
599                         default:
600                                 goto tr_stalled;
601                         }
602                         break;
603                 default:
604                         goto tr_stalled;
605                 }
606                 break;
607
608         case UT_READ_ENDPOINT:
609                 switch (req.bRequest) {
610                 case UR_GET_STATUS:
611                         goto tr_handle_get_ep_status;
612                 default:
613                         goto tr_stalled;
614                 }
615                 break;
616         default:
617                 /* we use "USB_ADD_BYTES" to de-const the src_zcopy */
618                 err = usb_handle_iface_request(xfer,
619                     USB_ADD_BYTES(&src_zcopy, 0),
620                     &max_len, req, off, state);
621                 if (err == 0) {
622                         is_complete = 0;
623                         goto tr_valid;
624                 } else if (err == USB_ERR_SHORT_XFER) {
625                         goto tr_valid;
626                 }
627                 /*
628                  * Reset zero-copy pointer and max length
629                  * variable in case they were unintentionally
630                  * set:
631                  */
632                 src_zcopy = NULL;
633                 max_len = 0;
634
635                 /*
636                  * Check if we have a vendor specific
637                  * descriptor:
638                  */
639                 goto tr_handle_get_descriptor;
640         }
641         goto tr_valid;
642
643 tr_handle_get_descriptor:
644         err = (usb_temp_get_desc_p) (udev, &req, &src_zcopy, &max_len);
645         if (err)
646                 goto tr_stalled;
647         if (src_zcopy == NULL)
648                 goto tr_stalled;
649         goto tr_valid;
650
651 tr_handle_get_config:
652         temp.buf[0] = udev->curr_config_no;
653         src_mcopy = temp.buf;
654         max_len = 1;
655         goto tr_valid;
656
657 tr_handle_get_status:
658
659         wValue = 0;
660
661         USB_BUS_LOCK(udev->bus);
662         if (udev->flags.remote_wakeup) {
663                 wValue |= UDS_REMOTE_WAKEUP;
664         }
665         if (udev->flags.self_powered) {
666                 wValue |= UDS_SELF_POWERED;
667         }
668         USB_BUS_UNLOCK(udev->bus);
669
670         USETW(temp.wStatus, wValue);
671         src_mcopy = temp.wStatus;
672         max_len = sizeof(temp.wStatus);
673         goto tr_valid;
674
675 tr_handle_set_address:
676         if (state == USB_HR_NOT_COMPLETE) {
677                 if (wValue >= 0x80) {
678                         /* invalid value */
679                         goto tr_stalled;
680                 } else if (udev->curr_config_no != 0) {
681                         /* we are configured ! */
682                         goto tr_stalled;
683                 }
684         } else if (state != USB_HR_NOT_COMPLETE) {
685                 udev->address = (wValue & 0x7F);
686                 goto tr_bad_context;
687         }
688         goto tr_valid;
689
690 tr_handle_set_config:
691         if (state == USB_HR_NOT_COMPLETE) {
692                 if (usb_handle_set_config(xfer, req.wValue[0])) {
693                         goto tr_stalled;
694                 }
695         }
696         goto tr_valid;
697
698 tr_handle_clear_halt:
699         if (state == USB_HR_NOT_COMPLETE) {
700                 if (usb_handle_set_stall(xfer, req.wIndex[0], 0)) {
701                         goto tr_stalled;
702                 }
703         }
704         goto tr_valid;
705
706 tr_handle_clear_wakeup:
707         if (state == USB_HR_NOT_COMPLETE) {
708                 if (usb_handle_remote_wakeup(xfer, 0)) {
709                         goto tr_stalled;
710                 }
711         }
712         goto tr_valid;
713
714 tr_handle_set_halt:
715         if (state == USB_HR_NOT_COMPLETE) {
716                 if (usb_handle_set_stall(xfer, req.wIndex[0], 1)) {
717                         goto tr_stalled;
718                 }
719         }
720         goto tr_valid;
721
722 tr_handle_set_wakeup:
723         if (state == USB_HR_NOT_COMPLETE) {
724                 if (usb_handle_remote_wakeup(xfer, 1)) {
725                         goto tr_stalled;
726                 }
727         }
728         goto tr_valid;
729
730 tr_handle_get_ep_status:
731         if (state == USB_HR_NOT_COMPLETE) {
732                 temp.wStatus[0] =
733                     usb_handle_get_stall(udev, req.wIndex[0]);
734                 temp.wStatus[1] = 0;
735                 src_mcopy = temp.wStatus;
736                 max_len = sizeof(temp.wStatus);
737         }
738         goto tr_valid;
739
740 tr_valid:
741         if (state != USB_HR_NOT_COMPLETE) {
742                 goto tr_stalled;
743         }
744         /* subtract offset from length */
745
746         max_len -= off;
747
748         /* Compute the real maximum data length */
749
750         if (max_len > xfer->max_data_length) {
751                 max_len = usbd_xfer_max_len(xfer);
752         }
753         if (max_len > rem) {
754                 max_len = rem;
755         }
756         /*
757          * If the remainder is greater than the maximum data length,
758          * we need to truncate the value for the sake of the
759          * comparison below:
760          */
761         if (rem > xfer->max_data_length) {
762                 rem = usbd_xfer_max_len(xfer);
763         }
764         if ((rem != max_len) && (is_complete != 0)) {
765                 /*
766                  * If we don't transfer the data we can transfer, then
767                  * the transfer is short !
768                  */
769                 xfer->flags.force_short_xfer = 1;
770                 xfer->nframes = 2;
771         } else {
772                 /*
773                  * Default case
774                  */
775                 xfer->flags.force_short_xfer = 0;
776                 xfer->nframes = max_len ? 2 : 1;
777         }
778         if (max_len > 0) {
779                 if (src_mcopy) {
780                         src_mcopy = USB_ADD_BYTES(src_mcopy, off);
781                         usbd_copy_in(xfer->frbuffers + 1, 0,
782                             src_mcopy, max_len);
783                         usbd_xfer_set_frame_len(xfer, 1, max_len);
784                 } else {
785                         usbd_xfer_set_frame_data(xfer, 1,
786                             USB_ADD_BYTES(src_zcopy, off), max_len);
787                 }
788         } else {
789                 /* the end is reached, send status */
790                 xfer->flags.manual_status = 0;
791                 usbd_xfer_set_frame_len(xfer, 1, 0);
792         }
793         DPRINTF("success\n");
794         return (0);                     /* success */
795
796 tr_stalled:
797         DPRINTF("%s\n", (state != USB_HR_NOT_COMPLETE) ?
798             "complete" : "stalled");
799         return (USB_ERR_STALLED);
800
801 tr_bad_context:
802         DPRINTF("bad context\n");
803         return (USB_ERR_BAD_CONTEXT);
804 }