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