Changeset 54464f6a in mainline for uspace/lib/usbdev/src
- Timestamp:
- 2011-11-11T19:48:33Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 50a01a9
- Parents:
- c2e50d7 (diff), 747ef72 (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/usbdev/src
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usbdev/src/altiface.c
rc2e50d7 r54464f6a 90 90 * @return Error code. 91 91 */ 92 int usb_alternate_interfaces_create(const uint8_t *config_descr, 93 size_t config_descr_size, int interface_number, 94 usb_alternate_interfaces_t **alternates_ptr) 92 int usb_alternate_interfaces_init(usb_alternate_interfaces_t *alternates, 93 const uint8_t *config_descr, size_t config_descr_size, int interface_number) 95 94 { 96 assert(alternates _ptr!= NULL);95 assert(alternates != NULL); 97 96 assert(config_descr != NULL); 98 97 assert(config_descr_size > 0); 99 98 100 *alternates_ptr = NULL; 99 alternates->alternatives = NULL; 100 alternates->alternative_count = 0; 101 alternates->current = 0; 102 101 103 if (interface_number < 0) { 102 104 return EOK; 103 }104 105 usb_alternate_interfaces_t *alternates106 = malloc(sizeof(usb_alternate_interfaces_t));107 if (alternates == NULL) {108 return ENOMEM;109 105 } 110 106 … … 114 110 115 111 if (alternates->alternative_count == 0) { 116 free(alternates);117 112 return ENOENT; 118 113 } … … 121 116 sizeof(usb_alternate_interface_descriptors_t)); 122 117 if (alternates->alternatives == NULL) { 123 free(alternates);124 118 return ENOMEM; 125 119 } 126 120 127 alternates->current = 0; 128 129 usb_dp_parser_t dp_parser = { 121 const usb_dp_parser_t dp_parser = { 130 122 .nesting = usb_dp_standard_descriptor_nesting 131 123 }; 132 usb_dp_parser_data_t dp_data = {124 const usb_dp_parser_data_t dp_data = { 133 125 .data = config_descr, 134 126 .size = config_descr_size, … … 147 139 || (iface->interface_number != interface_number)) { 148 140 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, 149 &dp_data, 150 dp_data.data, iface_ptr); 141 &dp_data, dp_data.data, iface_ptr); 151 142 continue; 152 143 } … … 170 161 } 171 162 172 *alternates_ptr = alternates;173 174 163 return EOK; 175 164 } 176 165 177 void usb_alternate_interfaces_de stroy(usb_alternate_interfaces_t *alternate)166 void usb_alternate_interfaces_deinit(usb_alternate_interfaces_t *alternate) 178 167 { 179 168 if (!alternate) 180 169 return; 181 170 free(alternate->alternatives); 182 free(alternate);183 171 } 184 172 /** -
uspace/lib/usbdev/src/devdrv.c
rc2e50d7 r54464f6a 81 81 * @return Number of pipes (excluding default control pipe). 82 82 */ 83 static size_t count_other_pipes(const usb_endpoint_description_t **endpoints) 84 { 85 size_t count = 0; 86 if (endpoints == NULL) { 87 return 0; 88 } 89 90 while (endpoints[count] != NULL) { 91 count++; 92 } 93 83 static inline size_t count_other_pipes( 84 const usb_endpoint_description_t **endpoints) 85 { 86 size_t count; 87 for (count = 0; endpoints && endpoints[count] != NULL; ++count); 94 88 return count; 95 89 } … … 104 98 usb_device_t *dev, int alternate_setting) 105 99 { 100 assert(dev); 101 106 102 if (endpoints == NULL) { 107 103 dev->pipes = NULL; … … 300 296 301 297 return rc; 298 } 299 300 /** Cleanup structure initialized via usb_device_retrieve_descriptors. 301 * 302 * @param[in] descriptors Where to store the descriptors. 303 */ 304 void usb_device_release_descriptors(usb_device_descriptors_t *descriptors) 305 { 306 assert(descriptors); 307 free(descriptors->configuration); 308 descriptors->configuration = NULL; 302 309 } 303 310 … … 319 326 * (not NULL terminated). 320 327 * @param[out] pipes_count_ptr Where to store number of pipes 321 * (set to if you wish to ignore the count).328 * (set to NULL if you wish to ignore the count). 322 329 * @return Error code. 323 330 */ … … 340 347 const size_t pipe_count = count_other_pipes(endpoints); 341 348 if (pipe_count == 0) { 342 *pipes_count_ptr = pipe_count; 349 if (pipes_count_ptr) 350 *pipes_count_ptr = pipe_count; 343 351 *pipes_ptr = NULL; 344 352 return EOK; … … 346 354 347 355 usb_endpoint_mapping_t *pipes 348 = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count);356 = calloc(pipe_count, sizeof(usb_endpoint_mapping_t)); 349 357 if (pipes == NULL) { 350 358 return ENOMEM; 351 359 } 352 360 353 /* Initialize to NULL to allow smooth rollback. */354 for (i = 0; i < pipe_count; i++) {355 pipes[i].pipe = NULL;356 }357 358 361 /* Now allocate and fully initialize. */ 359 362 for (i = 0; i < pipe_count; i++) { 360 pipes[i].pipe = malloc(sizeof(usb_pipe_t));361 if (pipes[i].pipe == NULL) {362 rc = ENOMEM;363 goto rollback_free_only;364 }365 363 pipes[i].description = endpoints[i]; 366 364 pipes[i].interface_no = interface_no; … … 389 387 for (i = 0; i < pipe_count; i++) { 390 388 if (pipes[i].present) { 391 rc = usb_pipe_register( pipes[i].pipe,389 rc = usb_pipe_register(&pipes[i].pipe, 392 390 pipes[i].descriptor->poll_interval, &hc_conn); 393 391 if (rc != EOK) { … … 398 396 399 397 if (usb_hc_connection_close(&hc_conn) != EOK) 400 usb_log_warning(" usb_device_create_pipes(): "401 "Failed to close connection.\n");398 usb_log_warning("%s: Failed to close connection.\n", 399 __FUNCTION__); 402 400 403 401 *pipes_ptr = pipes; … … 417 415 for (i = 0; i < pipe_count; i++) { 418 416 if (pipes[i].present) { 419 usb_pipe_unregister( pipes[i].pipe, &hc_conn);417 usb_pipe_unregister(&pipes[i].pipe, &hc_conn); 420 418 } 421 419 } … … 431 429 */ 432 430 rollback_free_only: 433 for (i = 0; i < pipe_count; i++) {434 if (pipes[i].pipe != NULL) {435 free(pipes[i].pipe);436 }437 }438 431 free(pipes); 439 432 … … 477 470 i, pipes[i].present ? "" : "not "); 478 471 if (pipes[i].present) 479 usb_pipe_unregister(pipes[i].pipe, &hc_conn); 480 free(pipes[i].pipe); 472 usb_pipe_unregister(&pipes[i].pipe, &hc_conn); 481 473 } 482 474 … … 489 481 return EOK; 490 482 } 491 492 /** Initialize control pipe in a device.493 *494 * @param dev USB device in question.495 * @param errmsg Where to store error context.496 * @return497 */498 static int init_wire_and_ctrl_pipe(usb_device_t *dev, const char **errmsg)499 {500 int rc;501 502 rc = usb_device_connection_initialize_from_device(&dev->wire,503 dev->ddf_dev);504 if (rc != EOK) {505 *errmsg = "device connection initialization";506 return rc;507 }508 509 rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe,510 &dev->wire);511 if (rc != EOK) {512 *errmsg = "default control pipe initialization";513 return rc;514 }515 516 return EOK;517 }518 519 483 520 484 /** Initialize new instance of USB device. … … 533 497 assert(ddf_dev != NULL); 534 498 499 *errstr_ptr = NULL; 500 535 501 usb_dev->ddf_dev = ddf_dev; 536 502 usb_dev->driver_data = NULL; 537 503 usb_dev->descriptors.configuration = NULL; 538 usb_dev->alternate_interfaces = NULL;539 504 usb_dev->pipes_count = 0; 540 505 usb_dev->pipes = NULL; 541 506 542 507 /* Initialize backing wire and control pipe. */ 543 int rc = init_wire_and_ctrl_pipe(usb_dev, errstr_ptr); 544 if (rc != EOK) { 508 int rc = usb_device_connection_initialize_from_device( 509 &usb_dev->wire, ddf_dev); 510 if (rc != EOK) { 511 *errstr_ptr = "device connection initialization"; 512 return rc; 513 } 514 515 /* This pipe was registered by the hub driver, 516 * during device initialization. */ 517 rc = usb_pipe_initialize_default_control(&usb_dev->ctrl_pipe, 518 &usb_dev->wire); 519 if (rc != EOK) { 520 *errstr_ptr = "default control pipe initialization"; 545 521 return rc; 546 522 } … … 553 529 &usb_dev->descriptors); 554 530 if (rc != EOK) { 555 /* Nothing allocated, nothing to free. */556 531 *errstr_ptr = "descriptor retrieval"; 557 532 return rc; 558 533 } 559 534 560 /* Create alternate interfaces. We will silently ignore failure. */ 561 //TODO Why ignore? 562 usb_alternate_interfaces_create(usb_dev->descriptors.configuration, 563 usb_dev->descriptors.configuration_size, usb_dev->interface_no, 564 &usb_dev->alternate_interfaces); 565 566 rc = initialize_other_pipes(endpoints, usb_dev, 0); 535 /* Create alternate interfaces. We will silently ignore failure. 536 * We might either control one interface or an entire device, 537 * it makes no sense to speak about alternate interfaces when 538 * controlling a device. */ 539 rc = usb_alternate_interfaces_init(&usb_dev->alternate_interfaces, 540 usb_dev->descriptors.configuration, 541 usb_dev->descriptors.configuration_size, usb_dev->interface_no); 542 const int alternate_iface = 543 (rc == EOK) ? usb_dev->alternate_interfaces.current : 0; 544 545 /* TODO Add comment here. */ 546 rc = initialize_other_pipes(endpoints, usb_dev, alternate_iface); 567 547 if (rc != EOK) { 568 548 /* Full configuration descriptor is allocated. */ 569 free(usb_dev->descriptors.configuration);549 usb_device_release_descriptors(&usb_dev->descriptors); 570 550 /* Alternate interfaces may be allocated */ 571 usb_alternate_interfaces_de stroy(usb_dev->alternate_interfaces);551 usb_alternate_interfaces_deinit(&usb_dev->alternate_interfaces); 572 552 *errstr_ptr = "pipes initialization"; 573 553 return rc; 574 554 } 575 576 *errstr_ptr = NULL;577 555 578 556 return EOK; … … 591 569 destroy_current_pipes(dev); 592 570 593 usb_alternate_interfaces_de stroy(dev->alternate_interfaces);594 free(dev->descriptors.configuration);571 usb_alternate_interfaces_deinit(&dev->alternate_interfaces); 572 usb_device_release_descriptors(&dev->descriptors); 595 573 free(dev->driver_data); 596 574 } -
uspace/lib/usbdev/src/devpoll.c
rc2e50d7 r54464f6a 73 73 74 74 usb_pipe_t *pipe 75 = polling_data->dev->pipes[polling_data->pipe_index].pipe;75 = &polling_data->dev->pipes[polling_data->pipe_index].pipe; 76 76 77 77 if (polling_data->debug > 0) { … … 208 208 return EINVAL; 209 209 } 210 if ((dev->pipes[pipe_index].pipe ->transfer_type != USB_TRANSFER_INTERRUPT)211 || (dev->pipes[pipe_index].pipe ->direction != USB_DIRECTION_IN)) {210 if ((dev->pipes[pipe_index].pipe.transfer_type != USB_TRANSFER_INTERRUPT) 211 || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) { 212 212 return EINVAL; 213 213 } 214 214 215 usb_device_auto_polling_t *auto_polling 216 = malloc(sizeof(usb_device_auto_polling_t)); 217 if (auto_polling == NULL) { 218 return ENOMEM; 219 } 220 221 auto_polling->debug = 1; 222 auto_polling->auto_clear_halt = true; 223 auto_polling->delay = 0; 224 auto_polling->max_failures = MAX_FAILED_ATTEMPTS; 225 auto_polling->on_data = callback; 226 auto_polling->on_polling_end = terminated_callback; 227 auto_polling->on_error = NULL; 228 229 int rc = usb_device_auto_polling(dev, pipe_index, auto_polling, 215 const usb_device_auto_polling_t auto_polling = { 216 .debug = 1, 217 .auto_clear_halt = true, 218 .delay = 0, 219 .max_failures = MAX_FAILED_ATTEMPTS, 220 .on_data = callback, 221 .on_polling_end = terminated_callback, 222 .on_error = NULL, 223 }; 224 225 return usb_device_auto_polling(dev, pipe_index, &auto_polling, 230 226 request_size, arg); 231 232 free(auto_polling);233 234 return rc;235 227 } 236 228 … … 253 245 */ 254 246 int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index, 255 usb_device_auto_polling_t *polling,247 const usb_device_auto_polling_t *polling, 256 248 size_t request_size, void *arg) 257 249 { … … 262 254 return EINVAL; 263 255 } 264 if ((dev->pipes[pipe_index].pipe ->transfer_type != USB_TRANSFER_INTERRUPT)265 || (dev->pipes[pipe_index].pipe ->direction != USB_DIRECTION_IN)) {256 if ((dev->pipes[pipe_index].pipe.transfer_type != USB_TRANSFER_INTERRUPT) 257 || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) { 266 258 return EINVAL; 267 259 } -
uspace/lib/usbdev/src/dp.c
rc2e50d7 r54464f6a 57 57 58 58 /** Nesting of standard USB descriptors. */ 59 usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[] = {59 const usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[] = { 60 60 NESTING(CONFIGURATION, INTERFACE), 61 61 NESTING(INTERFACE, ENDPOINT), -
uspace/lib/usbdev/src/hub.c
rc2e50d7 r54464f6a 66 66 * 67 67 * @param connection Opened connection to host controller. 68 * @param preferred Preferred SUB address. 69 * @param strict Fail if the preferred address is not avialable. 68 70 * @param speed Speed of the new device (device that will be assigned 69 71 * the returned address). … … 71 73 */ 72 74 usb_address_t usb_hc_request_address(usb_hc_connection_t *connection, 73 usb_ speed_t speed)75 usb_address_t preferred, bool strict, usb_speed_t speed) 74 76 { 75 77 CHECK_CONNECTION(connection); … … 78 80 79 81 sysarg_t address; 80 int rc = async_req_2_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 81 IPC_M_USBHC_REQUEST_ADDRESS, speed, 82 &address); 82 int rc = async_req_4_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 83 IPC_M_USBHC_REQUEST_ADDRESS, preferred, strict, speed, &address); 83 84 84 85 async_exchange_end(exch); … … 132 133 } 133 134 134 135 static void unregister_control_endpoint_on_default_address( 136 usb_hc_connection_t *connection) 135 /** Change address of connected device. 136 * This function automatically updates the backing connection to point to 137 * the new address. It also unregisterrs the old endpoint and registers 138 * a new one. 139 * This creates whole bunch of problems: 140 * 1. All pipes using this wire are broken because they are not 141 * registered for new address 142 * 2. All other pipes for this device are using wrong address, 143 * possibly targeting completely different device 144 * 145 * @param pipe Control endpoint pipe (session must be already started). 146 * @param new_address New USB address to be set (in native endianness). 147 * @return Error code. 148 */ 149 static int usb_request_set_address(usb_pipe_t *pipe, usb_address_t new_address, 150 usb_hc_connection_t *hc_conn) 137 151 { 138 usb_device_connection_t dev_conn; 139 int rc = usb_device_connection_initialize_on_default_address(&dev_conn, 140 connection); 141 if (rc != EOK) { 142 return; 143 } 144 145 usb_pipe_t ctrl_pipe; 146 rc = usb_pipe_initialize_default_control(&ctrl_pipe, &dev_conn); 147 if (rc != EOK) { 148 return; 149 } 150 151 usb_pipe_unregister(&ctrl_pipe, connection); 152 if ((new_address < 0) || (new_address >= USB11_ADDRESS_MAX)) { 153 return EINVAL; 154 } 155 assert(pipe); 156 assert(hc_conn); 157 assert(pipe->wire != NULL); 158 159 const uint16_t addr = uint16_host2usb((uint16_t)new_address); 160 161 int rc = usb_control_request_set(pipe, 162 USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE, 163 USB_DEVREQ_SET_ADDRESS, addr, 0, NULL, 0); 164 165 if (rc != EOK) { 166 return rc; 167 } 168 169 /* TODO: prevent others from accessing the wire now. */ 170 if (usb_pipe_unregister(pipe, hc_conn) != EOK) { 171 usb_log_warning( 172 "Failed to unregister the old pipe on address change.\n"); 173 } 174 /* The address is already changed so set it in the wire */ 175 pipe->wire->address = new_address; 176 rc = usb_pipe_register(pipe, 0, hc_conn); 177 if (rc != EOK) 178 return EADDRNOTAVAIL; 179 180 return EOK; 152 181 } 153 182 … … 171 200 * 172 201 * @param[in] parent Parent device (i.e. the hub device). 173 * @param[in] connection Connection to host controller. 202 * @param[in] connection Connection to host controller. Must be non-null. 174 203 * @param[in] dev_speed New device speed. 175 204 * @param[in] enable_port Function for enabling signaling through the port the … … 177 206 * @param[in] arg Any data argument to @p enable_port. 178 207 * @param[out] assigned_address USB address of the device. 179 * @param[in] dev_ops Child device ops. 208 * @param[in] dev_ops Child device ops. Will use default if not provided. 180 209 * @param[in] new_dev_data Arbitrary pointer to be stored in the child 181 * as @c driver_data. 210 * as @c driver_data. Will allocate and assign usb_hub_attached_device_t 211 * structure if NULL. 182 212 * @param[out] new_fun Storage where pointer to allocated child function 183 * will be written. 213 * will be written. Must be non-null. 184 214 * @return Error code. 215 * @retval EINVAL Either connection or new_fun is a NULL pointer. 185 216 * @retval ENOENT Connection to HC not opened. 186 217 * @retval EADDRNOTAVAIL Failed retrieving free address from host controller. … … 195 226 ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun) 196 227 { 197 assert(connection != NULL); 228 if (new_fun == NULL || connection == NULL) 229 return EINVAL; 230 198 231 // FIXME: this is awful, we are accessing directly the structure. 232 // TODO: Why not use provided connection? 199 233 usb_hc_connection_t hc_conn = { 200 234 .hc_handle = connection->hc_handle, … … 215 249 } 216 250 217 218 251 /* 219 252 * Request new address. 220 253 */ 221 usb_address_t dev_addr = usb_hc_request_address(&hc_conn, dev_speed); 254 usb_address_t dev_addr = 255 usb_hc_request_address(&hc_conn, 0, false, dev_speed); 222 256 if (dev_addr < 0) { 223 257 rc = EADDRNOTAVAIL; … … 240 274 241 275 usb_pipe_t ctrl_pipe; 242 rc = usb_pipe_initialize_default_control(&ctrl_pipe, 243 &dev_conn); 276 rc = usb_pipe_initialize_default_control(&ctrl_pipe, &dev_conn); 244 277 if (rc != EOK) { 245 278 rc = ENOTCONN; … … 248 281 249 282 do { 250 rc = usb_ pipe_register_with_speed(&ctrl_pipe, dev_speed, 0,251 &hc_conn);252 if (rc != EOK) {283 rc = usb_hc_request_address(&hc_conn, USB_ADDRESS_DEFAULT, 284 true, dev_speed); 285 if (rc == ENOENT) { 253 286 /* Do not overheat the CPU ;-). */ 254 287 async_usleep(ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC); 255 288 } 256 } while (rc != EOK); 289 } while (rc == ENOENT); 290 if (rc < 0) { 291 goto leave_release_free_address; 292 } 293 294 /* Register control pipe on default address. */ 295 rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn); 296 if (rc != EOK) { 297 rc = ENOTCONN; 298 goto leave_release_default_address; 299 } 300 257 301 struct timeval end_time; 258 302 … … 267 311 * above might use much of this time so we should only wait to fill 268 312 * up the 100ms quota*/ 269 suseconds_t elapsed = tv_sub(&end_time, &start_time);313 const suseconds_t elapsed = tv_sub(&end_time, &start_time); 270 314 if (elapsed < 100000) { 271 315 async_usleep(100000 - elapsed); 272 316 } 273 317 274 /* 275 * Endpoint is registered. We can enable the port and change 276 * device address. 277 */ 318 /* Endpoint is registered. We can enable the port and change address. */ 278 319 rc = enable_port(arg); 279 320 if (rc != EOK) { … … 287 328 async_usleep(10000); 288 329 330 /* Get max_packet_size value. */ 289 331 rc = usb_pipe_probe_default_control(&ctrl_pipe); 290 332 if (rc != EOK) { … … 293 335 } 294 336 295 rc = usb_request_set_address(&ctrl_pipe, dev_addr );337 rc = usb_request_set_address(&ctrl_pipe, dev_addr, &hc_conn); 296 338 if (rc != EOK) { 297 339 rc = ESTALL; … … 299 341 } 300 342 301 /* 302 * Address changed. We can release the original endpoint, thus 303 * allowing other to access the default address. 304 */ 305 unregister_control_endpoint_on_default_address(&hc_conn); 306 307 /* 308 * Time to register the new endpoint. 309 */ 310 rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn); 311 if (rc != EOK) { 312 goto leave_release_free_address; 313 } 314 315 /* 316 * It is time to register the device with devman. 317 */ 343 /* Address changed. We can release the default, thus 344 * allowing other to access the default address. */ 345 usb_hc_unregister_device(&hc_conn, USB_ADDRESS_DEFAULT); 346 347 /* Register the device with devman. */ 318 348 /* FIXME: create device_register that will get opened ctrl pipe. */ 319 349 ddf_fun_t *child_fun; 320 rc = usb_device_register_child_in_devman( dev_addr, dev_conn.hc_handle,350 rc = usb_device_register_child_in_devman(&ctrl_pipe, 321 351 parent, dev_ops, new_dev_data, &child_fun); 322 352 if (rc != EOK) { 323 rc = ESTALL;324 353 goto leave_release_free_address; 325 354 } 326 355 327 /* 328 * And now inform the host controller about the handle. 329 */ 330 usb_hub_attached_device_t new_device = { 356 const usb_hub_attached_device_t new_device = { 331 357 .address = dev_addr, 332 358 .fun = child_fun, 333 359 }; 360 361 362 /* Inform the host controller about the handle. */ 334 363 rc = usb_hc_register_device(&hc_conn, &new_device); 335 364 if (rc != EOK) { 365 /* We know nothing about that data. */ 366 if (new_dev_data) 367 child_fun->driver_data = NULL; 368 /* The child function is already created. */ 369 ddf_fun_destroy(child_fun); 336 370 rc = EDESTADDRREQ; 337 371 goto leave_release_free_address; 338 372 } 339 373 340 341 /*342 * And we are done.343 */344 374 if (assigned_address != NULL) { 345 375 *assigned_address = dev_addr; 346 376 } 347 if (new_fun != NULL) { 348 *new_fun = child_fun; 349 } 377 378 *new_fun = child_fun; 350 379 351 380 rc = EOK; … … 357 386 */ 358 387 leave_release_default_address: 359 usb_ pipe_unregister(&ctrl_pipe, &hc_conn);388 usb_hc_unregister_device(&hc_conn, USB_ADDRESS_DEFAULT); 360 389 361 390 leave_release_free_address: 362 usb_hc_unregister_device(&hc_conn, dev_addr); 391 /* This might be either 0:0 or dev_addr:0 */ 392 if (usb_pipe_unregister(&ctrl_pipe, &hc_conn) != EOK) 393 usb_log_warning("%s: Failed to unregister default pipe.\n", 394 __FUNCTION__); 395 396 if (usb_hc_unregister_device(&hc_conn, dev_addr) != EOK) 397 usb_log_warning("%s: Failed to unregister device.\n", 398 __FUNCTION__); 363 399 364 400 close_connection: 365 401 if (usb_hc_connection_close(&hc_conn) != EOK) 366 usb_log_warning(" usb_hc_new_device_wrapper(): Failed to close "367 "connection.\n");402 usb_log_warning("%s: Failed to close hc connection.\n", 403 __FUNCTION__); 368 404 369 405 return rc; -
uspace/lib/usbdev/src/pipes.c
rc2e50d7 r54464f6a 56 56 async_exch_t *exch = async_exchange_begin(sess); 57 57 58 /*59 * We are sending special value as a handle - zero - to get60 * handle of the parent function (that handle was used61 * when registering our device @p dev.62 */63 58 sysarg_t address; 64 int rc = async_req_ 2_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),65 IPC_M_USB_GET_ ADDRESS, 0, &address);59 int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE), 60 IPC_M_USB_GET_MY_ADDRESS, &address); 66 61 67 62 async_exchange_end(exch); … … 80 75 int usb_device_get_assigned_interface(const ddf_dev_t *device) 81 76 { 77 assert(device); 82 78 async_sess_t *parent_sess = 83 79 devman_parent_device_connect(EXCHANGE_ATOMIC, device->handle, -
uspace/lib/usbdev/src/pipesinit.c
rc2e50d7 r54464f6a 192 192 } 193 193 194 if (ep_mapping->pipe == NULL) {195 return EBADMEM;196 }197 194 if (ep_mapping->present) { 198 195 return EEXISTS; 199 196 } 200 197 201 int rc = usb_pipe_initialize( ep_mapping->pipe, wire,198 int rc = usb_pipe_initialize(&ep_mapping->pipe, wire, 202 199 ep_no, description.transfer_type, endpoint->max_packet_size, 203 200 description.direction); … … 254 251 * 255 252 * The mapping array is expected to conform to following rules: 256 * - @c pipe must point to already allocated structure withuninitialized pipe253 * - @c pipe must be uninitialized pipe 257 254 * - @c description must point to prepared endpoint description 258 255 * - @c descriptor does not need to be initialized (will be overwritten) … … 297 294 } 298 295 299 /* 300 * Go through the mapping and set all endpoints to not present. 301 */ 302 size_t i; 303 for (i = 0; i < mapping_count; i++) { 296 /* Go through the mapping and set all endpoints to not present. */ 297 for (size_t i = 0; i < mapping_count; i++) { 304 298 mapping[i].present = false; 305 299 mapping[i].descriptor = NULL; … … 307 301 } 308 302 309 /* 310 * Prepare the descriptor parser. 311 */ 303 /* Prepare the descriptor parser. */ 312 304 const usb_dp_parser_t dp_parser = { 313 305 .nesting = descriptor_nesting … … 454 446 * @return Error code. 455 447 */ 456 int usb_pipe_register(usb_pipe_t *pipe, 457 unsigned int interval, 458 usb_hc_connection_t *hc_connection) 459 { 460 return usb_pipe_register_with_speed(pipe, USB_SPEED_MAX + 1, 461 interval, hc_connection); 462 } 463 464 /** Register endpoint with a speed at the host controller. 465 * 466 * You will rarely need to use this function because it is needed only 467 * if the registered endpoint is of address 0 and there is no other way 468 * to tell speed of the device at address 0. 469 * 470 * @param pipe Pipe to be registered. 471 * @param speed Speed of the device 472 * (invalid speed means use previously specified one). 473 * @param interval Polling interval. 474 * @param hc_connection Connection to the host controller (must be opened). 475 * @return Error code. 476 */ 477 int usb_pipe_register_with_speed(usb_pipe_t *pipe, usb_speed_t speed, 478 unsigned int interval, 448 int usb_pipe_register(usb_pipe_t *pipe, unsigned interval, 479 449 usb_hc_connection_t *hc_connection) 480 450 { 481 451 assert(pipe); 482 452 assert(hc_connection); 483 453 484 454 if (!usb_hc_connection_is_opened(hc_connection)) 485 455 return EBADF; 486 456 487 457 const usb_target_t target = 488 458 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }}; 489 #define _PACK2(high, low) (((high) << 16) + (low)) 490 #define _PACK3(high, middle, low) (((((high) << 8) + (middle)) << 8) + (low)) 491 459 #define _PACK2(high, low) (((high & 0xffff) << 16) | (low & 0xffff)) 460 492 461 async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess); 493 462 int rc = async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 494 463 IPC_M_USBHC_REGISTER_ENDPOINT, target.packed, 495 _PACK 3(speed,pipe->transfer_type, pipe->direction),464 _PACK2(pipe->transfer_type, pipe->direction), 496 465 _PACK2(pipe->max_packet_size, interval)); 497 466 async_exchange_end(exch); 498 467 499 468 #undef _PACK2 500 #undef _PACK3501 502 469 return rc; 503 470 } -
uspace/lib/usbdev/src/recognise.c
rc2e50d7 r54464f6a 35 35 #include <sys/types.h> 36 36 #include <fibril_synch.h> 37 #include <usb/debug.h> 38 #include <usb/dev/hub.h> 37 39 #include <usb/dev/pipes.h> 38 40 #include <usb/dev/recognise.h> … … 50 52 51 53 /** DDF operations of child devices. */ 52 ddf_dev_ops_t child_ops = {54 static ddf_dev_ops_t child_ops = { 53 55 .interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl 54 56 }; … … 64 66 #define BCD_ARGS(a) BCD_INT((a)), BCD_FRAC((a)) 65 67 66 /* FIXME: make this dynamic */67 #define MATCH_STRING_MAX 25668 69 68 /** Add formatted match id. 70 69 * … … 75 74 */ 76 75 static int usb_add_match_id(match_id_list_t *matches, int score, 77 const char * format, ...)76 const char *match_str) 78 77 { 79 char *match_str = NULL; 80 match_id_t *match_id = NULL; 81 int rc; 82 83 match_str = malloc(MATCH_STRING_MAX + 1); 84 if (match_str == NULL) { 85 rc = ENOMEM; 86 goto failure; 87 } 88 89 /* 90 * FIXME: replace with dynamic allocation of exact size 91 */ 92 va_list args; 93 va_start(args, format ); 94 vsnprintf(match_str, MATCH_STRING_MAX, format, args); 95 match_str[MATCH_STRING_MAX] = 0; 96 va_end(args); 97 98 match_id = create_match_id(); 78 assert(matches); 79 80 match_id_t *match_id = create_match_id(); 99 81 if (match_id == NULL) { 100 rc = ENOMEM; 101 goto failure; 82 return ENOMEM; 102 83 } 103 84 … … 107 88 108 89 return EOK; 109 110 failure:111 if (match_str != NULL) {112 free(match_str);113 }114 if (match_id != NULL) {115 match_id->id = NULL;116 delete_match_id(match_id);117 }118 119 return rc;120 90 } 121 91 … … 129 99 #define ADD_MATCHID_OR_RETURN(match_ids, score, format, ...) \ 130 100 do { \ 131 int __rc = usb_add_match_id((match_ids), (score), \ 132 format, ##__VA_ARGS__); \ 101 char *str = NULL; \ 102 int __rc = asprintf(&str, format, ##__VA_ARGS__); \ 103 if (__rc > 0) { \ 104 __rc = usb_add_match_id((match_ids), (score), str); \ 105 } \ 133 106 if (__rc != EOK) { \ 107 free(str); \ 134 108 return __rc; \ 135 109 } \ … … 150 124 match_id_list_t *matches) 151 125 { 152 if (desc_interface == NULL) { 153 return EINVAL; 154 } 155 if (matches == NULL) { 126 if (desc_interface == NULL || matches == NULL) { 156 127 return EINVAL; 157 128 } … … 314 285 match_id_list_t *matches) 315 286 { 287 assert(ctrl_pipe); 316 288 int rc; 317 289 /* … … 336 308 /** Probe for device kind and register it in devman. 337 309 * 338 * @param[in] address Address of the (unknown) attached device. 339 * @param[in] hc_handle Handle of the host controller. 310 * @param[in] ctrl_pipe Control pipe to the device. 340 311 * @param[in] parent Parent device. 341 * @param[in] dev_ops Child device ops. 312 * @param[in] dev_ops Child device ops. Default child_ops will be used if NULL. 342 313 * @param[in] dev_data Arbitrary pointer to be stored in the child 343 314 * as @c driver_data. … … 346 317 * @return Error code. 347 318 */ 348 int usb_device_register_child_in_devman(usb_ address_t address,349 d evman_handle_t hc_handle, ddf_dev_t *parent,350 ddf_ dev_ops_t *dev_ops, void *dev_data, ddf_fun_t **child_fun)319 int usb_device_register_child_in_devman(usb_pipe_t *ctrl_pipe, 320 ddf_dev_t *parent, ddf_dev_ops_t *dev_ops, void *dev_data, 321 ddf_fun_t **child_fun) 351 322 { 352 size_t this_device_name_index; 323 if (child_fun == NULL || ctrl_pipe == NULL) 324 return EINVAL; 325 326 if (!dev_ops && dev_data) { 327 usb_log_warning("Using standard fun ops with arbitrary " 328 "driver data. This does not have to work.\n"); 329 } 353 330 354 331 fibril_mutex_lock(&device_name_index_mutex); 355 this_device_name_index = device_name_index; 356 device_name_index++; 332 const size_t this_device_name_index = device_name_index++; 357 333 fibril_mutex_unlock(&device_name_index_mutex); 358 334 359 335 ddf_fun_t *child = NULL; 360 char *child_name = NULL;361 336 int rc; 362 usb_device_connection_t dev_connection;363 usb_pipe_t ctrl_pipe;364 365 rc = usb_device_connection_initialize(&dev_connection, hc_handle, address);366 if (rc != EOK) {367 goto failure;368 }369 370 rc = usb_pipe_initialize_default_control(&ctrl_pipe,371 &dev_connection);372 if (rc != EOK) {373 goto failure;374 }375 rc = usb_pipe_probe_default_control(&ctrl_pipe);376 if (rc != EOK) {377 goto failure;378 }379 337 380 338 /* … … 382 340 * naming etc., something more descriptive could be created. 383 341 */ 384 rc = asprintf(&child_name, "usb%02zu_a%d", 385 this_device_name_index, address); 342 char child_name[12]; /* The format is: "usbAB_aXYZ", length 11 */ 343 rc = snprintf(child_name, sizeof(child_name), 344 "usb%02zu_a%d", this_device_name_index, ctrl_pipe->wire->address); 386 345 if (rc < 0) { 387 346 goto failure; … … 401 360 402 361 child->driver_data = dev_data; 403 404 rc = usb_device_create_match_ids(&ctrl_pipe, &child->match_ids); 362 /* Store the attached device in fun driver data if there is no 363 * other data */ 364 if (!dev_data) { 365 usb_hub_attached_device_t *new_device = ddf_fun_data_alloc( 366 child, sizeof(usb_hub_attached_device_t)); 367 if (!new_device) { 368 rc = ENOMEM; 369 goto failure; 370 } 371 new_device->address = ctrl_pipe->wire->address; 372 new_device->fun = child; 373 } 374 375 376 rc = usb_device_create_match_ids(ctrl_pipe, &child->match_ids); 405 377 if (rc != EOK) { 406 378 goto failure; … … 412 384 } 413 385 414 if (child_fun != NULL) { 415 *child_fun = child; 416 } 417 386 *child_fun = child; 418 387 return EOK; 419 388 420 389 failure: 421 390 if (child != NULL) { 422 child->name = NULL; 391 /* We know nothing about the data if it came from outside. */ 392 if (dev_data) { 393 child->driver_data = NULL; 394 } 423 395 /* This takes care of match_id deallocation as well. */ 424 396 ddf_fun_destroy(child); 425 397 } 426 if (child_name != NULL) {427 free(child_name);428 }429 398 430 399 return rc; -
uspace/lib/usbdev/src/request.c
rc2e50d7 r54464f6a 250 250 } 251 251 252 /** Change address of connected device.253 * This function automatically updates the backing connection to point to254 * the new address.255 *256 * @param pipe Control endpoint pipe (session must be already started).257 * @param new_address New USB address to be set (in native endianness).258 * @return Error code.259 */260 int usb_request_set_address(usb_pipe_t *pipe,261 usb_address_t new_address)262 {263 if ((new_address < 0) || (new_address >= USB11_ADDRESS_MAX)) {264 return EINVAL;265 }266 267 uint16_t addr = uint16_host2usb((uint16_t)new_address);268 269 int rc = usb_control_request_set(pipe,270 USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,271 USB_DEVREQ_SET_ADDRESS,272 addr, 0,273 NULL, 0);274 275 if (rc != EOK) {276 return rc;277 }278 279 assert(pipe->wire != NULL);280 /* TODO: prevent other from accessing wire now. */281 pipe->wire->address = new_address;282 283 return EOK;284 }285 286 252 /** Retrieve USB descriptor of a USB device. 287 253 *
Note:
See TracChangeset
for help on using the changeset viewer.
