usb_util.c revision 190180
1184610Salfred/* $FreeBSD: head/sys/dev/usb/usb_util.c 190180 2009-03-20 21:48:11Z thompsa $ */ 2184610Salfred/*- 3184610Salfred * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 4184610Salfred * 5184610Salfred * Redistribution and use in source and binary forms, with or without 6184610Salfred * modification, are permitted provided that the following conditions 7184610Salfred * are met: 8184610Salfred * 1. Redistributions of source code must retain the above copyright 9184610Salfred * notice, this list of conditions and the following disclaimer. 10184610Salfred * 2. Redistributions in binary form must reproduce the above copyright 11184610Salfred * notice, this list of conditions and the following disclaimer in the 12184610Salfred * documentation and/or other materials provided with the distribution. 13184610Salfred * 14184610Salfred * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15184610Salfred * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16184610Salfred * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17184610Salfred * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18184610Salfred * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19184610Salfred * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20184610Salfred * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21184610Salfred * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22184610Salfred * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23184610Salfred * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24184610Salfred * SUCH DAMAGE. 25184610Salfred */ 26184610Salfred 27188942Sthompsa#include <dev/usb/usb_mfunc.h> 28188942Sthompsa#include <dev/usb/usb_error.h> 29188942Sthompsa#include <dev/usb/usb.h> 30184610Salfred 31188942Sthompsa#include <dev/usb/usb_core.h> 32188942Sthompsa#include <dev/usb/usb_util.h> 33188942Sthompsa#include <dev/usb/usb_process.h> 34188942Sthompsa#include <dev/usb/usb_device.h> 35188942Sthompsa#include <dev/usb/usb_request.h> 36188942Sthompsa#include <dev/usb/usb_busdma.h> 37184610Salfred 38188942Sthompsa#include <dev/usb/usb_controller.h> 39188942Sthompsa#include <dev/usb/usb_bus.h> 40184610Salfred 41184610Salfred/* function prototypes */ 42190180Sthompsa#if (USB_HAVE_CONDVAR == 0) 43184610Salfredstatic int usb2_msleep(void *chan, struct mtx *mtx, int priority, const char *wmesg, int timo); 44184610Salfred 45184610Salfred#endif 46184610Salfred 47184610Salfred/*------------------------------------------------------------------------* 48184610Salfred * device_delete_all_children - delete all children of a device 49184610Salfred *------------------------------------------------------------------------*/ 50190180Sthompsa#ifndef device_delete_all_children 51184610Salfredint 52184610Salfreddevice_delete_all_children(device_t dev) 53184610Salfred{ 54184610Salfred device_t *devlist; 55184610Salfred int devcount; 56184610Salfred int error; 57184610Salfred 58184610Salfred error = device_get_children(dev, &devlist, &devcount); 59184610Salfred if (error == 0) { 60184610Salfred while (devcount-- > 0) { 61184610Salfred error = device_delete_child(dev, devlist[devcount]); 62184610Salfred if (error) { 63184610Salfred break; 64184610Salfred } 65184610Salfred } 66184610Salfred free(devlist, M_TEMP); 67184610Salfred } 68184610Salfred return (error); 69184610Salfred} 70190180Sthompsa#endif 71184610Salfred 72184610Salfred/*------------------------------------------------------------------------* 73184610Salfred * device_set_usb2_desc 74184610Salfred * 75184610Salfred * This function can be called at probe or attach to set the USB 76184610Salfred * device supplied textual description for the given device. 77184610Salfred *------------------------------------------------------------------------*/ 78184610Salfredvoid 79184610Salfreddevice_set_usb2_desc(device_t dev) 80184610Salfred{ 81190180Sthompsa#if USB_HAVE_STRINGS 82184610Salfred struct usb2_attach_arg *uaa; 83184610Salfred struct usb2_device *udev; 84184610Salfred struct usb2_interface *iface; 85184610Salfred char *temp_p; 86184610Salfred usb2_error_t err; 87184610Salfred 88184610Salfred if (dev == NULL) { 89184610Salfred /* should not happen */ 90184610Salfred return; 91184610Salfred } 92184610Salfred uaa = device_get_ivars(dev); 93184610Salfred if (uaa == NULL) { 94185087Salfred /* can happen if called at the wrong time */ 95184610Salfred return; 96184610Salfred } 97184610Salfred udev = uaa->device; 98184610Salfred iface = uaa->iface; 99184610Salfred 100184610Salfred if ((iface == NULL) || 101184610Salfred (iface->idesc == NULL) || 102184610Salfred (iface->idesc->iInterface == 0)) { 103184610Salfred err = USB_ERR_INVAL; 104184610Salfred } else { 105184610Salfred err = 0; 106184610Salfred } 107184610Salfred 108184610Salfred temp_p = (char *)udev->bus->scratch[0].data; 109184610Salfred 110184610Salfred if (!err) { 111184610Salfred /* try to get the interface string ! */ 112184610Salfred err = usb2_req_get_string_any 113184610Salfred (udev, NULL, temp_p, 114184610Salfred sizeof(udev->bus->scratch), iface->idesc->iInterface); 115184610Salfred } 116184610Salfred if (err) { 117184610Salfred /* use default description */ 118184610Salfred usb2_devinfo(udev, temp_p, 119184610Salfred sizeof(udev->bus->scratch)); 120184610Salfred } 121184610Salfred device_set_desc_copy(dev, temp_p); 122184610Salfred device_printf(dev, "<%s> on %s\n", temp_p, 123184610Salfred device_get_nameunit(udev->bus->bdev)); 124190180Sthompsa#endif 125184610Salfred} 126184610Salfred 127184610Salfred/*------------------------------------------------------------------------* 128184610Salfred * usb2_pause_mtx - factored out code 129184610Salfred * 130188411Sthompsa * This function will delay the code by the passed number of system 131188411Sthompsa * ticks. The passed mutex "mtx" will be dropped while waiting, if 132188411Sthompsa * "mtx" is not NULL. 133184610Salfred *------------------------------------------------------------------------*/ 134184610Salfredvoid 135188411Sthompsausb2_pause_mtx(struct mtx *mtx, int _ticks) 136184610Salfred{ 137188411Sthompsa if (mtx != NULL) 138188411Sthompsa mtx_unlock(mtx); 139188411Sthompsa 140184610Salfred if (cold) { 141188411Sthompsa /* convert to milliseconds */ 142188411Sthompsa _ticks = (_ticks * 1000) / hz; 143188411Sthompsa /* convert to microseconds, rounded up */ 144188411Sthompsa _ticks = (_ticks + 1) * 1000; 145188411Sthompsa DELAY(_ticks); 146184610Salfred 147184610Salfred } else { 148184610Salfred 149184610Salfred /* 150184610Salfred * Add one to the number of ticks so that we don't return 151184610Salfred * too early! 152184610Salfred */ 153188411Sthompsa _ticks++; 154184610Salfred 155188411Sthompsa if (pause("USBWAIT", _ticks)) { 156184610Salfred /* ignore */ 157184610Salfred } 158184610Salfred } 159188411Sthompsa if (mtx != NULL) 160188411Sthompsa mtx_lock(mtx); 161184610Salfred} 162184610Salfred 163184610Salfred/*------------------------------------------------------------------------* 164184610Salfred * usb2_printBCD 165184610Salfred * 166184610Salfred * This function will print the version number "bcd" to the string 167184610Salfred * pointed to by "p" having a maximum length of "p_len" bytes 168184610Salfred * including the terminating zero. 169184610Salfred *------------------------------------------------------------------------*/ 170190180Sthompsa#if USB_HAVE_STRINGS 171184610Salfredvoid 172184610Salfredusb2_printBCD(char *p, uint16_t p_len, uint16_t bcd) 173184610Salfred{ 174184610Salfred if (snprintf(p, p_len, "%x.%02x", bcd >> 8, bcd & 0xff)) { 175184610Salfred /* ignore any errors */ 176184610Salfred } 177184610Salfred} 178190180Sthompsa#endif 179184610Salfred 180184610Salfred/*------------------------------------------------------------------------* 181184610Salfred * usb2_trim_spaces 182184610Salfred * 183184610Salfred * This function removes spaces at the beginning and the end of the string 184184610Salfred * pointed to by the "p" argument. 185184610Salfred *------------------------------------------------------------------------*/ 186190180Sthompsa#if USB_HAVE_STRINGS 187184610Salfredvoid 188184610Salfredusb2_trim_spaces(char *p) 189184610Salfred{ 190184610Salfred char *q; 191184610Salfred char *e; 192184610Salfred 193184610Salfred if (p == NULL) 194184610Salfred return; 195184610Salfred q = e = p; 196184610Salfred while (*q == ' ') /* skip leading spaces */ 197184610Salfred q++; 198184610Salfred while ((*p = *q++)) /* copy string */ 199184610Salfred if (*p++ != ' ') /* remember last non-space */ 200184610Salfred e = p; 201184610Salfred *e = 0; /* kill trailing spaces */ 202184610Salfred} 203190180Sthompsa#endif 204184610Salfred 205184610Salfred/*------------------------------------------------------------------------* 206184610Salfred * usb2_get_devid 207184610Salfred * 208184610Salfred * This function returns the USB Vendor and Product ID like a 32-bit 209184610Salfred * unsigned integer. 210184610Salfred *------------------------------------------------------------------------*/ 211184610Salfreduint32_t 212184610Salfredusb2_get_devid(device_t dev) 213184610Salfred{ 214184610Salfred struct usb2_attach_arg *uaa = device_get_ivars(dev); 215184610Salfred 216184610Salfred return ((uaa->info.idVendor << 16) | (uaa->info.idProduct)); 217184610Salfred} 218184610Salfred 219184610Salfred/*------------------------------------------------------------------------* 220184610Salfred * usb2_make_str_desc - convert an ASCII string into a UNICODE string 221184610Salfred *------------------------------------------------------------------------*/ 222184610Salfreduint8_t 223184610Salfredusb2_make_str_desc(void *ptr, uint16_t max_len, const char *s) 224184610Salfred{ 225184610Salfred struct usb2_string_descriptor *p = ptr; 226184610Salfred uint8_t totlen; 227184610Salfred int j; 228184610Salfred 229184610Salfred if (max_len < 2) { 230184610Salfred /* invalid length */ 231184610Salfred return (0); 232184610Salfred } 233184610Salfred max_len = ((max_len / 2) - 1); 234184610Salfred 235184610Salfred j = strlen(s); 236184610Salfred 237184610Salfred if (j < 0) { 238184610Salfred j = 0; 239184610Salfred } 240184610Salfred if (j > 126) { 241184610Salfred j = 126; 242184610Salfred } 243184610Salfred if (max_len > j) { 244184610Salfred max_len = j; 245184610Salfred } 246184610Salfred totlen = (max_len + 1) * 2; 247184610Salfred 248184610Salfred p->bLength = totlen; 249184610Salfred p->bDescriptorType = UDESC_STRING; 250184610Salfred 251184610Salfred while (max_len--) { 252184610Salfred USETW2(p->bString[max_len], 0, s[max_len]); 253184610Salfred } 254184610Salfred return (totlen); 255184610Salfred} 256184610Salfred 257190180Sthompsa#if (USB_HAVE_CONDVAR == 0) 258184610Salfred 259184610Salfred/*------------------------------------------------------------------------* 260184610Salfred * usb2_cv_init - wrapper function 261184610Salfred *------------------------------------------------------------------------*/ 262184610Salfredvoid 263184610Salfredusb2_cv_init(struct cv *cv, const char *desc) 264184610Salfred{ 265184610Salfred cv_init(cv, desc); 266184610Salfred} 267184610Salfred 268184610Salfred/*------------------------------------------------------------------------* 269184610Salfred * usb2_cv_destroy - wrapper function 270184610Salfred *------------------------------------------------------------------------*/ 271184610Salfredvoid 272184610Salfredusb2_cv_destroy(struct cv *cv) 273184610Salfred{ 274184610Salfred cv_destroy(cv); 275184610Salfred} 276184610Salfred 277184610Salfred/*------------------------------------------------------------------------* 278184610Salfred * usb2_cv_wait - wrapper function 279184610Salfred *------------------------------------------------------------------------*/ 280184610Salfredvoid 281184610Salfredusb2_cv_wait(struct cv *cv, struct mtx *mtx) 282184610Salfred{ 283184610Salfred int err; 284184610Salfred 285184610Salfred err = usb2_msleep(cv, mtx, 0, cv_wmesg(cv), 0); 286184610Salfred} 287184610Salfred 288184610Salfred/*------------------------------------------------------------------------* 289184610Salfred * usb2_cv_wait_sig - wrapper function 290184610Salfred *------------------------------------------------------------------------*/ 291184610Salfredint 292184610Salfredusb2_cv_wait_sig(struct cv *cv, struct mtx *mtx) 293184610Salfred{ 294184610Salfred int err; 295184610Salfred 296184610Salfred err = usb2_msleep(cv, mtx, PCATCH, cv_wmesg(cv), 0); 297184610Salfred return (err); 298184610Salfred} 299184610Salfred 300184610Salfred/*------------------------------------------------------------------------* 301184610Salfred * usb2_cv_timedwait - wrapper function 302184610Salfred *------------------------------------------------------------------------*/ 303184610Salfredint 304184610Salfredusb2_cv_timedwait(struct cv *cv, struct mtx *mtx, int timo) 305184610Salfred{ 306184610Salfred int err; 307184610Salfred 308184610Salfred if (timo == 0) 309184610Salfred timo = 1; /* zero means no timeout */ 310184610Salfred err = usb2_msleep(cv, mtx, 0, cv_wmesg(cv), timo); 311184610Salfred return (err); 312184610Salfred} 313184610Salfred 314184610Salfred/*------------------------------------------------------------------------* 315184610Salfred * usb2_cv_signal - wrapper function 316184610Salfred *------------------------------------------------------------------------*/ 317184610Salfredvoid 318184610Salfredusb2_cv_signal(struct cv *cv) 319184610Salfred{ 320184610Salfred wakeup_one(cv); 321184610Salfred} 322184610Salfred 323184610Salfred/*------------------------------------------------------------------------* 324184610Salfred * usb2_cv_broadcast - wrapper function 325184610Salfred *------------------------------------------------------------------------*/ 326184610Salfredvoid 327184610Salfredusb2_cv_broadcast(struct cv *cv) 328184610Salfred{ 329184610Salfred wakeup(cv); 330184610Salfred} 331184610Salfred 332184610Salfred/*------------------------------------------------------------------------* 333184610Salfred * usb2_msleep - wrapper function 334184610Salfred *------------------------------------------------------------------------*/ 335184610Salfredstatic int 336184610Salfredusb2_msleep(void *chan, struct mtx *mtx, int priority, const char *wmesg, 337184610Salfred int timo) 338184610Salfred{ 339184610Salfred int err; 340184610Salfred 341184610Salfred if (mtx == &Giant) { 342184610Salfred err = tsleep(chan, priority, wmesg, timo); 343184610Salfred } else { 344184610Salfred#ifdef mtx_sleep 345184610Salfred err = mtx_sleep(chan, mtx, priority, wmesg, timo); 346184610Salfred#else 347184610Salfred err = msleep(chan, mtx, priority, wmesg, timo); 348184610Salfred#endif 349184610Salfred } 350184610Salfred return (err); 351184610Salfred} 352184610Salfred 353184610Salfred#endif 354