Changeset b04967a in mainline for uspace/drv/usbhub
- Timestamp:
- 2011-04-07T15:53:46Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- c156c2d
- Parents:
- 64dbc83 (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. - Location:
- uspace/drv/usbhub
- Files:
-
- 1 added
- 5 edited
- 1 moved
-
Makefile (modified) (1 diff)
-
port_status.h (modified) (1 diff)
-
ports.c (added)
-
ports.h (moved) (moved from uspace/drv/usbhub/usblist.c ) (2 diffs)
-
usbhub.c (modified) (10 diffs)
-
usbhub.h (modified) (2 diffs)
-
usbhub_private.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/usbhub/Makefile
r64dbc83 rb04967a 34 34 SOURCES = \ 35 35 main.c \ 36 ports.c \ 36 37 utils.c \ 37 usbhub.c \ 38 usblist.c 38 usbhub.c 39 39 40 40 include $(USPACE_PREFIX)/Makefile.common -
uspace/drv/usbhub/port_status.h
r64dbc83 rb04967a 95 95 } 96 96 97 /** 98 * set the device request to be a port feature clear request 99 * @param request 100 * @param port 101 * @param feature_selector 102 */ 103 static inline void usb_hub_set_disable_port_feature_request( 104 usb_device_request_setup_packet_t * request, uint16_t port, 105 uint16_t feature_selector 106 ){ 107 request->index = port; 108 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; 109 request->request = USB_HUB_REQUEST_CLEAR_FEATURE; 110 request->value = feature_selector; 111 request->length = 0; 112 } 97 113 98 114 /** -
uspace/drv/usbhub/ports.h
r64dbc83 rb04967a 1 1 /* 2 * Copyright (c) 201 0 Matus Dekanek2 * Copyright (c) 2011 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 28 29 /** @addtogroup drvusbhub 29 30 * @{ 30 31 */ 31 32 /** @file 32 * @brief usblist implementation33 * Hub ports related functions. 33 34 */ 34 #include <sys/types.h> 35 #ifndef DRV_USBHUB_PORTS_H 36 #define DRV_USBHUB_PORTS_H 35 37 36 #include "usbhub_private.h" 38 #include <ipc/devman.h> 39 #include <usb/usb.h> 40 #include <ddf/driver.h> 41 #include <fibril_synch.h> 42 43 #include <usb/hub.h> 44 45 #include <usb/pipes.h> 46 #include <usb/devdrv.h> 47 48 /** Information about single port on a hub. */ 49 typedef struct { 50 /** Mutex needed by CV for checking port reset. */ 51 fibril_mutex_t reset_mutex; 52 /** CV for waiting to port reset completion. */ 53 fibril_condvar_t reset_cv; 54 /** Whether port reset is completed. 55 * Guarded by @c reset_mutex. 56 */ 57 bool reset_completed; 58 59 /** Information about attached device. */ 60 usb_hc_attached_device_t attached_device; 61 } usb_hub_port_t; 62 63 /** Initialize hub port information. 64 * 65 * @param port Port to be initialized. 66 */ 67 static inline void usb_hub_port_init(usb_hub_port_t *port) { 68 port->attached_device.address = -1; 69 port->attached_device.handle = 0; 70 fibril_mutex_initialize(&port->reset_mutex); 71 fibril_condvar_initialize(&port->reset_cv); 72 } 73 74 bool hub_port_changes_callback(usb_device_t *, uint8_t *, size_t, void *); 37 75 38 76 39 usb_general_list_t * usb_lst_create(void) { 40 usb_general_list_t* result = usb_new(usb_general_list_t); 41 usb_lst_init(result); 42 return result; 43 } 44 45 void usb_lst_init(usb_general_list_t * lst) { 46 lst->prev = lst; 47 lst->next = lst; 48 lst->data = NULL; 49 } 50 51 void usb_lst_prepend(usb_general_list_t* item, void* data) { 52 usb_general_list_t* appended = usb_new(usb_general_list_t); 53 appended->data = data; 54 appended->next = item; 55 appended->prev = item->prev; 56 item->prev->next = appended; 57 item->prev = appended; 58 } 59 60 void usb_lst_append(usb_general_list_t* item, void* data) { 61 usb_general_list_t* appended = usb_new(usb_general_list_t); 62 appended->data = data; 63 appended->next = item->next; 64 appended->prev = item; 65 item->next->prev = appended; 66 item->next = appended; 67 } 68 69 void usb_lst_remove(usb_general_list_t* item) { 70 item->next->prev = item->prev; 71 item->prev->next = item->next; 72 } 73 74 75 77 #endif 76 78 /** 77 79 * @} 78 80 */ 79 80 -
uspace/drv/usbhub/usbhub.c
r64dbc83 rb04967a 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 /** -
uspace/drv/usbhub/usbhub.h
r64dbc83 rb04967a 47 47 #include <usb/devdrv.h> 48 48 49 #include "ports.h" 50 51 49 52 50 53 /** Information about attached hub. */ 51 54 typedef struct { 52 55 /** Number of ports. */ 53 int port_count;56 size_t port_count; 54 57 55 /** attached device handles, for each port one*/56 usb_h c_attached_device_t * attached_devs;58 /** Ports. */ 59 usb_hub_port_t *ports; 57 60 58 61 /** connection to hcd */ … … 100 103 int usb_hub_check_hub_changes(usb_hub_info_t * hub_info_param); 101 104 105 void usb_hub_removed_device(usb_hub_info_t *, uint16_t); 106 void usb_hub_over_current(usb_hub_info_t *, uint16_t); 102 107 103 108 int usb_hub_add_device(usb_device_t * usb_dev); -
uspace/drv/usbhub/usbhub_private.h
r64dbc83 rb04967a 38 38 39 39 #include "usbhub.h" 40 #include "usblist.h"41 40 42 41 #include <adt/list.h>
Note:
See TracChangeset
for help on using the changeset viewer.
