Changeset 26d46d2 in mainline for uspace/lib/usb/src/devdrv.c
- Timestamp:
- 2011-04-10T22:33:27Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 1a46610, fd153d3
- Parents:
- c6fe469 (diff), c7bdfa7 (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/devdrv.c
rc6fe469 r26d46d2 100 100 usb_device_t *dev, int alternate_setting) 101 101 { 102 if (endpoints == NULL) { 103 dev->pipes = NULL; 104 dev->pipes_count = 0; 105 return EOK; 106 } 107 102 108 usb_endpoint_mapping_t *pipes; 103 109 size_t pipes_count; … … 109 115 110 116 if (rc != EOK) { 111 usb_log_error(112 "Failed to create endpoint pipes for `%s': %s.\n",113 dev->ddf_dev->name, str_error(rc));114 117 return rc; 115 118 } … … 117 120 dev->pipes = pipes; 118 121 dev->pipes_count = pipes_count; 119 120 return EOK;121 }122 123 /** Initialize all endpoint pipes.124 *125 * @param drv The driver.126 * @param dev The device to be initialized.127 * @return Error code.128 */129 static int initialize_pipes(usb_device_t *dev)130 {131 int rc;132 133 rc = usb_device_connection_initialize_from_device(&dev->wire,134 dev->ddf_dev);135 if (rc != EOK) {136 usb_log_error(137 "Failed initializing connection on device `%s'. %s.\n",138 dev->ddf_dev->name, str_error(rc));139 return rc;140 }141 142 rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe,143 &dev->wire);144 if (rc != EOK) {145 usb_log_error("Failed to initialize default control pipe " \146 "on device `%s': %s.\n",147 dev->ddf_dev->name, str_error(rc));148 return rc;149 }150 151 rc = usb_pipe_probe_default_control(&dev->ctrl_pipe);152 if (rc != EOK) {153 usb_log_error(154 "Probing default control pipe on device `%s' failed: %s.\n",155 dev->ddf_dev->name, str_error(rc));156 return rc;157 }158 159 /* Get our interface. */160 dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);161 162 /*163 * We will do some querying of the device, it is worth to prepare164 * the long transfer.165 */166 rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe);167 if (rc != EOK) {168 usb_log_error("Failed to start transfer: %s.\n",169 str_error(rc));170 return rc;171 }172 173 /* Retrieve the descriptors. */174 rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe,175 &dev->descriptors);176 if (rc != EOK) {177 usb_log_error("Failed to retrieve standard device " \178 "descriptors of %s: %s.\n",179 dev->ddf_dev->name, str_error(rc));180 return rc;181 }182 183 184 if (driver->endpoints != NULL) {185 rc = initialize_other_pipes(driver->endpoints, dev, 0);186 }187 188 usb_pipe_end_long_transfer(&dev->ctrl_pipe);189 190 /* Rollback actions. */191 if (rc != EOK) {192 if (dev->descriptors.configuration != NULL) {193 free(dev->descriptors.configuration);194 }195 }196 197 return rc;198 }199 200 /** Count number of alternate settings of a interface.201 *202 * @param config_descr Full configuration descriptor.203 * @param config_descr_size Size of @p config_descr in bytes.204 * @param interface_no Interface number.205 * @return Number of alternate interfaces for @p interface_no interface.206 */207 size_t usb_interface_count_alternates(uint8_t *config_descr,208 size_t config_descr_size, uint8_t interface_no)209 {210 assert(config_descr != NULL);211 assert(config_descr_size > 0);212 213 usb_dp_parser_t dp_parser = {214 .nesting = usb_dp_standard_descriptor_nesting215 };216 usb_dp_parser_data_t dp_data = {217 .data = config_descr,218 .size = config_descr_size,219 .arg = NULL220 };221 222 size_t alternate_count = 0;223 224 uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,225 &dp_data, config_descr);226 while (iface_ptr != NULL) {227 usb_standard_interface_descriptor_t *iface228 = (usb_standard_interface_descriptor_t *) iface_ptr;229 if (iface->descriptor_type == USB_DESCTYPE_INTERFACE) {230 if (iface->interface_number == interface_no) {231 alternate_count++;232 }233 }234 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,235 config_descr, iface_ptr);236 }237 238 return alternate_count;239 }240 241 /** Initialize structures related to alternate interfaces.242 *243 * @param dev Device where alternate settings shall be initialized.244 * @return Error code.245 */246 static int initialize_alternate_interfaces(usb_device_t *dev)247 {248 if (dev->interface_no < 0) {249 dev->alternate_interfaces = NULL;250 return EOK;251 }252 253 usb_alternate_interfaces_t *alternates254 = malloc(sizeof(usb_alternate_interfaces_t));255 256 if (alternates == NULL) {257 return ENOMEM;258 }259 260 alternates->alternative_count261 = usb_interface_count_alternates(dev->descriptors.configuration,262 dev->descriptors.configuration_size, dev->interface_no);263 264 if (alternates->alternative_count == 0) {265 free(alternates);266 return ENOENT;267 }268 269 alternates->alternatives = malloc(alternates->alternative_count270 * sizeof(usb_alternate_interface_descriptors_t));271 if (alternates->alternatives == NULL) {272 free(alternates);273 return ENOMEM;274 }275 276 alternates->current = 0;277 278 usb_dp_parser_t dp_parser = {279 .nesting = usb_dp_standard_descriptor_nesting280 };281 usb_dp_parser_data_t dp_data = {282 .data = dev->descriptors.configuration,283 .size = dev->descriptors.configuration_size,284 .arg = NULL285 };286 287 usb_alternate_interface_descriptors_t *cur_alt_iface288 = &alternates->alternatives[0];289 290 uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,291 &dp_data, dp_data.data);292 while (iface_ptr != NULL) {293 usb_standard_interface_descriptor_t *iface294 = (usb_standard_interface_descriptor_t *) iface_ptr;295 if ((iface->descriptor_type != USB_DESCTYPE_INTERFACE)296 || (iface->interface_number != dev->interface_no)) {297 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser,298 &dp_data,299 dp_data.data, iface_ptr);300 continue;301 }302 303 cur_alt_iface->interface = iface;304 cur_alt_iface->nested_descriptors = iface_ptr + sizeof(*iface);305 306 /* Find next interface to count size of nested descriptors. */307 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,308 dp_data.data, iface_ptr);309 if (iface_ptr == NULL) {310 uint8_t *next = dp_data.data + dp_data.size;311 cur_alt_iface->nested_descriptors_size312 = next - cur_alt_iface->nested_descriptors;313 } else {314 cur_alt_iface->nested_descriptors_size315 = iface_ptr - cur_alt_iface->nested_descriptors;316 }317 318 cur_alt_iface++;319 }320 321 dev->alternate_interfaces = alternates;322 122 323 123 return EOK; … … 339 139 int rc; 340 140 341 usb_device_t *dev = malloc(sizeof(usb_device_t)); 342 if (dev == NULL) { 343 usb_log_error("Out of memory when adding device `%s'.\n", 344 gen_dev->name); 345 return ENOMEM; 346 } 347 348 349 dev->ddf_dev = gen_dev; 350 dev->ddf_dev->driver_data = dev; 351 dev->driver_data = NULL; 352 dev->descriptors.configuration = NULL; 353 354 dev->pipes_count = 0; 355 dev->pipes = NULL; 356 357 rc = initialize_pipes(dev); 358 if (rc != EOK) { 359 free(dev); 360 return rc; 361 } 362 363 (void) initialize_alternate_interfaces(dev); 141 usb_device_t *dev = NULL; 142 const char *err_msg = NULL; 143 rc = usb_device_create(gen_dev, driver->endpoints, &dev, &err_msg); 144 if (rc != EOK) { 145 usb_log_error("USB device `%s' creation failed (%s): %s.\n", 146 gen_dev->name, err_msg, str_error(rc)); 147 return rc; 148 } 364 149 365 150 return driver->ops->add_device(dev); … … 395 180 * with usb_pipe_initialize_from_configuration(). 396 181 * 182 * @warning This is a wrapper function that does several operations that 183 * can fail and that cannot be rollbacked easily. That means that a failure 184 * during the SET_INTERFACE request would result in having a device with 185 * no pipes at all (except the default control one). That is because the old 186 * pipes needs to be unregistered at HC first and the new ones could not 187 * be created. 188 * 397 189 * @param dev USB device. 398 190 * @param alternate_setting Alternate setting to choose. … … 409 201 int rc; 410 202 411 /* TODO: more transactional behavior. */412 413 203 /* Destroy existing pipes. */ 414 204 rc = destroy_current_pipes(dev); … … 432 222 /** Retrieve basic descriptors from the device. 433 223 * 434 * @param[in] ctrl_pipe Control pipe with opened session.224 * @param[in] ctrl_pipe Control endpoint pipe. 435 225 * @param[out] descriptors Where to store the descriptors. 436 226 * @return Error code. … … 440 230 { 441 231 assert(descriptors != NULL); 442 assert(usb_pipe_is_session_started(ctrl_pipe));443 232 444 233 descriptors->configuration = NULL; 445 234 446 235 int rc; 236 237 /* It is worth to start a long transfer. */ 238 rc = usb_pipe_start_long_transfer(ctrl_pipe); 239 if (rc != EOK) { 240 return rc; 241 } 447 242 448 243 /* Get the device descriptor. */ 449 244 rc = usb_request_get_device_descriptor(ctrl_pipe, &descriptors->device); 450 245 if (rc != EOK) { 451 return rc;246 goto leave; 452 247 } 453 248 … … 456 251 ctrl_pipe, 0, (void **) &descriptors->configuration, 457 252 &descriptors->configuration_size); 458 if (rc != EOK) { 459 return rc; 460 }461 462 return EOK;253 254 leave: 255 usb_pipe_end_long_transfer(ctrl_pipe); 256 257 return rc; 463 258 } 464 259 … … 641 436 } 642 437 438 /** Initialize control pipe in a device. 439 * 440 * @param dev USB device in question. 441 * @param errmsg Where to store error context. 442 * @return 443 */ 444 static int init_wire_and_ctrl_pipe(usb_device_t *dev, const char **errmsg) 445 { 446 int rc; 447 448 rc = usb_device_connection_initialize_from_device(&dev->wire, 449 dev->ddf_dev); 450 if (rc != EOK) { 451 *errmsg = "device connection initialization"; 452 return rc; 453 } 454 455 rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe, 456 &dev->wire); 457 if (rc != EOK) { 458 *errmsg = "default control pipe initialization"; 459 return rc; 460 } 461 462 return EOK; 463 } 464 465 466 /** Create new instance of USB device. 467 * 468 * @param[in] ddf_dev Generic DDF device backing the USB one. 469 * @param[in] endpoints NULL terminated array of endpoints (NULL for none). 470 * @param[out] dev_ptr Where to store pointer to the new device. 471 * @param[out] errstr_ptr Where to store description of context 472 * (in case error occurs). 473 * @return Error code. 474 */ 475 int usb_device_create(ddf_dev_t *ddf_dev, 476 usb_endpoint_description_t **endpoints, 477 usb_device_t **dev_ptr, const char **errstr_ptr) 478 { 479 assert(dev_ptr != NULL); 480 assert(ddf_dev != NULL); 481 482 int rc; 483 484 usb_device_t *dev = malloc(sizeof(usb_device_t)); 485 if (dev == NULL) { 486 *errstr_ptr = "structure allocation"; 487 return ENOMEM; 488 } 489 490 // FIXME: proper deallocation in case of errors 491 492 dev->ddf_dev = ddf_dev; 493 dev->driver_data = NULL; 494 dev->descriptors.configuration = NULL; 495 dev->alternate_interfaces = NULL; 496 497 dev->pipes_count = 0; 498 dev->pipes = NULL; 499 500 /* Initialize backing wire and control pipe. */ 501 rc = init_wire_and_ctrl_pipe(dev, errstr_ptr); 502 if (rc != EOK) { 503 return rc; 504 } 505 506 /* Get our interface. */ 507 dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev); 508 509 /* Retrieve standard descriptors. */ 510 rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe, 511 &dev->descriptors); 512 if (rc != EOK) { 513 *errstr_ptr = "descriptor retrieval"; 514 return rc; 515 } 516 517 /* Create alternate interfaces. */ 518 rc = usb_alternate_interfaces_create(dev->descriptors.configuration, 519 dev->descriptors.configuration_size, dev->interface_no, 520 &dev->alternate_interfaces); 521 if (rc != EOK) { 522 /* We will try to silently ignore this. */ 523 dev->alternate_interfaces = NULL; 524 } 525 526 rc = initialize_other_pipes(endpoints, dev, 0); 527 if (rc != EOK) { 528 *errstr_ptr = "pipes initialization"; 529 return rc; 530 } 531 532 *errstr_ptr = NULL; 533 *dev_ptr = dev; 534 535 return EOK; 536 } 537 643 538 /** 644 539 * @}
Note:
See TracChangeset
for help on using the changeset viewer.