Ignore:
File:
1 edited

Legend:

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

    r15b0432 rad4562c2  
    3333 */
    3434
    35 #include <driver.h>
     35#include <ddf/driver.h>
    3636#include <bool.h>
    3737#include <errno.h>
     
    4444#include <usb/request.h>
    4545#include <usb/classes/hub.h>
     46#include <stdio.h>
    4647
    4748#include "usbhub.h"
     
    5253#include "usb/classes/classes.h"
    5354
    54 static device_ops_t hub_device_ops = {
     55static ddf_dev_ops_t hub_device_ops = {
    5556        .interfaces[USB_DEV_IFACE] = &usb_iface_hub_impl
    5657};
    5758
    58 /** Hub status-change endpoint description */
     59/** Hub status-change endpoint description
     60 *
     61 * For more see usb hub specification in 11.15.1 of
     62 */
    5963static usb_endpoint_description_t status_change_endpoint_description = {
    6064        .transfer_type = USB_TRANSFER_INTERRUPT,
    6165        .direction = USB_DIRECTION_IN,
    6266        .interface_class = USB_CLASS_HUB,
     67        .interface_subclass = 0,
     68        .interface_protocol = 0,
    6369        .flags = 0
    6470};
     71
     72int usb_hub_control_loop(void * hub_info_param){
     73        usb_hub_info_t * hub_info = (usb_hub_info_t*)hub_info_param;
     74        while(true){
     75                usb_hub_check_hub_changes(hub_info);
     76                async_usleep(1000 * 1000 );/// \TODO proper number once
     77        }
     78        return 0;
     79}
    6580
    6681
     
    7994 */
    8095static int usb_hub_init_communication(usb_hub_info_t * hub){
     96        usb_log_debug("Initializing hub USB communication (hub->device->handle=%zu).\n", hub->device->handle);
    8197        int opResult;
    8298        opResult = usb_device_connection_initialize_from_device(
     
    88104                return opResult;
    89105        }
     106        usb_log_debug("Initializing USB wire abstraction.\n");
    90107        opResult = usb_hc_connection_initialize_from_device(&hub->connection,
    91108                        hub->device);
     
    95112                return opResult;
    96113        }
     114        usb_log_debug("Initializing default control pipe.\n");
    97115        opResult = usb_endpoint_pipe_initialize_default_control(&hub->endpoints.control,
    98116            &hub->device_connection);
     
    132150
    133151        //configuration descriptor
    134         /// \TODO check other configurations
     152        /// \TODO check other configurations?
    135153        usb_standard_configuration_descriptor_t config_descriptor;
    136154        opResult = usb_request_get_bare_configuration_descriptor(
     
    176194        }
    177195
    178         /**
    179          * Initialize the interrupt in endpoint.
    180          * \TODO this code should be checked...
    181          */
    182196        usb_endpoint_mapping_t endpoint_mapping[1] = {
    183197                {
     
    207221        return EOK;
    208222       
    209 
    210         // Initialize the interrupt(=status change) endpoint.
    211         /*usb_endpoint_pipe_initialize(
    212                 &result->endpoints->status_change,
    213                 &result->device_connection, );USB_TRANSFER_INTERRUPT
    214         USB_DIRECTION_IN*/
    215 
    216223}
    217224
     
    222229 * @return pointer to created structure or NULL in case of error
    223230 */
    224 usb_hub_info_t * usb_create_hub_info(device_t * device) {
     231usb_hub_info_t * usb_create_hub_info(ddf_dev_t * device) {
    225232        usb_hub_info_t* result = usb_new(usb_hub_info_t);
    226233        result->device = device;
     
    246253        usb_endpoint_pipe_start_session(&result->endpoints.control);
    247254        opResult = usb_request_get_descriptor(&result->endpoints.control,
    248                         USB_REQUEST_TYPE_CLASS,
    249                         USB_DESCTYPE_HUB, 0, 0, serialized_descriptor,
     255                        USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,
     256                        USB_DESCTYPE_HUB,
     257                        0, 0, serialized_descriptor,
    250258                        USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size);
    251259        usb_endpoint_pipe_end_session(&result->endpoints.control);
     
    264272        }
    265273
    266        
    267274        dprintf(USB_LOG_LEVEL_INFO, "setting port count to %d",descriptor->ports_count);
    268275        result->port_count = descriptor->ports_count;
     
    291298 * @return
    292299 */
    293 int usb_add_hub_device(device_t *dev) {
     300int usb_add_hub_device(ddf_dev_t *dev) {
    294301        dprintf(USB_LOG_LEVEL_INFO, "add_hub_device(handle=%d)", (int) dev->handle);
    295302
    296         dev->ops = &hub_device_ops;
     303        //dev->ops = &hub_device_ops;
     304        (void) hub_device_ops;
    297305
    298306        usb_hub_info_t * hub_info = usb_create_hub_info(dev);
     
    325333
    326334        //add the hub to list
     335        //is this needed now?
    327336        fibril_mutex_lock(&usb_hub_list_lock);
    328337        usb_lst_append(&usb_hub_list, hub_info);
    329338        fibril_mutex_unlock(&usb_hub_list_lock);
    330 
    331339        dprintf(USB_LOG_LEVEL_DEBUG, "hub info added to list");
     340
     341        dprintf(USB_LOG_LEVEL_DEBUG, "adding to ddf");
     342        ddf_fun_t *hub_fun = ddf_fun_create(dev, fun_exposed, "hub");
     343        assert(hub_fun != NULL);
     344        hub_fun->ops = NULL;
     345
     346        int rc = ddf_fun_bind(hub_fun);
     347        assert(rc == EOK);
     348        rc = ddf_fun_add_to_class(hub_fun, "hub");
     349        assert(rc == EOK);
     350
     351        fid_t fid = fibril_create(usb_hub_control_loop, hub_info);
     352        if (fid == 0) {
     353                dprintf(USB_LOG_LEVEL_ERROR,
     354                                ": failed to start monitoring fibril for new hub");
     355                return ENOMEM;
     356        }
     357        fibril_add_ready(fid);
     358
     359        dprintf(USB_LOG_LEVEL_DEBUG, "hub fibril created");
    332360        //(void)hub_info;
    333         usb_hub_check_hub_changes();
     361        //usb_hub_check_hub_changes();
    334362       
    335363        dprintf(USB_LOG_LEVEL_INFO, "hub dev added");
     
    364392        //opResult = usb_drv_reserve_default_address(hc);
    365393        opResult = usb_hc_reserve_default_address(&hub->connection, USB_SPEED_LOW);
    366 
    367         if (opResult != EOK) {
    368                 dprintf(USB_LOG_LEVEL_WARNING, "cannot assign default address, it is probably used");
     394       
     395        if (opResult != EOK) {
     396                dprintf(USB_LOG_LEVEL_WARNING,
     397                                "cannot assign default address, it is probably used %d",opResult);
    369398                return;
    370399        }
     
    377406                        );
    378407        if (opResult != EOK) {
    379                 dprintf(USB_LOG_LEVEL_ERROR, "something went wrong when reseting a port");
     408                dprintf(USB_LOG_LEVEL_ERROR,
     409                                "something went wrong when reseting a port %d",opResult);
    380410                //usb_hub_release_default_address(hc);
    381411                usb_hc_release_default_address(&hub->connection);
     
    390420 */
    391421static void usb_hub_finalize_add_device( usb_hub_info_t * hub,
    392                 uint16_t port) {
     422                uint16_t port, bool isLowSpeed) {
    393423
    394424        int opResult;
     
    413443                        &new_device_connection);
    414444        /// \TODO get highspeed info
    415 
    416 
    417 
     445        usb_speed_t speed = isLowSpeed?USB_SPEED_LOW:USB_SPEED_FULL;
    418446
    419447
     
    421449        usb_address_t new_device_address = usb_hc_request_address(
    422450                        &hub->connection,
    423                         USB_SPEED_LOW/// \TODO fullspeed??
     451                        speed/// \TODO fullspeed??
    424452                        );
    425453        if (new_device_address < 0) {
     
    432460        //opResult = usb_drv_req_set_address(hc, USB_ADDRESS_DEFAULT,
    433461        //    new_device_address);
     462        usb_endpoint_pipe_start_session(&new_device_pipe);
    434463        opResult = usb_request_set_address(&new_device_pipe,new_device_address);
    435 
    436         if (opResult != EOK) {
    437                 dprintf(USB_LOG_LEVEL_ERROR, "could not set address for new device");
     464        usb_endpoint_pipe_end_session(&new_device_pipe);
     465        if (opResult != EOK) {
     466                dprintf(USB_LOG_LEVEL_ERROR,
     467                                "could not set address for new device %d",opResult);
    438468                usb_hc_release_default_address(&hub->connection);
    439469                return;
     
    450480        //??
    451481    opResult = usb_device_register_child_in_devman(new_device_address,
    452             hub->connection.hc_handle, hub->device, &child_handle);
    453 
    454         if (opResult != EOK) {
    455                 dprintf(USB_LOG_LEVEL_ERROR, "could not start driver for new device");
     482            hub->connection.hc_handle, hub->device, &child_handle,
     483            NULL, NULL, NULL);
     484
     485        if (opResult != EOK) {
     486                dprintf(USB_LOG_LEVEL_ERROR,
     487                                "could not start driver for new device %d",opResult);
    456488                return;
    457489        }
     
    464496                        &hub->attached_devs[port]);
    465497        if (opResult != EOK) {
    466                 dprintf(USB_LOG_LEVEL_ERROR, "could not assign address of device in hcd");
     498                dprintf(USB_LOG_LEVEL_ERROR,
     499                                "could not assign address of device in hcd %d",opResult);
    467500                return;
    468501        }
     
    506539}
    507540
     541
     542/**
     543 *Process over current condition on port.
     544 *
     545 * Turn off the power on the port.
     546 *
     547 * @param hub
     548 * @param port
     549 */
     550static void usb_hub_over_current( usb_hub_info_t * hub,
     551                uint16_t port){
     552        int opResult;
     553        opResult = usb_hub_clear_port_feature(&hub->endpoints.control,
     554            port, USB_HUB_FEATURE_PORT_POWER);
     555        if(opResult!=EOK){
     556                dprintf(USB_LOG_LEVEL_ERROR, "cannot power off port %d;  %d",
     557                                port, opResult);
     558        }
     559}
     560
    508561/**
    509562 * Process interrupts on given hub port
     
    517570        //determine type of change
    518571        usb_endpoint_pipe_t *pipe = &hub->endpoints.control;
    519         int opResult = usb_endpoint_pipe_start_session(pipe);
    520572       
    521         if(opResult != EOK){
    522                 dprintf(USB_LOG_LEVEL_ERROR, "cannot open pipe %d", opResult);
    523         }
    524 
    525         /*
    526         usb_target_t target;
    527         target.address=address;
    528         target.endpoint=0;
    529         */
     573        int opResult;
    530574
    531575        usb_port_status_t status;
     
    542586                        );
    543587        if (opResult != EOK) {
    544                 dprintf(USB_LOG_LEVEL_ERROR, "ERROR: could not get port status");
     588                dprintf(USB_LOG_LEVEL_ERROR, "could not get port status");
    545589                return;
    546590        }
    547591        if (rcvd_size != sizeof (usb_port_status_t)) {
    548                 dprintf(USB_LOG_LEVEL_ERROR, "ERROR: received status has incorrect size");
     592                dprintf(USB_LOG_LEVEL_ERROR, "received status has incorrect size");
    549593                return;
    550594        }
     
    561605                }
    562606        }
     607        //over current
     608        if (usb_port_overcurrent_change(&status)) {
     609                //check if it was not auto-resolved
     610                if(usb_port_over_current(&status)){
     611                        usb_hub_over_current(hub,port);
     612                }else{
     613                        dprintf(USB_LOG_LEVEL_INFO,
     614                                "over current condition was auto-resolved on port %d",port);
     615                }
     616        }
    563617        //port reset
    564618        if (usb_port_reset_completed(&status)) {
    565619                dprintf(USB_LOG_LEVEL_INFO, "port reset complete");
    566620                if (usb_port_enabled(&status)) {
    567                         usb_hub_finalize_add_device(hub, port);
     621                        usb_hub_finalize_add_device(hub, port, usb_port_low_speed(&status));
    568622                } else {
    569                         dprintf(USB_LOG_LEVEL_WARNING, "ERROR: port reset, but port still not enabled");
     623                        dprintf(USB_LOG_LEVEL_WARNING, "port reset, but port still not enabled");
    570624                }
    571625        }
     
    580634        }
    581635        /// \TODO handle other changes
    582         /// \TODO debug log for various situations
    583         usb_endpoint_pipe_end_session(pipe);
    584 
    585 
    586 }
    587 
    588 /**
    589  * Check changes on all known hubs.
    590  */
    591 void usb_hub_check_hub_changes(void) {
     636}
     637
     638/**
     639 * Check changes on particular hub
     640 * @param hub_info_param
     641 */
     642void usb_hub_check_hub_changes(usb_hub_info_t * hub_info){
     643        int opResult;
     644        opResult = usb_endpoint_pipe_start_session(&hub_info->endpoints.status_change);
     645        if(opResult != EOK){
     646                dprintf(USB_LOG_LEVEL_ERROR,
     647                                "could not initialize communication for hub; %d", opResult);
     648                return;
     649        }
     650
     651        size_t port_count = hub_info->port_count;
     652
     653        /// FIXME: count properly
     654        size_t byte_length = ((port_count+1) / 8) + 1;
     655                void *change_bitmap = malloc(byte_length);
     656        size_t actual_size;
     657
    592658        /*
    593          * Iterate through all hubs.
     659         * Send the request.
    594660         */
    595         usb_general_list_t * lst_item;
    596         fibril_mutex_lock(&usb_hub_list_lock);
    597         for (lst_item = usb_hub_list.next;
    598                         lst_item != &usb_hub_list;
    599                         lst_item = lst_item->next) {
    600                 fibril_mutex_unlock(&usb_hub_list_lock);
    601                 usb_hub_info_t * hub_info = ((usb_hub_info_t*)lst_item->data);
    602                 int opResult;
    603 
    604                 opResult = usb_endpoint_pipe_start_session(&hub_info->endpoints.status_change);
    605                 if(opResult != EOK){
    606                         continue;
     661        opResult = usb_endpoint_pipe_read(
     662                        &hub_info->endpoints.status_change,
     663                        change_bitmap, byte_length, &actual_size
     664                        );
     665
     666        if (opResult != EOK) {
     667                free(change_bitmap);
     668                dprintf(USB_LOG_LEVEL_WARNING, "something went wrong while getting status of hub");
     669                usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
     670                return;
     671        }
     672        unsigned int port;
     673        opResult = usb_endpoint_pipe_start_session(&hub_info->endpoints.control);
     674        if(opResult!=EOK){
     675                dprintf(USB_LOG_LEVEL_ERROR, "could not start control pipe session %d",
     676                                opResult);
     677                usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
     678                return;
     679        }
     680        opResult = usb_hc_connection_open(&hub_info->connection);
     681        if(opResult!=EOK){
     682                dprintf(USB_LOG_LEVEL_ERROR, "could not start host controller session %d",
     683                                opResult);
     684                usb_endpoint_pipe_end_session(&hub_info->endpoints.control);
     685                usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
     686                return;
     687        }
     688
     689        ///todo, opresult check, pre obe konekce
     690        for (port = 1; port < port_count+1; ++port) {
     691                bool interrupt =
     692                                (((uint8_t*) change_bitmap)[port / 8] >> (port % 8)) % 2;
     693                if (interrupt) {
     694                        usb_hub_process_interrupt(
     695                                hub_info, port);
    607696                }
    608                 /*
    609                  * Check status change pipe of this hub.
    610                  */
    611                 /*
    612                 usb_target_t target;
    613                 target.address = hub_info->address;
    614                 target.endpoint = 1;/// \TODO get from endpoint descriptor
    615                 dprintf(USB_LOG_LEVEL_INFO, "checking changes for hub at addr %d",
    616                     target.address);
    617                 */
    618                 size_t port_count = hub_info->port_count;
    619 
    620                 /*
    621                  * Connect to respective HC.
    622                  *
    623                 int hc = usb_drv_hc_connect_auto(hub_info->device, 0);
    624                 if (hc < 0) {
    625                         continue;
    626                 }*/
    627 
    628                 /// FIXME: count properly
    629                 size_t byte_length = ((port_count+1) / 8) + 1;
    630 
    631                 void *change_bitmap = malloc(byte_length);
    632                 size_t actual_size;
    633                 //usb_handle_t handle;
    634 
    635                 /*
    636                  * Send the request.
    637                  */
    638                 opResult = usb_endpoint_pipe_read(
    639                                 &hub_info->endpoints.status_change,
    640                                 change_bitmap, byte_length, &actual_size
    641                                 );
    642 
    643                 //usb_drv_async_wait_for(handle);
    644 
    645                 if (opResult != EOK) {
    646                         free(change_bitmap);
    647                         dprintf(USB_LOG_LEVEL_WARNING, "something went wrong while getting status of hub");
    648                         continue;
    649                 }
    650                 unsigned int port;
    651                 for (port = 1; port < port_count+1; ++port) {
    652                         bool interrupt =
    653                                         (((uint8_t*) change_bitmap)[port / 8] >> (port % 8)) % 2;
    654                         if (interrupt) {
    655                                 usb_hub_process_interrupt(
    656                                         hub_info, port);
    657                         }
    658                 }
    659                 usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
    660                 free(change_bitmap);
    661                
    662 
    663                 //async_hangup(hc);
    664                 fibril_mutex_lock(&usb_hub_list_lock);
    665         }
    666         fibril_mutex_unlock(&usb_hub_list_lock);
    667 }
    668 
    669 
     697        }
     698        usb_hc_connection_close(&hub_info->connection);
     699        usb_endpoint_pipe_end_session(&hub_info->endpoints.control);
     700        usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
     701        free(change_bitmap);
     702}
    670703
    671704
Note: See TracChangeset for help on using the changeset viewer.