Changeset fd3940c1 in mainline
- 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. - Location:
- uspace
- Files:
-
- 1 added
- 1 deleted
- 6 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/usbhub/Makefile
r049eb87 rfd3940c1 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/ports.h
r049eb87 rfd3940c1 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
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 /** -
uspace/drv/usbhub/usbhub.h
r049eb87 rfd3940c1 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
r049eb87 rfd3940c1 38 38 39 39 #include "usbhub.h" 40 #include "usblist.h"41 40 42 41 #include <adt/list.h> -
uspace/lib/usb/src/host/usb_endpoint_manager.c
r049eb87 rfd3940c1 91 91 size_t size, size_t max_packet_size) 92 92 { 93 /* We care about bandwidth only for interrupt and isochronous. */ 94 if ((type != USB_TRANSFER_INTERRUPT) 95 && (type != USB_TRANSFER_ISOCHRONOUS)) { 96 return 0; 97 } 98 93 99 const unsigned packet_count = 94 100 (size + max_packet_size - 1) / max_packet_size; -
uspace/lib/usb/src/hub.c
r049eb87 rfd3940c1 142 142 DEV_IFACE_ID(USBHC_DEV_IFACE), 143 143 IPC_M_USBHC_RELEASE_ADDRESS, address); 144 } 145 146 static void unregister_control_endpoint_on_default_address( 147 usb_hc_connection_t *connection) 148 { 149 usb_device_connection_t dev_conn; 150 int rc = usb_device_connection_initialize_on_default_address(&dev_conn, 151 connection); 152 if (rc != EOK) { 153 return; 154 } 155 156 usb_pipe_t ctrl_pipe; 157 rc = usb_pipe_initialize_default_control(&ctrl_pipe, &dev_conn); 158 if (rc != EOK) { 159 return; 160 } 161 162 usb_pipe_unregister(&ctrl_pipe, connection); 144 163 } 145 164 … … 235 254 goto leave_release_default_address; 236 255 } 256 257 /* Before sending any traffic, we need to register this 258 * endpoint. 259 */ 260 rc = usb_pipe_register(&ctrl_pipe, 0, connection); 261 if (rc != EOK) { 262 rc = EREFUSED; 263 goto leave_release_default_address; 264 } 237 265 rc = usb_pipe_probe_default_control(&ctrl_pipe); 238 266 if (rc != EOK) { … … 244 272 if (rc != EOK) { 245 273 rc = ENOTCONN; 246 goto leave_ release_default_address;274 goto leave_unregister_endpoint; 247 275 } 248 276 … … 256 284 257 285 /* 286 * Register the control endpoint for the new device. 287 */ 288 rc = usb_pipe_register(&ctrl_pipe, 0, connection); 289 if (rc != EOK) { 290 rc = EREFUSED; 291 goto leave_unregister_endpoint; 292 } 293 294 /* 295 * Release the original endpoint. 296 */ 297 unregister_control_endpoint_on_default_address(connection); 298 299 /* 258 300 * Once the address is changed, we can return the default address. 259 301 */ 260 302 usb_hc_release_default_address(connection); 303 261 304 262 305 /* … … 273 316 } 274 317 318 319 275 320 /* 276 321 * And now inform the host controller about the handle. … … 308 353 usb_pipe_end_session(&ctrl_pipe); 309 354 355 leave_unregister_endpoint: 356 usb_pipe_unregister(&ctrl_pipe, connection); 357 310 358 leave_release_default_address: 311 359 usb_hc_release_default_address(connection);
Note:
See TracChangeset
for help on using the changeset viewer.