Ignore:
File:
1 edited

Legend:

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

    r15b0432 rdff940f8  
    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;
     
    264271        }
    265272
    266        
    267273        dprintf(USB_LOG_LEVEL_INFO, "setting port count to %d",descriptor->ports_count);
    268274        result->port_count = descriptor->ports_count;
     
    291297 * @return
    292298 */
    293 int usb_add_hub_device(device_t *dev) {
     299int usb_add_hub_device(ddf_dev_t *dev) {
    294300        dprintf(USB_LOG_LEVEL_INFO, "add_hub_device(handle=%d)", (int) dev->handle);
    295301
    296         dev->ops = &hub_device_ops;
     302        //dev->ops = &hub_device_ops;
     303        (void) hub_device_ops;
    297304
    298305        usb_hub_info_t * hub_info = usb_create_hub_info(dev);
     
    325332
    326333        //add the hub to list
     334        //is this needed now?
    327335        fibril_mutex_lock(&usb_hub_list_lock);
    328336        usb_lst_append(&usb_hub_list, hub_info);
    329337        fibril_mutex_unlock(&usb_hub_list_lock);
    330 
    331338        dprintf(USB_LOG_LEVEL_DEBUG, "hub info added to list");
     339
     340        dprintf(USB_LOG_LEVEL_DEBUG, "adding to ddf");
     341        ddf_fun_t *hub_fun = ddf_fun_create(dev, fun_exposed, "hub");
     342        assert(hub_fun != NULL);
     343        hub_fun->ops = NULL;
     344
     345        int rc = ddf_fun_bind(hub_fun);
     346        assert(rc == EOK);
     347        rc = ddf_fun_add_to_class(hub_fun, "hub");
     348        assert(rc == EOK);
     349
     350        fid_t fid = fibril_create(usb_hub_control_loop, hub_info);
     351        if (fid == 0) {
     352                dprintf(USB_LOG_LEVEL_ERROR,
     353                                ": failed to start monitoring fibril for new hub");
     354                return ENOMEM;
     355        }
     356        fibril_add_ready(fid);
     357
     358        dprintf(USB_LOG_LEVEL_DEBUG, "hub fibril created");
    332359        //(void)hub_info;
    333         usb_hub_check_hub_changes();
     360        //usb_hub_check_hub_changes();
    334361       
    335362        dprintf(USB_LOG_LEVEL_INFO, "hub dev added");
     
    364391        //opResult = usb_drv_reserve_default_address(hc);
    365392        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");
     393       
     394        if (opResult != EOK) {
     395                dprintf(USB_LOG_LEVEL_WARNING,
     396                                "cannot assign default address, it is probably used %d",opResult);
    369397                return;
    370398        }
     
    377405                        );
    378406        if (opResult != EOK) {
    379                 dprintf(USB_LOG_LEVEL_ERROR, "something went wrong when reseting a port");
     407                dprintf(USB_LOG_LEVEL_ERROR,
     408                                "something went wrong when reseting a port %d",opResult);
    380409                //usb_hub_release_default_address(hc);
    381410                usb_hc_release_default_address(&hub->connection);
     
    390419 */
    391420static void usb_hub_finalize_add_device( usb_hub_info_t * hub,
    392                 uint16_t port) {
     421                uint16_t port, bool isLowSpeed) {
    393422
    394423        int opResult;
     
    413442                        &new_device_connection);
    414443        /// \TODO get highspeed info
    415 
    416 
    417 
     444        usb_speed_t speed = isLowSpeed?USB_SPEED_LOW:USB_SPEED_FULL;
    418445
    419446
     
    421448        usb_address_t new_device_address = usb_hc_request_address(
    422449                        &hub->connection,
    423                         USB_SPEED_LOW/// \TODO fullspeed??
     450                        speed/// \TODO fullspeed??
    424451                        );
    425452        if (new_device_address < 0) {
     
    432459        //opResult = usb_drv_req_set_address(hc, USB_ADDRESS_DEFAULT,
    433460        //    new_device_address);
     461        usb_endpoint_pipe_start_session(&new_device_pipe);
    434462        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");
     463        usb_endpoint_pipe_end_session(&new_device_pipe);
     464        if (opResult != EOK) {
     465                dprintf(USB_LOG_LEVEL_ERROR,
     466                                "could not set address for new device %d",opResult);
    438467                usb_hc_release_default_address(&hub->connection);
    439468                return;
     
    450479        //??
    451480    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");
     481            hub->connection.hc_handle, hub->device, &child_handle,
     482            NULL, NULL, NULL);
     483
     484        if (opResult != EOK) {
     485                dprintf(USB_LOG_LEVEL_ERROR,
     486                                "could not start driver for new device %d",opResult);
    456487                return;
    457488        }
     
    464495                        &hub->attached_devs[port]);
    465496        if (opResult != EOK) {
    466                 dprintf(USB_LOG_LEVEL_ERROR, "could not assign address of device in hcd");
     497                dprintf(USB_LOG_LEVEL_ERROR,
     498                                "could not assign address of device in hcd %d",opResult);
    467499                return;
    468500        }
     
    506538}
    507539
     540
     541/**
     542 *Process over current condition on port.
     543 *
     544 * Turn off the power on the port.
     545 *
     546 * @param hub
     547 * @param port
     548 */
     549static void usb_hub_over_current( usb_hub_info_t * hub,
     550                uint16_t port){
     551        int opResult;
     552        opResult = usb_hub_clear_port_feature(&hub->endpoints.control,
     553            port, USB_HUB_FEATURE_PORT_POWER);
     554        if(opResult!=EOK){
     555                dprintf(USB_LOG_LEVEL_ERROR, "cannot power off port %d;  %d",
     556                                port, opResult);
     557        }
     558}
     559
    508560/**
    509561 * Process interrupts on given hub port
     
    517569        //determine type of change
    518570        usb_endpoint_pipe_t *pipe = &hub->endpoints.control;
    519         int opResult = usb_endpoint_pipe_start_session(pipe);
    520571       
    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         */
     572        int opResult;
    530573
    531574        usb_port_status_t status;
     
    542585                        );
    543586        if (opResult != EOK) {
    544                 dprintf(USB_LOG_LEVEL_ERROR, "ERROR: could not get port status");
     587                dprintf(USB_LOG_LEVEL_ERROR, "could not get port status");
    545588                return;
    546589        }
    547590        if (rcvd_size != sizeof (usb_port_status_t)) {
    548                 dprintf(USB_LOG_LEVEL_ERROR, "ERROR: received status has incorrect size");
     591                dprintf(USB_LOG_LEVEL_ERROR, "received status has incorrect size");
    549592                return;
    550593        }
     
    561604                }
    562605        }
     606        //over current
     607        if (usb_port_overcurrent_change(&status)) {
     608                //check if it was not auto-resolved
     609                if(usb_port_over_current(&status)){
     610                        usb_hub_over_current(hub,port);
     611                }else{
     612                        dprintf(USB_LOG_LEVEL_INFO,
     613                                "over current condition was auto-resolved on port %d",port);
     614                }
     615        }
    563616        //port reset
    564617        if (usb_port_reset_completed(&status)) {
    565618                dprintf(USB_LOG_LEVEL_INFO, "port reset complete");
    566619                if (usb_port_enabled(&status)) {
    567                         usb_hub_finalize_add_device(hub, port);
     620                        usb_hub_finalize_add_device(hub, port, usb_port_low_speed(&status));
    568621                } else {
    569                         dprintf(USB_LOG_LEVEL_WARNING, "ERROR: port reset, but port still not enabled");
     622                        dprintf(USB_LOG_LEVEL_WARNING, "port reset, but port still not enabled");
    570623                }
    571624        }
     
    580633        }
    581634        /// \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) {
     635}
     636
     637/**
     638 * Check changes on particular hub
     639 * @param hub_info_param
     640 */
     641void usb_hub_check_hub_changes(usb_hub_info_t * hub_info){
     642        int opResult;
     643        opResult = usb_endpoint_pipe_start_session(&hub_info->endpoints.status_change);
     644        if(opResult != EOK){
     645                dprintf(USB_LOG_LEVEL_ERROR,
     646                                "could not initialize communication for hub; %d", opResult);
     647                return;
     648        }
     649
     650        size_t port_count = hub_info->port_count;
     651
     652        /// FIXME: count properly
     653        size_t byte_length = ((port_count+1) / 8) + 1;
     654                void *change_bitmap = malloc(byte_length);
     655        size_t actual_size;
     656
    592657        /*
    593          * Iterate through all hubs.
     658         * Send the request.
    594659         */
    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;
     660        opResult = usb_endpoint_pipe_read(
     661                        &hub_info->endpoints.status_change,
     662                        change_bitmap, byte_length, &actual_size
     663                        );
     664
     665        if (opResult != EOK) {
     666                free(change_bitmap);
     667                dprintf(USB_LOG_LEVEL_WARNING, "something went wrong while getting status of hub");
     668                usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
     669                return;
     670        }
     671        unsigned int port;
     672        opResult = usb_endpoint_pipe_start_session(&hub_info->endpoints.control);
     673        if(opResult!=EOK){
     674                dprintf(USB_LOG_LEVEL_ERROR, "could not start control pipe session %d",
     675                                opResult);
     676                usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
     677                return;
     678        }
     679        opResult = usb_hc_connection_open(&hub_info->connection);
     680        if(opResult!=EOK){
     681                dprintf(USB_LOG_LEVEL_ERROR, "could not start host controller session %d",
     682                                opResult);
     683                usb_endpoint_pipe_end_session(&hub_info->endpoints.control);
     684                usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
     685                return;
     686        }
     687
     688        ///todo, opresult check, pre obe konekce
     689        for (port = 1; port < port_count+1; ++port) {
     690                bool interrupt =
     691                                (((uint8_t*) change_bitmap)[port / 8] >> (port % 8)) % 2;
     692                if (interrupt) {
     693                        usb_hub_process_interrupt(
     694                                hub_info, port);
    607695                }
    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 
     696        }
     697        usb_hc_connection_close(&hub_info->connection);
     698        usb_endpoint_pipe_end_session(&hub_info->endpoints.control);
     699        usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
     700        free(change_bitmap);
     701}
    670702
    671703
Note: See TracChangeset for help on using the changeset viewer.