1/* 2 * Main API entry point 3 * 4 * Copyright (c) 2000-2003 Johannes Erdfelt <johannes@erdfelt.com> 5 * 6 * This library is covered by the LGPL, read LICENSE for details. 7 */ 8 9#include <stdlib.h> /* getenv */ 10#include <stdio.h> /* stderr */ 11#include <string.h> /* strcmp */ 12#include <errno.h> 13 14#include "usbi.h" 15 16int usb_debug = 0; 17struct usb_bus *usb_busses = NULL; 18 19int usb_find_busses(void) 20{ 21 struct usb_bus *busses, *bus; 22 int ret, changes = 0; 23 24 ret = usb_os_find_busses(&busses); 25 if (ret < 0) 26 return ret; 27 28 /* 29 * Now walk through all of the busses we know about and compare against 30 * this new list. Any duplicates will be removed from the new list. 31 * If we don't find it in the new list, the bus was removed. Any 32 * busses still in the new list, are new to us. 33 */ 34 bus = usb_busses; 35 while (bus) { 36 int found = 0; 37 struct usb_bus *nbus, *tbus = bus->next; 38 39 nbus = busses; 40 while (nbus) { 41 struct usb_bus *tnbus = nbus->next; 42 43 if (!strcmp(bus->dirname, nbus->dirname)) { 44 /* Remove it from the new busses list */ 45 LIST_DEL(busses, nbus); 46 47 usb_free_bus(nbus); 48 found = 1; 49 break; 50 } 51 52 nbus = tnbus; 53 } 54 55 if (!found) { 56 /* The bus was removed from the system */ 57 LIST_DEL(usb_busses, bus); 58 usb_free_bus(bus); 59 changes++; 60 } 61 62 bus = tbus; 63 } 64 65 /* 66 * Anything on the *busses list is new. So add them to usb_busses and 67 * process them like the new bus it is. 68 */ 69 bus = busses; 70 while (bus) { 71 struct usb_bus *tbus = bus->next; 72 73 /* 74 * Remove it from the temporary list first and add it to the real 75 * usb_busses list. 76 */ 77 LIST_DEL(busses, bus); 78 79 LIST_ADD(usb_busses, bus); 80 81 changes++; 82 83 bus = tbus; 84 } 85 86 return changes; 87} 88 89int usb_find_devices(void) 90{ 91 struct usb_bus *bus; 92 int ret, changes = 0; 93 94 for (bus = usb_busses; bus; bus = bus->next) { 95 struct usb_device *devices, *dev; 96 97 /* Find all of the devices and put them into a temporary list */ 98 ret = usb_os_find_devices(bus, &devices); 99 if (ret < 0) 100 return ret; 101 102 /* 103 * Now walk through all of the devices we know about and compare 104 * against this new list. Any duplicates will be removed from the new 105 * list. If we don't find it in the new list, the device was removed. 106 * Any devices still in the new list, are new to us. 107 */ 108 dev = bus->devices; 109 while (dev) { 110 int found = 0; 111 struct usb_device *ndev, *tdev = dev->next; 112 113 ndev = devices; 114 while (ndev) { 115 struct usb_device *tndev = ndev->next; 116 117 if (!strcmp(dev->filename, ndev->filename)) { 118 /* Remove it from the new devices list */ 119 LIST_DEL(devices, ndev); 120 121 usb_free_dev(ndev); 122 found = 1; 123 break; 124 } 125 126 ndev = tndev; 127 } 128 129 if (!found) { 130 /* The device was removed from the system */ 131 LIST_DEL(bus->devices, dev); 132 usb_free_dev(dev); 133 changes++; 134 } 135 136 dev = tdev; 137 } 138 139 /* 140 * Anything on the *devices list is new. So add them to bus->devices and 141 * process them like the new device it is. 142 */ 143 dev = devices; 144 while (dev) { 145 struct usb_device *tdev = dev->next; 146 147 /* 148 * Remove it from the temporary list first and add it to the real 149 * bus->devices list. 150 */ 151 LIST_DEL(devices, dev); 152 153 LIST_ADD(bus->devices, dev); 154 155 /* 156 * Some ports fetch the descriptors on scanning (like Linux) so we don't 157 * need to fetch them again. 158 */ 159 if (!dev->config) { 160 usb_dev_handle *udev; 161 162 udev = usb_open(dev); 163 if (udev) { 164 usb_fetch_and_parse_descriptors(udev); 165 166 usb_close(udev); 167 } 168 } 169 170 changes++; 171 172 dev = tdev; 173 } 174 175 usb_os_determine_children(bus); 176 } 177 178 return changes; 179} 180 181void usb_set_debug(int level) 182{ 183 if (usb_debug || level) 184 fprintf(stderr, "usb_set_debug: Setting debugging level to %d (%s)\n", 185 level, level ? "on" : "off"); 186 187 usb_debug = level; 188} 189 190void usb_init(void) 191{ 192 if (getenv("USB_DEBUG")) 193 usb_set_debug(atoi(getenv("USB_DEBUG"))); 194 195 usb_os_init(); 196} 197 198usb_dev_handle *usb_open(struct usb_device *dev) 199{ 200 usb_dev_handle *udev; 201 202 udev = malloc(sizeof(*udev)); 203 if (!udev) 204 return NULL; 205 206 udev->fd = -1; 207 udev->device = dev; 208 udev->bus = dev->bus; 209 udev->config = udev->interface = udev->altsetting = -1; 210 211 if (usb_os_open(udev) < 0) { 212 free(udev); 213 return NULL; 214 } 215 216 return udev; 217} 218 219int usb_get_string(usb_dev_handle *dev, int index, int langid, char *buf, 220 size_t buflen) 221{ 222 /* 223 * We can't use usb_get_descriptor() because it's lacking the index 224 * parameter. This will be fixed in libusb 1.0 225 */ 226 return usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, 227 (USB_DT_STRING << 8) + index, langid, buf, buflen, 1000); 228} 229 230int usb_get_string_simple(usb_dev_handle *dev, int index, char *buf, size_t buflen) 231{ 232 char tbuf[255]; /* Some devices choke on size > 255 */ 233 int ret, langid, si, di; 234 235 /* 236 * Asking for the zero'th index is special - it returns a string 237 * descriptor that contains all the language IDs supported by the 238 * device. Typically there aren't many - often only one. The 239 * language IDs are 16 bit numbers, and they start at the third byte 240 * in the descriptor. See USB 2.0 specification, section 9.6.7, for 241 * more information on this. */ 242 ret = usb_get_string(dev, 0, 0, tbuf, sizeof(tbuf)); 243 if (ret < 0) 244 return ret; 245 246 if (ret < 4) 247 return -EIO; 248 249 langid = tbuf[2] | (tbuf[3] << 8); 250 251 ret = usb_get_string(dev, index, langid, tbuf, sizeof(tbuf)); 252 if (ret < 0) 253 return ret; 254 255 if (tbuf[1] != USB_DT_STRING) 256 return -EIO; 257 258 if (tbuf[0] > ret) 259 return -EFBIG; 260 261 for (di = 0, si = 2; si < tbuf[0]; si += 2) { 262 if (di >= (buflen - 1)) 263 break; 264 265 if (tbuf[si + 1]) /* high byte */ 266 buf[di++] = '?'; 267 else 268 buf[di++] = tbuf[si]; 269 } 270 271 buf[di] = 0; 272 273 return di; 274} 275 276int usb_close(usb_dev_handle *dev) 277{ 278 int ret; 279 280 ret = usb_os_close(dev); 281 free(dev); 282 283 return ret; 284} 285 286struct usb_device *usb_device(usb_dev_handle *dev) 287{ 288 return dev->device; 289} 290 291void usb_free_dev(struct usb_device *dev) 292{ 293 usb_destroy_configuration(dev); 294 free(dev->children); 295 free(dev); 296} 297 298struct usb_bus *usb_get_busses(void) 299{ 300 return usb_busses; 301} 302 303void usb_free_bus(struct usb_bus *bus) 304{ 305 free(bus); 306} 307 308