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

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since f244de9 was f244de9, checked in by Sebastian Huber <sebastian.huber@…>, on 11/06/13 at 07:56:38

Rename rtems-bsd-config.h

Rename rtems-bsd-config.h in rtems-bsd-kernel-space.h.

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