Changeset bf73a02 in mainline
- Timestamp:
- 2011-09-19T15:18:23Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- ea6de35
- Parents:
- 7a05ced0
- Location:
- uspace/drv/bus/usb/usbhub
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/usbhub/port_status.h
r7a05ced0 rbf73a02 50 50 /** 51 51 * structure holding hub status and changes flags. 52 * should not be accessed directly, use supplied getter/setter methods.53 52 * 54 53 * For more information refer to table 11.16.2.5 in … … 57 56 */ 58 57 typedef uint32_t usb_hub_status_t; 58 // TODO Mind the endiannes, changes are in the first byte of the second word 59 // status is int he first byte of the first word 60 #define USB_HUB_STATUS_OVER_CURRENT \ 61 (1 << (USB_HUB_FEATURE_HUB_OVER_CURRENT)) 62 #define USB_HUB_STATUS_LOCAL_POWER \ 63 (1 << (USB_HUB_FEATURE_HUB_LOCAL_POWER)) 64 65 #define USB_HUB_STATUS_C_OVER_CURRENT \ 66 (1 << (16 + USB_HUB_FEATURE_C_HUB_OVER_CURRENT)) 67 #define USB_HUB_STATUS_C_LOCAL_POWER \ 68 (1 << (16 + USB_HUB_FEATURE_C_HUB_LOCAL_POWER)) 59 69 60 70 /** … … 64 74 */ 65 75 static inline void usb_hub_set_port_status_request( 66 usb_device_request_setup_packet_t *request, uint16_t port) { 76 usb_device_request_setup_packet_t *request, uint16_t port) 77 { 67 78 request->index = port; 68 79 request->request_type = USB_HUB_REQ_TYPE_GET_PORT_STATUS; … … 73 84 74 85 /** 75 * set values in request to be it a port status request76 * @param request77 * @param port78 */79 static inline void usb_hub_set_hub_status_request(80 usb_device_request_setup_packet_t *request) {81 request->index = 0;82 request->request_type = USB_HUB_REQ_TYPE_GET_HUB_STATUS;83 request->request = USB_HUB_REQUEST_GET_STATUS;84 request->value = 0;85 request->length = 4;86 }87 88 /**89 86 * create request for usb hub port status 90 87 * @param port … … 92 89 */ 93 90 static inline usb_device_request_setup_packet_t * 94 usb_hub_create_port_status_request(uint16_t port) { 91 usb_hub_create_port_status_request(uint16_t port) 92 { 95 93 usb_device_request_setup_packet_t *result = 96 malloc(sizeof 94 malloc(sizeof(usb_device_request_setup_packet_t)); 97 95 usb_hub_set_port_status_request(result, port); 98 96 return result; … … 355 353 356 354 #endif /* HUB_PORT_STATUS_H */ 357 358 355 /** 359 356 * @} -
uspace/drv/bus/usb/usbhub/usbhub.c
r7a05ced0 rbf73a02 57 57 #define HUB_FNC_NAME "hub" 58 58 59 /** Standard get hub global status request */ 60 static const usb_device_request_setup_packet_t get_hub_status_request = { 61 .index = 0, 62 .request_type = USB_HUB_REQ_TYPE_GET_HUB_STATUS, 63 .request = USB_HUB_REQUEST_GET_STATUS, 64 .value = 0, 65 .length = sizeof(usb_hub_status_t), 66 }; 67 59 68 static int usb_set_first_configuration(usb_device_t *usb_device); 60 69 static usb_hub_info_t * usb_hub_info_create(usb_device_t *usb_dev); 61 70 static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info); 62 static int usb_process_hub_over_current(usb_hub_info_t *hub_info, 63 usb_hub_status_t status); 64 static int usb_process_hub_local_power_change(usb_hub_info_t *hub_info, 71 static void usb_process_hub_over_current(usb_hub_info_t *hub_info, 65 72 usb_hub_status_t status); 66 73 static void usb_hub_process_global_interrupt(usb_hub_info_t *hub_info); … … 371 378 * @return error code 372 379 */ 373 static int usb_process_hub_over_current(usb_hub_info_t *hub_info, 374 usb_hub_status_t status) { 375 int opResult; 376 if (usb_hub_is_status(status, USB_HUB_FEATURE_HUB_OVER_CURRENT)) { 377 //poweroff all ports 378 unsigned int port; 380 static void usb_process_hub_over_current(usb_hub_info_t *hub_info, 381 usb_hub_status_t status) 382 { 383 if (status & USB_HUB_STATUS_OVER_CURRENT) { 384 /* Over-current detected on one or all ports, 385 * switch them all off to prevent damage. */ 386 //TODO Consider ganged power switching here. 387 size_t port; 379 388 for (port = 1; port <= hub_info->port_count; ++port) { 380 opResult = usb_hub_clear_port_feature(389 const int opResult = usb_hub_clear_port_feature( 381 390 hub_info->control_pipe, port, 382 391 USB_HUB_FEATURE_PORT_POWER); 383 392 if (opResult != EOK) { 384 393 usb_log_warning( 385 "Cannot power off port %d; %s\n", 394 "HUB OVER-CURRENT: Cannot power off port" 395 " %d: %s\n", 386 396 port, str_error(opResult)); 387 397 } 388 398 } 389 399 } else { 390 //power all ports 391 unsigned int port; 400 /* Over-current condition is gone, it is safe to turn the 401 * ports on. */ 402 size_t port; 392 403 for (port = 1; port <= hub_info->port_count; ++port) { 393 opResult = usb_hub_set_port_feature(404 const int opResult = usb_hub_set_port_feature( 394 405 hub_info->control_pipe, port, 395 406 USB_HUB_FEATURE_PORT_POWER); 396 407 if (opResult != EOK) { 397 408 usb_log_warning( 398 "Cannot power off port %d; %s\n", 409 "HUB OVER-CURRENT GONE: Cannot power on " 410 "port %d; %s\n", 399 411 port, str_error(opResult)); 400 412 } 401 413 } 402 414 } 403 return opResult; 404 } 405 406 /** 407 * process hub local power change 408 * 409 * This change is ignored. 410 * @param hub_info hub instance 411 * @param status hub status bitmask 412 * @return error code 413 */ 414 static int usb_process_hub_local_power_change(usb_hub_info_t *hub_info, 415 usb_hub_status_t status) { 416 int opResult = EOK; 417 opResult = usb_hub_clear_feature(hub_info->control_pipe, 418 USB_HUB_FEATURE_C_HUB_LOCAL_POWER); 419 if (opResult != EOK) { 420 usb_log_error("Cannnot clear hub power change flag: " 421 "%s\n", 422 str_error(opResult)); 423 } 424 return opResult; 425 } 426 415 } 416 /*----------------------------------------------------------------------------*/ 427 417 /** 428 418 * process hub interrupts … … 432 422 * @param hub_info hub instance 433 423 */ 434 static void usb_hub_process_global_interrupt(usb_hub_info_t *hub_info) { 424 static void usb_hub_process_global_interrupt(usb_hub_info_t *hub_info) 425 { 426 assert(hub_info); 427 assert(hub_info->usb_device); 435 428 usb_log_debug("Global interrupt on a hub\n"); 436 usb_pipe_t * pipe = hub_info->control_pipe;429 usb_pipe_t *ctrlpipe = &hub_info->usb_device->ctrl_pipe; 437 430 int opResult; 438 431 439 usb_ port_status_t status;432 usb_hub_status_t status; 440 433 size_t rcvd_size; 441 usb_device_request_setup_packet_t request;442 //int opResult;443 usb_hub_set_hub_status_request(&request);444 //endpoint 0445 434 446 435 opResult = usb_pipe_control_read( 447 pipe, 448 &request, sizeof (usb_device_request_setup_packet_t), 449 &status, 4, &rcvd_size 450 ); 436 ctrlpipe, &get_hub_status_request, sizeof(get_hub_status_request), 437 &status, sizeof(usb_hub_status_t), &rcvd_size); 451 438 if (opResult != EOK) { 452 439 usb_log_error("Could not get hub status: %s\n", … … 454 441 return; 455 442 } 456 if (rcvd_size != sizeof (usb_port_status_t)) {443 if (rcvd_size != sizeof(usb_hub_status_t)) { 457 444 usb_log_error("Received status has incorrect size\n"); 458 445 return; 459 446 } 460 //port reset 461 if (462 usb_hub_is_status(status, 16 + USB_HUB_FEATURE_C_HUB_OVER_CURRENT)) {447 448 /* Handle status changes */ 449 if (status & USB_HUB_STATUS_C_OVER_CURRENT) 463 450 usb_process_hub_over_current(hub_info, status); 464 } 465 if ( 466 usb_hub_is_status(status, 16 + USB_HUB_FEATURE_C_HUB_LOCAL_POWER)) { 467 usb_process_hub_local_power_change(hub_info, status); 451 452 if (status & USB_HUB_STATUS_C_LOCAL_POWER) { 453 /* NOTE: Handling this is more complicated. 454 * If the transition is from bus power to local power, all 455 * is good and we may signal the parent hub that we don't 456 * need the power. 457 * If the transition is from local power to bus power 458 * the hub should turn off all the ports and devices need 459 * to be reinitialized taking into account the limited power 460 * that is now available. 461 * There is no support for power distribution in HelenOS, 462 * (or other OSes/hub devices that I've seen) so this is not 463 * implemented. 464 * Just ACK the change. 465 */ 466 const int opResult = usb_hub_clear_feature(ctrlpipe, 467 USB_HUB_FEATURE_C_HUB_LOCAL_POWER); 468 if (opResult != EOK) { 469 usb_log_error("Cannot clear hub power change flag: " 470 "%s\n", 471 str_error(opResult)); 472 } 468 473 } 469 474 }
Note:
See TracChangeset
for help on using the changeset viewer.