Changeset 040ab02 in mainline


Ignore:
Timestamp:
2011-04-05T19:45:52Z (13 years ago)
Author:
Matus Dekanek <smekideki@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
90d0522
Parents:
3bb6b35
Message:

usb hub global over-current and power changes

Location:
uspace/drv/usbhub
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/usbhub/port_status.h

    r3bb6b35 r040ab02  
    4949
    5050/**
     51 * structure holding hub status and changes flags.
     52 * should not be accessed directly, use supplied getter/setter methods.
     53 *
     54 * For more information refer to table 11.16.2.5 in
     55 * "Universal Serial Bus Specification Revision 1.1"
     56 *
     57 */
     58typedef uint32_t usb_hub_status_t;
     59
     60/**
    5161 * set values in request to be it a port status request
    5262 * @param request
     
    5868        request->index = port;
    5969        request->request_type = USB_HUB_REQ_TYPE_GET_PORT_STATUS;
     70        request->request = USB_HUB_REQUEST_GET_STATUS;
     71        request->value = 0;
     72        request->length = 4;
     73}
     74
     75/**
     76 * set values in request to be it a port status request
     77 * @param request
     78 * @param port
     79 */
     80static inline void usb_hub_set_hub_status_request(
     81usb_device_request_setup_packet_t * request
     82){
     83        request->index = 0;
     84        request->request_type = USB_HUB_REQ_TYPE_GET_HUB_STATUS;
    6085        request->request = USB_HUB_REQUEST_GET_STATUS;
    6186        request->value = 0;
     
    242267}
    243268
     269/** get i`th bit of hub status */
     270static inline bool usb_hub_get_bit(usb_hub_status_t * status, int idx)
     271{
     272        return (((*status)>>(idx))%2);
     273}
     274
     275/** set i`th bit of hub status */
     276static inline void usb_hub_set_bit(
     277        usb_hub_status_t * status, int idx, bool value)
     278{
     279        (*status) = value?
     280                               ((*status)|(1<<(idx))):
     281                               ((*status)&(~(1<<(idx))));
     282}
     283
     284
    244285//device connnected on port
    245286static inline bool usb_port_dev_connected(usb_port_status_t * status){
     
    368409}
    369410
     411//local power status
     412static inline bool usb_hub_local_power_lost(usb_hub_status_t * status){
     413        return usb_hub_get_bit(status,0);
     414}
     415
     416static inline void usb_hub_set_local_power_lost(usb_port_status_t * status,
     417        bool power_lost){
     418        usb_hub_set_bit(status,0,power_lost);
     419}
     420
     421//over current ocndition
     422static inline bool usb_hub_over_current(usb_hub_status_t * status){
     423        return usb_hub_get_bit(status,1);
     424}
     425
     426static inline void usb_hub_set_over_current(usb_port_status_t * status,
     427        bool over_current){
     428        usb_hub_set_bit(status,1,over_current);
     429}
     430
     431//local power change
     432static inline bool usb_hub_local_power_change(usb_hub_status_t * status){
     433        return usb_hub_get_bit(status,16);
     434}
     435
     436static inline void usb_hub_set_local_power_change(usb_port_status_t * status,
     437        bool change){
     438        usb_hub_set_bit(status,16,change);
     439}
     440
     441//local power status
     442static inline bool usb_hub_over_current_change(usb_hub_status_t * status){
     443        return usb_hub_get_bit(status,17);
     444}
     445
     446static inline void usb_hub_set_over_current_change(usb_port_status_t * status,
     447        bool change){
     448        usb_hub_set_bit(status,17,change);
     449}
    370450
    371451
  • uspace/drv/usbhub/usbhub.c

    r3bb6b35 r040ab02  
    8484}
    8585
     86/// \TODO set_port_feature use
    8687
    8788//*********************************************
     
    123124        void * serialized_descriptor = malloc(USB_HUB_MAX_DESCRIPTOR_SIZE);
    124125        usb_hub_descriptor_t * descriptor;
     126        int opResult;
    125127
    126128        /* this was one fix of some bug, should not be needed anymore
    127129         * these lines allow to reset hub once more, it can be used as
    128130         * brute-force initialization for non-removable devices
    129          */
    130         int opResult = usb_request_set_configuration(hub_info->control_pipe,
     131         *
     132        opResult = usb_request_set_configuration(hub_info->control_pipe,
    131133                1);
    132134        if (opResult != EOK) {
     
    134136                        opResult);
    135137                return opResult;
    136         }
     138        }*/
    137139
    138140
     
    662664 * @param port port number, starting from 1
    663665 */
    664 static void usb_hub_over_current(usb_hub_info_t * hub,
    665         uint16_t port) {
     666static void usb_hub_port_over_current(usb_hub_info_t * hub,
     667        uint16_t port, uint32_t status) {
     668        /// \todo no, this is not proper sollution
     669        /// get affected ports
     670        /// power them off
     671        /// wait until there over-current is cleared
     672        /// power them on
     673
    666674        int opResult;
    667         opResult = usb_hub_clear_port_feature(hub->control_pipe,
    668                 port, USB_HUB_FEATURE_PORT_POWER);
    669         if (opResult != EOK) {
    670                 usb_log_error("cannot power off port %d;  %d\n",
    671                         port, opResult);
     675        if(usb_port_over_current(&status)){
     676                opResult = usb_hub_clear_port_feature(hub->control_pipe,
     677                        port, USB_HUB_FEATURE_PORT_POWER);
     678                if (opResult != EOK) {
     679                        usb_log_error("cannot power off port %d;  %d\n",
     680                                port, opResult);
     681                }
     682        }else{
     683                opResult = usb_hub_set_port_feature(hub->control_pipe,
     684                        port, USB_HUB_FEATURE_PORT_POWER);
     685                if (opResult != EOK) {
     686                        usb_log_error("cannot power on port %d;  %d\n",
     687                                port, opResult);
     688                }
    672689        }
    673690}
     
    723740                //check if it was not auto-resolved
    724741                usb_log_debug("overcurrent change on port\n");
    725                 if (usb_port_over_current(&status)) {
    726                         usb_hub_over_current(hub, port);
    727                 } else {
    728                         usb_log_debug("over current condition was "
    729                                 "auto-resolved on port %d\n",
    730                                 port);
    731                 }
     742                usb_hub_port_over_current(hub, port, status);
    732743        }
    733744        //port reset
     
    752763                        port, status);
    753764
     765        }
     766}
     767
     768static int usb_process_hub_over_current(usb_hub_info_t * hub_info,
     769        usb_hub_status_t status)
     770{
     771        int opResult;
     772        if(usb_hub_over_current(&status)){
     773                opResult = usb_hub_clear_feature(hub_info->control_pipe,
     774                        USB_HUB_FEATURE_PORT_POWER);
     775                if (opResult != EOK) {
     776                        usb_log_error("cannot power off hub: %d\n",
     777                                opResult);
     778                }
     779        }else{
     780                opResult = usb_hub_set_feature(hub_info->control_pipe,
     781                        USB_HUB_FEATURE_PORT_POWER);
     782                if (opResult != EOK) {
     783                        usb_log_error("cannot power on hub: %d\n",
     784                                opResult);
     785                }
     786        }
     787        return opResult;
     788}
     789
     790static int usb_process_hub_power_change(usb_hub_info_t * hub_info,
     791        usb_hub_status_t status)
     792{
     793        int opResult;
     794        if(usb_hub_local_power_lost(&status)){
     795                //restart power on hub
     796                opResult = usb_hub_set_feature(hub_info->control_pipe,
     797                        USB_HUB_FEATURE_PORT_POWER);
     798                if (opResult != EOK) {
     799                        usb_log_error("cannot power on hub: %d\n",
     800                                opResult);
     801                }
     802        }else{//power reestablished on hub- restart ports
     803                int port;
     804                for(port=0;port<hub_info->port_count;++port){
     805                        opResult = usb_hub_set_port_feature(
     806                                hub_info->control_pipe,
     807                                port, USB_HUB_FEATURE_PORT_POWER);
     808                        if (opResult != EOK) {
     809                                usb_log_error("cannot power on port %d;  %d\n",
     810                                        port, opResult);
     811                        }
     812                }
     813        }
     814        return opResult;
     815}
     816
     817
     818static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info){
     819        usb_log_debug("global interrupt on a hub\n");
     820        usb_pipe_t *pipe = hub_info->control_pipe;
     821        int opResult;
     822
     823        usb_port_status_t status;
     824        size_t rcvd_size;
     825        usb_device_request_setup_packet_t request;
     826        //int opResult;
     827        usb_hub_set_hub_status_request(&request);
     828        //endpoint 0
     829
     830        opResult = usb_pipe_control_read(
     831                pipe,
     832                &request, sizeof (usb_device_request_setup_packet_t),
     833                &status, 4, &rcvd_size
     834                );
     835        if (opResult != EOK) {
     836                usb_log_error("could not get hub status\n");
     837                return;
     838        }
     839        if (rcvd_size != sizeof (usb_port_status_t)) {
     840                usb_log_error("received status has incorrect size\n");
     841                return;
     842        }
     843        //port reset
     844        if (usb_hub_over_current_change(&status)) {
     845                usb_process_hub_over_current(hub_info,status);
     846        }
     847        if (usb_hub_local_power_change(&status)) {
     848                usb_process_hub_power_change(hub_info,status);
    754849        }
    755850}
     
    866961
    867962        ///todo, opresult check, pre obe konekce
     963        bool interrupt;
     964        interrupt = ((uint8_t*)change_bitmap)[0] & 1;
     965        if(interrupt){
     966                usb_hub_process_global_interrupt(hub_info);
     967        }
    868968        for (port = 1; port < port_count + 1; ++port) {
    869                 bool interrupt =
    870                         (((uint8_t*) change_bitmap)[port / 8] >> (port % 8)) % 2;
     969                interrupt =
     970                        ((uint8_t*) change_bitmap)[port / 8] & (1<<(port % 8));
    871971                if (interrupt) {
    872972                        usb_hub_process_interrupt(
     
    874974                }
    875975        }
     976        /// \todo check hub status
    876977        usb_hc_connection_close(&hub_info->connection);
    877978        usb_pipe_end_session(hub_info->control_pipe);
  • uspace/drv/usbhub/usbhub.h

    r3bb6b35 r040ab02  
    9090        /** not yet initialized non-removable devices */
    9191        uint8_t * not_initialized_non_removables;
    92 
     92       
    9393} usb_hub_info_t;
    9494
  • uspace/drv/usbhub/usbhub_private.h

    r3bb6b35 r040ab02  
    111111
    112112/**
     113 * Clear feature on hub port.
     114 *
     115 * @param hc Host controller telephone
     116 * @param address Hub address
     117 * @param port_index Port
     118 * @param feature Feature selector
     119 * @return Operation result
     120 */
     121static inline int usb_hub_set_port_feature(usb_pipe_t *pipe,
     122    int port_index,
     123    usb_hub_class_feature_t feature) {
     124
     125        usb_device_request_setup_packet_t clear_request = {
     126                .request_type = USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE,
     127                .request = USB_DEVREQ_SET_FEATURE,
     128                .length = 0,
     129                .index = port_index
     130        };
     131        clear_request.value = feature;
     132        return usb_pipe_control_write(pipe, &clear_request,
     133            sizeof(clear_request), NULL, 0);
     134}
     135
     136
     137/**
     138 * Clear feature on hub port.
     139 *
     140 * @param pipe pipe to hub control endpoint
     141 * @param feature Feature selector
     142 * @return Operation result
     143 */
     144static inline int usb_hub_clear_feature(usb_pipe_t *pipe,
     145    usb_hub_class_feature_t feature) {
     146
     147        usb_device_request_setup_packet_t clear_request = {
     148                .request_type = USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE,
     149                .request = USB_DEVREQ_CLEAR_FEATURE,
     150                .length = 0,
     151                .index = 0
     152        };
     153        clear_request.value = feature;
     154        return usb_pipe_control_write(pipe, &clear_request,
     155            sizeof(clear_request), NULL, 0);
     156}
     157
     158/**
     159 * Clear feature on hub port.
     160 *
     161 * @param pipe pipe to hub control endpoint
     162 * @param feature Feature selector
     163 * @return Operation result
     164 */
     165static inline int usb_hub_set_feature(usb_pipe_t *pipe,
     166    usb_hub_class_feature_t feature) {
     167
     168        usb_device_request_setup_packet_t clear_request = {
     169                .request_type = USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE,
     170                .request = USB_DEVREQ_SET_FEATURE,
     171                .length = 0,
     172                .index = 0
     173        };
     174        clear_request.value = feature;
     175        return usb_pipe_control_write(pipe, &clear_request,
     176            sizeof(clear_request), NULL, 0);
     177}
     178
     179/**
    113180 * create uint8_t array with serialized descriptor
    114181 *
Note: See TracChangeset for help on using the changeset viewer.