Changes in uspace/drv/usbhub/usbhub.c [df3ad97:c50941f] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/usbhub/usbhub.c
rdf3ad97 rc50941f 53 53 #include "usb/classes/classes.h" 54 54 55 56 static void usb_hub_init_add_device(usb_hub_info_t * hub, uint16_t port,57 usb_speed_t speed);58 59 55 static int usb_hub_trigger_connecting_non_removable_devices( 60 56 usb_hub_info_t * hub, usb_hub_descriptor_t * descriptor); 61 62 /**63 * control loop running in hub`s fibril64 *65 * Hub`s fibril periodically asks for changes on hub and if needded calls66 * change handling routine.67 * @warning currently hub driver asks for changes once a second68 * @param hub_info_param hub representation pointer69 * @return zero70 */71 int usb_hub_control_loop(void * hub_info_param){72 usb_hub_info_t * hub_info = (usb_hub_info_t*)hub_info_param;73 int errorCode = EOK;74 75 while(errorCode == EOK){76 errorCode = usb_hub_check_hub_changes(hub_info);77 async_usleep(1000 * 1000 );/// \TODO proper number once78 }79 usb_log_error("something in ctrl loop went wrong, errno %d\n",errorCode);80 81 return 0;82 }83 57 84 58 … … 152 126 usb_log_debug("setting port count to %d\n",descriptor->ports_count); 153 127 hub_info->port_count = descriptor->ports_count; 154 hub_info->attached_devs = (usb_hc_attached_device_t*) 155 malloc((hub_info->port_count+1) * sizeof(usb_hc_attached_device_t)); 156 int i; 157 for(i=0;i<hub_info->port_count+1;++i){ 158 hub_info->attached_devs[i].handle=0; 159 hub_info->attached_devs[i].address=0; 128 hub_info->ports = malloc(sizeof(usb_hub_port_t) * (hub_info->port_count+1)); 129 size_t port; 130 for (port = 0; port < hub_info->port_count + 1; port++) { 131 usb_hub_port_init(&hub_info->ports[port]); 160 132 } 161 133 //handle non-removable devices … … 259 231 assert(rc == EOK); 260 232 261 //create fibril for the hub control loop 262 fid_t fid = fibril_create(usb_hub_control_loop, hub_info); 263 if (fid == 0) { 264 usb_log_error("failed to start monitoring fibril for new hub.\n"); 265 return ENOMEM; 266 } 267 fibril_add_ready(fid); 268 usb_log_debug("Hub fibril created.\n"); 233 /* 234 * The processing will require opened control pipe and connection 235 * to the host controller. 236 * It is waste of resources but let's hope there will be less 237 * hubs than the phone limit. 238 * FIXME: with some proper locking over pipes and session 239 * auto destruction, this could work better. 240 */ 241 rc = usb_pipe_start_session(&usb_dev->ctrl_pipe); 242 if (rc != EOK) { 243 usb_log_error("Failed to start session on control pipe: %s.\n", 244 str_error(rc)); 245 goto leave; 246 } 247 rc = usb_hc_connection_open(&hub_info->connection); 248 if (rc != EOK) { 249 usb_pipe_end_session(&usb_dev->ctrl_pipe); 250 usb_log_error("Failed to open connection to HC: %s.\n", 251 str_error(rc)); 252 goto leave; 253 } 254 255 rc = usb_device_auto_poll(hub_info->usb_device, 0, 256 hub_port_changes_callback, ((hub_info->port_count+1) / 8) + 1, 257 NULL, hub_info); 258 if (rc != EOK) { 259 usb_log_error("Failed to create polling fibril: %s.\n", 260 str_error(rc)); 261 free(hub_info); 262 return rc; 263 } 269 264 270 265 usb_log_info("Controlling hub `%s' (%d ports).\n", 271 266 hub_info->usb_device->ddf_dev->name, hub_info->port_count); 272 267 return EOK; 268 269 leave: 270 free(hub_info); 271 272 return rc; 273 273 } 274 274 … … 317 317 //set the status change bit, so it will be noticed in driver loop 318 318 if(usb_port_dev_connected(&status)){ 319 usb_hub_set_ enable_port_feature_request(&request, port,320 USB_HUB_FEATURE_ C_PORT_CONNECTION);319 usb_hub_set_disable_port_feature_request(&request, port, 320 USB_HUB_FEATURE_PORT_CONNECTION); 321 321 opResult = usb_pipe_control_read( 322 322 hub->control_pipe, … … 326 326 if (opResult != EOK) { 327 327 usb_log_warning( 328 "could not set port changeon port %d errno:%d\n",328 "could not clear port connection on port %d errno:%d\n", 329 329 port, opResult); 330 330 } 331 usb_log_debug("cleared port connection\n"); 332 usb_hub_set_enable_port_feature_request(&request, port, 333 USB_HUB_FEATURE_PORT_ENABLE); 334 opResult = usb_pipe_control_read( 335 hub->control_pipe, 336 &request, sizeof(usb_device_request_setup_packet_t), 337 &status, 4, &rcvd_size 338 ); 339 if (opResult != EOK) { 340 usb_log_warning( 341 "could not set port enabled on port %d errno:%d\n", 342 port, opResult); 343 } 344 usb_log_debug("port set to enabled - should lead to connection change\n"); 331 345 } 346 } 347 } 348 /// \TODO this is just a debug code 349 for(port=1;port<=descriptor->ports_count;++port){ 350 bool is_non_removable = 351 ((non_removable_dev_bitmap[port/8]) >> (port%8)) %2; 352 if(is_non_removable){ 353 usb_log_debug("port %d is non-removable\n",port); 354 usb_port_status_t status; 355 size_t rcvd_size; 356 usb_device_request_setup_packet_t request; 357 //int opResult; 358 usb_hub_set_port_status_request(&request, port); 359 //endpoint 0 360 opResult = usb_pipe_control_read( 361 hub->control_pipe, 362 &request, sizeof(usb_device_request_setup_packet_t), 363 &status, 4, &rcvd_size 364 ); 365 if (opResult != EOK) { 366 usb_log_error("could not get port status %d\n",opResult); 367 } 368 if (rcvd_size != sizeof (usb_port_status_t)) { 369 usb_log_error("received status has incorrect size\n"); 370 } 371 //something connected/disconnected 372 if (usb_port_connect_change(&status)) { 373 usb_log_debug("some connection changed\n"); 374 } 375 usb_log_debug("status: %s\n",usb_debug_str_buffer( 376 (uint8_t *)&status,4,4)); 332 377 } 333 378 } … … 352 397 hub->is_default_address_used = false; 353 398 return EOK; 354 }355 356 /**357 * Reset the port with new device and reserve the default address.358 * @param hub hub representation359 * @param port port number, starting from 1360 * @param speed transfer speed of attached device, one of low, full or high361 */362 static void usb_hub_init_add_device(usb_hub_info_t * hub, uint16_t port,363 usb_speed_t speed) {364 //if this hub already uses default address, it cannot request it once more365 if(hub->is_default_address_used) return;366 usb_log_debug("some connection changed\n");367 assert(hub->control_pipe->hc_phone);368 int opResult = usb_hub_clear_port_feature(hub->control_pipe,369 port, USB_HUB_FEATURE_C_PORT_CONNECTION);370 if(opResult != EOK){371 usb_log_warning("could not clear port-change-connection flag\n");372 }373 usb_device_request_setup_packet_t request;374 375 //get default address376 opResult = usb_hc_reserve_default_address(&hub->connection, speed);377 378 if (opResult != EOK) {379 usb_log_warning("cannot assign default address, it is probably used %d\n",380 opResult);381 return;382 }383 hub->is_default_address_used = true;384 //reset port385 usb_hub_set_reset_port_request(&request, port);386 opResult = usb_pipe_control_write(387 hub->control_pipe,388 &request,sizeof(usb_device_request_setup_packet_t),389 NULL, 0390 );391 if (opResult != EOK) {392 usb_log_error("something went wrong when reseting a port %d\n",opResult);393 usb_hub_release_default_address(hub);394 }395 return;396 }397 398 /**399 * Finalize adding new device after port reset400 *401 * Set device`s address and start it`s driver.402 * @param hub hub representation403 * @param port port number, starting from 1404 * @param speed transfer speed of attached device, one of low, full or high405 */406 static void usb_hub_finalize_add_device( usb_hub_info_t * hub,407 uint16_t port, usb_speed_t speed) {408 409 int opResult;410 usb_log_debug("finalizing add device\n");411 opResult = usb_hub_clear_port_feature(hub->control_pipe,412 port, USB_HUB_FEATURE_C_PORT_RESET);413 414 if (opResult != EOK) {415 usb_log_error("failed to clear port reset feature\n");416 usb_hub_release_default_address(hub);417 return;418 }419 //create connection to device420 usb_pipe_t new_device_pipe;421 usb_device_connection_t new_device_connection;422 usb_device_connection_initialize_on_default_address(423 &new_device_connection,424 &hub->connection425 );426 usb_pipe_initialize_default_control(427 &new_device_pipe,428 &new_device_connection);429 usb_pipe_probe_default_control(&new_device_pipe);430 431 /* Request address from host controller. */432 usb_address_t new_device_address = usb_hc_request_address(433 &hub->connection,434 speed435 );436 if (new_device_address < 0) {437 usb_log_error("failed to get free USB address\n");438 opResult = new_device_address;439 usb_hub_release_default_address(hub);440 return;441 }442 usb_log_debug("setting new address %d\n",new_device_address);443 //opResult = usb_drv_req_set_address(hc, USB_ADDRESS_DEFAULT,444 // new_device_address);445 usb_pipe_start_session(&new_device_pipe);446 opResult = usb_request_set_address(&new_device_pipe,new_device_address);447 usb_pipe_end_session(&new_device_pipe);448 if (opResult != EOK) {449 usb_log_error("could not set address for new device %d\n",opResult);450 usb_hub_release_default_address(hub);451 return;452 }453 454 //opResult = usb_hub_release_default_address(hc);455 opResult = usb_hub_release_default_address(hub);456 if(opResult!=EOK){457 return;458 }459 460 devman_handle_t child_handle;461 //??462 opResult = usb_device_register_child_in_devman(new_device_address,463 hub->connection.hc_handle, hub->usb_device->ddf_dev, &child_handle,464 NULL, NULL, NULL);465 466 if (opResult != EOK) {467 usb_log_error("could not start driver for new device %d\n",opResult);468 return;469 }470 hub->attached_devs[port].handle = child_handle;471 hub->attached_devs[port].address = new_device_address;472 473 //opResult = usb_drv_bind_address(hc, new_device_address, child_handle);474 opResult = usb_hc_register_device(475 &hub->connection,476 &hub->attached_devs[port]);477 if (opResult != EOK) {478 usb_log_error("could not assign address of device in hcd %d\n",opResult);479 return;480 }481 usb_log_info("Detected new device on `%s' (port %d), " \482 "address %d (handle %llu).\n",483 hub->usb_device->ddf_dev->name, (int) port,484 new_device_address, child_handle);485 399 } 486 400 … … 494 408 * @param port port number, starting from 1 495 409 */ 496 staticvoid usb_hub_removed_device(410 void usb_hub_removed_device( 497 411 usb_hub_info_t * hub,uint16_t port) { 498 412 … … 507 421 508 422 //close address 509 if(hub-> attached_devs[port].address!=0){423 if(hub->ports[port].attached_device.address >= 0){ 510 424 /*uncomment this code to use it when DDF allows device removal 511 425 opResult = usb_hc_unregister_device( … … 534 448 * @param port port number, starting from 1 535 449 */ 536 staticvoid usb_hub_over_current( usb_hub_info_t * hub,450 void usb_hub_over_current( usb_hub_info_t * hub, 537 451 uint16_t port){ 538 452 int opResult; … … 545 459 } 546 460 547 /**548 * Process interrupts on given hub port549 *550 * Accepts connection, over current and port reset change.551 * @param hub hub representation552 * @param port port number, starting from 1553 */554 static void usb_hub_process_interrupt(usb_hub_info_t * hub,555 uint16_t port) {556 usb_log_debug("interrupt at port %d\n", port);557 //determine type of change558 usb_pipe_t *pipe = hub->control_pipe;559 560 int opResult;561 562 usb_port_status_t status;563 size_t rcvd_size;564 usb_device_request_setup_packet_t request;565 //int opResult;566 usb_hub_set_port_status_request(&request, port);567 //endpoint 0568 569 opResult = usb_pipe_control_read(570 pipe,571 &request, sizeof(usb_device_request_setup_packet_t),572 &status, 4, &rcvd_size573 );574 if (opResult != EOK) {575 usb_log_error("could not get port status\n");576 return;577 }578 if (rcvd_size != sizeof (usb_port_status_t)) {579 usb_log_error("received status has incorrect size\n");580 return;581 }582 //something connected/disconnected583 if (usb_port_connect_change(&status)) {584 if (usb_port_dev_connected(&status)) {585 usb_log_debug("some connection changed\n");586 usb_hub_init_add_device(hub, port, usb_port_speed(&status));587 } else {588 usb_hub_removed_device(hub, port);589 }590 }591 //over current592 if (usb_port_overcurrent_change(&status)) {593 //check if it was not auto-resolved594 if(usb_port_over_current(&status)){595 usb_hub_over_current(hub,port);596 }else{597 usb_log_debug("over current condition was auto-resolved on port %d\n",598 port);599 }600 }601 //port reset602 if (usb_port_reset_completed(&status)) {603 usb_log_debug("port reset complete\n");604 if (usb_port_enabled(&status)) {605 usb_hub_finalize_add_device(hub, port, usb_port_speed(&status));606 } else {607 usb_log_warning("port reset, but port still not enabled\n");608 }609 }610 611 usb_port_set_connect_change(&status, false);612 usb_port_set_reset(&status, false);613 usb_port_set_reset_completed(&status, false);614 usb_port_set_dev_connected(&status, false);615 if (status>>16) {616 usb_log_info("there was some unsupported change on port %d: %X\n",617 port,status);618 619 }620 }621 622 /**623 * check changes on hub624 *625 * Handles changes on each port with a status change.626 * @param hub_info hub representation627 * @return error code628 */629 int usb_hub_check_hub_changes(usb_hub_info_t * hub_info){630 int opResult;631 opResult = usb_pipe_start_session(632 hub_info->status_change_pipe);633 if(opResult != EOK){634 usb_log_error("could not initialize communication for hub; %d\n",635 opResult);636 return opResult;637 }638 639 size_t port_count = hub_info->port_count;640 641 /// FIXME: count properly642 size_t byte_length = ((port_count+1) / 8) + 1;643 void *change_bitmap = malloc(byte_length);644 size_t actual_size;645 646 /*647 * Send the request.648 */649 opResult = usb_pipe_read(650 hub_info->status_change_pipe,651 change_bitmap, byte_length, &actual_size652 );653 654 if (opResult != EOK) {655 free(change_bitmap);656 usb_log_warning("something went wrong while getting status of hub\n");657 usb_pipe_end_session(hub_info->status_change_pipe);658 return opResult;659 }660 unsigned int port;661 opResult = usb_pipe_start_session(hub_info->control_pipe);662 if(opResult!=EOK){663 usb_log_error("could not start control pipe session %d\n", opResult);664 usb_pipe_end_session(hub_info->status_change_pipe);665 return opResult;666 }667 opResult = usb_hc_connection_open(&hub_info->connection);668 if(opResult!=EOK){669 usb_log_error("could not start host controller session %d\n",670 opResult);671 usb_pipe_end_session(hub_info->control_pipe);672 usb_pipe_end_session(hub_info->status_change_pipe);673 return opResult;674 }675 676 ///todo, opresult check, pre obe konekce677 for (port = 1; port < port_count+1; ++port) {678 bool interrupt =679 (((uint8_t*) change_bitmap)[port / 8] >> (port % 8)) % 2;680 if (interrupt) {681 usb_hub_process_interrupt(682 hub_info, port);683 }684 }685 usb_hc_connection_close(&hub_info->connection);686 usb_pipe_end_session(hub_info->control_pipe);687 usb_pipe_end_session(hub_info->status_change_pipe);688 free(change_bitmap);689 return EOK;690 }691 692 693 461 694 462 /**
Note:
See TracChangeset
for help on using the changeset viewer.