Changeset fd3940c1 in mainline for uspace/drv/usbhub/usbhub.c
- Timestamp:
- 2011-04-07T13:30:49Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 8f30c2e
- Parents:
- 049eb87 (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/usbhub/usbhub.c
r049eb87 rfd3940c1 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 async_usleep(1000 * 1000 * 10 );/// \TODO proper number once77 errorCode = usb_hub_check_hub_changes(hub_info);78 }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 … … 400 400 401 401 /** 402 * Reset the port with new device and reserve the default address.403 * @param hub hub representation404 * @param port port number, starting from 1405 * @param speed transfer speed of attached device, one of low, full or high406 */407 static void usb_hub_init_add_device(usb_hub_info_t * hub, uint16_t port,408 usb_speed_t speed) {409 //if this hub already uses default address, it cannot request it once more410 if(hub->is_default_address_used) return;411 usb_log_debug("some connection changed\n");412 assert(hub->control_pipe->hc_phone);413 int opResult = usb_hub_clear_port_feature(hub->control_pipe,414 port, USB_HUB_FEATURE_C_PORT_CONNECTION);415 if(opResult != EOK){416 usb_log_warning("could not clear port-change-connection flag\n");417 }418 usb_device_request_setup_packet_t request;419 420 //get default address421 opResult = usb_hc_reserve_default_address(&hub->connection, speed);422 423 if (opResult != EOK) {424 usb_log_warning("cannot assign default address, it is probably used %d\n",425 opResult);426 return;427 }428 hub->is_default_address_used = true;429 //reset port430 usb_hub_set_reset_port_request(&request, port);431 opResult = usb_pipe_control_write(432 hub->control_pipe,433 &request,sizeof(usb_device_request_setup_packet_t),434 NULL, 0435 );436 if (opResult != EOK) {437 usb_log_error("something went wrong when reseting a port %d\n",opResult);438 usb_hub_release_default_address(hub);439 }440 return;441 }442 443 /**444 * Finalize adding new device after port reset445 *446 * Set device`s address and start it`s driver.447 * @param hub hub representation448 * @param port port number, starting from 1449 * @param speed transfer speed of attached device, one of low, full or high450 */451 static void usb_hub_finalize_add_device( usb_hub_info_t * hub,452 uint16_t port, usb_speed_t speed) {453 454 int opResult;455 usb_log_debug("finalizing add device\n");456 opResult = usb_hub_clear_port_feature(hub->control_pipe,457 port, USB_HUB_FEATURE_C_PORT_RESET);458 459 if (opResult != EOK) {460 usb_log_error("failed to clear port reset feature\n");461 usb_hub_release_default_address(hub);462 return;463 }464 //create connection to device465 usb_pipe_t new_device_pipe;466 usb_device_connection_t new_device_connection;467 usb_device_connection_initialize_on_default_address(468 &new_device_connection,469 &hub->connection470 );471 usb_pipe_initialize_default_control(472 &new_device_pipe,473 &new_device_connection);474 usb_pipe_probe_default_control(&new_device_pipe);475 476 /* Request address from host controller. */477 usb_address_t new_device_address = usb_hc_request_address(478 &hub->connection,479 speed480 );481 if (new_device_address < 0) {482 usb_log_error("failed to get free USB address\n");483 opResult = new_device_address;484 usb_hub_release_default_address(hub);485 return;486 }487 usb_log_debug("setting new address %d\n",new_device_address);488 //opResult = usb_drv_req_set_address(hc, USB_ADDRESS_DEFAULT,489 // new_device_address);490 usb_pipe_start_session(&new_device_pipe);491 opResult = usb_request_set_address(&new_device_pipe,new_device_address);492 usb_pipe_end_session(&new_device_pipe);493 if (opResult != EOK) {494 usb_log_error("could not set address for new device %d\n",opResult);495 usb_hub_release_default_address(hub);496 return;497 }498 499 //opResult = usb_hub_release_default_address(hc);500 opResult = usb_hub_release_default_address(hub);501 if(opResult!=EOK){502 return;503 }504 505 devman_handle_t child_handle;506 //??507 opResult = usb_device_register_child_in_devman(new_device_address,508 hub->connection.hc_handle, hub->usb_device->ddf_dev, &child_handle,509 NULL, NULL, NULL);510 511 if (opResult != EOK) {512 usb_log_error("could not start driver for new device %d\n",opResult);513 return;514 }515 hub->attached_devs[port].handle = child_handle;516 hub->attached_devs[port].address = new_device_address;517 518 //opResult = usb_drv_bind_address(hc, new_device_address, child_handle);519 opResult = usb_hc_register_device(520 &hub->connection,521 &hub->attached_devs[port]);522 if (opResult != EOK) {523 usb_log_error("could not assign address of device in hcd %d\n",opResult);524 return;525 }526 usb_log_info("Detected new device on `%s' (port %d), " \527 "address %d (handle %llu).\n",528 hub->usb_device->ddf_dev->name, (int) port,529 new_device_address, child_handle);530 }531 532 /**533 402 * routine called when a device on port has been removed 534 403 * … … 539 408 * @param port port number, starting from 1 540 409 */ 541 staticvoid usb_hub_removed_device(410 void usb_hub_removed_device( 542 411 usb_hub_info_t * hub,uint16_t port) { 543 412 … … 552 421 553 422 //close address 554 if(hub-> attached_devs[port].address!=0){423 if(hub->ports[port].attached_device.address >= 0){ 555 424 /*uncomment this code to use it when DDF allows device removal 556 425 opResult = usb_hc_unregister_device( … … 579 448 * @param port port number, starting from 1 580 449 */ 581 staticvoid usb_hub_over_current( usb_hub_info_t * hub,450 void usb_hub_over_current( usb_hub_info_t * hub, 582 451 uint16_t port){ 583 452 int opResult; … … 590 459 } 591 460 592 /**593 * Process interrupts on given hub port594 *595 * Accepts connection, over current and port reset change.596 * @param hub hub representation597 * @param port port number, starting from 1598 */599 static void usb_hub_process_interrupt(usb_hub_info_t * hub,600 uint16_t port) {601 usb_log_debug("interrupt at port %d\n", port);602 //determine type of change603 usb_pipe_t *pipe = hub->control_pipe;604 605 int opResult;606 607 usb_port_status_t status;608 size_t rcvd_size;609 usb_device_request_setup_packet_t request;610 //int opResult;611 usb_hub_set_port_status_request(&request, port);612 //endpoint 0613 614 opResult = usb_pipe_control_read(615 pipe,616 &request, sizeof(usb_device_request_setup_packet_t),617 &status, 4, &rcvd_size618 );619 if (opResult != EOK) {620 usb_log_error("could not get port status\n");621 return;622 }623 if (rcvd_size != sizeof (usb_port_status_t)) {624 usb_log_error("received status has incorrect size\n");625 return;626 }627 //something connected/disconnected628 if (usb_port_connect_change(&status)) {629 usb_log_debug("connection change on port\n");630 if (usb_port_dev_connected(&status)) {631 usb_log_debug("some connection changed\n");632 usb_hub_init_add_device(hub, port, usb_port_speed(&status));633 } else {634 usb_hub_removed_device(hub, port);635 }636 }637 //over current638 if (usb_port_overcurrent_change(&status)) {639 //check if it was not auto-resolved640 usb_log_debug("overcurrent change on port\n");641 if(usb_port_over_current(&status)){642 usb_hub_over_current(hub,port);643 }else{644 usb_log_debug("over current condition was auto-resolved on port %d\n",645 port);646 }647 }648 //port reset649 if (usb_port_reset_completed(&status)) {650 usb_log_debug("port reset complete\n");651 if (usb_port_enabled(&status)) {652 usb_hub_finalize_add_device(hub, port, usb_port_speed(&status));653 } else {654 usb_log_warning("port reset, but port still not enabled\n");655 }656 }657 usb_log_debug("status %x\n ",status);658 659 usb_port_set_connect_change(&status, false);660 usb_port_set_reset(&status, false);661 usb_port_set_reset_completed(&status, false);662 usb_port_set_dev_connected(&status, false);663 if (status>>16) {664 usb_log_info("there was some unsupported change on port %d: %X\n",665 port,status);666 667 }668 }669 670 /**671 * check changes on hub672 *673 * Handles changes on each port with a status change.674 * @param hub_info hub representation675 * @return error code676 */677 int usb_hub_check_hub_changes(usb_hub_info_t * hub_info){678 int opResult;679 opResult = usb_pipe_start_session(680 hub_info->status_change_pipe);681 if(opResult != EOK){682 usb_log_error("could not initialize communication for hub; %d\n",683 opResult);684 return opResult;685 }686 687 size_t port_count = hub_info->port_count;688 689 /// FIXME: count properly690 size_t byte_length = ((port_count+1) / 8) + 1;691 void *change_bitmap = malloc(byte_length);692 size_t actual_size;693 694 /*695 * Send the request.696 */697 opResult = usb_pipe_read(698 hub_info->status_change_pipe,699 change_bitmap, byte_length, &actual_size700 );701 702 if (opResult != EOK) {703 free(change_bitmap);704 usb_log_warning("something went wrong while getting status of hub\n");705 usb_pipe_end_session(hub_info->status_change_pipe);706 return opResult;707 }708 unsigned int port;709 opResult = usb_pipe_start_session(hub_info->control_pipe);710 if(opResult!=EOK){711 usb_log_error("could not start control pipe session %d\n", opResult);712 usb_pipe_end_session(hub_info->status_change_pipe);713 return opResult;714 }715 opResult = usb_hc_connection_open(&hub_info->connection);716 if(opResult!=EOK){717 usb_log_error("could not start host controller session %d\n",718 opResult);719 usb_pipe_end_session(hub_info->control_pipe);720 usb_pipe_end_session(hub_info->status_change_pipe);721 return opResult;722 }723 724 ///todo, opresult check, pre obe konekce725 for (port = 1; port < port_count+1; ++port) {726 bool interrupt =727 (((uint8_t*) change_bitmap)[port / 8] >> (port % 8)) % 2;728 if (interrupt) {729 usb_hub_process_interrupt(730 hub_info, port);731 }732 }733 usb_hc_connection_close(&hub_info->connection);734 usb_pipe_end_session(hub_info->control_pipe);735 usb_pipe_end_session(hub_info->status_change_pipe);736 free(change_bitmap);737 return EOK;738 }739 740 741 461 742 462 /**
Note:
See TracChangeset
for help on using the changeset viewer.