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