Changes in uspace/drv/usbhub/usbhub.c [c50941f:8123695a] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/usbhub/usbhub.c
rc50941f r8123695a 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 55 59 static int usb_hub_trigger_connecting_non_removable_devices( 56 60 usb_hub_info_t * hub, usb_hub_descriptor_t * descriptor); 61 62 /** 63 * control loop running in hub`s fibril 64 * 65 * Hub`s fibril periodically asks for changes on hub and if needded calls 66 * change handling routine. 67 * @warning currently hub driver asks for changes once a second 68 * @param hub_info_param hub representation pointer 69 * @return zero 70 */ 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 once 77 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 } 57 83 58 84 … … 126 152 usb_log_debug("setting port count to %d\n",descriptor->ports_count); 127 153 hub_info->port_count = descriptor->ports_count; 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]); 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; 132 160 } 133 161 //handle non-removable devices … … 231 259 assert(rc == EOK); 232 260 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 } 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"); 264 269 265 270 usb_log_info("Controlling hub `%s' (%d ports).\n", 266 271 hub_info->usb_device->ddf_dev->name, hub_info->port_count); 267 272 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 representation 404 * @param port port number, starting from 1 405 * @param speed transfer speed of attached device, one of low, full or high 406 */ 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 more 410 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 address 421 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 port 430 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, 0 435 ); 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 reset 445 * 446 * Set device`s address and start it`s driver. 447 * @param hub hub representation 448 * @param port port number, starting from 1 449 * @param speed transfer speed of attached device, one of low, full or high 450 */ 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 device 465 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->connection 470 ); 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 speed 480 ); 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 /** 402 533 * routine called when a device on port has been removed 403 534 * … … 408 539 * @param port port number, starting from 1 409 540 */ 410 void usb_hub_removed_device(541 static void usb_hub_removed_device( 411 542 usb_hub_info_t * hub,uint16_t port) { 412 543 … … 421 552 422 553 //close address 423 if(hub-> ports[port].attached_device.address >=0){554 if(hub->attached_devs[port].address!=0){ 424 555 /*uncomment this code to use it when DDF allows device removal 425 556 opResult = usb_hc_unregister_device( … … 448 579 * @param port port number, starting from 1 449 580 */ 450 void usb_hub_over_current( usb_hub_info_t * hub,581 static void usb_hub_over_current( usb_hub_info_t * hub, 451 582 uint16_t port){ 452 583 int opResult; … … 459 590 } 460 591 592 /** 593 * Process interrupts on given hub port 594 * 595 * Accepts connection, over current and port reset change. 596 * @param hub hub representation 597 * @param port port number, starting from 1 598 */ 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 change 603 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 0 613 614 opResult = usb_pipe_control_read( 615 pipe, 616 &request, sizeof(usb_device_request_setup_packet_t), 617 &status, 4, &rcvd_size 618 ); 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/disconnected 628 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 current 638 if (usb_port_overcurrent_change(&status)) { 639 //check if it was not auto-resolved 640 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 reset 649 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 hub 672 * 673 * Handles changes on each port with a status change. 674 * @param hub_info hub representation 675 * @return error code 676 */ 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 properly 690 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_size 700 ); 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 konekce 725 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 461 741 462 742 /**
Note:
See TracChangeset
for help on using the changeset viewer.