usb_util.c revision 194228
1184610Salfred/* $FreeBSD: head/sys/dev/usb/usb_util.c 194228 2009-06-15 01:02:43Z 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 42184610Salfred/*------------------------------------------------------------------------* 43184610Salfred * device_delete_all_children - delete all children of a device 44184610Salfred *------------------------------------------------------------------------*/ 45190180Sthompsa#ifndef device_delete_all_children 46184610Salfredint 47184610Salfreddevice_delete_all_children(device_t dev) 48184610Salfred{ 49184610Salfred device_t *devlist; 50184610Salfred int devcount; 51184610Salfred int error; 52184610Salfred 53184610Salfred error = device_get_children(dev, &devlist, &devcount); 54184610Salfred if (error == 0) { 55184610Salfred while (devcount-- > 0) { 56184610Salfred error = device_delete_child(dev, devlist[devcount]); 57184610Salfred if (error) { 58184610Salfred break; 59184610Salfred } 60184610Salfred } 61184610Salfred free(devlist, M_TEMP); 62184610Salfred } 63184610Salfred return (error); 64184610Salfred} 65190180Sthompsa#endif 66184610Salfred 67184610Salfred/*------------------------------------------------------------------------* 68194228Sthompsa * device_set_usb_desc 69184610Salfred * 70184610Salfred * This function can be called at probe or attach to set the USB 71184610Salfred * device supplied textual description for the given device. 72184610Salfred *------------------------------------------------------------------------*/ 73184610Salfredvoid 74194228Sthompsadevice_set_usb_desc(device_t dev) 75184610Salfred{ 76192984Sthompsa struct usb_attach_arg *uaa; 77192984Sthompsa struct usb_device *udev; 78192984Sthompsa struct usb_interface *iface; 79184610Salfred char *temp_p; 80193045Sthompsa usb_error_t err; 81184610Salfred 82184610Salfred if (dev == NULL) { 83184610Salfred /* should not happen */ 84184610Salfred return; 85184610Salfred } 86184610Salfred uaa = device_get_ivars(dev); 87184610Salfred if (uaa == NULL) { 88185087Salfred /* can happen if called at the wrong time */ 89184610Salfred return; 90184610Salfred } 91184610Salfred udev = uaa->device; 92184610Salfred iface = uaa->iface; 93184610Salfred 94184610Salfred if ((iface == NULL) || 95184610Salfred (iface->idesc == NULL) || 96184610Salfred (iface->idesc->iInterface == 0)) { 97184610Salfred err = USB_ERR_INVAL; 98184610Salfred } else { 99184610Salfred err = 0; 100184610Salfred } 101184610Salfred 102184610Salfred temp_p = (char *)udev->bus->scratch[0].data; 103184610Salfred 104184610Salfred if (!err) { 105184610Salfred /* try to get the interface string ! */ 106194228Sthompsa err = usbd_req_get_string_any 107184610Salfred (udev, NULL, temp_p, 108184610Salfred sizeof(udev->bus->scratch), iface->idesc->iInterface); 109184610Salfred } 110184610Salfred if (err) { 111184610Salfred /* use default description */ 112194228Sthompsa usb_devinfo(udev, temp_p, 113184610Salfred sizeof(udev->bus->scratch)); 114184610Salfred } 115184610Salfred device_set_desc_copy(dev, temp_p); 116184610Salfred device_printf(dev, "<%s> on %s\n", temp_p, 117184610Salfred device_get_nameunit(udev->bus->bdev)); 118184610Salfred} 119184610Salfred 120184610Salfred/*------------------------------------------------------------------------* 121194228Sthompsa * usb_pause_mtx - factored out code 122184610Salfred * 123188411Sthompsa * This function will delay the code by the passed number of system 124188411Sthompsa * ticks. The passed mutex "mtx" will be dropped while waiting, if 125188411Sthompsa * "mtx" is not NULL. 126184610Salfred *------------------------------------------------------------------------*/ 127184610Salfredvoid 128194228Sthompsausb_pause_mtx(struct mtx *mtx, int _ticks) 129184610Salfred{ 130188411Sthompsa if (mtx != NULL) 131188411Sthompsa mtx_unlock(mtx); 132188411Sthompsa 133184610Salfred if (cold) { 134188411Sthompsa /* convert to milliseconds */ 135188411Sthompsa _ticks = (_ticks * 1000) / hz; 136188411Sthompsa /* convert to microseconds, rounded up */ 137188411Sthompsa _ticks = (_ticks + 1) * 1000; 138188411Sthompsa DELAY(_ticks); 139184610Salfred 140184610Salfred } else { 141184610Salfred 142184610Salfred /* 143184610Salfred * Add one to the number of ticks so that we don't return 144184610Salfred * too early! 145184610Salfred */ 146188411Sthompsa _ticks++; 147184610Salfred 148188411Sthompsa if (pause("USBWAIT", _ticks)) { 149184610Salfred /* ignore */ 150184610Salfred } 151184610Salfred } 152188411Sthompsa if (mtx != NULL) 153188411Sthompsa mtx_lock(mtx); 154184610Salfred} 155184610Salfred 156184610Salfred/*------------------------------------------------------------------------* 157194228Sthompsa * usb_printbcd 158184610Salfred * 159184610Salfred * This function will print the version number "bcd" to the string 160184610Salfred * pointed to by "p" having a maximum length of "p_len" bytes 161184610Salfred * including the terminating zero. 162184610Salfred *------------------------------------------------------------------------*/ 163184610Salfredvoid 164194228Sthompsausb_printbcd(char *p, uint16_t p_len, uint16_t bcd) 165184610Salfred{ 166184610Salfred if (snprintf(p, p_len, "%x.%02x", bcd >> 8, bcd & 0xff)) { 167184610Salfred /* ignore any errors */ 168184610Salfred } 169184610Salfred} 170184610Salfred 171184610Salfred/*------------------------------------------------------------------------* 172194228Sthompsa * usb_trim_spaces 173184610Salfred * 174184610Salfred * This function removes spaces at the beginning and the end of the string 175184610Salfred * pointed to by the "p" argument. 176184610Salfred *------------------------------------------------------------------------*/ 177184610Salfredvoid 178194228Sthompsausb_trim_spaces(char *p) 179184610Salfred{ 180184610Salfred char *q; 181184610Salfred char *e; 182184610Salfred 183184610Salfred if (p == NULL) 184184610Salfred return; 185184610Salfred q = e = p; 186184610Salfred while (*q == ' ') /* skip leading spaces */ 187184610Salfred q++; 188184610Salfred while ((*p = *q++)) /* copy string */ 189184610Salfred if (*p++ != ' ') /* remember last non-space */ 190184610Salfred e = p; 191184610Salfred *e = 0; /* kill trailing spaces */ 192184610Salfred} 193184610Salfred 194184610Salfred/*------------------------------------------------------------------------* 195194228Sthompsa * usb_make_str_desc - convert an ASCII string into a UNICODE string 196184610Salfred *------------------------------------------------------------------------*/ 197184610Salfreduint8_t 198194228Sthompsausb_make_str_desc(void *ptr, uint16_t max_len, const char *s) 199184610Salfred{ 200192984Sthompsa struct usb_string_descriptor *p = ptr; 201184610Salfred uint8_t totlen; 202184610Salfred int j; 203184610Salfred 204184610Salfred if (max_len < 2) { 205184610Salfred /* invalid length */ 206184610Salfred return (0); 207184610Salfred } 208184610Salfred max_len = ((max_len / 2) - 1); 209184610Salfred 210184610Salfred j = strlen(s); 211184610Salfred 212184610Salfred if (j < 0) { 213184610Salfred j = 0; 214184610Salfred } 215184610Salfred if (j > 126) { 216184610Salfred j = 126; 217184610Salfred } 218184610Salfred if (max_len > j) { 219184610Salfred max_len = j; 220184610Salfred } 221184610Salfred totlen = (max_len + 1) * 2; 222184610Salfred 223184610Salfred p->bLength = totlen; 224184610Salfred p->bDescriptorType = UDESC_STRING; 225184610Salfred 226184610Salfred while (max_len--) { 227184610Salfred USETW2(p->bString[max_len], 0, s[max_len]); 228184610Salfred } 229184610Salfred return (totlen); 230184610Salfred} 231