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