usb_handle_request.c revision 190633
1/* $FreeBSD: head/sys/dev/usb/usb_handle_request.c 190633 2009-04-01 20:23:47Z piso $ */
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 usb2_device *, uint8_t);
55static usb2_error_t	 usb2_handle_remote_wakeup(struct usb2_xfer *, uint8_t);
56static usb2_error_t	 usb2_handle_request(struct usb2_xfer *);
57static usb2_error_t	 usb2_handle_set_config(struct usb2_xfer *, uint8_t);
58static usb2_error_t	 usb2_handle_set_stall(struct usb2_xfer *, uint8_t,
59			    uint8_t);
60static usb2_error_t	 usb2_handle_iface_request(struct usb2_xfer *, void **,
61			    uint16_t *, struct usb2_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 usb2_xfer *xfer)
72{
73	usb2_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 usb2_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 usb2_error_t
126usb2_handle_set_config(struct usb2_xfer *xfer, uint8_t conf_no)
127{
128	struct usb2_device *udev = xfer->xroot->udev;
129	usb2_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 usb2_error_t
174usb2_handle_iface_request(struct usb2_xfer *xfer,
175    void **ppdata, uint16_t *plen,
176    struct usb2_device_request req, uint16_t off, uint8_t state)
177{
178	struct usb2_interface *iface;
179	struct usb2_interface *iface_parent;	/* parent interface */
180	struct usb2_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 usb2_error_t
337usb2_handle_set_stall(struct usb2_xfer *xfer, uint8_t ep, uint8_t do_stall)
338{
339	struct usb2_device *udev = xfer->xroot->udev;
340	usb2_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 usb2_device *udev, uint8_t ea_val)
358{
359	struct usb2_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 usb2_error_t
382usb2_handle_remote_wakeup(struct usb2_xfer *xfer, uint8_t is_on)
383{
384	struct usb2_device *udev;
385	struct usb2_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
402	usb2_bus_power_update(udev->bus);
403
404	return (0);			/* success */
405}
406
407/*------------------------------------------------------------------------*
408 *	usb2_handle_request
409 *
410 * Internal state sequence:
411 *
412 * ST_DATA -> ST_POST_STATUS
413 *
414 * Returns:
415 * 0: Ready to start hardware
416 * Else: Stall current transfer, if any
417 *------------------------------------------------------------------------*/
418static usb2_error_t
419usb2_handle_request(struct usb2_xfer *xfer)
420{
421	struct usb2_device_request req;
422	struct usb2_device *udev;
423	const void *src_zcopy;		/* zero-copy source pointer */
424	const void *src_mcopy;		/* non zero-copy source pointer */
425	uint16_t off;			/* data offset */
426	uint16_t rem;			/* data remainder */
427	uint16_t max_len;		/* max fragment length */
428	uint16_t wValue;
429	uint16_t wIndex;
430	uint8_t state;
431	usb2_error_t err;
432	union {
433		uWord	wStatus;
434		uint8_t	buf[2];
435	}     temp;
436
437	/*
438	 * Filter the USB transfer state into
439	 * something which we understand:
440	 */
441
442	switch (USB_GET_STATE(xfer)) {
443	case USB_ST_SETUP:
444		state = ST_DATA;
445
446		if (!xfer->flags_int.control_act) {
447			/* nothing to do */
448			goto tr_stalled;
449		}
450		break;
451
452	default:			/* USB_ST_TRANSFERRED */
453		if (!xfer->flags_int.control_act) {
454			state = ST_POST_STATUS;
455		} else {
456			state = ST_DATA;
457		}
458		break;
459	}
460
461	/* reset frame stuff */
462
463	xfer->frlengths[0] = 0;
464
465	usb2_set_frame_offset(xfer, 0, 0);
466	usb2_set_frame_offset(xfer, sizeof(req), 1);
467
468	/* get the current request, if any */
469
470	usb2_copy_out(xfer->frbuffers, 0, &req, sizeof(req));
471
472	if (xfer->flags_int.control_rem == 0xFFFF) {
473		/* first time - not initialised */
474		rem = UGETW(req.wLength);
475		off = 0;
476	} else {
477		/* not first time - initialised */
478		rem = xfer->flags_int.control_rem;
479		off = UGETW(req.wLength) - rem;
480	}
481
482	/* set some defaults */
483
484	max_len = 0;
485	src_zcopy = NULL;
486	src_mcopy = NULL;
487	udev = xfer->xroot->udev;
488
489	/* get some request fields decoded */
490
491	wValue = UGETW(req.wValue);
492	wIndex = UGETW(req.wIndex);
493
494	DPRINTF("req 0x%02x 0x%02x 0x%04x 0x%04x "
495	    "off=0x%x rem=0x%x, state=%d\n", req.bmRequestType,
496	    req.bRequest, wValue, wIndex, off, rem, state);
497
498	/* demultiplex the control request */
499
500	switch (req.bmRequestType) {
501	case UT_READ_DEVICE:
502		if (state != ST_DATA) {
503			break;
504		}
505		switch (req.bRequest) {
506		case UR_GET_DESCRIPTOR:
507			goto tr_handle_get_descriptor;
508		case UR_GET_CONFIG:
509			goto tr_handle_get_config;
510		case UR_GET_STATUS:
511			goto tr_handle_get_status;
512		default:
513			goto tr_stalled;
514		}
515		break;
516
517	case UT_WRITE_DEVICE:
518		switch (req.bRequest) {
519		case UR_SET_ADDRESS:
520			goto tr_handle_set_address;
521		case UR_SET_CONFIG:
522			goto tr_handle_set_config;
523		case UR_CLEAR_FEATURE:
524			switch (wValue) {
525			case UF_DEVICE_REMOTE_WAKEUP:
526				goto tr_handle_clear_wakeup;
527			default:
528				goto tr_stalled;
529			}
530			break;
531		case UR_SET_FEATURE:
532			switch (wValue) {
533			case UF_DEVICE_REMOTE_WAKEUP:
534				goto tr_handle_set_wakeup;
535			default:
536				goto tr_stalled;
537			}
538			break;
539		default:
540			goto tr_stalled;
541		}
542		break;
543
544	case UT_WRITE_ENDPOINT:
545		switch (req.bRequest) {
546		case UR_CLEAR_FEATURE:
547			switch (wValue) {
548			case UF_ENDPOINT_HALT:
549				goto tr_handle_clear_halt;
550			default:
551				goto tr_stalled;
552			}
553			break;
554		case UR_SET_FEATURE:
555			switch (wValue) {
556			case UF_ENDPOINT_HALT:
557				goto tr_handle_set_halt;
558			default:
559				goto tr_stalled;
560			}
561			break;
562		default:
563			goto tr_stalled;
564		}
565		break;
566
567	case UT_READ_ENDPOINT:
568		switch (req.bRequest) {
569		case UR_GET_STATUS:
570			goto tr_handle_get_ep_status;
571		default:
572			goto tr_stalled;
573		}
574		break;
575	default:
576		/* we use "USB_ADD_BYTES" to de-const the src_zcopy */
577		err = usb2_handle_iface_request(xfer,
578		    USB_ADD_BYTES(&src_zcopy, 0),
579		    &max_len, req, off, state);
580		if (err == 0) {
581			goto tr_valid;
582		}
583		/*
584		 * Reset zero-copy pointer and max length
585		 * variable in case they were unintentionally
586		 * set:
587		 */
588		src_zcopy = NULL;
589		max_len = 0;
590
591		/*
592		 * Check if we have a vendor specific
593		 * descriptor:
594		 */
595		goto tr_handle_get_descriptor;
596	}
597	goto tr_valid;
598
599tr_handle_get_descriptor:
600	(usb2_temp_get_desc_p) (udev, &req, &src_zcopy, &max_len);
601	if (src_zcopy == NULL) {
602		goto tr_stalled;
603	}
604	goto tr_valid;
605
606tr_handle_get_config:
607	temp.buf[0] = udev->curr_config_no;
608	src_mcopy = temp.buf;
609	max_len = 1;
610	goto tr_valid;
611
612tr_handle_get_status:
613
614	wValue = 0;
615
616	USB_BUS_LOCK(udev->bus);
617	if (udev->flags.remote_wakeup) {
618		wValue |= UDS_REMOTE_WAKEUP;
619	}
620	if (udev->flags.self_powered) {
621		wValue |= UDS_SELF_POWERED;
622	}
623	USB_BUS_UNLOCK(udev->bus);
624
625	USETW(temp.wStatus, wValue);
626	src_mcopy = temp.wStatus;
627	max_len = sizeof(temp.wStatus);
628	goto tr_valid;
629
630tr_handle_set_address:
631	if (state == ST_DATA) {
632		if (wValue >= 0x80) {
633			/* invalid value */
634			goto tr_stalled;
635		} else if (udev->curr_config_no != 0) {
636			/* we are configured ! */
637			goto tr_stalled;
638		}
639	} else if (state == ST_POST_STATUS) {
640		udev->address = (wValue & 0x7F);
641		goto tr_bad_context;
642	}
643	goto tr_valid;
644
645tr_handle_set_config:
646	if (state == ST_DATA) {
647		if (usb2_handle_set_config(xfer, req.wValue[0])) {
648			goto tr_stalled;
649		}
650	}
651	goto tr_valid;
652
653tr_handle_clear_halt:
654	if (state == ST_DATA) {
655		if (usb2_handle_set_stall(xfer, req.wIndex[0], 0)) {
656			goto tr_stalled;
657		}
658	}
659	goto tr_valid;
660
661tr_handle_clear_wakeup:
662	if (state == ST_DATA) {
663		if (usb2_handle_remote_wakeup(xfer, 0)) {
664			goto tr_stalled;
665		}
666	}
667	goto tr_valid;
668
669tr_handle_set_halt:
670	if (state == ST_DATA) {
671		if (usb2_handle_set_stall(xfer, req.wIndex[0], 1)) {
672			goto tr_stalled;
673		}
674	}
675	goto tr_valid;
676
677tr_handle_set_wakeup:
678	if (state == ST_DATA) {
679		if (usb2_handle_remote_wakeup(xfer, 1)) {
680			goto tr_stalled;
681		}
682	}
683	goto tr_valid;
684
685tr_handle_get_ep_status:
686	if (state == ST_DATA) {
687		temp.wStatus[0] =
688		    usb2_handle_get_stall(udev, req.wIndex[0]);
689		temp.wStatus[1] = 0;
690		src_mcopy = temp.wStatus;
691		max_len = sizeof(temp.wStatus);
692	}
693	goto tr_valid;
694
695tr_valid:
696	if (state == ST_POST_STATUS) {
697		goto tr_stalled;
698	}
699	/* subtract offset from length */
700
701	max_len -= off;
702
703	/* Compute the real maximum data length */
704
705	if (max_len > xfer->max_data_length) {
706		max_len = xfer->max_data_length;
707	}
708	if (max_len > rem) {
709		max_len = rem;
710	}
711	/*
712	 * If the remainder is greater than the maximum data length,
713	 * we need to truncate the value for the sake of the
714	 * comparison below:
715	 */
716	if (rem > xfer->max_data_length) {
717		rem = xfer->max_data_length;
718	}
719	if (rem != max_len) {
720		/*
721	         * If we don't transfer the data we can transfer, then
722	         * the transfer is short !
723	         */
724		xfer->flags.force_short_xfer = 1;
725		xfer->nframes = 2;
726	} else {
727		/*
728		 * Default case
729		 */
730		xfer->flags.force_short_xfer = 0;
731		xfer->nframes = max_len ? 2 : 1;
732	}
733	if (max_len > 0) {
734		if (src_mcopy) {
735			src_mcopy = USB_ADD_BYTES(src_mcopy, off);
736			usb2_copy_in(xfer->frbuffers + 1, 0,
737			    src_mcopy, max_len);
738		} else {
739			usb2_set_frame_data(xfer,
740			    USB_ADD_BYTES(src_zcopy, off), 1);
741		}
742		xfer->frlengths[1] = max_len;
743	} else {
744		/* the end is reached, send status */
745		xfer->flags.manual_status = 0;
746		xfer->frlengths[1] = 0;
747	}
748	DPRINTF("success\n");
749	return (0);			/* success */
750
751tr_stalled:
752	DPRINTF("%s\n", (state == ST_POST_STATUS) ?
753	    "complete" : "stalled");
754	return (USB_ERR_STALLED);
755
756tr_bad_context:
757	DPRINTF("bad context\n");
758	return (USB_ERR_BAD_CONTEXT);
759}
760