Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/usbhub/usbhub.c

    r63d4d4fd rb2387c2  
    5656
    5757
    58 static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev);
    59 
    60 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info);
    61 
    62 static int usb_hub_set_configuration(usb_hub_info_t * hub_info);
    63 
    64 static int usb_hub_start_hub_fibril(usb_hub_info_t * hub_info);
    65 
    66 static int usb_process_hub_over_current(usb_hub_info_t * hub_info,
     58static usb_hub_info_t * usb_hub_info_create(usb_device_t *usb_dev);
     59
     60static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info);
     61
     62static int usb_hub_set_configuration(usb_hub_info_t *hub_info);
     63
     64static int usb_hub_start_hub_fibril(usb_hub_info_t *hub_info);
     65
     66static int usb_process_hub_over_current(usb_hub_info_t *hub_info,
    6767    usb_hub_status_t status);
    6868
    69 static int usb_process_hub_local_power_change(usb_hub_info_t * hub_info,
     69static int usb_process_hub_local_power_change(usb_hub_info_t *hub_info,
    7070    usb_hub_status_t status);
    7171
    72 static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info);
    73 
    74 static void usb_hub_polling_terminted_callback(usb_device_t * device,
    75     bool was_error, void * data);
     72static void usb_hub_process_global_interrupt(usb_hub_info_t *hub_info);
     73
     74static void usb_hub_polling_terminated_callback(usb_device_t *device,
     75    bool was_error, void *data);
    7676
    7777
     
    9090 * @return error code
    9191 */
    92 int usb_hub_add_device(usb_device_t * usb_dev) {
     92int usb_hub_add_device(usb_device_t *usb_dev) {
    9393        if (!usb_dev) return EINVAL;
    94         usb_hub_info_t * hub_info = usb_hub_info_create(usb_dev);
     94        usb_hub_info_t *hub_info = usb_hub_info_create(usb_dev);
    9595        //create hc connection
    9696        usb_log_debug("Initializing USB wire abstraction.\n");
     
    9999            hub_info->usb_device->ddf_dev);
    100100        if (opResult != EOK) {
    101                 usb_log_error("could not initialize connection to device, "
    102                     "errno %d\n",
    103                     opResult);
     101                usb_log_error("Could not initialize connection to device, "
     102                    " %s\n",
     103                    str_error(opResult));
    104104                free(hub_info);
    105105                return opResult;
     
    109109        opResult = usb_hub_set_configuration(hub_info);
    110110        if (opResult != EOK) {
    111                 usb_log_error("could not set hub configuration, errno %d\n",
    112                     opResult);
     111                usb_log_error("Could not set hub configuration, %s\n",
     112                    str_error(opResult));
    113113                free(hub_info);
    114114                return opResult;
     
    117117        opResult = usb_hub_process_hub_specific_info(hub_info);
    118118        if (opResult != EOK) {
    119                 usb_log_error("could process hub specific info, errno %d\n",
    120                     opResult);
     119                usb_log_error("Could process hub specific info, %s\n",
     120                    str_error(opResult));
    121121                free(hub_info);
    122122                return opResult;
     
    135135
    136136        opResult = usb_hub_start_hub_fibril(hub_info);
    137         if(opResult!=EOK)
     137        if (opResult != EOK)
    138138                free(hub_info);
    139139        return opResult;
    140140}
    141 
    142141
    143142/** Callback for polling hub for changes.
     
    193192 * @return basic usb_hub_info_t structure
    194193 */
    195 static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev) {
    196         usb_hub_info_t * result = malloc(sizeof(usb_hub_info_t));
     194static usb_hub_info_t * usb_hub_info_create(usb_device_t *usb_dev) {
     195        usb_hub_info_t * result = malloc(sizeof (usb_hub_info_t));
    197196        if (!result) return NULL;
    198197        result->usb_device = usb_dev;
     
    200199        result->control_pipe = &usb_dev->ctrl_pipe;
    201200        result->is_default_address_used = false;
     201
     202        result->ports = NULL;
     203        result->port_count = (size_t) - 1;
     204        fibril_mutex_initialize(&result->port_mutex);
     205
     206        fibril_mutex_initialize(&result->pending_ops_mutex);
     207        fibril_condvar_initialize(&result->pending_ops_cv);
     208        result->pending_ops_count = 0;
    202209        return result;
    203210}
     
    213220 * @return error code
    214221 */
    215 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info) {
     222static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info) {
    216223        // get hub descriptor
    217         usb_log_debug("creating serialized descriptor\n");
     224        usb_log_debug("Creating serialized descriptor\n");
    218225        uint8_t serialized_descriptor[USB_HUB_MAX_DESCRIPTOR_SIZE];
    219226        usb_hub_descriptor_t * descriptor;
     
    227234
    228235        if (opResult != EOK) {
    229                 usb_log_error("failed when receiving hub descriptor, "
    230                     "badcode = %d\n",
    231                     opResult);
     236                usb_log_error("Failed when receiving hub descriptor, "
     237                    "%s\n",
     238                    str_error(opResult));
    232239                free(serialized_descriptor);
    233240                return opResult;
    234241        }
    235         usb_log_debug2("deserializing descriptor\n");
     242        usb_log_debug2("Deserializing descriptor\n");
    236243        descriptor = usb_create_deserialized_hub_desriptor(
    237244            serialized_descriptor);
     
    242249        usb_log_debug("setting port count to %d\n", descriptor->ports_count);
    243250        hub_info->port_count = descriptor->ports_count;
    244         /// \TODO this is not semantically correct
    245251        bool is_power_switched =
    246             ((descriptor->hub_characteristics & 1) ==0);
     252            ((descriptor->hub_characteristics & 1) == 0);
    247253        bool has_individual_port_powering =
    248             ((descriptor->hub_characteristics & 1) !=0);
     254            ((descriptor->hub_characteristics & 1) != 0);
    249255        hub_info->ports = malloc(
    250256            sizeof (usb_hub_port_t) * (hub_info->port_count + 1));
    251         if(!hub_info->ports){
     257        if (!hub_info->ports) {
    252258                return ENOMEM;
    253259        }
     
    256262                usb_hub_port_init(&hub_info->ports[port]);
    257263        }
    258         if(is_power_switched){
    259                 usb_log_debug("is_power_switched\n");
    260                
    261                 if(!has_individual_port_powering){
    262                         usb_log_debug("!has_individual_port_powering\n");
     264        if (is_power_switched) {
     265                usb_log_debug("Hub power switched\n");
     266
     267                if (!has_individual_port_powering) {
     268                        usb_log_debug("Has_global powering\n");
    263269                        opResult = usb_hub_set_feature(hub_info->control_pipe,
    264270                            USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
    265271                        if (opResult != EOK) {
    266                                 usb_log_error("cannot power hub: %s\n",
     272                                usb_log_error("Cannot power hub: %s\n",
    267273                                    str_error(opResult));
    268274                        }
     
    270276
    271277                for (port = 1; port <= hub_info->port_count; ++port) {
    272                         usb_log_debug("Powering port %zu.\n",port);
     278                        usb_log_debug("Powering port %zu.\n", port);
    273279                        opResult = usb_hub_set_port_feature(hub_info->control_pipe,
    274280                            port, USB_HUB_FEATURE_PORT_POWER);
     
    278284                        }
    279285                }
    280                
    281         }else{
    282                 usb_log_debug("!is_power_switched, not going to be powered\n");
    283         }
    284         usb_log_debug2("freeing data\n");
     286
     287        } else {
     288                usb_log_debug("Power not switched, not going to be powered\n");
     289        }
     290        usb_log_debug2("Freeing data\n");
    285291        free(descriptor);
    286292        return EOK;
     
    295301 * @return error code
    296302 */
    297 static int usb_hub_set_configuration(usb_hub_info_t * hub_info) {
     303static int usb_hub_set_configuration(usb_hub_info_t *hub_info) {
    298304        //device descriptor
    299305        usb_standard_device_descriptor_t *std_descriptor
    300306            = &hub_info->usb_device->descriptors.device;
    301         usb_log_debug("hub has %d configurations\n",
     307        usb_log_debug("Hub has %d configurations\n",
    302308            std_descriptor->configuration_count);
    303309        if (std_descriptor->configuration_count < 1) {
    304                 usb_log_error("there are no configurations available\n");
     310                usb_log_error("There are no configurations available\n");
    305311                return EINVAL;
    306312        }
     
    320326                return opResult;
    321327        }
    322         usb_log_debug("\tused configuration %d\n",
     328        usb_log_debug("\tUsed configuration %d\n",
    323329            config_descriptor->configuration_number);
    324330
     
    335341 * @return error code
    336342 */
    337 static int usb_hub_start_hub_fibril(usb_hub_info_t * hub_info){
    338         /*
    339          * The processing will require opened control pipe and connection
    340          * to the host controller.
    341          * It is waste of resources but let's hope there will be less
    342          * hubs than the phone limit.
    343          * FIXME: with some proper locking over pipes and session
    344          * auto destruction, this could work better.
    345          */
    346         int rc = usb_hc_connection_open(&hub_info->connection);
    347         if (rc != EOK) {
    348                 //usb_pipe_end_session(hub_info->control_pipe);
    349                 usb_log_error("Failed to open connection to HC: %s.\n",
    350                     str_error(rc));
    351                 return rc;
    352         }
     343static int usb_hub_start_hub_fibril(usb_hub_info_t *hub_info) {
     344        int rc;
    353345
    354346        rc = usb_device_auto_poll(hub_info->usb_device, 0,
    355347            hub_port_changes_callback, ((hub_info->port_count + 1) / 8) + 1,
    356             usb_hub_polling_terminted_callback, hub_info);
     348            usb_hub_polling_terminated_callback, hub_info);
    357349        if (rc != EOK) {
    358350                usb_log_error("Failed to create polling fibril: %s.\n",
     
    373365//*********************************************
    374366
    375 
    376367/**
    377368 * process hub over current change
     
    382373 * @return error code
    383374 */
    384 static int usb_process_hub_over_current(usb_hub_info_t * hub_info,
     375static int usb_process_hub_over_current(usb_hub_info_t *hub_info,
    385376    usb_hub_status_t status) {
    386377        int opResult;
    387         if (usb_hub_is_status(status,USB_HUB_FEATURE_HUB_OVER_CURRENT)){
     378        if (usb_hub_is_status(status, USB_HUB_FEATURE_HUB_OVER_CURRENT)) {
    388379                //poweroff all ports
    389380                unsigned int port;
    390                 for(port = 1;port <= hub_info->port_count;++port){
     381                for (port = 1; port <= hub_info->port_count; ++port) {
    391382                        opResult = usb_hub_clear_port_feature(
    392                             hub_info->control_pipe,port,
     383                            hub_info->control_pipe, port,
    393384                            USB_HUB_FEATURE_PORT_POWER);
    394385                        if (opResult != EOK) {
    395386                                usb_log_warning(
    396                                     "cannot power off port %d;  %d\n",
    397                                     port, opResult);
     387                                    "Cannot power off port %d;  %s\n",
     388                                    port, str_error(opResult));
    398389                        }
    399390                }
     
    401392                //power all ports
    402393                unsigned int port;
    403                 for(port = 1;port <= hub_info->port_count;++port){
     394                for (port = 1; port <= hub_info->port_count; ++port) {
    404395                        opResult = usb_hub_set_port_feature(
    405                             hub_info->control_pipe,port,
     396                            hub_info->control_pipe, port,
    406397                            USB_HUB_FEATURE_PORT_POWER);
    407398                        if (opResult != EOK) {
    408399                                usb_log_warning(
    409                                     "cannot power off port %d;  %d\n",
    410                                     port, opResult);
     400                                    "Cannot power off port %d;  %s\n",
     401                                    port, str_error(opResult));
    411402                        }
    412403                }
     
    423414 * @return error code
    424415 */
    425 static int usb_process_hub_local_power_change(usb_hub_info_t * hub_info,
     416static int usb_process_hub_local_power_change(usb_hub_info_t *hub_info,
    426417    usb_hub_status_t status) {
    427418        int opResult = EOK;
    428419        opResult = usb_hub_clear_feature(hub_info->control_pipe,
    429420            USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
    430                 if (opResult != EOK) {
    431                 usb_log_error("cannnot clear hub power change flag: "
    432                     "%d\n",
    433                     opResult);
     421        if (opResult != EOK) {
     422                usb_log_error("Cannnot clear hub power change flag: "
     423                    "%s\n",
     424                    str_error(opResult));
    434425        }
    435426        return opResult;
     
    443434 * @param hub_info hub instance
    444435 */
    445 static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info) {
    446         usb_log_debug("global interrupt on a hub\n");
     436static void usb_hub_process_global_interrupt(usb_hub_info_t *hub_info) {
     437        usb_log_debug("Global interrupt on a hub\n");
    447438        usb_pipe_t *pipe = hub_info->control_pipe;
    448439        int opResult;
     
    461452            );
    462453        if (opResult != EOK) {
    463                 usb_log_error("could not get hub status\n");
     454                usb_log_error("Could not get hub status: %s\n",
     455                    str_error(opResult));
    464456                return;
    465457        }
    466458        if (rcvd_size != sizeof (usb_port_status_t)) {
    467                 usb_log_error("received status has incorrect size\n");
     459                usb_log_error("Received status has incorrect size\n");
    468460                return;
    469461        }
    470462        //port reset
    471463        if (
    472             usb_hub_is_status(status,16+USB_HUB_FEATURE_C_HUB_OVER_CURRENT)) {
     464            usb_hub_is_status(status, 16 + USB_HUB_FEATURE_C_HUB_OVER_CURRENT)) {
    473465                usb_process_hub_over_current(hub_info, status);
    474466        }
    475467        if (
    476             usb_hub_is_status(status,16+USB_HUB_FEATURE_C_HUB_LOCAL_POWER)) {
     468            usb_hub_is_status(status, 16 + USB_HUB_FEATURE_C_HUB_LOCAL_POWER)) {
    477469                usb_process_hub_local_power_change(hub_info, status);
    478470        }
     
    487479 * @param data pointer to usb_hub_info_t structure
    488480 */
    489 static void usb_hub_polling_terminted_callback(usb_device_t * device,
    490     bool was_error, void * data){
    491         usb_hub_info_t * hub_info = data;
    492         if(!hub_info) return;
    493         free(hub_info->ports);
    494         free(hub_info);
     481static void usb_hub_polling_terminated_callback(usb_device_t *device,
     482    bool was_error, void *data) {
     483        usb_hub_info_t * hub = data;
     484        assert(hub);
     485
     486        fibril_mutex_lock(&hub->pending_ops_mutex);
     487
     488        /* The device is dead. However there might be some pending operations
     489         * that we need to wait for.
     490         * One of them is device adding in progress.
     491         * The respective fibril is probably waiting for status change
     492         * in port reset (port enable) callback.
     493         * Such change would never come (otherwise we would not be here).
     494         * Thus, we would flush all pending port resets.
     495         */
     496        if (hub->pending_ops_count > 0) {
     497                fibril_mutex_lock(&hub->port_mutex);
     498                size_t port;
     499                for (port = 0; port < hub->port_count; port++) {
     500                        usb_hub_port_t *the_port = hub->ports + port;
     501                        fibril_mutex_lock(&the_port->reset_mutex);
     502                        the_port->reset_completed = true;
     503                        the_port->reset_okay = false;
     504                        fibril_condvar_broadcast(&the_port->reset_cv);
     505                        fibril_mutex_unlock(&the_port->reset_mutex);
     506                }
     507                fibril_mutex_unlock(&hub->port_mutex);
     508        }
     509        /* And now wait for them. */
     510        while (hub->pending_ops_count > 0) {
     511                fibril_condvar_wait(&hub->pending_ops_cv,
     512                    &hub->pending_ops_mutex);
     513        }
     514        fibril_mutex_unlock(&hub->pending_ops_mutex);
     515
     516        usb_device_destroy(hub->usb_device);
     517
     518        free(hub->ports);
     519        free(hub);
    495520}
    496521
Note: See TracChangeset for help on using the changeset viewer.