1/* $FreeBSD: head/sys/dev/usb2/core/usb2_handle_request.c 186730 2009-01-04 00:12:01Z alfred $ */
| 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 */
| 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->udev->bus, 0);
| 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{
| 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;
|
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 */
| 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 */
|
137 sx_xlock(xfer->udev->default_sx + 1);
| 138 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
| 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
|
149 if (usb2_set_config_index(xfer->udev, conf_no)) {
| 150 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 }
| 151 DPRINTF("set config %d failed\n", conf_no); 152 err = USB_ERR_STALLED; 153 goto done; 154 }
|
154 if (usb2_probe_and_attach(xfer->udev, USB_IFACE_INDEX_ANY)) {
| 155 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 */
| 156 DPRINTF("probe and attach failed\n"); 157 err = USB_ERR_STALLED; 158 goto done; 159 } 160done: 161 mtx_unlock(&Giant); /* XXX */
|
161 sx_unlock(xfer->udev->default_sx + 1);
| 162 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 */
| 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 */
|
180 struct usb2_device *udev = xfer->udev;
| 181 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(usb2_handle_request, NULL); /* dummy */ 215#endif 216 error = USB2_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 = USB2_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 error = usb2_set_alt_interface_index(udev, 280 iface_index, req.wValue[0]); 281 if (error) { 282 DPRINTF("alt setting failed %s\n", 283 usb2_errstr(error)); 284 goto tr_stalled; 285 } 286 error = usb2_probe_and_attach(udev, 287 iface_index); 288 if (error) { 289 DPRINTF("alt setting probe failed\n"); 290 goto tr_stalled; 291 } 292 break; 293 default: 294 goto tr_stalled; 295 } 296 break; 297 298 case UT_READ_INTERFACE: 299 switch (req.bRequest) { 300 case UR_GET_INTERFACE: 301 *ppdata = &iface->alt_index; 302 *plen = 1; 303 break; 304 305 default: 306 goto tr_stalled; 307 } 308 break; 309 default: 310 goto tr_stalled; 311 } 312tr_valid: 313 mtx_unlock(&Giant); 314 sx_unlock(udev->default_sx + 1); 315 USB_XFER_LOCK(xfer); 316 return (0); 317 318tr_stalled: 319 mtx_unlock(&Giant); 320 sx_unlock(udev->default_sx + 1); 321 USB_XFER_LOCK(xfer); 322 return (USB_ERR_STALLED); 323} 324 325/*------------------------------------------------------------------------* 326 * usb2_handle_stall 327 * 328 * Returns: 329 * 0: Success 330 * Else: Failure 331 *------------------------------------------------------------------------*/ 332static usb2_error_t 333usb2_handle_set_stall(struct usb2_xfer *xfer, uint8_t ep, uint8_t do_stall) 334{
| 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;
|
335 usb2_error_t err; 336 337 USB_XFER_UNLOCK(xfer);
| 337 usb2_error_t err; 338 339 USB_XFER_UNLOCK(xfer);
|
338 err = usb2_set_endpoint_stall(xfer->udev, 339 usb2_get_pipe_by_addr(xfer->udev, ep), do_stall);
| 340 err = usb2_set_endpoint_stall(udev, 341 usb2_get_pipe_by_addr(udev, ep), do_stall);
|
340 USB_XFER_LOCK(xfer); 341 return (err); 342} 343 344/*------------------------------------------------------------------------* 345 * usb2_handle_get_stall 346 * 347 * Returns: 348 * 0: Success 349 * Else: Failure 350 *------------------------------------------------------------------------*/ 351static uint8_t 352usb2_handle_get_stall(struct usb2_device *udev, uint8_t ea_val) 353{ 354 struct usb2_pipe *pipe; 355 uint8_t halted; 356 357 pipe = usb2_get_pipe_by_addr(udev, ea_val); 358 if (pipe == NULL) { 359 /* nothing to do */ 360 return (0); 361 } 362 USB_BUS_LOCK(udev->bus); 363 halted = pipe->is_stalled; 364 USB_BUS_UNLOCK(udev->bus); 365 366 return (halted); 367} 368 369/*------------------------------------------------------------------------* 370 * usb2_handle_remote_wakeup 371 * 372 * Returns: 373 * 0: Success 374 * Else: Failure 375 *------------------------------------------------------------------------*/ 376static usb2_error_t 377usb2_handle_remote_wakeup(struct usb2_xfer *xfer, uint8_t is_on) 378{ 379 struct usb2_device *udev; 380 struct usb2_bus *bus; 381
| 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
|
382 udev = xfer->udev;
| 384 udev = xfer->xroot->udev;
|
383 bus = udev->bus; 384 385 USB_BUS_LOCK(bus); 386 387 if (is_on) { 388 udev->flags.remote_wakeup = 1; 389 } else { 390 udev->flags.remote_wakeup = 0; 391 } 392 393 USB_BUS_UNLOCK(bus); 394 395 /* In case we are out of sync, update the power state. */ 396 397 usb2_bus_power_update(udev->bus); 398 399 return (0); /* success */ 400} 401 402/*------------------------------------------------------------------------* 403 * usb2_handle_request 404 * 405 * Internal state sequence: 406 * 407 * ST_DATA -> ST_POST_STATUS 408 * 409 * Returns: 410 * 0: Ready to start hardware 411 * Else: Stall current transfer, if any 412 *------------------------------------------------------------------------*/ 413static usb2_error_t 414usb2_handle_request(struct usb2_xfer *xfer) 415{ 416 struct usb2_device_request req; 417 struct usb2_device *udev; 418 const void *src_zcopy; /* zero-copy source pointer */ 419 const void *src_mcopy; /* non zero-copy source pointer */ 420 uint16_t off; /* data offset */ 421 uint16_t rem; /* data remainder */ 422 uint16_t max_len; /* max fragment length */ 423 uint16_t wValue; 424 uint16_t wIndex; 425 uint8_t state; 426 usb2_error_t err; 427 union { 428 uWord wStatus; 429 uint8_t buf[2]; 430 } temp; 431 432 /* 433 * Filter the USB transfer state into 434 * something which we understand: 435 */ 436 437 switch (USB_GET_STATE(xfer)) { 438 case USB_ST_SETUP: 439 state = ST_DATA; 440 441 if (!xfer->flags_int.control_act) { 442 /* nothing to do */ 443 goto tr_stalled; 444 } 445 break; 446 447 default: /* USB_ST_TRANSFERRED */ 448 if (!xfer->flags_int.control_act) { 449 state = ST_POST_STATUS; 450 } else { 451 state = ST_DATA; 452 } 453 break; 454 } 455 456 /* reset frame stuff */ 457 458 xfer->frlengths[0] = 0; 459 460 usb2_set_frame_offset(xfer, 0, 0); 461 usb2_set_frame_offset(xfer, sizeof(req), 1); 462 463 /* get the current request, if any */ 464 465 usb2_copy_out(xfer->frbuffers, 0, &req, sizeof(req)); 466 467 if (xfer->flags_int.control_rem == 0xFFFF) { 468 /* first time - not initialised */ 469 rem = UGETW(req.wLength); 470 off = 0; 471 } else { 472 /* not first time - initialised */ 473 rem = xfer->flags_int.control_rem; 474 off = UGETW(req.wLength) - rem; 475 } 476 477 /* set some defaults */ 478 479 max_len = 0; 480 src_zcopy = NULL; 481 src_mcopy = NULL;
| 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;
|
482 udev = xfer->udev;
| 484 udev = xfer->xroot->udev;
|
483 484 /* get some request fields decoded */ 485 486 wValue = UGETW(req.wValue); 487 wIndex = UGETW(req.wIndex); 488 489 DPRINTF("req 0x%02x 0x%02x 0x%04x 0x%04x " 490 "off=0x%x rem=0x%x, state=%d\n", req.bmRequestType, 491 req.bRequest, wValue, wIndex, off, rem, state); 492 493 /* demultiplex the control request */ 494 495 switch (req.bmRequestType) { 496 case UT_READ_DEVICE: 497 if (state != ST_DATA) { 498 break; 499 } 500 switch (req.bRequest) { 501 case UR_GET_DESCRIPTOR: 502 goto tr_handle_get_descriptor; 503 case UR_GET_CONFIG: 504 goto tr_handle_get_config; 505 case UR_GET_STATUS: 506 goto tr_handle_get_status; 507 default: 508 goto tr_stalled; 509 } 510 break; 511 512 case UT_WRITE_DEVICE: 513 switch (req.bRequest) { 514 case UR_SET_ADDRESS: 515 goto tr_handle_set_address; 516 case UR_SET_CONFIG: 517 goto tr_handle_set_config; 518 case UR_CLEAR_FEATURE: 519 switch (wValue) { 520 case UF_DEVICE_REMOTE_WAKEUP: 521 goto tr_handle_clear_wakeup; 522 default: 523 goto tr_stalled; 524 } 525 break; 526 case UR_SET_FEATURE: 527 switch (wValue) { 528 case UF_DEVICE_REMOTE_WAKEUP: 529 goto tr_handle_set_wakeup; 530 default: 531 goto tr_stalled; 532 } 533 break; 534 default: 535 goto tr_stalled; 536 } 537 break; 538 539 case UT_WRITE_ENDPOINT: 540 switch (req.bRequest) { 541 case UR_CLEAR_FEATURE: 542 switch (wValue) { 543 case UF_ENDPOINT_HALT: 544 goto tr_handle_clear_halt; 545 default: 546 goto tr_stalled; 547 } 548 break; 549 case UR_SET_FEATURE: 550 switch (wValue) { 551 case UF_ENDPOINT_HALT: 552 goto tr_handle_set_halt; 553 default: 554 goto tr_stalled; 555 } 556 break; 557 default: 558 goto tr_stalled; 559 } 560 break; 561 562 case UT_READ_ENDPOINT: 563 switch (req.bRequest) { 564 case UR_GET_STATUS: 565 goto tr_handle_get_ep_status; 566 default: 567 goto tr_stalled; 568 } 569 break; 570 default: 571 /* we use "USB_ADD_BYTES" to de-const the src_zcopy */ 572 err = usb2_handle_iface_request(xfer, 573 USB_ADD_BYTES(&src_zcopy, 0), 574 &max_len, req, off, state); 575 if (err == 0) { 576 goto tr_valid; 577 } 578 /* 579 * Reset zero-copy pointer and max length 580 * variable in case they were unintentionally 581 * set: 582 */ 583 src_zcopy = NULL; 584 max_len = 0; 585 586 /* 587 * Check if we have a vendor specific 588 * descriptor: 589 */ 590 goto tr_handle_get_descriptor; 591 } 592 goto tr_valid; 593 594tr_handle_get_descriptor: 595 (usb2_temp_get_desc_p) (udev, &req, &src_zcopy, &max_len); 596 if (src_zcopy == NULL) { 597 goto tr_stalled; 598 } 599 goto tr_valid; 600 601tr_handle_get_config: 602 temp.buf[0] = udev->curr_config_no; 603 src_mcopy = temp.buf; 604 max_len = 1; 605 goto tr_valid; 606 607tr_handle_get_status: 608 609 wValue = 0; 610 611 USB_BUS_LOCK(udev->bus); 612 if (udev->flags.remote_wakeup) { 613 wValue |= UDS_REMOTE_WAKEUP; 614 } 615 if (udev->flags.self_powered) { 616 wValue |= UDS_SELF_POWERED; 617 } 618 USB_BUS_UNLOCK(udev->bus); 619 620 USETW(temp.wStatus, wValue); 621 src_mcopy = temp.wStatus; 622 max_len = sizeof(temp.wStatus); 623 goto tr_valid; 624 625tr_handle_set_address: 626 if (state == ST_DATA) { 627 if (wValue >= 0x80) { 628 /* invalid value */ 629 goto tr_stalled; 630 } else if (udev->curr_config_no != 0) { 631 /* we are configured ! */ 632 goto tr_stalled; 633 } 634 } else if (state == ST_POST_STATUS) { 635 udev->address = (wValue & 0x7F); 636 goto tr_bad_context; 637 } 638 goto tr_valid; 639 640tr_handle_set_config: 641 if (state == ST_DATA) { 642 if (usb2_handle_set_config(xfer, req.wValue[0])) { 643 goto tr_stalled; 644 } 645 } 646 goto tr_valid; 647 648tr_handle_clear_halt: 649 if (state == ST_DATA) { 650 if (usb2_handle_set_stall(xfer, req.wIndex[0], 0)) { 651 goto tr_stalled; 652 } 653 } 654 goto tr_valid; 655 656tr_handle_clear_wakeup: 657 if (state == ST_DATA) { 658 if (usb2_handle_remote_wakeup(xfer, 0)) { 659 goto tr_stalled; 660 } 661 } 662 goto tr_valid; 663 664tr_handle_set_halt: 665 if (state == ST_DATA) { 666 if (usb2_handle_set_stall(xfer, req.wIndex[0], 1)) { 667 goto tr_stalled; 668 } 669 } 670 goto tr_valid; 671 672tr_handle_set_wakeup: 673 if (state == ST_DATA) { 674 if (usb2_handle_remote_wakeup(xfer, 1)) { 675 goto tr_stalled; 676 } 677 } 678 goto tr_valid; 679 680tr_handle_get_ep_status: 681 if (state == ST_DATA) { 682 temp.wStatus[0] = 683 usb2_handle_get_stall(udev, req.wIndex[0]); 684 temp.wStatus[1] = 0; 685 src_mcopy = temp.wStatus; 686 max_len = sizeof(temp.wStatus); 687 } 688 goto tr_valid; 689 690tr_valid: 691 if (state == ST_POST_STATUS) { 692 goto tr_stalled; 693 } 694 /* subtract offset from length */ 695 696 max_len -= off; 697 698 /* Compute the real maximum data length */ 699 700 if (max_len > xfer->max_data_length) { 701 max_len = xfer->max_data_length; 702 } 703 if (max_len > rem) { 704 max_len = rem; 705 } 706 /* 707 * If the remainder is greater than the maximum data length, 708 * we need to truncate the value for the sake of the 709 * comparison below: 710 */ 711 if (rem > xfer->max_data_length) { 712 rem = xfer->max_data_length; 713 } 714 if (rem != max_len) { 715 /* 716 * If we don't transfer the data we can transfer, then 717 * the transfer is short ! 718 */ 719 xfer->flags.force_short_xfer = 1; 720 xfer->nframes = 2; 721 } else { 722 /* 723 * Default case 724 */ 725 xfer->flags.force_short_xfer = 0; 726 xfer->nframes = max_len ? 2 : 1; 727 } 728 if (max_len > 0) { 729 if (src_mcopy) { 730 src_mcopy = USB_ADD_BYTES(src_mcopy, off); 731 usb2_copy_in(xfer->frbuffers + 1, 0, 732 src_mcopy, max_len); 733 } else { 734 usb2_set_frame_data(xfer, 735 USB_ADD_BYTES(src_zcopy, off), 1); 736 } 737 xfer->frlengths[1] = max_len; 738 } else { 739 /* the end is reached, send status */ 740 xfer->flags.manual_status = 0; 741 xfer->frlengths[1] = 0; 742 } 743 DPRINTF("success\n"); 744 return (0); /* success */ 745 746tr_stalled: 747 DPRINTF("%s\n", (state == ST_POST_STATUS) ? 748 "complete" : "stalled"); 749 return (USB_ERR_STALLED); 750 751tr_bad_context: 752 DPRINTF("bad context\n"); 753 return (USB_ERR_BAD_CONTEXT); 754}
| 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}
|