Changeset d6e2938 in mainline
- Timestamp:
- 2011-09-23T12:17:27Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 48a31be
- Parents:
- bba0f1fc
- Location:
- uspace/drv/bus/usb/usbhub
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/usbhub/port_status.h
rbba0f1fc rd6e2938 47 47 */ 48 48 typedef uint32_t usb_port_status_t; 49 // TODO Mind the endiannes, changes are in the first byte of the second word 50 // status is in the first byte of the first word 51 #define USB_HUB_PORT_STATUS_CONNECTION (1 << (USB_HUB_FEATURE_PORT_CONNECTION)) 52 #define USB_HUB_PORT_STATUS_ENABLED (1 << (USB_HUB_FEATURE_PORT_ENABLE)) 53 #define USB_HUB_PORT_STATUS_SUSPEND (1 << (USB_HUB_FEATURE_PORT_SUSPEND)) 54 #define USB_HUB_PORT_STATUS_OC (1 << (USB_HUB_FEATURE_PORT_OVER_CURRENT)) 55 #define USB_HUB_PORT_STATUS_RESET (1 << (USB_HUB_FEATURE_PORT_RESET)) 56 #define USB_HUB_PORT_STATUS_POWER (1 << (USB_HUB_FEATURE_PORT_POWER)) 57 #define USB_HUB_PORT_STATUS_LOW_SPEED (1 << (USB_HUB_FEATURE_PORT_LOW_SPEED)) 58 59 #define USB_HUB_PORT_C_STATUS_CONNECTION \ 60 (1 << (USB_HUB_FEATURE_C_PORT_CONNECTION)) 61 #define USB_HUB_PORT_C_STATUS_ENABLED \ 62 (1 << (USB_HUB_FEATURE_C_PORT_ENABLE)) 63 #define USB_HUB_PORT_C_STATUS_SUSPEND \ 64 (1 << (USB_HUB_FEATURE_C_PORT_SUSPEND)) 65 #define USB_HUB_PORT_C_STATUS_OC \ 66 (1 << (USB_HUB_FEATURE_C_PORT_OVER_CURRENT)) 67 #define USB_HUB_PORT_C_STATUS_RESET \ 68 (1 << (USB_HUB_FEATURE_C_PORT_RESET)) 49 69 50 70 /** … … 57 77 typedef uint32_t usb_hub_status_t; 58 78 // TODO Mind the endiannes, changes are in the first byte of the second word 59 // status is in the first byte of the first word79 // status is in the first byte of the first word 60 80 #define USB_HUB_STATUS_OVER_CURRENT \ 61 81 (1 << (USB_HUB_FEATURE_HUB_OVER_CURRENT)) -
uspace/drv/bus/usb/usbhub/ports.c
rbba0f1fc rd6e2938 54 54 }; 55 55 56 /** 57 * count of port status changes that are not explicitly handled by 58 * any function here and must be cleared by hand 59 */ 60 static const unsigned int non_handled_changes_count = 2; 61 62 /** 63 * port status changes that are not explicitly handled by 64 * any function here and must be cleared by hand 65 */ 66 static const int non_handled_changes[] = { 67 USB_HUB_FEATURE_C_PORT_ENABLE, 68 USB_HUB_FEATURE_C_PORT_SUSPEND 69 }; 70 71 static void usb_hub_removed_device( 72 usb_hub_info_t *hub, uint16_t port); 73 56 static void usb_hub_removed_device(usb_hub_info_t *hub, size_t port); 74 57 static void usb_hub_port_reset_completed(usb_hub_info_t *hub, 75 58 uint16_t port, uint32_t status); 76 77 static void usb_hub_port_over_current(usb_hub_info_t *hub,78 uint16_t port, uint32_t status);79 80 59 static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port, 81 60 usb_port_status_t *status); 82 83 61 static int enable_port_callback(int port_no, void *arg); 84 85 62 static int add_device_phase1_worker_fibril(void *arg); 86 87 63 static int create_add_device_fibril(usb_hub_info_t *hub, size_t port, 88 64 usb_speed_t speed); … … 95 71 * @param port port number, starting from 1 96 72 */ 97 void usb_hub_process_port_interrupt(usb_hub_info_t *hub, uint16_t port)98 { 99 usb_log_debug("Interrupt at port %zu\n", (size_t)port);73 void usb_hub_process_port_interrupt(usb_hub_info_t *hub, size_t port) 74 { 75 usb_log_debug("Interrupt at port %zu\n", port); 100 76 101 77 usb_port_status_t status; … … 104 80 if (opResult != EOK) { 105 81 usb_log_error("Failed to get port %zu status: %s.\n", 106 (size_t)port, str_error(opResult));82 port, str_error(opResult)); 107 83 return; 108 84 } 109 //connection change 110 if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_CONNECTION)) { 111 bool device_connected = usb_port_is_status(status, 112 USB_HUB_FEATURE_PORT_CONNECTION); 113 usb_log_debug("Connection change on port %zu: %s.\n", 114 (size_t) port, 115 device_connected ? "device attached" : "device removed"); 85 86 /* Connection change */ 87 if (status & USB_HUB_PORT_C_STATUS_CONNECTION) { 88 const bool device_connected = 89 (status & USB_HUB_PORT_STATUS_CONNECTION) != 0; 90 usb_log_debug("Connection change on port %zu: device %s.\n", 91 port, device_connected ? "attached" : "removed"); 92 /* ACK the change */ 93 const int opResult = 94 usb_hub_clear_port_feature(hub->control_pipe, 95 port, USB_HUB_FEATURE_C_PORT_CONNECTION); 96 if (opResult != EOK) { 97 usb_log_warning("Failed to clear " 98 "port-change-connection flag: %s.\n", 99 str_error(opResult)); 100 } 116 101 117 102 if (device_connected) { … … 121 106 usb_log_error( 122 107 "Cannot handle change on port %zu: %s.\n", 123 (size_t)port, str_error(opResult));108 port, str_error(opResult)); 124 109 } 125 110 } else { … … 127 112 } 128 113 } 129 //over current 130 if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT)) { 131 //check if it was not auto-resolved 132 usb_log_debug("Overcurrent change on port\n"); 133 usb_hub_port_over_current(hub, port, status); 134 } 135 //port reset 136 if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_RESET)) { 114 115 /* Enable change, ports are automatically disabled on errors. */ 116 if (status & USB_HUB_PORT_C_STATUS_ENABLED) { 117 // TODO: Remove device that was connected 118 // TODO: Clear feature C_PORT_ENABLE 119 120 } 121 122 /* Suspend change */ 123 if (status & USB_HUB_PORT_C_STATUS_SUSPEND) { 124 usb_log_error("Port %zu went to suspend state, this should" 125 "NOT happen as we do not support suspend state!", port); 126 // TODO: Clear feature C_PORT_SUSPEND 127 } 128 129 /* Over current */ 130 if (status & USB_HUB_PORT_C_STATUS_OC) { 131 /* According to the USB specs: 132 * 11.13.5 Over-current Reporting and Recovery 133 * Hub device is responsible for putting port in power off 134 * mode. USB system software is responsible for powering port 135 * back on when the over-curent condition is gone */ 136 if (!(status & ~USB_HUB_PORT_STATUS_OC)) { 137 // TODO: Power port on, this will cause connect 138 // change and device initialization. 139 } 140 // TODO: Ack over-power change. 141 } 142 143 /* Port reset, set on port reset complete. */ 144 if (status & USB_HUB_PORT_C_STATUS_RESET) { 137 145 usb_hub_port_reset_completed(hub, port, status); 138 146 } 139 usb_log_debug("Port %d status 0x%08" PRIx32 "\n", (int) port, status); 140 141 usb_port_status_set_bit( 142 &status, USB_HUB_FEATURE_C_PORT_CONNECTION, false); 143 usb_port_status_set_bit( 144 &status, USB_HUB_FEATURE_C_PORT_RESET, false); 145 usb_port_status_set_bit( 146 &status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT, false); 147 148 //clearing not yet handled changes 149 unsigned int feature_idx; 150 for (feature_idx = 0; 151 feature_idx < non_handled_changes_count; 152 ++feature_idx) { 153 unsigned int bit_idx = non_handled_changes[feature_idx]; 154 if (status & (1 << bit_idx)) { 155 usb_log_info( 156 "There was not yet handled change on port %d: %d" 157 ";clearing it\n", 158 port, bit_idx); 159 int opResult = usb_hub_clear_port_feature( 160 hub->control_pipe, 161 port, bit_idx); 162 if (opResult != EOK) { 163 usb_log_warning( 164 "Could not clear port flag %d: %s\n", 165 bit_idx, str_error(opResult) 166 ); 167 } 168 usb_port_status_set_bit( 169 &status, bit_idx, false); 170 } 171 } 172 if (status >> 16) { 173 usb_log_info("There is still some unhandled change %X\n", 174 status); 175 } 147 148 usb_log_debug("Port %zu status 0x%08" PRIx32 "\n", port, status); 176 149 } 177 150 … … 185 158 * @param port port number, starting from 1 186 159 */ 187 static void usb_hub_removed_device( 188 usb_hub_info_t *hub, uint16_t port) { 189 190 int opResult = usb_hub_clear_port_feature(hub->control_pipe, 191 port, USB_HUB_FEATURE_C_PORT_CONNECTION); 192 if (opResult != EOK) { 193 usb_log_warning("Could not clear port-change-connection flag\n"); 194 } 160 static void usb_hub_removed_device(usb_hub_info_t *hub, size_t port) 161 { 162 195 163 /** \TODO remove device from device manager - not yet implemented in 196 164 * devide manager … … 237 205 */ 238 206 static void usb_hub_port_reset_completed(usb_hub_info_t *hub, 239 uint16_t port, uint32_t status) { 207 uint16_t port, uint32_t status) 208 { 240 209 usb_log_debug("Port %zu reset complete.\n", (size_t) port); 241 210 if (usb_port_is_status(status, USB_HUB_FEATURE_PORT_ENABLE)) { … … 261 230 } 262 231 263 /**264 * Process over current condition on port.265 *266 * Turn off the power on the port.267 *268 * @param hub hub representation269 * @param port port number, starting from 1270 */271 static void usb_hub_port_over_current(usb_hub_info_t *hub,272 uint16_t port, uint32_t status) {273 int opResult;274 if (usb_port_is_status(status, USB_HUB_FEATURE_PORT_OVER_CURRENT)) {275 opResult = usb_hub_clear_port_feature(hub->control_pipe,276 port, USB_HUB_FEATURE_PORT_POWER);277 if (opResult != EOK) {278 usb_log_error("Cannot power off port %d; %s\n",279 port, str_error(opResult));280 }281 } else {282 opResult = usb_hub_set_port_feature(hub->control_pipe,283 port, USB_HUB_FEATURE_PORT_POWER);284 if (opResult != EOK) {285 usb_log_error("Cannot power on port %d; %s\n",286 port, str_error(opResult));287 }288 }289 }290 291 232 /** Retrieve port status. 292 233 * … … 301 242 size_t recv_size; 302 243 usb_port_status_t status_tmp; 303 /* USB hub specific GET_PORT_STATUS request. See USB Spec 11.16.2.6 */ 244 /* USB hub specific GET_PORT_STATUS request. See USB Spec 11.16.2.6 245 * Generic GET_STATUS request cannot be used because of the difference 246 * in status data size (2B vs. 4B)*/ 304 247 const usb_device_request_setup_packet_t request = { 305 248 .request_type = USB_HUB_REQ_TYPE_GET_PORT_STATUS, … … 327 270 return EOK; 328 271 } 329 272 /*----------------------------------------------------------------------------*/ 330 273 /** Callback for enabling a specific port. 331 274 * … … 337 280 * @return Error code. 338 281 */ 339 static int enable_port_callback(int port_no, void *arg) { 282 static int enable_port_callback(int port_no, void *arg) 283 { 340 284 usb_hub_info_t *hub = arg; 341 int rc; 285 assert(hub); 286 usb_hub_port_t *my_port = hub->ports + port_no; 287 342 288 usb_device_request_setup_packet_t request; 343 usb_hub_port_t *my_port = hub->ports + port_no;344 345 289 usb_hub_set_reset_port_request(&request, port_no); 346 rc = usb_pipe_control_write(hub->control_pipe, 290 291 const int rc = usb_pipe_control_write(hub->control_pipe, 347 292 &request, sizeof (request), NULL, 0); 348 293 if (rc != EOK) { … … 375 320 * @return 0 Always. 376 321 */ 377 static int add_device_phase1_worker_fibril(void *arg) { 378 struct add_device_phase1 *data 379 = (struct add_device_phase1 *) arg; 322 static int add_device_phase1_worker_fibril(void *arg) 323 { 324 struct add_device_phase1 *data = arg; 325 assert(data); 380 326 381 327 usb_address_t new_address; 382 328 devman_handle_t child_handle; 383 329 384 int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev,330 const int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev, 385 331 &data->hub->connection, data->speed, 386 332 enable_port_callback, (int) data->port, data->hub, … … 427 373 */ 428 374 static int create_add_device_fibril(usb_hub_info_t *hub, size_t port, 429 usb_speed_t speed) { 375 usb_speed_t speed) 376 { 430 377 struct add_device_phase1 *data 431 378 = malloc(sizeof (struct add_device_phase1)); … … 443 390 fibril_mutex_unlock(&the_port->reset_mutex); 444 391 445 int rc = usb_hub_clear_port_feature(hub->control_pipe, port,446 USB_HUB_FEATURE_C_PORT_CONNECTION);447 if (rc != EOK) {448 free(data);449 usb_log_warning("Failed to clear port change flag: %s.\n",450 str_error(rc));451 return rc;452 }453 454 392 fid_t fibril = fibril_create(add_device_phase1_worker_fibril, data); 455 393 if (fibril == 0) { -
uspace/drv/bus/usb/usbhub/ports.h
rbba0f1fc rd6e2938 72 72 73 73 74 void usb_hub_process_port_interrupt(usb_hub_info_t *hub, uint16_t port);74 void usb_hub_process_port_interrupt(usb_hub_info_t *hub, size_t port); 75 75 76 76
Note:
See TracChangeset
for help on using the changeset viewer.