Changeset 10cd715 in mainline for uspace/lib/usbhost/src/usb2_bus.c
- Timestamp:
- 2017-12-14T14:25:40Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- bd05140
- Parents:
- 6455d39
- git-author:
- Ondřej Hlavatý <aearsis@…> (2017-12-14 14:24:28)
- git-committer:
- Ondřej Hlavatý <aearsis@…> (2017-12-14 14:25:40)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usbhost/src/usb2_bus.c
r6455d39 r10cd715 76 76 * @return Error code. 77 77 */ 78 static int usb2_bus_get_speed(bus_t *bus_base, usb_address_t address, usb_speed_t *speed) 79 { 80 usb2_bus_t *bus = bus_to_usb2_bus(bus_base); 81 82 if (!usb_address_is_valid(address)) { 78 static int get_speed(usb2_bus_t *bus, usb_address_t address, usb_speed_t *speed) 79 { 80 if (!usb_address_is_valid(address)) 83 81 return EINVAL; 84 } 82 83 if (!bus->devices[address].occupied) 84 return ENOENT; 85 86 if (speed) 87 *speed = bus->devices[address].speed; 88 89 return EOK; 90 } 91 92 /** Get a free USB address 93 * 94 * @param[in] bus Device manager structure to use. 95 * @return Free address, or error code. 96 */ 97 static int get_free_address(usb2_bus_t *bus, usb_address_t *addr) 98 { 99 usb_address_t new_address = bus->last_address; 100 do { 101 new_address = (new_address + 1) % USB_ADDRESS_COUNT; 102 if (new_address == USB_ADDRESS_DEFAULT) 103 new_address = 1; 104 if (new_address == bus->last_address) 105 return ENOSPC; 106 } while (bus->devices[new_address].occupied); 107 108 assert(new_address != USB_ADDRESS_DEFAULT); 109 bus->last_address = new_address; 110 111 *addr = new_address; 112 return EOK; 113 } 114 115 /** Unregister and destroy all endpoints using given address. 116 * @param bus usb_bus structure, non-null. 117 * @param address USB address. 118 * @param endpoint USB endpoint number. 119 * @param direction Communication direction. 120 * @return Error code. 121 */ 122 static int release_address(usb2_bus_t *bus, usb_address_t address) 123 { 124 if (!usb_address_is_valid(address)) 125 return EINVAL; 85 126 86 127 const int ret = bus->devices[address].occupied ? EOK : ENOENT; 87 if (speed && bus->devices[address].occupied) { 88 *speed = bus->devices[address].speed; 128 bus->devices[address].occupied = false; 129 130 list_t *list = get_list(bus, address); 131 for (link_t *link = list_first(list); link != NULL; ) { 132 endpoint_t *ep = list_get_instance(link, endpoint_t, link); 133 link = list_next(link, list); 134 135 assert(ep->device->address == address); 136 list_remove(&ep->link); 137 138 usb_log_warning("Endpoint %d:%d %s was left behind, removing.\n", 139 address, ep->endpoint, usb_str_direction(ep->direction)); 140 141 /* Drop bus reference */ 142 endpoint_del_ref(ep); 89 143 } 90 144 91 145 return ret; 146 } 147 148 /** Request USB address. 149 * @param bus usb_device_manager 150 * @param addr Pointer to requested address value, place to store new address 151 * @parma strict Fail if the requested address is not available. 152 * @return Error code. 153 * @note Default address is only available in strict mode. 154 */ 155 static int request_address(usb2_bus_t *bus, usb_address_t *addr, bool strict, usb_speed_t speed) 156 { 157 int err; 158 159 assert(bus); 160 assert(addr); 161 162 if (!usb_address_is_valid(*addr)) 163 return EINVAL; 164 165 /* Only grant default address to strict requests */ 166 if ((*addr == USB_ADDRESS_DEFAULT) && !strict) { 167 if ((err = get_free_address(bus, addr))) 168 return err; 169 } 170 else if (bus->devices[*addr].occupied) { 171 if (strict) { 172 return ENOENT; 173 } 174 if ((err = get_free_address(bus, addr))) 175 return err; 176 } 177 178 assert(usb_address_is_valid(*addr)); 179 assert(bus->devices[*addr].occupied == false); 180 assert(*addr != USB_ADDRESS_DEFAULT || strict); 181 182 bus->devices[*addr].occupied = true; 183 bus->devices[*addr].speed = speed; 184 185 return EOK; 92 186 } 93 187 … … 106 200 }}; 107 201 108 static int usb2_bus_address_device(bus_t *bus, hcd_t *hcd, device_t *dev)202 static int address_device(usb2_bus_t *bus, hcd_t *hcd, device_t *dev) 109 203 { 110 204 int err; … … 115 209 /** Reserve address early, we want pretty log messages */ 116 210 usb_address_t address; 117 if ((err = bus_request_address(bus, &address, false, dev->speed))) {211 if ((err = request_address(bus, &address, false, dev->speed))) { 118 212 usb_log_error("Failed to reserve new address: %s.", 119 213 str_error(err)); … … 126 220 127 221 endpoint_t *default_ep; 128 err = bus_add_endpoint( bus, dev, &usb2_default_control_ep, &default_ep);222 err = bus_add_endpoint(&bus->base, dev, &usb2_default_control_ep, &default_ep); 129 223 if (err != EOK) { 130 224 usb_log_error("Device(%d): Failed to add default target: %s.", … … 150 244 151 245 /* We need to remove ep before we change the address */ 152 if ((err = bus_remove_endpoint( bus, default_ep))) {246 if ((err = bus_remove_endpoint(&bus->base, default_ep))) { 153 247 usb_log_error("Device(%d): Failed to unregister default target: %s", address, str_error(err)); 154 248 goto err_address; … … 168 262 /* Register EP on the new address */ 169 263 usb_log_debug("Device(%d): Registering control EP.", address); 170 err = bus_add_endpoint( bus, dev, &control_ep, NULL);264 err = bus_add_endpoint(&bus->base, dev, &control_ep, NULL); 171 265 if (err != EOK) { 172 266 usb_log_error("Device(%d): Failed to register EP0: %s", … … 178 272 179 273 err_default_control_ep: 180 bus_remove_endpoint( bus, default_ep);274 bus_remove_endpoint(&bus->base, default_ep); 181 275 endpoint_del_ref(default_ep); 182 276 err_address: 183 bus_release_address(bus, address);277 release_address(bus, address); 184 278 return err; 185 279 } … … 187 281 /** Enumerate a new USB device 188 282 */ 189 static int usb2_bus_enumerate_device(bus_t *bus , hcd_t *hcd, device_t *dev)283 static int usb2_bus_enumerate_device(bus_t *bus_base, hcd_t *hcd, device_t *dev) 190 284 { 191 285 int err; 286 usb2_bus_t *bus = bus_to_usb2_bus(bus_base); 192 287 193 288 /* The speed of the new device was reported by the hub when reserving 194 289 * default address. 195 290 */ 196 if ((err = usb2_bus_get_speed(bus, USB_ADDRESS_DEFAULT, &dev->speed))) {291 if ((err = get_speed(bus, USB_ADDRESS_DEFAULT, &dev->speed))) { 197 292 usb_log_error("Failed to verify speed: %s.", str_error(err)); 198 293 return err; … … 211 306 212 307 /* Assign an address to the device */ 213 if ((err = usb2_bus_address_device(bus, hcd, dev))) {308 if ((err = address_device(bus, hcd, dev))) { 214 309 usb_log_error("Failed to setup address of the new device: %s", str_error(err)); 215 310 return err; … … 219 314 if ((err = hcd_ddf_device_explore(hcd, dev))) { 220 315 usb_log_error("Device(%d): Failed to explore device: %s", dev->address, str_error(err)); 221 bus_release_address(bus, dev->address);316 release_address(bus, dev->address); 222 317 return err; 223 318 } 224 319 225 return EOK;226 }227 228 /** Get a free USB address229 *230 * @param[in] bus Device manager structure to use.231 * @return Free address, or error code.232 */233 static int usb_bus_get_free_address(usb2_bus_t *bus, usb_address_t *addr)234 {235 usb_address_t new_address = bus->last_address;236 do {237 new_address = (new_address + 1) % USB_ADDRESS_COUNT;238 if (new_address == USB_ADDRESS_DEFAULT)239 new_address = 1;240 if (new_address == bus->last_address)241 return ENOSPC;242 } while (bus->devices[new_address].occupied);243 244 assert(new_address != USB_ADDRESS_DEFAULT);245 bus->last_address = new_address;246 247 *addr = new_address;248 320 return EOK; 249 321 } … … 367 439 } 368 440 369 /** Unregister and destroy all endpoints using given address. 370 * @param bus usb_bus structure, non-null. 371 * @param address USB address. 372 * @param endpoint USB endpoint number. 373 * @param direction Communication direction. 374 * @return Error code. 375 */ 376 static int usb2_bus_release_address(bus_t *bus_base, usb_address_t address) 377 { 378 usb2_bus_t *bus = bus_to_usb2_bus(bus_base); 379 380 if (!usb_address_is_valid(address)) 381 return EINVAL; 382 383 const int ret = bus->devices[address].occupied ? EOK : ENOENT; 384 bus->devices[address].occupied = false; 385 386 list_t *list = get_list(bus, address); 387 for (link_t *link = list_first(list); link != NULL; ) { 388 endpoint_t *ep = list_get_instance(link, endpoint_t, link); 389 link = list_next(link, list); 390 391 assert(ep->device->address == address); 392 list_remove(&ep->link); 393 394 usb_log_warning("Endpoint %d:%d %s was left behind, removing.\n", 395 address, ep->endpoint, usb_str_direction(ep->direction)); 396 397 /* Drop bus reference */ 398 endpoint_del_ref(ep); 399 } 400 401 return ret; 402 } 403 404 /** Request USB address. 405 * @param bus usb_device_manager 406 * @param addr Pointer to requested address value, place to store new address 407 * @parma strict Fail if the requested address is not available. 408 * @return Error code. 409 * @note Default address is only available in strict mode. 410 */ 411 static int usb2_bus_request_address(bus_t *bus_base, usb_address_t *addr, bool strict, usb_speed_t speed) 412 { 413 int err; 414 415 usb2_bus_t *bus = bus_to_usb2_bus(bus_base); 416 assert(addr); 417 418 if (!usb_address_is_valid(*addr)) 419 return EINVAL; 420 421 /* Only grant default address to strict requests */ 422 if ((*addr == USB_ADDRESS_DEFAULT) && !strict) { 423 if ((err = usb_bus_get_free_address(bus, addr))) 424 return err; 425 } 426 else if (bus->devices[*addr].occupied) { 427 if (strict) { 428 return ENOENT; 429 } 430 if ((err = usb_bus_get_free_address(bus, addr))) 431 return err; 432 } 433 434 assert(usb_address_is_valid(*addr)); 435 assert(bus->devices[*addr].occupied == false); 436 assert(*addr != USB_ADDRESS_DEFAULT || strict); 437 438 bus->devices[*addr].occupied = true; 439 bus->devices[*addr].speed = speed; 440 441 return EOK; 441 static int usb2_bus_register_default_address(bus_t *bus_base, usb_speed_t speed) 442 { 443 usb2_bus_t *bus = bus_to_usb2_bus(bus_base); 444 usb_address_t addr = USB_ADDRESS_DEFAULT; 445 return request_address(bus, &addr, true, speed); 446 } 447 448 static int usb2_bus_release_default_address(bus_t *bus_base) 449 { 450 usb2_bus_t *bus = bus_to_usb2_bus(bus_base); 451 return release_address(bus, USB_ADDRESS_DEFAULT); 442 452 } 443 453 444 454 static const bus_ops_t usb2_bus_ops = { 455 .reserve_default_address = usb2_bus_register_default_address, 456 .release_default_address = usb2_bus_release_default_address, 445 457 .enumerate_device = usb2_bus_enumerate_device, 446 458 .create_endpoint = usb2_bus_create_ep, … … 448 460 .unregister_endpoint = usb2_bus_unregister_ep, 449 461 .register_endpoint = usb2_bus_register_ep, 450 .request_address = usb2_bus_request_address,451 .release_address = usb2_bus_release_address,452 462 .reset_toggle = usb2_bus_reset_toggle, 453 463 };
Note:
See TracChangeset
for help on using the changeset viewer.