Changes in uspace/drv/usbhub/usbhub.c [c50941f:df3ad97] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/usbhub/usbhub.c
rc50941f rdf3ad97 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 errorCode = usb_hub_check_hub_changes(hub_info); 77 async_usleep(1000 * 1000 );/// \TODO proper number once 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 … … 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_ disable_port_feature_request(&request, port,320 USB_HUB_FEATURE_ PORT_CONNECTION);319 usb_hub_set_enable_port_feature_request(&request, port, 320 USB_HUB_FEATURE_C_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 clear port connectionon port %d errno:%d\n",328 "could not set port change 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_size338 );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");345 331 } 346 }347 }348 /// \TODO this is just a debug code349 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 0360 opResult = usb_pipe_control_read(361 hub->control_pipe,362 &request, sizeof(usb_device_request_setup_packet_t),363 &status, 4, &rcvd_size364 );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/disconnected372 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));377 332 } 378 333 } … … 397 352 hub->is_default_address_used = false; 398 353 return EOK; 354 } 355 356 /** 357 * Reset the port with new device and reserve the default address. 358 * @param hub hub representation 359 * @param port port number, starting from 1 360 * @param speed transfer speed of attached device, one of low, full or high 361 */ 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 more 365 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 address 376 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 port 385 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, 0 390 ); 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 reset 400 * 401 * Set device`s address and start it`s driver. 402 * @param hub hub representation 403 * @param port port number, starting from 1 404 * @param speed transfer speed of attached device, one of low, full or high 405 */ 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 device 420 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->connection 425 ); 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 speed 435 ); 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); 399 485 } 400 486 … … 408 494 * @param port port number, starting from 1 409 495 */ 410 void usb_hub_removed_device(496 static void usb_hub_removed_device( 411 497 usb_hub_info_t * hub,uint16_t port) { 412 498 … … 421 507 422 508 //close address 423 if(hub-> ports[port].attached_device.address >=0){509 if(hub->attached_devs[port].address!=0){ 424 510 /*uncomment this code to use it when DDF allows device removal 425 511 opResult = usb_hc_unregister_device( … … 448 534 * @param port port number, starting from 1 449 535 */ 450 void usb_hub_over_current( usb_hub_info_t * hub,536 static void usb_hub_over_current( usb_hub_info_t * hub, 451 537 uint16_t port){ 452 538 int opResult; … … 459 545 } 460 546 547 /** 548 * Process interrupts on given hub port 549 * 550 * Accepts connection, over current and port reset change. 551 * @param hub hub representation 552 * @param port port number, starting from 1 553 */ 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 change 558 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 0 568 569 opResult = usb_pipe_control_read( 570 pipe, 571 &request, sizeof(usb_device_request_setup_packet_t), 572 &status, 4, &rcvd_size 573 ); 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/disconnected 583 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 current 592 if (usb_port_overcurrent_change(&status)) { 593 //check if it was not auto-resolved 594 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 reset 602 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 hub 624 * 625 * Handles changes on each port with a status change. 626 * @param hub_info hub representation 627 * @return error code 628 */ 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 properly 642 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_size 652 ); 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 konekce 677 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 461 693 462 694 /**
Note:
See TracChangeset
for help on using the changeset viewer.