Changeset a4e18e1 in mainline for uspace/lib/usb/src
- Timestamp:
- 2011-04-07T15:04:16Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 36cd378
- Parents:
- 9d06563 (diff), a82889e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- uspace/lib/usb/src
- Files:
-
- 1 added
- 5 edited
- 1 moved
-
devdrv.c (modified) (10 diffs)
-
host/batch.c (modified) (2 diffs)
-
host/device_keeper.c (modified) (12 diffs)
-
host/endpoint.c (added)
-
host/usb_endpoint_manager.c (moved) (moved from uspace/lib/usb/src/host/bandwidth.c ) (6 diffs)
-
hub.c (modified) (6 diffs)
-
pipesinit.c (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/devdrv.c
r9d06563 ra4e18e1 36 36 #include <usb/request.h> 37 37 #include <usb/debug.h> 38 #include <usb/dp.h> 38 39 #include <errno.h> 39 40 #include <str_error.h> … … 86 87 * @return Number of pipes (excluding default control pipe). 87 88 */ 88 static size_t count_other_pipes(usb_ driver_t *drv)89 static size_t count_other_pipes(usb_endpoint_description_t **endpoints) 89 90 { 90 91 size_t count = 0; 91 if ( drv->endpoints == NULL) {92 if (endpoints == NULL) { 92 93 return 0; 93 94 } 94 95 95 while ( drv->endpoints[count] != NULL) {96 while (endpoints[count] != NULL) { 96 97 count++; 97 98 } … … 106 107 * @return Error code. 107 108 */ 108 static int initialize_other_pipes(usb_driver_t *drv, usb_device_t *dev) 109 static int initialize_other_pipes(usb_endpoint_description_t **endpoints, 110 usb_device_t *dev) 109 111 { 110 112 int rc; 111 dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev); 112 113 size_t pipe_count = count_other_pipes(drv); 113 114 size_t pipe_count = count_other_pipes(endpoints); 115 if (pipe_count == 0) { 116 return EOK; 117 } 118 114 119 dev->pipes = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count); 115 120 if (dev->pipes == NULL) { … … 133 138 } 134 139 135 dev->pipes[i].description = drv->endpoints[i];140 dev->pipes[i].description = endpoints[i]; 136 141 dev->pipes[i].interface_no = dev->interface_no; 142 dev->pipes[i].interface_setting = 0; 137 143 } 138 144 … … 178 184 usb_hc_connection_close(&hc_conn); 179 185 186 dev->pipes_count = pipe_count; 187 180 188 return EOK; 181 189 … … 227 235 } 228 236 237 /* Get our interface. */ 238 dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev); 239 229 240 /* 230 241 * For further actions, we need open session on default control pipe. … … 257 268 258 269 if (driver->endpoints != NULL) { 259 rc = initialize_other_pipes(driver , dev);270 rc = initialize_other_pipes(driver->endpoints, dev); 260 271 } 261 272 … … 271 282 272 283 return rc; 284 } 285 286 /** Count number of alternate settings of a interface. 287 * 288 * @param config_descr Full configuration descriptor. 289 * @param config_descr_size Size of @p config_descr in bytes. 290 * @param interface_no Interface number. 291 * @return Number of alternate interfaces for @p interface_no interface. 292 */ 293 static size_t count_alternate_interfaces(uint8_t *config_descr, 294 size_t config_descr_size, int interface_no) 295 { 296 assert(config_descr != NULL); 297 usb_dp_parser_t dp_parser = { 298 .nesting = usb_dp_standard_descriptor_nesting 299 }; 300 usb_dp_parser_data_t dp_data = { 301 .data = config_descr, 302 .size = config_descr_size, 303 .arg = NULL 304 }; 305 306 size_t alternate_count = 0; 307 308 uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser, 309 &dp_data, config_descr); 310 while (iface_ptr != NULL) { 311 usb_standard_interface_descriptor_t *iface 312 = (usb_standard_interface_descriptor_t *) iface_ptr; 313 if (iface->descriptor_type == USB_DESCTYPE_INTERFACE) { 314 if (iface->interface_number == interface_no) { 315 alternate_count++; 316 } 317 } 318 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data, 319 config_descr, iface_ptr); 320 } 321 322 return alternate_count; 323 } 324 325 /** Initialize structures related to alternate interfaces. 326 * 327 * @param dev Device where alternate settings shall be initialized. 328 * @return Error code. 329 */ 330 static int initialize_alternate_interfaces(usb_device_t *dev) 331 { 332 if (dev->interface_no < 0) { 333 dev->alternate_interfaces = NULL; 334 return EOK; 335 } 336 337 usb_alternate_interfaces_t *alternates 338 = malloc(sizeof(usb_alternate_interfaces_t)); 339 340 if (alternates == NULL) { 341 return ENOMEM; 342 } 343 344 alternates->alternative_count 345 = count_alternate_interfaces(dev->descriptors.configuration, 346 dev->descriptors.configuration_size, dev->interface_no); 347 348 if (alternates->alternative_count == 0) { 349 free(alternates); 350 return ENOENT; 351 } 352 353 alternates->alternatives = malloc(alternates->alternative_count 354 * sizeof(usb_alternate_interface_descriptors_t)); 355 if (alternates->alternatives == NULL) { 356 free(alternates); 357 return ENOMEM; 358 } 359 360 alternates->current = 0; 361 362 usb_dp_parser_t dp_parser = { 363 .nesting = usb_dp_standard_descriptor_nesting 364 }; 365 usb_dp_parser_data_t dp_data = { 366 .data = dev->descriptors.configuration, 367 .size = dev->descriptors.configuration_size, 368 .arg = NULL 369 }; 370 371 usb_alternate_interface_descriptors_t *cur_alt_iface 372 = &alternates->alternatives[0]; 373 374 uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser, 375 &dp_data, dp_data.data); 376 while (iface_ptr != NULL) { 377 usb_standard_interface_descriptor_t *iface 378 = (usb_standard_interface_descriptor_t *) iface_ptr; 379 if ((iface->descriptor_type != USB_DESCTYPE_INTERFACE) 380 || (iface->interface_number != dev->interface_no)) { 381 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, 382 &dp_data, 383 dp_data.data, iface_ptr); 384 continue; 385 } 386 387 cur_alt_iface->interface = iface; 388 cur_alt_iface->nested_descriptors = iface_ptr + sizeof(*iface); 389 390 /* Find next interface to count size of nested descriptors. */ 391 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data, 392 dp_data.data, iface_ptr); 393 if (iface_ptr == NULL) { 394 uint8_t *next = dp_data.data + dp_data.size; 395 cur_alt_iface->nested_descriptors_size 396 = next - cur_alt_iface->nested_descriptors; 397 } else { 398 cur_alt_iface->nested_descriptors_size 399 = iface_ptr - cur_alt_iface->nested_descriptors; 400 } 401 402 cur_alt_iface++; 403 } 404 405 dev->alternate_interfaces = alternates; 406 407 return EOK; 273 408 } 274 409 … … 301 436 dev->descriptors.configuration = NULL; 302 437 438 dev->pipes_count = 0; 439 dev->pipes = NULL; 440 303 441 rc = initialize_pipes(dev); 304 442 if (rc != EOK) { … … 307 445 } 308 446 447 (void) initialize_alternate_interfaces(dev); 448 309 449 return driver->ops->add_device(dev); 450 } 451 452 /** Destroy existing pipes of a USB device. 453 * 454 * @param dev Device where to destroy the pipes. 455 * @return Error code. 456 */ 457 static int destroy_current_pipes(usb_device_t *dev) 458 { 459 size_t i; 460 int rc; 461 462 /* TODO: this shall be done under some device mutex. */ 463 464 /* First check that no session is opened. */ 465 for (i = 0; i < dev->pipes_count; i++) { 466 if (usb_pipe_is_session_started(dev->pipes[i].pipe)) { 467 return EBUSY; 468 } 469 } 470 471 /* Prepare connection to HC. */ 472 usb_hc_connection_t hc_conn; 473 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev); 474 if (rc != EOK) { 475 return rc; 476 } 477 rc = usb_hc_connection_open(&hc_conn); 478 if (rc != EOK) { 479 return rc; 480 } 481 482 /* Destroy the pipes. */ 483 for (i = 0; i < dev->pipes_count; i++) { 484 usb_pipe_unregister(dev->pipes[i].pipe, &hc_conn); 485 free(dev->pipes[i].pipe); 486 } 487 488 usb_hc_connection_close(&hc_conn); 489 490 free(dev->pipes); 491 dev->pipes = NULL; 492 dev->pipes_count = 0; 493 494 return EOK; 495 } 496 497 /** Change interface setting of a device. 498 * This function selects new alternate setting of an interface by issuing 499 * proper USB command to the device and also creates new USB pipes 500 * under @c dev->pipes. 501 * 502 * @warning This function is intended for drivers working at interface level. 503 * For drivers controlling the whole device, you need to change interface 504 * manually using usb_request_set_interface() and creating new pipes 505 * with usb_pipe_initialize_from_configuration(). 506 * 507 * @param dev USB device. 508 * @param alternate_setting Alternate setting to choose. 509 * @param endpoints New endpoint descriptions. 510 * @return Error code. 511 */ 512 int usb_device_select_interface(usb_device_t *dev, uint8_t alternate_setting, 513 usb_endpoint_description_t **endpoints) 514 { 515 if (dev->interface_no < 0) { 516 return EINVAL; 517 } 518 519 int rc; 520 521 /* TODO: more transactional behavior. */ 522 523 /* Destroy existing pipes. */ 524 rc = destroy_current_pipes(dev); 525 if (rc != EOK) { 526 return rc; 527 } 528 529 /* Change the interface itself. */ 530 rc = usb_request_set_interface(&dev->ctrl_pipe, dev->interface_no, 531 alternate_setting); 532 if (rc != EOK) { 533 return rc; 534 } 535 536 /* Create new pipes. */ 537 rc = initialize_other_pipes(endpoints, dev); 538 539 return rc; 310 540 } 311 541 -
uspace/lib/usb/src/host/batch.c
r9d06563 ra4e18e1 54 54 void *arg, 55 55 ddf_fun_t *fun, 56 endpoint_t *ep, 56 57 void *private_data 57 58 ) … … 77 78 instance->next_step = NULL; 78 79 instance->error = EOK; 79 80 instance->ep = ep; 80 81 } 81 82 /*----------------------------------------------------------------------------*/ -
uspace/lib/usb/src/host/device_keeper.c
r9d06563 ra4e18e1 56 56 instance->devices[i].control_used = 0; 57 57 instance->devices[i].handle = 0; 58 instance->devices[i].toggle_status[0] = 0; 59 instance->devices[i].toggle_status[1] = 0; 60 } 58 list_initialize(&instance->devices[i].endpoints); 59 } 60 } 61 /*----------------------------------------------------------------------------*/ 62 void usb_device_keeper_add_ep( 63 usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep) 64 { 65 assert(instance); 66 fibril_mutex_lock(&instance->guard); 67 assert(instance->devices[address].occupied); 68 list_append(&ep->same_device_eps, &instance->devices[address].endpoints); 69 fibril_mutex_unlock(&instance->guard); 61 70 } 62 71 /*----------------------------------------------------------------------------*/ … … 66 75 * @param[in] speed Speed of the device requesting default address. 67 76 */ 68 void usb_device_keeper_reserve_default_address( usb_device_keeper_t *instance,69 usb_ speed_t speed)77 void usb_device_keeper_reserve_default_address( 78 usb_device_keeper_t *instance, usb_speed_t speed) 70 79 { 71 80 assert(instance); … … 101 110 * Really ugly one. 102 111 */ 103 void usb_device_keeper_reset_if_need( usb_device_keeper_t *instance,104 usb_ target_t target, const uint8_t *data)112 void usb_device_keeper_reset_if_need( 113 usb_device_keeper_t *instance, usb_target_t target, const uint8_t *data) 105 114 { 106 115 assert(instance); … … 119 128 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */ 120 129 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) { 130 link_t *current = 131 instance->devices[target.address].endpoints.next; 132 while (current != 133 &instance->devices[target.address].endpoints) 134 { 121 135 /* endpoint number is < 16, thus first byte is enough */ 122 instance->devices[target.address].toggle_status[0] &=123 ~(1 <<data[4]);124 instance->devices[target.address].toggle_status[1] &=125 ~(1 << data[4]);136 endpoint_toggle_reset_filtered( 137 current, data[4]); 138 current = current->next; 139 } 126 140 } 127 141 break; … … 131 145 /* target must be device */ 132 146 if ((data[0] & 0xf) == 0) { 133 instance->devices[target.address].toggle_status[0] = 0; 134 instance->devices[target.address].toggle_status[1] = 0; 147 link_t *current = 148 instance->devices[target.address].endpoints.next; 149 while (current != 150 &instance->devices[target.address].endpoints) 151 { 152 endpoint_toggle_reset(current); 153 current = current->next; 154 } 135 155 } 136 156 break; 137 157 } 138 158 fibril_mutex_unlock(&instance->guard); 139 }140 /*----------------------------------------------------------------------------*/141 /** Get current value of endpoint toggle.142 *143 * @param[in] instance Device keeper structure to use.144 * @param[in] target Device and endpoint used.145 * @return Error code146 */147 int usb_device_keeper_get_toggle(usb_device_keeper_t *instance,148 usb_target_t target, usb_direction_t direction)149 {150 assert(instance);151 /* only control pipes are bi-directional and those do not need toggle */152 if (direction == USB_DIRECTION_BOTH)153 return ENOENT;154 int ret;155 fibril_mutex_lock(&instance->guard);156 if (target.endpoint > 15 || target.endpoint < 0157 || target.address >= USB_ADDRESS_COUNT || target.address < 0158 || !instance->devices[target.address].occupied) {159 usb_log_error("Invalid data when asking for toggle value.\n");160 ret = EINVAL;161 } else {162 ret = (instance->devices[target.address].toggle_status[direction]163 >> target.endpoint) & 1;164 }165 fibril_mutex_unlock(&instance->guard);166 return ret;167 }168 /*----------------------------------------------------------------------------*/169 /** Set current value of endpoint toggle.170 *171 * @param[in] instance Device keeper structure to use.172 * @param[in] target Device and endpoint used.173 * @param[in] toggle Toggle value.174 * @return Error code.175 */176 int usb_device_keeper_set_toggle(usb_device_keeper_t *instance,177 usb_target_t target, usb_direction_t direction, bool toggle)178 {179 assert(instance);180 /* only control pipes are bi-directional and those do not need toggle */181 if (direction == USB_DIRECTION_BOTH)182 return ENOENT;183 int ret;184 fibril_mutex_lock(&instance->guard);185 if (target.endpoint > 15 || target.endpoint < 0186 || target.address >= USB_ADDRESS_COUNT || target.address < 0187 || !instance->devices[target.address].occupied) {188 usb_log_error("Invalid data when setting toggle value.\n");189 ret = EINVAL;190 } else {191 if (toggle) {192 instance->devices[target.address].toggle_status[direction]193 |= (1 << target.endpoint);194 } else {195 instance->devices[target.address].toggle_status[direction]196 &= ~(1 << target.endpoint);197 }198 ret = EOK;199 }200 fibril_mutex_unlock(&instance->guard);201 return ret;202 159 } 203 160 /*----------------------------------------------------------------------------*/ … … 208 165 * @return Free address, or error code. 209 166 */ 210 usb_address_t device_keeper_get_free_address( usb_device_keeper_t *instance,211 usb_ speed_t speed)167 usb_address_t device_keeper_get_free_address( 168 usb_device_keeper_t *instance, usb_speed_t speed) 212 169 { 213 170 assert(instance); … … 229 186 instance->devices[new_address].occupied = true; 230 187 instance->devices[new_address].speed = speed; 231 instance->devices[new_address].toggle_status[0] = 0;232 instance->devices[new_address].toggle_status[1] = 0;233 188 instance->last_address = new_address; 234 189 fibril_mutex_unlock(&instance->guard); … … 259 214 * @param[in] address Device address 260 215 */ 261 void usb_device_keeper_release( usb_device_keeper_t *instance,262 usb_ address_t address)216 void usb_device_keeper_release( 217 usb_device_keeper_t *instance, usb_address_t address) 263 218 { 264 219 assert(instance); … … 278 233 * @return USB Address, or error code. 279 234 */ 280 usb_address_t usb_device_keeper_find( usb_device_keeper_t *instance,281 devman_handle_t handle)235 usb_address_t usb_device_keeper_find( 236 usb_device_keeper_t *instance, devman_handle_t handle) 282 237 { 283 238 assert(instance); … … 301 256 * @return USB speed. 302 257 */ 303 usb_speed_t usb_device_keeper_get_speed( usb_device_keeper_t *instance,304 usb_ address_t address)258 usb_speed_t usb_device_keeper_get_speed( 259 usb_device_keeper_t *instance, usb_address_t address) 305 260 { 306 261 assert(instance); … … 310 265 } 311 266 /*----------------------------------------------------------------------------*/ 312 void usb_device_keeper_use_control( usb_device_keeper_t *instance,313 usb_ target_t target)267 void usb_device_keeper_use_control( 268 usb_device_keeper_t *instance, usb_target_t target) 314 269 { 315 270 assert(instance); … … 323 278 } 324 279 /*----------------------------------------------------------------------------*/ 325 void usb_device_keeper_release_control( usb_device_keeper_t *instance,326 usb_ target_t target)280 void usb_device_keeper_release_control( 281 usb_device_keeper_t *instance, usb_target_t target) 327 282 { 328 283 assert(instance); -
uspace/lib/usb/src/host/usb_endpoint_manager.c
r9d06563 ra4e18e1 1 1 /* 2 2 * Copyright (c) 2011 Jan Vesely 3 * All rights reserved.3 * All rights eps. 4 4 * 5 5 * Redistribution and use in source and binary forms, with or without … … 27 27 */ 28 28 29 #include <bool.h> 29 30 #include <assert.h> 30 31 #include <errno.h> 31 #include <usb/host/bandwidth.h> 32 32 33 #include <usb/host/usb_endpoint_manager.h> 34 35 #define BUCKET_COUNT 7 36 37 #define MAX_KEYS (3) 33 38 typedef struct { 34 usb_address_t address;35 usb_endpoint_t endpoint;36 usb_direction_t direction;37 } __attribute__((aligned (sizeof(unsigned long)))) transfer_t;38 /*----------------------------------------------------------------------------*/39 typedef struct {40 transfer_t transfer;41 39 link_t link; 42 bool used; 43 size_t required; 44 } transfer_status_t; 45 /*----------------------------------------------------------------------------*/ 46 #define BUCKET_COUNT 7 47 #define MAX_KEYS (sizeof(transfer_t) / sizeof(unsigned long)) 48 /*----------------------------------------------------------------------------*/ 49 static hash_index_t transfer_hash(unsigned long key[]) 40 size_t bw; 41 endpoint_t *ep; 42 } node_t; 43 /*----------------------------------------------------------------------------*/ 44 static hash_index_t node_hash(unsigned long key[]) 50 45 { 51 46 hash_index_t hash = 0; … … 58 53 } 59 54 /*----------------------------------------------------------------------------*/ 60 static int transfer_compare( 61 unsigned long key[], hash_count_t keys, link_t *item) 55 static int node_compare(unsigned long key[], hash_count_t keys, link_t *item) 62 56 { 63 57 assert(item); 64 transfer_status_t *status = 65 hash_table_get_instance(item, transfer_status_t, link); 66 const size_t bytes = 67 keys < MAX_KEYS ? keys * sizeof(unsigned long) : sizeof(transfer_t); 68 return bcmp(key, &status->transfer, bytes); 69 } 70 /*----------------------------------------------------------------------------*/ 71 static void transfer_remove(link_t *item) 58 node_t *node = hash_table_get_instance(item, node_t, link); 59 assert(node); 60 assert(node->ep); 61 bool match = true; 62 switch (keys) { 63 case 3: 64 match = match && (key[2] == node->ep->direction); 65 case 2: 66 match = match && (key[1] == (unsigned long)node->ep->endpoint); 67 case 1: 68 match = match && (key[0] == (unsigned long)node->ep->address); 69 break; 70 default: 71 match = false; 72 } 73 return match; 74 } 75 /*----------------------------------------------------------------------------*/ 76 static void node_remove(link_t *item) 72 77 { 73 78 assert(item); 74 transfer_status_t *status = 75 hash_table_get_instance(item, transfer_status_t, link); 76 assert(status); 77 free(status); 78 } 79 /*----------------------------------------------------------------------------*/ 80 hash_table_operations_t op = { 81 .hash = transfer_hash, 82 .compare = transfer_compare, 83 .remove_callback = transfer_remove, 79 node_t *node = hash_table_get_instance(item, node_t, link); 80 endpoint_destroy(node->ep); 81 free(node); 82 } 83 /*----------------------------------------------------------------------------*/ 84 static hash_table_operations_t op = { 85 .hash = node_hash, 86 .compare = node_compare, 87 .remove_callback = node_remove, 84 88 }; 85 89 /*----------------------------------------------------------------------------*/ … … 87 91 size_t size, size_t max_packet_size) 88 92 { 93 /* We care about bandwidth only for interrupt and isochronous. */ 94 if ((type != USB_TRANSFER_INTERRUPT) 95 && (type != USB_TRANSFER_ISOCHRONOUS)) { 96 return 0; 97 } 98 89 99 const unsigned packet_count = 90 100 (size + max_packet_size - 1) / max_packet_size; … … 120 130 } 121 131 /*----------------------------------------------------------------------------*/ 122 int bandwidth_init(bandwidth_t *instance, size_t bandwidth,123 size_t (*usage_fnc)(usb_speed_t, usb_transfer_type_t, size_t, size_t))132 int usb_endpoint_manager_init(usb_endpoint_manager_t *instance, 133 size_t available_bandwidth) 124 134 { 125 135 assert(instance); 126 136 fibril_mutex_initialize(&instance->guard); 127 instance->free = bandwidth;128 instance-> usage_fnc = usage_fnc;137 fibril_condvar_initialize(&instance->change); 138 instance->free_bw = available_bandwidth; 129 139 bool ht = 130 hash_table_create(&instance-> reserved, BUCKET_COUNT, MAX_KEYS, &op);140 hash_table_create(&instance->ep_table, BUCKET_COUNT, MAX_KEYS, &op); 131 141 return ht ? EOK : ENOMEM; 132 142 } 133 143 /*----------------------------------------------------------------------------*/ 134 void bandwidth_destroy(bandwidth_t *instance) 135 { 136 hash_table_destroy(&instance->reserved); 137 } 138 /*----------------------------------------------------------------------------*/ 139 int bandwidth_reserve(bandwidth_t *instance, usb_address_t address, 140 usb_endpoint_t endpoint, usb_direction_t direction, usb_speed_t speed, 141 usb_transfer_type_t transfer_type, size_t max_packet_size, size_t size, 142 unsigned interval) 143 { 144 if (transfer_type != USB_TRANSFER_ISOCHRONOUS && 145 transfer_type != USB_TRANSFER_INTERRUPT) { 146 return ENOTSUP; 147 } 148 149 assert(instance); 150 assert(instance->usage_fnc); 151 152 transfer_t trans = { 153 .address = address, 154 .endpoint = endpoint, 155 .direction = direction, 156 }; 144 void usb_endpoint_manager_destroy(usb_endpoint_manager_t *instance) 145 { 146 hash_table_destroy(&instance->ep_table); 147 } 148 /*----------------------------------------------------------------------------*/ 149 int usb_endpoint_manager_register_ep(usb_endpoint_manager_t *instance, 150 endpoint_t *ep, size_t data_size) 151 { 152 assert(ep); 153 size_t bw = bandwidth_count_usb11(ep->speed, ep->transfer_type, 154 data_size, ep->max_packet_size); 155 assert(instance); 156 157 unsigned long key[MAX_KEYS] = 158 {ep->address, ep->endpoint, ep->direction}; 157 159 fibril_mutex_lock(&instance->guard); 158 const size_t required = 159 instance->usage_fnc(speed, transfer_type, size, max_packet_size); 160 161 if (required > instance->free) { 160 161 link_t *item = 162 hash_table_find(&instance->ep_table, key); 163 if (item != NULL) { 164 fibril_mutex_unlock(&instance->guard); 165 return EEXISTS; 166 } 167 168 if (bw > instance->free_bw) { 162 169 fibril_mutex_unlock(&instance->guard); 163 170 return ENOSPC; 164 171 } 165 172 166 link_t *item = 167 hash_table_find(&instance->reserved, (unsigned long*)&trans); 168 if (item != NULL) { 169 fibril_mutex_unlock(&instance->guard); 170 return EEXISTS; 171 } 172 173 transfer_status_t *status = malloc(sizeof(transfer_status_t)); 174 if (status == NULL) { 173 node_t *node = malloc(sizeof(node_t)); 174 if (node == NULL) { 175 175 fibril_mutex_unlock(&instance->guard); 176 176 return ENOMEM; 177 177 } 178 178 179 status->transfer = trans; 180 status->required = required; 181 status->used = false; 182 link_initialize(&status->link); 183 184 hash_table_insert(&instance->reserved, 185 (unsigned long*)&status->transfer, &status->link); 186 instance->free -= required; 179 node->bw = bw; 180 node->ep = ep; 181 link_initialize(&node->link); 182 183 hash_table_insert(&instance->ep_table, key, &node->link); 184 instance->free_bw -= bw; 187 185 fibril_mutex_unlock(&instance->guard); 186 fibril_condvar_broadcast(&instance->change); 188 187 return EOK; 189 /* TODO: compute bandwidth used */ 190 } 191 /*----------------------------------------------------------------------------*/ 192 int bandwidth_release(bandwidth_t *instance, usb_address_t address, 193 usb_endpoint_t endpoint, usb_direction_t direction) 194 { 195 assert(instance); 196 transfer_t trans = { 197 .address = address, 198 .endpoint = endpoint, 199 .direction = direction, 200 }; 188 } 189 /*----------------------------------------------------------------------------*/ 190 int usb_endpoint_manager_unregister_ep(usb_endpoint_manager_t *instance, 191 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction) 192 { 193 assert(instance); 194 unsigned long key[MAX_KEYS] = {address, endpoint, direction}; 195 201 196 fibril_mutex_lock(&instance->guard); 202 link_t *item = 203 hash_table_find(&instance->reserved, (unsigned long*)&trans); 197 link_t *item = hash_table_find(&instance->ep_table, key); 204 198 if (item == NULL) { 205 199 fibril_mutex_unlock(&instance->guard); … … 207 201 } 208 202 209 transfer_status_t *status = 210 hash_table_get_instance(item, transfer_status_t, link); 211 212 instance->free += status->required; 213 214 hash_table_remove(&instance->reserved, 215 (unsigned long*)&trans, MAX_KEYS); 203 node_t *node = hash_table_get_instance(item, node_t, link); 204 instance->free_bw += node->bw; 205 hash_table_remove(&instance->ep_table, key, MAX_KEYS); 216 206 217 207 fibril_mutex_unlock(&instance->guard); 208 fibril_condvar_broadcast(&instance->change); 218 209 return EOK; 219 /* TODO: compute bandwidth freed */ 220 } 221 /*----------------------------------------------------------------------------*/ 222 int bandwidth_use(bandwidth_t *instance, usb_address_t address, 223 usb_endpoint_t endpoint, usb_direction_t direction) 224 { 225 assert(instance); 226 transfer_t trans = { 227 .address = address, 228 .endpoint = endpoint, 229 .direction = direction, 230 }; 210 } 211 /*----------------------------------------------------------------------------*/ 212 endpoint_t * usb_endpoint_manager_get_ep(usb_endpoint_manager_t *instance, 213 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction, 214 size_t *bw) 215 { 216 assert(instance); 217 unsigned long key[MAX_KEYS] = {address, endpoint, direction}; 218 231 219 fibril_mutex_lock(&instance->guard); 232 link_t *item = 233 hash_table_find(&instance->reserved, (unsigned long*)&trans); 234 int ret = EOK; 235 if (item != NULL) { 236 transfer_status_t *status = 237 hash_table_get_instance(item, transfer_status_t, link); 238 assert(status); 239 if (status->used) { 240 ret = EINPROGRESS; 241 } 242 status->used = true; 243 } else { 244 ret = EINVAL; 245 } 220 link_t *item = hash_table_find(&instance->ep_table, key); 221 if (item == NULL) { 222 fibril_mutex_unlock(&instance->guard); 223 return NULL; 224 } 225 node_t *node = hash_table_get_instance(item, node_t, link); 226 if (bw) 227 *bw = node->bw; 228 246 229 fibril_mutex_unlock(&instance->guard); 247 return ret; 248 } 249 /*----------------------------------------------------------------------------*/ 250 int bandwidth_free(bandwidth_t *instance, usb_address_t address, 251 usb_endpoint_t endpoint, usb_direction_t direction) 252 { 253 assert(instance); 254 transfer_t trans = { 255 .address = address, 256 .endpoint = endpoint, 257 .direction = direction, 258 }; 259 fibril_mutex_lock(&instance->guard); 260 link_t *item = 261 hash_table_find(&instance->reserved, (unsigned long*)&trans); 262 int ret = EOK; 263 if (item != NULL) { 264 transfer_status_t *status = 265 hash_table_get_instance(item, transfer_status_t, link); 266 assert(status); 267 if (!status->used) { 268 ret = ENOENT; 269 } 270 status->used = false; 271 } else { 272 ret = EINVAL; 273 } 274 fibril_mutex_unlock(&instance->guard); 275 return ret; 276 } 230 return node->ep; 231 } -
uspace/lib/usb/src/hub.c
r9d06563 ra4e18e1 142 142 DEV_IFACE_ID(USBHC_DEV_IFACE), 143 143 IPC_M_USBHC_RELEASE_ADDRESS, address); 144 } 145 146 static void unregister_control_endpoint_on_default_address( 147 usb_hc_connection_t *connection) 148 { 149 usb_device_connection_t dev_conn; 150 int rc = usb_device_connection_initialize_on_default_address(&dev_conn, 151 connection); 152 if (rc != EOK) { 153 return; 154 } 155 156 usb_pipe_t ctrl_pipe; 157 rc = usb_pipe_initialize_default_control(&ctrl_pipe, &dev_conn); 158 if (rc != EOK) { 159 return; 160 } 161 162 usb_pipe_unregister(&ctrl_pipe, connection); 144 163 } 145 164 … … 235 254 goto leave_release_default_address; 236 255 } 256 257 /* Before sending any traffic, we need to register this 258 * endpoint. 259 */ 260 rc = usb_pipe_register(&ctrl_pipe, 0, connection); 261 if (rc != EOK) { 262 rc = EREFUSED; 263 goto leave_release_default_address; 264 } 237 265 rc = usb_pipe_probe_default_control(&ctrl_pipe); 238 266 if (rc != EOK) { … … 244 272 if (rc != EOK) { 245 273 rc = ENOTCONN; 246 goto leave_ release_default_address;274 goto leave_unregister_endpoint; 247 275 } 248 276 … … 256 284 257 285 /* 286 * Register the control endpoint for the new device. 287 */ 288 rc = usb_pipe_register(&ctrl_pipe, 0, connection); 289 if (rc != EOK) { 290 rc = EREFUSED; 291 goto leave_unregister_endpoint; 292 } 293 294 /* 295 * Release the original endpoint. 296 */ 297 unregister_control_endpoint_on_default_address(connection); 298 299 /* 258 300 * Once the address is changed, we can return the default address. 259 301 */ 260 302 usb_hc_release_default_address(connection); 303 261 304 262 305 /* … … 273 316 } 274 317 318 319 275 320 /* 276 321 * And now inform the host controller about the handle. … … 308 353 usb_pipe_end_session(&ctrl_pipe); 309 354 355 leave_unregister_endpoint: 356 usb_pipe_unregister(&ctrl_pipe, connection); 357 310 358 leave_release_default_address: 311 359 usb_hc_release_default_address(connection); -
uspace/lib/usb/src/pipesinit.c
r9d06563 ra4e18e1 121 121 usb_endpoint_mapping_t *mapping, size_t mapping_count, 122 122 usb_endpoint_description_t *found_endpoint, 123 int interface_number )123 int interface_number, int interface_setting) 124 124 { 125 125 while (mapping_count > 0) { … … 127 127 || (mapping->interface_no == interface_number); 128 128 129 bool interface_setting_fits = (mapping->interface_setting < 0) 130 || (mapping->interface_setting == interface_setting); 131 129 132 bool endpoint_descriptions_fits = endpoint_fits_description( 130 133 mapping->description, found_endpoint); 131 134 132 if (interface_number_fits && endpoint_descriptions_fits) { 135 if (interface_number_fits 136 && interface_setting_fits 137 && endpoint_descriptions_fits) { 133 138 return mapping; 134 139 } … … 181 186 */ 182 187 usb_endpoint_mapping_t *ep_mapping = find_endpoint_mapping(mapping, 183 mapping_count, &description, interface->interface_number); 188 mapping_count, &description, 189 interface->interface_number, interface->alternate_setting); 184 190 if (ep_mapping == NULL) { 185 191 return ENOENT;
Note:
See TracChangeset
for help on using the changeset viewer.
