1 /* $FreeBSD$ */
2 /*-
3 * SPDX-License-Identifier: BSD-2-Clause-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 <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 <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 <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 "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
73 static uint8_t usb_handle_get_stall(struct usb_device *, uint8_t);
74 static usb_error_t usb_handle_remote_wakeup(struct usb_xfer *, uint8_t);
75 static usb_error_t usb_handle_request(struct usb_xfer *);
76 static usb_error_t usb_handle_set_config(struct usb_xfer *, uint8_t);
77 static usb_error_t usb_handle_set_stall(struct usb_xfer *, uint8_t,
78 uint8_t);
79 static 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 *------------------------------------------------------------------------*/
89 void
usb_handle_request_callback(struct usb_xfer * xfer,usb_error_t error)90 usb_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
129 tr_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 *------------------------------------------------------------------------*/
149 static usb_error_t
usb_handle_set_config(struct usb_xfer * xfer,uint8_t conf_no)150 usb_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 }
185 done:
186 if (do_unlock)
187 usbd_enum_unlock(udev);
188 USB_XFER_LOCK(xfer);
189 return (err);
190 }
191
192 static usb_error_t
usb_check_alt_setting(struct usb_device * udev,struct usb_interface * iface,uint8_t alt_index)193 usb_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 *------------------------------------------------------------------------*/
218 static usb_error_t
usb_handle_iface_request(struct usb_xfer * xfer,void ** ppdata,uint16_t * plen,struct usb_device_request req,uint16_t off,uint8_t state)219 usb_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
248 tr_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 * across 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 }
359 tr_valid:
360 if (do_unlock)
361 usbd_enum_unlock(udev);
362 USB_XFER_LOCK(xfer);
363 return (0);
364
365 tr_short:
366 if (do_unlock)
367 usbd_enum_unlock(udev);
368 USB_XFER_LOCK(xfer);
369 return (USB_ERR_SHORT_XFER);
370
371 tr_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 *------------------------------------------------------------------------*/
385 static usb_error_t
usb_handle_set_stall(struct usb_xfer * xfer,uint8_t ep,uint8_t do_stall)386 usb_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 *------------------------------------------------------------------------*/
405 static uint8_t
usb_handle_get_stall(struct usb_device * udev,uint8_t ea_val)406 usb_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 *------------------------------------------------------------------------*/
430 static usb_error_t
usb_handle_remote_wakeup(struct usb_xfer * xfer,uint8_t is_on)431 usb_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 *------------------------------------------------------------------------*/
467 static usb_error_t
usb_handle_request(struct usb_xfer * xfer)468 usb_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
652 tr_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
660 tr_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
666 tr_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
684 tr_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
699 tr_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
707 tr_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
715 tr_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
723 tr_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
731 tr_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
739 tr_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
749 tr_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
805 tr_stalled:
806 DPRINTF("%s\n", (state != USB_HR_NOT_COMPLETE) ?
807 "complete" : "stalled");
808 return (USB_ERR_STALLED);
809
810 tr_bad_context:
811 DPRINTF("bad context\n");
812 return (USB_ERR_BAD_CONTEXT);
813 }
814