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