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}
|