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