source: rtems-libbsd/freebsd/sys/dev/usb/usb_handle_request.c @ 3d1e767

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 3d1e767 was 3d1e767, checked in by Sebastian Huber <sebastian.huber@…>, on 04/27/16 at 08:25:22

Directly use <sys/types.h> provided by Newlib

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