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