usb_request.c revision 187173
1184610Salfred/* $FreeBSD: head/sys/dev/usb2/core/usb2_request.c 187173 2009-01-13 19:03:12Z thompsa $ */ 2184610Salfred/*- 3184610Salfred * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved. 4184610Salfred * Copyright (c) 1998 Lennart Augustsson. All rights reserved. 5184610Salfred * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 6184610Salfred * 7184610Salfred * Redistribution and use in source and binary forms, with or without 8184610Salfred * modification, are permitted provided that the following conditions 9184610Salfred * are met: 10184610Salfred * 1. Redistributions of source code must retain the above copyright 11184610Salfred * notice, this list of conditions and the following disclaimer. 12184610Salfred * 2. Redistributions in binary form must reproduce the above copyright 13184610Salfred * notice, this list of conditions and the following disclaimer in the 14184610Salfred * documentation and/or other materials provided with the distribution. 15184610Salfred * 16184610Salfred * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17184610Salfred * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18184610Salfred * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19184610Salfred * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20184610Salfred * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21184610Salfred * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22184610Salfred * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23184610Salfred * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24184610Salfred * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25184610Salfred * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26184610Salfred * SUCH DAMAGE. 27184610Salfred */ 28184610Salfred 29184610Salfred#include <dev/usb2/include/usb2_defs.h> 30184610Salfred#include <dev/usb2/include/usb2_mfunc.h> 31184610Salfred#include <dev/usb2/include/usb2_error.h> 32184610Salfred#include <dev/usb2/include/usb2_standard.h> 33184610Salfred#include <dev/usb2/include/usb2_ioctl.h> 34184610Salfred#include <dev/usb2/include/usb2_hid.h> 35184610Salfred 36184610Salfred#define USB_DEBUG_VAR usb2_debug 37184610Salfred 38184610Salfred#include <dev/usb2/core/usb2_core.h> 39184610Salfred#include <dev/usb2/core/usb2_busdma.h> 40184610Salfred#include <dev/usb2/core/usb2_request.h> 41184610Salfred#include <dev/usb2/core/usb2_process.h> 42184610Salfred#include <dev/usb2/core/usb2_transfer.h> 43184610Salfred#include <dev/usb2/core/usb2_debug.h> 44184610Salfred#include <dev/usb2/core/usb2_device.h> 45184610Salfred#include <dev/usb2/core/usb2_util.h> 46184610Salfred#include <dev/usb2/core/usb2_dynamic.h> 47184610Salfred 48184824Sthompsa#include <dev/usb2/controller/usb2_controller.h> 49184824Sthompsa#include <dev/usb2/controller/usb2_bus.h> 50184610Salfred#include <sys/ctype.h> 51184610Salfred 52184610Salfred#if USB_DEBUG 53184610Salfredstatic int usb2_pr_poll_delay = USB_PORT_RESET_DELAY; 54184610Salfredstatic int usb2_pr_recovery_delay = USB_PORT_RESET_RECOVERY; 55184610Salfredstatic int usb2_ss_delay = 0; 56184610Salfred 57184610SalfredSYSCTL_INT(_hw_usb2, OID_AUTO, pr_poll_delay, CTLFLAG_RW, 58184610Salfred &usb2_pr_poll_delay, 0, "USB port reset poll delay in ms"); 59184610SalfredSYSCTL_INT(_hw_usb2, OID_AUTO, pr_recovery_delay, CTLFLAG_RW, 60184610Salfred &usb2_pr_recovery_delay, 0, "USB port reset recovery delay in ms"); 61184610SalfredSYSCTL_INT(_hw_usb2, OID_AUTO, ss_delay, CTLFLAG_RW, 62184610Salfred &usb2_ss_delay, 0, "USB status stage delay in ms"); 63184610Salfred#endif 64184610Salfred 65184610Salfred/*------------------------------------------------------------------------* 66184610Salfred * usb2_do_request_callback 67184610Salfred * 68184610Salfred * This function is the USB callback for generic USB Host control 69184610Salfred * transfers. 70184610Salfred *------------------------------------------------------------------------*/ 71184610Salfredvoid 72184610Salfredusb2_do_request_callback(struct usb2_xfer *xfer) 73184610Salfred{ 74184610Salfred ; /* workaround for a bug in "indent" */ 75184610Salfred 76184610Salfred DPRINTF("st=%u\n", USB_GET_STATE(xfer)); 77184610Salfred 78184610Salfred switch (USB_GET_STATE(xfer)) { 79184610Salfred case USB_ST_SETUP: 80184610Salfred usb2_start_hardware(xfer); 81184610Salfred break; 82184610Salfred default: 83187173Sthompsa usb2_cv_signal(xfer->xroot->udev->default_cv); 84184610Salfred break; 85184610Salfred } 86184610Salfred} 87184610Salfred 88184610Salfred/*------------------------------------------------------------------------* 89184610Salfred * usb2_do_clear_stall_callback 90184610Salfred * 91184610Salfred * This function is the USB callback for generic clear stall requests. 92184610Salfred *------------------------------------------------------------------------*/ 93184610Salfredvoid 94184610Salfredusb2_do_clear_stall_callback(struct usb2_xfer *xfer) 95184610Salfred{ 96184610Salfred struct usb2_device_request req; 97187173Sthompsa struct usb2_device *udev; 98184610Salfred struct usb2_pipe *pipe; 99184610Salfred struct usb2_pipe *pipe_end; 100184610Salfred struct usb2_pipe *pipe_first; 101184610Salfred uint8_t to = USB_EP_MAX; 102184610Salfred 103187173Sthompsa udev = xfer->xroot->udev; 104184610Salfred 105187173Sthompsa USB_BUS_LOCK(udev->bus); 106187173Sthompsa 107184610Salfred /* round robin pipe clear stall */ 108184610Salfred 109187173Sthompsa pipe = udev->pipe_curr; 110187173Sthompsa pipe_end = udev->pipes + USB_EP_MAX; 111187173Sthompsa pipe_first = udev->pipes; 112184610Salfred if (pipe == NULL) { 113184610Salfred pipe = pipe_first; 114184610Salfred } 115184610Salfred switch (USB_GET_STATE(xfer)) { 116184610Salfred case USB_ST_TRANSFERRED: 117184610Salfred if (pipe->edesc && 118184610Salfred pipe->is_stalled) { 119184610Salfred pipe->toggle_next = 0; 120184610Salfred pipe->is_stalled = 0; 121184610Salfred /* start up the current or next transfer, if any */ 122184610Salfred usb2_command_wrapper(&pipe->pipe_q, 123184610Salfred pipe->pipe_q.curr); 124184610Salfred } 125184610Salfred pipe++; 126184610Salfred 127184610Salfred case USB_ST_SETUP: 128184610Salfredtr_setup: 129184610Salfred if (pipe == pipe_end) { 130184610Salfred pipe = pipe_first; 131184610Salfred } 132184610Salfred if (pipe->edesc && 133184610Salfred pipe->is_stalled) { 134184610Salfred 135184610Salfred /* setup a clear-stall packet */ 136184610Salfred 137184610Salfred req.bmRequestType = UT_WRITE_ENDPOINT; 138184610Salfred req.bRequest = UR_CLEAR_FEATURE; 139184610Salfred USETW(req.wValue, UF_ENDPOINT_HALT); 140184610Salfred req.wIndex[0] = pipe->edesc->bEndpointAddress; 141184610Salfred req.wIndex[1] = 0; 142184610Salfred USETW(req.wLength, 0); 143184610Salfred 144184610Salfred /* copy in the transfer */ 145184610Salfred 146184610Salfred usb2_copy_in(xfer->frbuffers, 0, &req, sizeof(req)); 147184610Salfred 148184610Salfred /* set length */ 149184610Salfred xfer->frlengths[0] = sizeof(req); 150184610Salfred xfer->nframes = 1; 151187173Sthompsa USB_BUS_UNLOCK(udev->bus); 152184610Salfred 153184610Salfred usb2_start_hardware(xfer); 154184610Salfred 155187173Sthompsa USB_BUS_LOCK(udev->bus); 156184610Salfred break; 157184610Salfred } 158184610Salfred pipe++; 159184610Salfred if (--to) 160184610Salfred goto tr_setup; 161184610Salfred break; 162184610Salfred 163184610Salfred default: 164184610Salfred if (xfer->error == USB_ERR_CANCELLED) { 165184610Salfred break; 166184610Salfred } 167184610Salfred goto tr_setup; 168184610Salfred } 169184610Salfred 170184610Salfred /* store current pipe */ 171187173Sthompsa udev->pipe_curr = pipe; 172187173Sthompsa USB_BUS_UNLOCK(udev->bus); 173184610Salfred} 174184610Salfred 175184610Salfred/*------------------------------------------------------------------------* 176184610Salfred * usb2_do_request_flags and usb2_do_request 177184610Salfred * 178184610Salfred * Description of arguments passed to these functions: 179184610Salfred * 180184610Salfred * "udev" - this is the "usb2_device" structure pointer on which the 181184610Salfred * request should be performed. It is possible to call this function 182184610Salfred * in both Host Side mode and Device Side mode. 183184610Salfred * 184184610Salfred * "mtx" - if this argument is non-NULL the mutex pointed to by it 185184610Salfred * will get dropped and picked up during the execution of this 186184610Salfred * function, hence this function sometimes needs to sleep. If this 187184610Salfred * argument is NULL it has no effect. 188184610Salfred * 189184610Salfred * "req" - this argument must always be non-NULL and points to an 190184610Salfred * 8-byte structure holding the USB request to be done. The USB 191184610Salfred * request structure has a bit telling the direction of the USB 192184610Salfred * request, if it is a read or a write. 193184610Salfred * 194184610Salfred * "data" - if the "wLength" part of the structure pointed to by "req" 195184610Salfred * is non-zero this argument must point to a valid kernel buffer which 196184610Salfred * can hold at least "wLength" bytes. If "wLength" is zero "data" can 197184610Salfred * be NULL. 198184610Salfred * 199184610Salfred * "flags" - here is a list of valid flags: 200184610Salfred * 201184610Salfred * o USB_SHORT_XFER_OK: allows the data transfer to be shorter than 202184610Salfred * specified 203184610Salfred * 204184610Salfred * o USB_USE_POLLING: forces the transfer to complete from the 205184610Salfred * current context by polling the interrupt handler. This flag can be 206184610Salfred * used to perform USB transfers after that the kernel has crashed. 207184610Salfred * 208184610Salfred * o USB_DELAY_STATUS_STAGE: allows the status stage to be performed 209184610Salfred * at a later point in time. This is tunable by the "hw.usb.ss_delay" 210184610Salfred * sysctl. This flag is mostly useful for debugging. 211184610Salfred * 212184610Salfred * o USB_USER_DATA_PTR: treat the "data" pointer like a userland 213184610Salfred * pointer. 214184610Salfred * 215184610Salfred * "actlen" - if non-NULL the actual transfer length will be stored in 216184610Salfred * the 16-bit unsigned integer pointed to by "actlen". This 217184610Salfred * information is mostly useful when the "USB_SHORT_XFER_OK" flag is 218184610Salfred * used. 219184610Salfred * 220184610Salfred * "timeout" - gives the timeout for the control transfer in 221184610Salfred * milliseconds. A "timeout" value less than 50 milliseconds is 222184610Salfred * treated like a 50 millisecond timeout. A "timeout" value greater 223184610Salfred * than 30 seconds is treated like a 30 second timeout. This USB stack 224184610Salfred * does not allow control requests without a timeout. 225184610Salfred * 226184610Salfred * NOTE: This function is thread safe. All calls to 227184610Salfred * "usb2_do_request_flags" will be serialised by the use of an 228184610Salfred * internal "sx_lock". 229184610Salfred * 230184610Salfred * Returns: 231184610Salfred * 0: Success 232184610Salfred * Else: Failure 233184610Salfred *------------------------------------------------------------------------*/ 234184610Salfredusb2_error_t 235184610Salfredusb2_do_request_flags(struct usb2_device *udev, struct mtx *mtx, 236184610Salfred struct usb2_device_request *req, void *data, uint32_t flags, 237184610Salfred uint16_t *actlen, uint32_t timeout) 238184610Salfred{ 239184610Salfred struct usb2_xfer *xfer; 240184610Salfred const void *desc; 241184610Salfred int err = 0; 242184610Salfred uint32_t start_ticks; 243184610Salfred uint32_t delta_ticks; 244184610Salfred uint32_t max_ticks; 245184610Salfred uint16_t length; 246184610Salfred uint16_t temp; 247184610Salfred 248184610Salfred if (timeout < 50) { 249184610Salfred /* timeout is too small */ 250184610Salfred timeout = 50; 251184610Salfred } 252184610Salfred if (timeout > 30000) { 253184610Salfred /* timeout is too big */ 254184610Salfred timeout = 30000; 255184610Salfred } 256184610Salfred length = UGETW(req->wLength); 257184610Salfred 258184610Salfred DPRINTFN(5, "udev=%p bmRequestType=0x%02x bRequest=0x%02x " 259184610Salfred "wValue=0x%02x%02x wIndex=0x%02x%02x wLength=0x%02x%02x\n", 260184610Salfred udev, req->bmRequestType, req->bRequest, 261184610Salfred req->wValue[1], req->wValue[0], 262184610Salfred req->wIndex[1], req->wIndex[0], 263184610Salfred req->wLength[1], req->wLength[0]); 264184610Salfred 265184610Salfred /* 266184610Salfred * Set "actlen" to a known value in case the caller does not 267184610Salfred * check the return value: 268184610Salfred */ 269184610Salfred if (actlen) { 270184610Salfred *actlen = 0; 271184610Salfred } 272184610Salfred if (udev->flags.usb2_mode == USB_MODE_DEVICE) { 273184610Salfred DPRINTF("USB device mode\n"); 274184610Salfred (usb2_temp_get_desc_p) (udev, req, &desc, &temp); 275184610Salfred if (length > temp) { 276184610Salfred if (!(flags & USB_SHORT_XFER_OK)) { 277184610Salfred return (USB_ERR_SHORT_XFER); 278184610Salfred } 279184610Salfred length = temp; 280184610Salfred } 281184610Salfred if (actlen) { 282184610Salfred *actlen = length; 283184610Salfred } 284184610Salfred if (length > 0) { 285184610Salfred if (flags & USB_USER_DATA_PTR) { 286184610Salfred if (copyout(desc, data, length)) { 287184610Salfred return (USB_ERR_INVAL); 288184610Salfred } 289184610Salfred } else { 290184610Salfred bcopy(desc, data, length); 291184610Salfred } 292184610Salfred } 293184610Salfred return (0); /* success */ 294184610Salfred } 295184610Salfred if (mtx) { 296184610Salfred mtx_unlock(mtx); 297184610Salfred if (mtx != &Giant) { 298184610Salfred mtx_assert(mtx, MA_NOTOWNED); 299184610Salfred } 300184610Salfred } 301184610Salfred /* 302184610Salfred * Grab the default sx-lock so that serialisation 303184610Salfred * is achieved when multiple threads are involved: 304184610Salfred */ 305184610Salfred 306184610Salfred sx_xlock(udev->default_sx); 307184610Salfred 308184610Salfred /* 309184610Salfred * Setup a new USB transfer or use the existing one, if any: 310184610Salfred */ 311184610Salfred usb2_default_transfer_setup(udev); 312184610Salfred 313184610Salfred xfer = udev->default_xfer[0]; 314184610Salfred if (xfer == NULL) { 315184610Salfred /* most likely out of memory */ 316184610Salfred err = USB_ERR_NOMEM; 317184610Salfred goto done; 318184610Salfred } 319184824Sthompsa USB_XFER_LOCK(xfer); 320184610Salfred 321184610Salfred if (flags & USB_DELAY_STATUS_STAGE) { 322184610Salfred xfer->flags.manual_status = 1; 323184610Salfred } else { 324184610Salfred xfer->flags.manual_status = 0; 325184610Salfred } 326184610Salfred 327184610Salfred xfer->timeout = timeout; 328184610Salfred 329184610Salfred start_ticks = ticks; 330184610Salfred 331184610Salfred max_ticks = USB_MS_TO_TICKS(timeout); 332184610Salfred 333184610Salfred usb2_copy_in(xfer->frbuffers, 0, req, sizeof(*req)); 334184610Salfred 335184610Salfred xfer->frlengths[0] = sizeof(*req); 336184610Salfred xfer->nframes = 2; 337184610Salfred 338184610Salfred while (1) { 339184610Salfred temp = length; 340184610Salfred if (temp > xfer->max_data_length) { 341184610Salfred temp = xfer->max_data_length; 342184610Salfred } 343184610Salfred xfer->frlengths[1] = temp; 344184610Salfred 345184610Salfred if (temp > 0) { 346184610Salfred if (!(req->bmRequestType & UT_READ)) { 347184610Salfred if (flags & USB_USER_DATA_PTR) { 348184824Sthompsa USB_XFER_UNLOCK(xfer); 349184610Salfred err = usb2_copy_in_user(xfer->frbuffers + 1, 350184610Salfred 0, data, temp); 351184824Sthompsa USB_XFER_LOCK(xfer); 352184610Salfred if (err) { 353184610Salfred err = USB_ERR_INVAL; 354184610Salfred break; 355184610Salfred } 356184610Salfred } else { 357184610Salfred usb2_copy_in(xfer->frbuffers + 1, 0, data, temp); 358184610Salfred } 359184610Salfred } 360184610Salfred xfer->nframes = 2; 361184610Salfred } else { 362184610Salfred if (xfer->frlengths[0] == 0) { 363184610Salfred if (xfer->flags.manual_status) { 364184610Salfred#if USB_DEBUG 365184610Salfred int temp; 366184610Salfred 367184610Salfred temp = usb2_ss_delay; 368184610Salfred if (temp > 5000) { 369184610Salfred temp = 5000; 370184610Salfred } 371184610Salfred if (temp > 0) { 372184610Salfred usb2_pause_mtx( 373187173Sthompsa xfer->xroot->xfer_mtx, 374187173Sthompsa temp); 375184610Salfred } 376184610Salfred#endif 377184610Salfred xfer->flags.manual_status = 0; 378184610Salfred } else { 379184610Salfred break; 380184610Salfred } 381184610Salfred } 382184610Salfred xfer->nframes = 1; 383184610Salfred } 384184610Salfred 385184610Salfred usb2_transfer_start(xfer); 386184610Salfred 387184610Salfred while (usb2_transfer_pending(xfer)) { 388184610Salfred if ((flags & USB_USE_POLLING) || cold) { 389184610Salfred usb2_do_poll(udev->default_xfer, USB_DEFAULT_XFER_MAX); 390184610Salfred } else { 391187173Sthompsa usb2_cv_wait(udev->default_cv, 392187173Sthompsa xfer->xroot->xfer_mtx); 393184610Salfred } 394184610Salfred } 395184610Salfred 396184610Salfred err = xfer->error; 397184610Salfred 398184610Salfred if (err) { 399184610Salfred break; 400184610Salfred } 401184610Salfred /* subtract length of SETUP packet, if any */ 402184610Salfred 403184610Salfred if (xfer->aframes > 0) { 404184610Salfred xfer->actlen -= xfer->frlengths[0]; 405184610Salfred } else { 406184610Salfred xfer->actlen = 0; 407184610Salfred } 408184610Salfred 409184610Salfred /* check for short packet */ 410184610Salfred 411184610Salfred if (temp > xfer->actlen) { 412184610Salfred temp = xfer->actlen; 413184610Salfred if (!(flags & USB_SHORT_XFER_OK)) { 414184610Salfred err = USB_ERR_SHORT_XFER; 415184610Salfred } 416184610Salfred length = temp; 417184610Salfred } 418184610Salfred if (temp > 0) { 419184610Salfred if (req->bmRequestType & UT_READ) { 420184610Salfred if (flags & USB_USER_DATA_PTR) { 421184824Sthompsa USB_XFER_UNLOCK(xfer); 422184610Salfred err = usb2_copy_out_user(xfer->frbuffers + 1, 423184610Salfred 0, data, temp); 424184824Sthompsa USB_XFER_LOCK(xfer); 425184610Salfred if (err) { 426184610Salfred err = USB_ERR_INVAL; 427184610Salfred break; 428184610Salfred } 429184610Salfred } else { 430184610Salfred usb2_copy_out(xfer->frbuffers + 1, 431184610Salfred 0, data, temp); 432184610Salfred } 433184610Salfred } 434184610Salfred } 435184610Salfred /* 436184610Salfred * Clear "frlengths[0]" so that we don't send the setup 437184610Salfred * packet again: 438184610Salfred */ 439184610Salfred xfer->frlengths[0] = 0; 440184610Salfred 441184610Salfred /* update length and data pointer */ 442184610Salfred length -= temp; 443184610Salfred data = USB_ADD_BYTES(data, temp); 444184610Salfred 445184610Salfred if (actlen) { 446184610Salfred (*actlen) += temp; 447184610Salfred } 448184610Salfred /* check for timeout */ 449184610Salfred 450184610Salfred delta_ticks = ticks - start_ticks; 451184610Salfred if (delta_ticks > max_ticks) { 452184610Salfred if (!err) { 453184610Salfred err = USB_ERR_TIMEOUT; 454184610Salfred } 455184610Salfred } 456184610Salfred if (err) { 457184610Salfred break; 458184610Salfred } 459184610Salfred } 460184610Salfred 461184610Salfred if (err) { 462184610Salfred /* 463184610Salfred * Make sure that the control endpoint is no longer 464184610Salfred * blocked in case of a non-transfer related error: 465184610Salfred */ 466184610Salfred usb2_transfer_stop(xfer); 467184610Salfred } 468184824Sthompsa USB_XFER_UNLOCK(xfer); 469184610Salfred 470184610Salfreddone: 471184610Salfred sx_xunlock(udev->default_sx); 472184610Salfred 473184610Salfred if (mtx) { 474184610Salfred mtx_lock(mtx); 475184610Salfred } 476184610Salfred return ((usb2_error_t)err); 477184610Salfred} 478184610Salfred 479184610Salfred/*------------------------------------------------------------------------* 480184610Salfred * usb2_req_reset_port 481184610Salfred * 482184610Salfred * This function will instruct an USB HUB to perform a reset sequence 483184610Salfred * on the specified port number. 484184610Salfred * 485184610Salfred * Returns: 486184610Salfred * 0: Success. The USB device should now be at address zero. 487184610Salfred * Else: Failure. No USB device is present and the USB port should be 488184610Salfred * disabled. 489184610Salfred *------------------------------------------------------------------------*/ 490184610Salfredusb2_error_t 491184610Salfredusb2_req_reset_port(struct usb2_device *udev, struct mtx *mtx, uint8_t port) 492184610Salfred{ 493184610Salfred struct usb2_port_status ps; 494184610Salfred usb2_error_t err; 495184610Salfred uint16_t n; 496184610Salfred 497184610Salfred#if USB_DEBUG 498184610Salfred uint16_t pr_poll_delay; 499184610Salfred uint16_t pr_recovery_delay; 500184610Salfred 501184610Salfred#endif 502184610Salfred err = usb2_req_set_port_feature(udev, mtx, port, UHF_PORT_RESET); 503184610Salfred if (err) { 504184610Salfred goto done; 505184610Salfred } 506184610Salfred#if USB_DEBUG 507184610Salfred /* range check input parameters */ 508184610Salfred pr_poll_delay = usb2_pr_poll_delay; 509184610Salfred if (pr_poll_delay < 1) { 510184610Salfred pr_poll_delay = 1; 511184610Salfred } else if (pr_poll_delay > 1000) { 512184610Salfred pr_poll_delay = 1000; 513184610Salfred } 514184610Salfred pr_recovery_delay = usb2_pr_recovery_delay; 515184610Salfred if (pr_recovery_delay > 1000) { 516184610Salfred pr_recovery_delay = 1000; 517184610Salfred } 518184610Salfred#endif 519184610Salfred n = 0; 520184610Salfred while (1) { 521184610Salfred#if USB_DEBUG 522184610Salfred /* wait for the device to recover from reset */ 523184610Salfred usb2_pause_mtx(mtx, pr_poll_delay); 524184610Salfred n += pr_poll_delay; 525184610Salfred#else 526184610Salfred /* wait for the device to recover from reset */ 527184610Salfred usb2_pause_mtx(mtx, USB_PORT_RESET_DELAY); 528184610Salfred n += USB_PORT_RESET_DELAY; 529184610Salfred#endif 530184610Salfred err = usb2_req_get_port_status(udev, mtx, &ps, port); 531184610Salfred if (err) { 532184610Salfred goto done; 533184610Salfred } 534184610Salfred /* if the device disappeared, just give up */ 535184610Salfred if (!(UGETW(ps.wPortStatus) & UPS_CURRENT_CONNECT_STATUS)) { 536184610Salfred goto done; 537184610Salfred } 538184610Salfred /* check if reset is complete */ 539184610Salfred if (UGETW(ps.wPortChange) & UPS_C_PORT_RESET) { 540184610Salfred break; 541184610Salfred } 542184610Salfred /* check for timeout */ 543184610Salfred if (n > 1000) { 544184610Salfred n = 0; 545184610Salfred break; 546184610Salfred } 547184610Salfred } 548184610Salfred 549184610Salfred /* clear port reset first */ 550184610Salfred err = usb2_req_clear_port_feature( 551184610Salfred udev, mtx, port, UHF_C_PORT_RESET); 552184610Salfred if (err) { 553184610Salfred goto done; 554184610Salfred } 555184610Salfred /* check for timeout */ 556184610Salfred if (n == 0) { 557184610Salfred err = USB_ERR_TIMEOUT; 558184610Salfred goto done; 559184610Salfred } 560184610Salfred#if USB_DEBUG 561184610Salfred /* wait for the device to recover from reset */ 562184610Salfred usb2_pause_mtx(mtx, pr_recovery_delay); 563184610Salfred#else 564184610Salfred /* wait for the device to recover from reset */ 565184610Salfred usb2_pause_mtx(mtx, USB_PORT_RESET_RECOVERY); 566184610Salfred#endif 567184610Salfred 568184610Salfreddone: 569184610Salfred DPRINTFN(2, "port %d reset returning error=%s\n", 570184610Salfred port, usb2_errstr(err)); 571184610Salfred return (err); 572184610Salfred} 573184610Salfred 574184610Salfred/*------------------------------------------------------------------------* 575184610Salfred * usb2_req_get_desc 576184610Salfred * 577184610Salfred * This function can be used to retrieve USB descriptors. It contains 578184610Salfred * some additional logic like zeroing of missing descriptor bytes and 579184610Salfred * retrying an USB descriptor in case of failure. The "min_len" 580184610Salfred * argument specifies the minimum descriptor length. The "max_len" 581184610Salfred * argument specifies the maximum descriptor length. If the real 582184610Salfred * descriptor length is less than the minimum length the missing 583184610Salfred * byte(s) will be zeroed. The length field, first byte, of the USB 584184610Salfred * descriptor will get overwritten in case it indicates a length that 585184610Salfred * is too big. Also the type field, second byte, of the USB descriptor 586184610Salfred * will get forced to the correct type. 587184610Salfred * 588184610Salfred * Returns: 589184610Salfred * 0: Success 590184610Salfred * Else: Failure 591184610Salfred *------------------------------------------------------------------------*/ 592184610Salfredusb2_error_t 593184610Salfredusb2_req_get_desc(struct usb2_device *udev, struct mtx *mtx, void *desc, 594184610Salfred uint16_t min_len, uint16_t max_len, 595184610Salfred uint16_t id, uint8_t type, uint8_t index, 596184610Salfred uint8_t retries) 597184610Salfred{ 598184610Salfred struct usb2_device_request req; 599184610Salfred uint8_t *buf; 600184610Salfred usb2_error_t err; 601184610Salfred 602184610Salfred DPRINTFN(4, "id=%d, type=%d, index=%d, max_len=%d\n", 603184610Salfred id, type, index, max_len); 604184610Salfred 605184610Salfred req.bmRequestType = UT_READ_DEVICE; 606184610Salfred req.bRequest = UR_GET_DESCRIPTOR; 607184610Salfred USETW2(req.wValue, type, index); 608184610Salfred USETW(req.wIndex, id); 609184610Salfred 610184610Salfred while (1) { 611184610Salfred 612184610Salfred if ((min_len < 2) || (max_len < 2)) { 613184610Salfred err = USB_ERR_INVAL; 614184610Salfred goto done; 615184610Salfred } 616184610Salfred USETW(req.wLength, min_len); 617184610Salfred 618186730Salfred err = usb2_do_request_flags(udev, mtx, &req, 619186730Salfred desc, 0, NULL, 1000); 620184610Salfred 621184610Salfred if (err) { 622184610Salfred if (!retries) { 623184610Salfred goto done; 624184610Salfred } 625184610Salfred retries--; 626184610Salfred 627184610Salfred usb2_pause_mtx(mtx, 200); 628184610Salfred 629184610Salfred continue; 630184610Salfred } 631184610Salfred buf = desc; 632184610Salfred 633184610Salfred if (min_len == max_len) { 634184610Salfred 635184610Salfred /* enforce correct type and length */ 636184610Salfred 637184610Salfred if (buf[0] > min_len) { 638184610Salfred buf[0] = min_len; 639184610Salfred } 640184610Salfred buf[1] = type; 641184610Salfred 642184610Salfred goto done; 643184610Salfred } 644184610Salfred /* range check */ 645184610Salfred 646184610Salfred if (max_len > buf[0]) { 647184610Salfred max_len = buf[0]; 648184610Salfred } 649184610Salfred /* zero minimum data */ 650184610Salfred 651184610Salfred while (min_len > max_len) { 652184610Salfred min_len--; 653184610Salfred buf[min_len] = 0; 654184610Salfred } 655184610Salfred 656184610Salfred /* set new minimum length */ 657184610Salfred 658184610Salfred min_len = max_len; 659184610Salfred } 660184610Salfreddone: 661184610Salfred return (err); 662184610Salfred} 663184610Salfred 664184610Salfred/*------------------------------------------------------------------------* 665184610Salfred * usb2_req_get_string_any 666184610Salfred * 667184610Salfred * This function will return the string given by "string_index" 668184610Salfred * using the first language ID. The maximum length "len" includes 669184610Salfred * the terminating zero. The "len" argument should be twice as 670184610Salfred * big pluss 2 bytes, compared with the actual maximum string length ! 671184610Salfred * 672184610Salfred * Returns: 673184610Salfred * 0: Success 674184610Salfred * Else: Failure 675184610Salfred *------------------------------------------------------------------------*/ 676184610Salfredusb2_error_t 677184610Salfredusb2_req_get_string_any(struct usb2_device *udev, struct mtx *mtx, char *buf, 678184610Salfred uint16_t len, uint8_t string_index) 679184610Salfred{ 680184610Salfred char *s; 681184610Salfred uint8_t *temp; 682184610Salfred uint16_t i; 683184610Salfred uint16_t n; 684184610Salfred uint16_t c; 685184610Salfred uint8_t swap; 686184610Salfred usb2_error_t err; 687184610Salfred 688184610Salfred if (len == 0) { 689184610Salfred /* should not happen */ 690184610Salfred return (USB_ERR_NORMAL_COMPLETION); 691184610Salfred } 692184610Salfred if (string_index == 0) { 693184610Salfred /* this is the language table */ 694185087Salfred buf[0] = 0; 695184610Salfred return (USB_ERR_INVAL); 696184610Salfred } 697184610Salfred if (udev->flags.no_strings) { 698185087Salfred buf[0] = 0; 699184610Salfred return (USB_ERR_STALLED); 700184610Salfred } 701184610Salfred err = usb2_req_get_string_desc 702184610Salfred (udev, mtx, buf, len, udev->langid, string_index); 703184610Salfred if (err) { 704185087Salfred buf[0] = 0; 705184610Salfred return (err); 706184610Salfred } 707184610Salfred temp = (uint8_t *)buf; 708184610Salfred 709184610Salfred if (temp[0] < 2) { 710184610Salfred /* string length is too short */ 711185087Salfred buf[0] = 0; 712184610Salfred return (USB_ERR_INVAL); 713184610Salfred } 714184610Salfred /* reserve one byte for terminating zero */ 715184610Salfred len--; 716184610Salfred 717184610Salfred /* find maximum length */ 718184610Salfred s = buf; 719184610Salfred n = (temp[0] / 2) - 1; 720184610Salfred if (n > len) { 721184610Salfred n = len; 722184610Salfred } 723184610Salfred /* skip descriptor header */ 724184610Salfred temp += 2; 725184610Salfred 726184610Salfred /* reset swap state */ 727184610Salfred swap = 3; 728184610Salfred 729184610Salfred /* convert and filter */ 730184610Salfred for (i = 0; (i != n); i++) { 731184610Salfred c = UGETW(temp + (2 * i)); 732184610Salfred 733184610Salfred /* convert from Unicode, handle buggy strings */ 734184610Salfred if (((c & 0xff00) == 0) && (swap & 1)) { 735184610Salfred /* Little Endian, default */ 736184610Salfred *s = c; 737184610Salfred swap = 1; 738184610Salfred } else if (((c & 0x00ff) == 0) && (swap & 2)) { 739184610Salfred /* Big Endian */ 740184610Salfred *s = c >> 8; 741184610Salfred swap = 2; 742184610Salfred } else { 743185087Salfred /* silently skip bad character */ 744185087Salfred continue; 745184610Salfred } 746184610Salfred 747184610Salfred /* 748184610Salfred * Filter by default - we don't allow greater and less than 749184610Salfred * signs because they might confuse the dmesg printouts! 750184610Salfred */ 751184610Salfred if ((*s == '<') || (*s == '>') || (!isprint(*s))) { 752185087Salfred /* silently skip bad character */ 753185087Salfred continue; 754184610Salfred } 755184610Salfred s++; 756184610Salfred } 757185087Salfred *s = 0; /* zero terminate resulting string */ 758184610Salfred return (USB_ERR_NORMAL_COMPLETION); 759184610Salfred} 760184610Salfred 761184610Salfred/*------------------------------------------------------------------------* 762184610Salfred * usb2_req_get_string_desc 763184610Salfred * 764184610Salfred * If you don't know the language ID, consider using 765184610Salfred * "usb2_req_get_string_any()". 766184610Salfred * 767184610Salfred * Returns: 768184610Salfred * 0: Success 769184610Salfred * Else: Failure 770184610Salfred *------------------------------------------------------------------------*/ 771184610Salfredusb2_error_t 772184610Salfredusb2_req_get_string_desc(struct usb2_device *udev, struct mtx *mtx, void *sdesc, 773184610Salfred uint16_t max_len, uint16_t lang_id, 774184610Salfred uint8_t string_index) 775184610Salfred{ 776184610Salfred return (usb2_req_get_desc(udev, mtx, sdesc, 2, max_len, lang_id, 777184610Salfred UDESC_STRING, string_index, 0)); 778184610Salfred} 779184610Salfred 780184610Salfred/*------------------------------------------------------------------------* 781184610Salfred * usb2_req_get_config_desc 782184610Salfred * 783184610Salfred * Returns: 784184610Salfred * 0: Success 785184610Salfred * Else: Failure 786184610Salfred *------------------------------------------------------------------------*/ 787184610Salfredusb2_error_t 788184610Salfredusb2_req_get_config_desc(struct usb2_device *udev, struct mtx *mtx, 789184610Salfred struct usb2_config_descriptor *d, uint8_t conf_index) 790184610Salfred{ 791184610Salfred usb2_error_t err; 792184610Salfred 793184610Salfred DPRINTFN(4, "confidx=%d\n", conf_index); 794184610Salfred 795184610Salfred err = usb2_req_get_desc(udev, mtx, d, sizeof(*d), 796184610Salfred sizeof(*d), 0, UDESC_CONFIG, conf_index, 0); 797184610Salfred if (err) { 798184610Salfred goto done; 799184610Salfred } 800184610Salfred /* Extra sanity checking */ 801184610Salfred if (UGETW(d->wTotalLength) < sizeof(*d)) { 802184610Salfred err = USB_ERR_INVAL; 803184610Salfred } 804184610Salfreddone: 805184610Salfred return (err); 806184610Salfred} 807184610Salfred 808184610Salfred/*------------------------------------------------------------------------* 809184610Salfred * usb2_req_get_config_desc_full 810184610Salfred * 811184610Salfred * This function gets the complete USB configuration descriptor and 812184610Salfred * ensures that "wTotalLength" is correct. 813184610Salfred * 814184610Salfred * Returns: 815184610Salfred * 0: Success 816184610Salfred * Else: Failure 817184610Salfred *------------------------------------------------------------------------*/ 818184610Salfredusb2_error_t 819184610Salfredusb2_req_get_config_desc_full(struct usb2_device *udev, struct mtx *mtx, 820184610Salfred struct usb2_config_descriptor **ppcd, struct malloc_type *mtype, 821184610Salfred uint8_t index) 822184610Salfred{ 823184610Salfred struct usb2_config_descriptor cd; 824184610Salfred struct usb2_config_descriptor *cdesc; 825184610Salfred uint16_t len; 826184610Salfred usb2_error_t err; 827184610Salfred 828184610Salfred DPRINTFN(4, "index=%d\n", index); 829184610Salfred 830184610Salfred *ppcd = NULL; 831184610Salfred 832184610Salfred err = usb2_req_get_config_desc(udev, mtx, &cd, index); 833184610Salfred if (err) { 834184610Salfred return (err); 835184610Salfred } 836184610Salfred /* get full descriptor */ 837184610Salfred len = UGETW(cd.wTotalLength); 838184610Salfred if (len < sizeof(*cdesc)) { 839184610Salfred /* corrupt descriptor */ 840184610Salfred return (USB_ERR_INVAL); 841184610Salfred } 842184610Salfred cdesc = malloc(len, mtype, M_WAITOK); 843184610Salfred if (cdesc == NULL) { 844184610Salfred return (USB_ERR_NOMEM); 845184610Salfred } 846184610Salfred err = usb2_req_get_desc(udev, mtx, cdesc, len, len, 0, 847184610Salfred UDESC_CONFIG, index, 3); 848184610Salfred if (err) { 849184610Salfred free(cdesc, mtype); 850184610Salfred return (err); 851184610Salfred } 852184610Salfred /* make sure that the device is not fooling us: */ 853184610Salfred USETW(cdesc->wTotalLength, len); 854184610Salfred 855184610Salfred *ppcd = cdesc; 856184610Salfred 857184610Salfred return (0); /* success */ 858184610Salfred} 859184610Salfred 860184610Salfred/*------------------------------------------------------------------------* 861184610Salfred * usb2_req_get_device_desc 862184610Salfred * 863184610Salfred * Returns: 864184610Salfred * 0: Success 865184610Salfred * Else: Failure 866184610Salfred *------------------------------------------------------------------------*/ 867184610Salfredusb2_error_t 868184610Salfredusb2_req_get_device_desc(struct usb2_device *udev, struct mtx *mtx, 869184610Salfred struct usb2_device_descriptor *d) 870184610Salfred{ 871184610Salfred DPRINTFN(4, "\n"); 872184610Salfred return (usb2_req_get_desc(udev, mtx, d, sizeof(*d), 873184610Salfred sizeof(*d), 0, UDESC_DEVICE, 0, 3)); 874184610Salfred} 875184610Salfred 876184610Salfred/*------------------------------------------------------------------------* 877184610Salfred * usb2_req_get_alt_interface_no 878184610Salfred * 879184610Salfred * Returns: 880184610Salfred * 0: Success 881184610Salfred * Else: Failure 882184610Salfred *------------------------------------------------------------------------*/ 883184610Salfredusb2_error_t 884184610Salfredusb2_req_get_alt_interface_no(struct usb2_device *udev, struct mtx *mtx, 885184610Salfred uint8_t *alt_iface_no, uint8_t iface_index) 886184610Salfred{ 887184610Salfred struct usb2_interface *iface = usb2_get_iface(udev, iface_index); 888184610Salfred struct usb2_device_request req; 889184610Salfred 890184610Salfred if ((iface == NULL) || (iface->idesc == NULL)) { 891184610Salfred return (USB_ERR_INVAL); 892184610Salfred } 893184610Salfred req.bmRequestType = UT_READ_INTERFACE; 894184610Salfred req.bRequest = UR_GET_INTERFACE; 895184610Salfred USETW(req.wValue, 0); 896184610Salfred req.wIndex[0] = iface->idesc->bInterfaceNumber; 897184610Salfred req.wIndex[1] = 0; 898184610Salfred USETW(req.wLength, 1); 899184610Salfred return (usb2_do_request(udev, mtx, &req, alt_iface_no)); 900184610Salfred} 901184610Salfred 902184610Salfred/*------------------------------------------------------------------------* 903184610Salfred * usb2_req_set_alt_interface_no 904184610Salfred * 905184610Salfred * Returns: 906184610Salfred * 0: Success 907184610Salfred * Else: Failure 908184610Salfred *------------------------------------------------------------------------*/ 909184610Salfredusb2_error_t 910184610Salfredusb2_req_set_alt_interface_no(struct usb2_device *udev, struct mtx *mtx, 911184610Salfred uint8_t iface_index, uint8_t alt_no) 912184610Salfred{ 913184610Salfred struct usb2_interface *iface = usb2_get_iface(udev, iface_index); 914184610Salfred struct usb2_device_request req; 915184610Salfred 916184610Salfred if ((iface == NULL) || (iface->idesc == NULL)) { 917184610Salfred return (USB_ERR_INVAL); 918184610Salfred } 919184610Salfred req.bmRequestType = UT_WRITE_INTERFACE; 920184610Salfred req.bRequest = UR_SET_INTERFACE; 921184610Salfred req.wValue[0] = alt_no; 922184610Salfred req.wValue[1] = 0; 923184610Salfred req.wIndex[0] = iface->idesc->bInterfaceNumber; 924184610Salfred req.wIndex[1] = 0; 925184610Salfred USETW(req.wLength, 0); 926184610Salfred return (usb2_do_request(udev, mtx, &req, 0)); 927184610Salfred} 928184610Salfred 929184610Salfred/*------------------------------------------------------------------------* 930184610Salfred * usb2_req_get_device_status 931184610Salfred * 932184610Salfred * Returns: 933184610Salfred * 0: Success 934184610Salfred * Else: Failure 935184610Salfred *------------------------------------------------------------------------*/ 936184610Salfredusb2_error_t 937184610Salfredusb2_req_get_device_status(struct usb2_device *udev, struct mtx *mtx, 938184610Salfred struct usb2_status *st) 939184610Salfred{ 940184610Salfred struct usb2_device_request req; 941184610Salfred 942184610Salfred req.bmRequestType = UT_READ_DEVICE; 943184610Salfred req.bRequest = UR_GET_STATUS; 944184610Salfred USETW(req.wValue, 0); 945184610Salfred USETW(req.wIndex, 0); 946184610Salfred USETW(req.wLength, sizeof(*st)); 947184610Salfred return (usb2_do_request(udev, mtx, &req, st)); 948184610Salfred} 949184610Salfred 950184610Salfred/*------------------------------------------------------------------------* 951184610Salfred * usb2_req_get_hub_descriptor 952184610Salfred * 953184610Salfred * Returns: 954184610Salfred * 0: Success 955184610Salfred * Else: Failure 956184610Salfred *------------------------------------------------------------------------*/ 957184610Salfredusb2_error_t 958184610Salfredusb2_req_get_hub_descriptor(struct usb2_device *udev, struct mtx *mtx, 959184610Salfred struct usb2_hub_descriptor *hd, uint8_t nports) 960184610Salfred{ 961184610Salfred struct usb2_device_request req; 962184610Salfred uint16_t len = (nports + 7 + (8 * 8)) / 8; 963184610Salfred 964184610Salfred req.bmRequestType = UT_READ_CLASS_DEVICE; 965184610Salfred req.bRequest = UR_GET_DESCRIPTOR; 966184610Salfred USETW2(req.wValue, UDESC_HUB, 0); 967184610Salfred USETW(req.wIndex, 0); 968184610Salfred USETW(req.wLength, len); 969184610Salfred return (usb2_do_request(udev, mtx, &req, hd)); 970184610Salfred} 971184610Salfred 972184610Salfred/*------------------------------------------------------------------------* 973184610Salfred * usb2_req_get_hub_status 974184610Salfred * 975184610Salfred * Returns: 976184610Salfred * 0: Success 977184610Salfred * Else: Failure 978184610Salfred *------------------------------------------------------------------------*/ 979184610Salfredusb2_error_t 980184610Salfredusb2_req_get_hub_status(struct usb2_device *udev, struct mtx *mtx, 981184610Salfred struct usb2_hub_status *st) 982184610Salfred{ 983184610Salfred struct usb2_device_request req; 984184610Salfred 985184610Salfred req.bmRequestType = UT_READ_CLASS_DEVICE; 986184610Salfred req.bRequest = UR_GET_STATUS; 987184610Salfred USETW(req.wValue, 0); 988184610Salfred USETW(req.wIndex, 0); 989184610Salfred USETW(req.wLength, sizeof(struct usb2_hub_status)); 990184610Salfred return (usb2_do_request(udev, mtx, &req, st)); 991184610Salfred} 992184610Salfred 993184610Salfred/*------------------------------------------------------------------------* 994184610Salfred * usb2_req_set_address 995184610Salfred * 996184610Salfred * This function is used to set the address for an USB device. After 997184610Salfred * port reset the USB device will respond at address zero. 998184610Salfred * 999184610Salfred * Returns: 1000184610Salfred * 0: Success 1001184610Salfred * Else: Failure 1002184610Salfred *------------------------------------------------------------------------*/ 1003184610Salfredusb2_error_t 1004184610Salfredusb2_req_set_address(struct usb2_device *udev, struct mtx *mtx, uint16_t addr) 1005184610Salfred{ 1006184610Salfred struct usb2_device_request req; 1007184610Salfred 1008184610Salfred DPRINTFN(6, "setting device address=%d\n", addr); 1009184610Salfred 1010184610Salfred req.bmRequestType = UT_WRITE_DEVICE; 1011184610Salfred req.bRequest = UR_SET_ADDRESS; 1012184610Salfred USETW(req.wValue, addr); 1013184610Salfred USETW(req.wIndex, 0); 1014184610Salfred USETW(req.wLength, 0); 1015184610Salfred 1016184610Salfred /* Setting the address should not take more than 1 second ! */ 1017184610Salfred return (usb2_do_request_flags(udev, mtx, &req, NULL, 1018184610Salfred USB_DELAY_STATUS_STAGE, NULL, 1000)); 1019184610Salfred} 1020184610Salfred 1021184610Salfred/*------------------------------------------------------------------------* 1022184610Salfred * usb2_req_get_port_status 1023184610Salfred * 1024184610Salfred * Returns: 1025184610Salfred * 0: Success 1026184610Salfred * Else: Failure 1027184610Salfred *------------------------------------------------------------------------*/ 1028184610Salfredusb2_error_t 1029184610Salfredusb2_req_get_port_status(struct usb2_device *udev, struct mtx *mtx, 1030184610Salfred struct usb2_port_status *ps, uint8_t port) 1031184610Salfred{ 1032184610Salfred struct usb2_device_request req; 1033184610Salfred 1034184610Salfred req.bmRequestType = UT_READ_CLASS_OTHER; 1035184610Salfred req.bRequest = UR_GET_STATUS; 1036184610Salfred USETW(req.wValue, 0); 1037184610Salfred req.wIndex[0] = port; 1038184610Salfred req.wIndex[1] = 0; 1039184610Salfred USETW(req.wLength, sizeof *ps); 1040184610Salfred return (usb2_do_request(udev, mtx, &req, ps)); 1041184610Salfred} 1042184610Salfred 1043184610Salfred/*------------------------------------------------------------------------* 1044184610Salfred * usb2_req_clear_hub_feature 1045184610Salfred * 1046184610Salfred * Returns: 1047184610Salfred * 0: Success 1048184610Salfred * Else: Failure 1049184610Salfred *------------------------------------------------------------------------*/ 1050184610Salfredusb2_error_t 1051184610Salfredusb2_req_clear_hub_feature(struct usb2_device *udev, struct mtx *mtx, 1052184610Salfred uint16_t sel) 1053184610Salfred{ 1054184610Salfred struct usb2_device_request req; 1055184610Salfred 1056184610Salfred req.bmRequestType = UT_WRITE_CLASS_DEVICE; 1057184610Salfred req.bRequest = UR_CLEAR_FEATURE; 1058184610Salfred USETW(req.wValue, sel); 1059184610Salfred USETW(req.wIndex, 0); 1060184610Salfred USETW(req.wLength, 0); 1061184610Salfred return (usb2_do_request(udev, mtx, &req, 0)); 1062184610Salfred} 1063184610Salfred 1064184610Salfred/*------------------------------------------------------------------------* 1065184610Salfred * usb2_req_set_hub_feature 1066184610Salfred * 1067184610Salfred * Returns: 1068184610Salfred * 0: Success 1069184610Salfred * Else: Failure 1070184610Salfred *------------------------------------------------------------------------*/ 1071184610Salfredusb2_error_t 1072184610Salfredusb2_req_set_hub_feature(struct usb2_device *udev, struct mtx *mtx, 1073184610Salfred uint16_t sel) 1074184610Salfred{ 1075184610Salfred struct usb2_device_request req; 1076184610Salfred 1077184610Salfred req.bmRequestType = UT_WRITE_CLASS_DEVICE; 1078184610Salfred req.bRequest = UR_SET_FEATURE; 1079184610Salfred USETW(req.wValue, sel); 1080184610Salfred USETW(req.wIndex, 0); 1081184610Salfred USETW(req.wLength, 0); 1082184610Salfred return (usb2_do_request(udev, mtx, &req, 0)); 1083184610Salfred} 1084184610Salfred 1085184610Salfred/*------------------------------------------------------------------------* 1086184610Salfred * usb2_req_clear_port_feature 1087184610Salfred * 1088184610Salfred * Returns: 1089184610Salfred * 0: Success 1090184610Salfred * Else: Failure 1091184610Salfred *------------------------------------------------------------------------*/ 1092184610Salfredusb2_error_t 1093184610Salfredusb2_req_clear_port_feature(struct usb2_device *udev, struct mtx *mtx, 1094184610Salfred uint8_t port, uint16_t sel) 1095184610Salfred{ 1096184610Salfred struct usb2_device_request req; 1097184610Salfred 1098184610Salfred req.bmRequestType = UT_WRITE_CLASS_OTHER; 1099184610Salfred req.bRequest = UR_CLEAR_FEATURE; 1100184610Salfred USETW(req.wValue, sel); 1101184610Salfred req.wIndex[0] = port; 1102184610Salfred req.wIndex[1] = 0; 1103184610Salfred USETW(req.wLength, 0); 1104184610Salfred return (usb2_do_request(udev, mtx, &req, 0)); 1105184610Salfred} 1106184610Salfred 1107184610Salfred/*------------------------------------------------------------------------* 1108184610Salfred * usb2_req_set_port_feature 1109184610Salfred * 1110184610Salfred * Returns: 1111184610Salfred * 0: Success 1112184610Salfred * Else: Failure 1113184610Salfred *------------------------------------------------------------------------*/ 1114184610Salfredusb2_error_t 1115184610Salfredusb2_req_set_port_feature(struct usb2_device *udev, struct mtx *mtx, 1116184610Salfred uint8_t port, uint16_t sel) 1117184610Salfred{ 1118184610Salfred struct usb2_device_request req; 1119184610Salfred 1120184610Salfred req.bmRequestType = UT_WRITE_CLASS_OTHER; 1121184610Salfred req.bRequest = UR_SET_FEATURE; 1122184610Salfred USETW(req.wValue, sel); 1123184610Salfred req.wIndex[0] = port; 1124184610Salfred req.wIndex[1] = 0; 1125184610Salfred USETW(req.wLength, 0); 1126184610Salfred return (usb2_do_request(udev, mtx, &req, 0)); 1127184610Salfred} 1128184610Salfred 1129184610Salfred/*------------------------------------------------------------------------* 1130184610Salfred * usb2_req_set_protocol 1131184610Salfred * 1132184610Salfred * Returns: 1133184610Salfred * 0: Success 1134184610Salfred * Else: Failure 1135184610Salfred *------------------------------------------------------------------------*/ 1136184610Salfredusb2_error_t 1137184610Salfredusb2_req_set_protocol(struct usb2_device *udev, struct mtx *mtx, 1138184610Salfred uint8_t iface_index, uint16_t report) 1139184610Salfred{ 1140184610Salfred struct usb2_interface *iface = usb2_get_iface(udev, iface_index); 1141184610Salfred struct usb2_device_request req; 1142184610Salfred 1143184610Salfred if ((iface == NULL) || (iface->idesc == NULL)) { 1144184610Salfred return (USB_ERR_INVAL); 1145184610Salfred } 1146184610Salfred DPRINTFN(5, "iface=%p, report=%d, endpt=%d\n", 1147184610Salfred iface, report, iface->idesc->bInterfaceNumber); 1148184610Salfred 1149184610Salfred req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 1150184610Salfred req.bRequest = UR_SET_PROTOCOL; 1151184610Salfred USETW(req.wValue, report); 1152184610Salfred req.wIndex[0] = iface->idesc->bInterfaceNumber; 1153184610Salfred req.wIndex[1] = 0; 1154184610Salfred USETW(req.wLength, 0); 1155184610Salfred return (usb2_do_request(udev, mtx, &req, 0)); 1156184610Salfred} 1157184610Salfred 1158184610Salfred/*------------------------------------------------------------------------* 1159184610Salfred * usb2_req_set_report 1160184610Salfred * 1161184610Salfred * Returns: 1162184610Salfred * 0: Success 1163184610Salfred * Else: Failure 1164184610Salfred *------------------------------------------------------------------------*/ 1165184610Salfredusb2_error_t 1166184610Salfredusb2_req_set_report(struct usb2_device *udev, struct mtx *mtx, void *data, uint16_t len, 1167184610Salfred uint8_t iface_index, uint8_t type, uint8_t id) 1168184610Salfred{ 1169184610Salfred struct usb2_interface *iface = usb2_get_iface(udev, iface_index); 1170184610Salfred struct usb2_device_request req; 1171184610Salfred 1172184610Salfred if ((iface == NULL) || (iface->idesc == NULL)) { 1173184610Salfred return (USB_ERR_INVAL); 1174184610Salfred } 1175184610Salfred DPRINTFN(5, "len=%d\n", len); 1176184610Salfred 1177184610Salfred req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 1178184610Salfred req.bRequest = UR_SET_REPORT; 1179184610Salfred USETW2(req.wValue, type, id); 1180184610Salfred req.wIndex[0] = iface->idesc->bInterfaceNumber; 1181184610Salfred req.wIndex[1] = 0; 1182184610Salfred USETW(req.wLength, len); 1183184610Salfred return (usb2_do_request(udev, mtx, &req, data)); 1184184610Salfred} 1185184610Salfred 1186184610Salfred/*------------------------------------------------------------------------* 1187184610Salfred * usb2_req_get_report 1188184610Salfred * 1189184610Salfred * Returns: 1190184610Salfred * 0: Success 1191184610Salfred * Else: Failure 1192184610Salfred *------------------------------------------------------------------------*/ 1193184610Salfredusb2_error_t 1194184610Salfredusb2_req_get_report(struct usb2_device *udev, struct mtx *mtx, void *data, 1195184610Salfred uint16_t len, uint8_t iface_index, uint8_t type, uint8_t id) 1196184610Salfred{ 1197184610Salfred struct usb2_interface *iface = usb2_get_iface(udev, iface_index); 1198184610Salfred struct usb2_device_request req; 1199184610Salfred 1200184610Salfred if ((iface == NULL) || (iface->idesc == NULL) || (id == 0)) { 1201184610Salfred return (USB_ERR_INVAL); 1202184610Salfred } 1203184610Salfred DPRINTFN(5, "len=%d\n", len); 1204184610Salfred 1205184610Salfred req.bmRequestType = UT_READ_CLASS_INTERFACE; 1206184610Salfred req.bRequest = UR_GET_REPORT; 1207184610Salfred USETW2(req.wValue, type, id); 1208184610Salfred req.wIndex[0] = iface->idesc->bInterfaceNumber; 1209184610Salfred req.wIndex[1] = 0; 1210184610Salfred USETW(req.wLength, len); 1211184610Salfred return (usb2_do_request(udev, mtx, &req, data)); 1212184610Salfred} 1213184610Salfred 1214184610Salfred/*------------------------------------------------------------------------* 1215184610Salfred * usb2_req_set_idle 1216184610Salfred * 1217184610Salfred * Returns: 1218184610Salfred * 0: Success 1219184610Salfred * Else: Failure 1220184610Salfred *------------------------------------------------------------------------*/ 1221184610Salfredusb2_error_t 1222184610Salfredusb2_req_set_idle(struct usb2_device *udev, struct mtx *mtx, 1223184610Salfred uint8_t iface_index, uint8_t duration, uint8_t id) 1224184610Salfred{ 1225184610Salfred struct usb2_interface *iface = usb2_get_iface(udev, iface_index); 1226184610Salfred struct usb2_device_request req; 1227184610Salfred 1228184610Salfred if ((iface == NULL) || (iface->idesc == NULL)) { 1229184610Salfred return (USB_ERR_INVAL); 1230184610Salfred } 1231184610Salfred DPRINTFN(5, "%d %d\n", duration, id); 1232184610Salfred 1233184610Salfred req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 1234184610Salfred req.bRequest = UR_SET_IDLE; 1235184610Salfred USETW2(req.wValue, duration, id); 1236184610Salfred req.wIndex[0] = iface->idesc->bInterfaceNumber; 1237184610Salfred req.wIndex[1] = 0; 1238184610Salfred USETW(req.wLength, 0); 1239184610Salfred return (usb2_do_request(udev, mtx, &req, 0)); 1240184610Salfred} 1241184610Salfred 1242184610Salfred/*------------------------------------------------------------------------* 1243184610Salfred * usb2_req_get_report_descriptor 1244184610Salfred * 1245184610Salfred * Returns: 1246184610Salfred * 0: Success 1247184610Salfred * Else: Failure 1248184610Salfred *------------------------------------------------------------------------*/ 1249184610Salfredusb2_error_t 1250184610Salfredusb2_req_get_report_descriptor(struct usb2_device *udev, struct mtx *mtx, 1251184610Salfred void *d, uint16_t size, uint8_t iface_index) 1252184610Salfred{ 1253184610Salfred struct usb2_interface *iface = usb2_get_iface(udev, iface_index); 1254184610Salfred struct usb2_device_request req; 1255184610Salfred 1256184610Salfred if ((iface == NULL) || (iface->idesc == NULL)) { 1257184610Salfred return (USB_ERR_INVAL); 1258184610Salfred } 1259184610Salfred req.bmRequestType = UT_READ_INTERFACE; 1260184610Salfred req.bRequest = UR_GET_DESCRIPTOR; 1261184610Salfred USETW2(req.wValue, UDESC_REPORT, 0); /* report id should be 0 */ 1262184610Salfred req.wIndex[0] = iface->idesc->bInterfaceNumber; 1263184610Salfred req.wIndex[1] = 0; 1264184610Salfred USETW(req.wLength, size); 1265184610Salfred return (usb2_do_request(udev, mtx, &req, d)); 1266184610Salfred} 1267184610Salfred 1268184610Salfred/*------------------------------------------------------------------------* 1269184610Salfred * usb2_req_set_config 1270184610Salfred * 1271184610Salfred * This function is used to select the current configuration number in 1272184610Salfred * both USB device side mode and USB host side mode. When setting the 1273184610Salfred * configuration the function of the interfaces can change. 1274184610Salfred * 1275184610Salfred * Returns: 1276184610Salfred * 0: Success 1277184610Salfred * Else: Failure 1278184610Salfred *------------------------------------------------------------------------*/ 1279184610Salfredusb2_error_t 1280184610Salfredusb2_req_set_config(struct usb2_device *udev, struct mtx *mtx, uint8_t conf) 1281184610Salfred{ 1282184610Salfred struct usb2_device_request req; 1283184610Salfred 1284184610Salfred DPRINTF("setting config %d\n", conf); 1285184610Salfred 1286184610Salfred /* do "set configuration" request */ 1287184610Salfred 1288184610Salfred req.bmRequestType = UT_WRITE_DEVICE; 1289184610Salfred req.bRequest = UR_SET_CONFIG; 1290184610Salfred req.wValue[0] = conf; 1291184610Salfred req.wValue[1] = 0; 1292184610Salfred USETW(req.wIndex, 0); 1293184610Salfred USETW(req.wLength, 0); 1294184610Salfred return (usb2_do_request(udev, mtx, &req, 0)); 1295184610Salfred} 1296184610Salfred 1297184610Salfred/*------------------------------------------------------------------------* 1298184610Salfred * usb2_req_get_config 1299184610Salfred * 1300184610Salfred * Returns: 1301184610Salfred * 0: Success 1302184610Salfred * Else: Failure 1303184610Salfred *------------------------------------------------------------------------*/ 1304184610Salfredusb2_error_t 1305184610Salfredusb2_req_get_config(struct usb2_device *udev, struct mtx *mtx, uint8_t *pconf) 1306184610Salfred{ 1307184610Salfred struct usb2_device_request req; 1308184610Salfred 1309184610Salfred req.bmRequestType = UT_READ_DEVICE; 1310184610Salfred req.bRequest = UR_GET_CONFIG; 1311184610Salfred USETW(req.wValue, 0); 1312184610Salfred USETW(req.wIndex, 0); 1313184610Salfred USETW(req.wLength, 1); 1314184610Salfred return (usb2_do_request(udev, mtx, &req, pconf)); 1315184610Salfred} 1316184610Salfred 1317184610Salfred/*------------------------------------------------------------------------* 1318184610Salfred * usb2_req_re_enumerate 1319184610Salfred * 1320185087Salfred * NOTE: After this function returns the hardware is in the 1321185087Salfred * unconfigured state! The application is responsible for setting a 1322185087Salfred * new configuration. 1323185087Salfred * 1324184610Salfred * Returns: 1325184610Salfred * 0: Success 1326184610Salfred * Else: Failure 1327184610Salfred *------------------------------------------------------------------------*/ 1328184610Salfredusb2_error_t 1329184610Salfredusb2_req_re_enumerate(struct usb2_device *udev, struct mtx *mtx) 1330184610Salfred{ 1331184610Salfred struct usb2_device *parent_hub; 1332184610Salfred usb2_error_t err; 1333184610Salfred uint8_t old_addr; 1334186730Salfred uint8_t do_retry = 1; 1335184610Salfred 1336185290Salfred if (udev->flags.usb2_mode != USB_MODE_HOST) { 1337185290Salfred return (USB_ERR_INVAL); 1338185290Salfred } 1339184610Salfred old_addr = udev->address; 1340184610Salfred parent_hub = udev->parent_hub; 1341184610Salfred if (parent_hub == NULL) { 1342185290Salfred return (USB_ERR_INVAL); 1343184610Salfred } 1344186730Salfredretry: 1345184610Salfred err = usb2_req_reset_port(parent_hub, mtx, udev->port_no); 1346184610Salfred if (err) { 1347184610Salfred DPRINTFN(0, "addr=%d, port reset failed\n", old_addr); 1348184610Salfred goto done; 1349184610Salfred } 1350184610Salfred /* 1351184610Salfred * After that the port has been reset our device should be at 1352184610Salfred * address zero: 1353184610Salfred */ 1354184610Salfred udev->address = USB_START_ADDR; 1355184610Salfred 1356185290Salfred /* reset "bMaxPacketSize" */ 1357185290Salfred udev->ddesc.bMaxPacketSize = USB_MAX_IPACKET; 1358185290Salfred 1359184610Salfred /* 1360184610Salfred * Restore device address: 1361184610Salfred */ 1362184610Salfred err = usb2_req_set_address(udev, mtx, old_addr); 1363184610Salfred if (err) { 1364184610Salfred /* XXX ignore any errors! */ 1365186730Salfred DPRINTFN(0, "addr=%d, set address failed! (ignored)\n", 1366184610Salfred old_addr); 1367184610Salfred } 1368184610Salfred /* restore device address */ 1369184610Salfred udev->address = old_addr; 1370184610Salfred 1371184610Salfred /* allow device time to set new address */ 1372184610Salfred usb2_pause_mtx(mtx, USB_SET_ADDRESS_SETTLE); 1373184610Salfred 1374184610Salfred /* get the device descriptor */ 1375185290Salfred err = usb2_req_get_desc(udev, mtx, &udev->ddesc, 1376185290Salfred USB_MAX_IPACKET, USB_MAX_IPACKET, 0, UDESC_DEVICE, 0, 0); 1377184610Salfred if (err) { 1378185290Salfred DPRINTFN(0, "getting device descriptor " 1379185290Salfred "at addr %d failed!\n", udev->address); 1380185290Salfred goto done; 1381185290Salfred } 1382185290Salfred /* get the full device descriptor */ 1383185290Salfred err = usb2_req_get_device_desc(udev, mtx, &udev->ddesc); 1384185290Salfred if (err) { 1385184610Salfred DPRINTFN(0, "addr=%d, getting device " 1386184610Salfred "descriptor failed!\n", old_addr); 1387184610Salfred goto done; 1388184610Salfred } 1389184610Salfreddone: 1390186730Salfred if (err && do_retry) { 1391186730Salfred /* give the USB firmware some time to load */ 1392186730Salfred usb2_pause_mtx(mtx, 500); 1393186730Salfred /* no more retries after this retry */ 1394186730Salfred do_retry = 0; 1395186730Salfred /* try again */ 1396186730Salfred goto retry; 1397186730Salfred } 1398184610Salfred /* restore address */ 1399184610Salfred udev->address = old_addr; 1400184610Salfred return (err); 1401184610Salfred} 1402186730Salfred 1403186730Salfred/*------------------------------------------------------------------------* 1404186730Salfred * usb2_req_clear_device_feature 1405186730Salfred * 1406186730Salfred * Returns: 1407186730Salfred * 0: Success 1408186730Salfred * Else: Failure 1409186730Salfred *------------------------------------------------------------------------*/ 1410186730Salfredusb2_error_t 1411186730Salfredusb2_req_clear_device_feature(struct usb2_device *udev, struct mtx *mtx, 1412186730Salfred uint16_t sel) 1413186730Salfred{ 1414186730Salfred struct usb2_device_request req; 1415186730Salfred 1416186730Salfred req.bmRequestType = UT_WRITE_DEVICE; 1417186730Salfred req.bRequest = UR_CLEAR_FEATURE; 1418186730Salfred USETW(req.wValue, sel); 1419186730Salfred USETW(req.wIndex, 0); 1420186730Salfred USETW(req.wLength, 0); 1421186730Salfred return (usb2_do_request(udev, mtx, &req, 0)); 1422186730Salfred} 1423186730Salfred 1424186730Salfred/*------------------------------------------------------------------------* 1425186730Salfred * usb2_req_set_device_feature 1426186730Salfred * 1427186730Salfred * Returns: 1428186730Salfred * 0: Success 1429186730Salfred * Else: Failure 1430186730Salfred *------------------------------------------------------------------------*/ 1431186730Salfredusb2_error_t 1432186730Salfredusb2_req_set_device_feature(struct usb2_device *udev, struct mtx *mtx, 1433186730Salfred uint16_t sel) 1434186730Salfred{ 1435186730Salfred struct usb2_device_request req; 1436186730Salfred 1437186730Salfred req.bmRequestType = UT_WRITE_DEVICE; 1438186730Salfred req.bRequest = UR_SET_FEATURE; 1439186730Salfred USETW(req.wValue, sel); 1440186730Salfred USETW(req.wIndex, 0); 1441186730Salfred USETW(req.wLength, 0); 1442186730Salfred return (usb2_do_request(udev, mtx, &req, 0)); 1443186730Salfred} 1444