Changeset 3a1aa20 in mainline for uspace/drv/usbhub/usbhub.c


Ignore:
Timestamp:
2011-02-26T15:22:27Z (14 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
ad4562c2
Parents:
0475e13 (diff), b8622e2 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merged development.

File:
1 edited

Legend:

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

    r0475e13 r3a1aa20  
    4444#include <usb/request.h>
    4545#include <usb/classes/hub.h>
     46#include <stdio.h>
    4647
    4748#include "usbhub.h"
     
    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
     
    135150
    136151        //configuration descriptor
    137         /// \TODO check other configurations
     152        /// \TODO check other configurations?
    138153        usb_standard_configuration_descriptor_t config_descriptor;
    139154        opResult = usb_request_get_bare_configuration_descriptor(
     
    179194        }
    180195
    181         /**
    182          * Initialize the interrupt in endpoint.
    183          * \TODO this code should be checked...
    184          */
    185196        usb_endpoint_mapping_t endpoint_mapping[1] = {
    186197                {
     
    210221        return EOK;
    211222       
    212 
    213         // Initialize the interrupt(=status change) endpoint.
    214         /*usb_endpoint_pipe_initialize(
    215                 &result->endpoints->status_change,
    216                 &result->device_connection, );USB_TRANSFER_INTERRUPT
    217         USB_DIRECTION_IN*/
    218 
    219223}
    220224
     
    267271        }
    268272
    269        
    270273        dprintf(USB_LOG_LEVEL_INFO, "setting port count to %d",descriptor->ports_count);
    271274        result->port_count = descriptor->ports_count;
     
    329332
    330333        //add the hub to list
     334        //is this needed now?
    331335        fibril_mutex_lock(&usb_hub_list_lock);
    332336        usb_lst_append(&usb_hub_list, hub_info);
    333337        fibril_mutex_unlock(&usb_hub_list_lock);
    334 
    335338        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");
    336359        //(void)hub_info;
    337         usb_hub_check_hub_changes();
     360        //usb_hub_check_hub_changes();
    338361       
    339362        dprintf(USB_LOG_LEVEL_INFO, "hub dev added");
     
    368391        //opResult = usb_drv_reserve_default_address(hc);
    369392        opResult = usb_hc_reserve_default_address(&hub->connection, USB_SPEED_LOW);
    370 
    371         if (opResult != EOK) {
    372                 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);
    373397                return;
    374398        }
     
    381405                        );
    382406        if (opResult != EOK) {
    383                 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);
    384409                //usb_hub_release_default_address(hc);
    385410                usb_hc_release_default_address(&hub->connection);
     
    394419 */
    395420static void usb_hub_finalize_add_device( usb_hub_info_t * hub,
    396                 uint16_t port) {
     421                uint16_t port, bool isLowSpeed) {
    397422
    398423        int opResult;
     
    417442                        &new_device_connection);
    418443        /// \TODO get highspeed info
    419 
    420 
    421 
     444        usb_speed_t speed = isLowSpeed?USB_SPEED_LOW:USB_SPEED_FULL;
    422445
    423446
     
    425448        usb_address_t new_device_address = usb_hc_request_address(
    426449                        &hub->connection,
    427                         USB_SPEED_LOW/// \TODO fullspeed??
     450                        speed/// \TODO fullspeed??
    428451                        );
    429452        if (new_device_address < 0) {
     
    436459        //opResult = usb_drv_req_set_address(hc, USB_ADDRESS_DEFAULT,
    437460        //    new_device_address);
     461        usb_endpoint_pipe_start_session(&new_device_pipe);
    438462        opResult = usb_request_set_address(&new_device_pipe,new_device_address);
    439 
    440         if (opResult != EOK) {
    441                 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);
    442467                usb_hc_release_default_address(&hub->connection);
    443468                return;
     
    458483
    459484        if (opResult != EOK) {
    460                 dprintf(USB_LOG_LEVEL_ERROR, "could not start driver for new device");
     485                dprintf(USB_LOG_LEVEL_ERROR,
     486                                "could not start driver for new device %d",opResult);
    461487                return;
    462488        }
     
    469495                        &hub->attached_devs[port]);
    470496        if (opResult != EOK) {
    471                 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);
    472499                return;
    473500        }
     
    511538}
    512539
     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
    513560/**
    514561 * Process interrupts on given hub port
     
    522569        //determine type of change
    523570        usb_endpoint_pipe_t *pipe = &hub->endpoints.control;
    524         int opResult = usb_endpoint_pipe_start_session(pipe);
    525571       
    526         if(opResult != EOK){
    527                 dprintf(USB_LOG_LEVEL_ERROR, "cannot open pipe %d", opResult);
    528         }
    529 
    530         /*
    531         usb_target_t target;
    532         target.address=address;
    533         target.endpoint=0;
    534         */
     572        int opResult;
    535573
    536574        usb_port_status_t status;
     
    547585                        );
    548586        if (opResult != EOK) {
    549                 dprintf(USB_LOG_LEVEL_ERROR, "ERROR: could not get port status");
     587                dprintf(USB_LOG_LEVEL_ERROR, "could not get port status");
    550588                return;
    551589        }
    552590        if (rcvd_size != sizeof (usb_port_status_t)) {
    553                 dprintf(USB_LOG_LEVEL_ERROR, "ERROR: received status has incorrect size");
     591                dprintf(USB_LOG_LEVEL_ERROR, "received status has incorrect size");
    554592                return;
    555593        }
     
    566604                }
    567605        }
     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        }
    568616        //port reset
    569617        if (usb_port_reset_completed(&status)) {
    570618                dprintf(USB_LOG_LEVEL_INFO, "port reset complete");
    571619                if (usb_port_enabled(&status)) {
    572                         usb_hub_finalize_add_device(hub, port);
     620                        usb_hub_finalize_add_device(hub, port, usb_port_low_speed(&status));
    573621                } else {
    574                         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");
    575623                }
    576624        }
     
    585633        }
    586634        /// \TODO handle other changes
    587         /// \TODO debug log for various situations
    588         usb_endpoint_pipe_end_session(pipe);
    589 
    590 
    591 }
    592 
    593 /**
    594  * Check changes on all known hubs.
    595  */
    596 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
    597657        /*
    598          * Iterate through all hubs.
     658         * Send the request.
    599659         */
    600         usb_general_list_t * lst_item;
    601         fibril_mutex_lock(&usb_hub_list_lock);
    602         for (lst_item = usb_hub_list.next;
    603                         lst_item != &usb_hub_list;
    604                         lst_item = lst_item->next) {
    605                 fibril_mutex_unlock(&usb_hub_list_lock);
    606                 usb_hub_info_t * hub_info = ((usb_hub_info_t*)lst_item->data);
    607                 int opResult;
    608 
    609                 opResult = usb_endpoint_pipe_start_session(&hub_info->endpoints.status_change);
    610                 if(opResult != EOK){
    611                         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);
    612695                }
    613                 /*
    614                  * Check status change pipe of this hub.
    615                  */
    616                 /*
    617                 usb_target_t target;
    618                 target.address = hub_info->address;
    619                 target.endpoint = 1;/// \TODO get from endpoint descriptor
    620                 dprintf(USB_LOG_LEVEL_INFO, "checking changes for hub at addr %d",
    621                     target.address);
    622                 */
    623                 size_t port_count = hub_info->port_count;
    624 
    625                 /*
    626                  * Connect to respective HC.
    627                  *
    628                 int hc = usb_drv_hc_connect_auto(hub_info->device, 0);
    629                 if (hc < 0) {
    630                         continue;
    631                 }*/
    632 
    633                 /// FIXME: count properly
    634                 size_t byte_length = ((port_count+1) / 8) + 1;
    635 
    636                 void *change_bitmap = malloc(byte_length);
    637                 size_t actual_size;
    638                 //usb_handle_t handle;
    639 
    640                 /*
    641                  * Send the request.
    642                  */
    643                 opResult = usb_endpoint_pipe_read(
    644                                 &hub_info->endpoints.status_change,
    645                                 change_bitmap, byte_length, &actual_size
    646                                 );
    647 
    648                 //usb_drv_async_wait_for(handle);
    649 
    650                 if (opResult != EOK) {
    651                         free(change_bitmap);
    652                         dprintf(USB_LOG_LEVEL_WARNING, "something went wrong while getting status of hub");
    653                         continue;
    654                 }
    655                 unsigned int port;
    656                 for (port = 1; port < port_count+1; ++port) {
    657                         bool interrupt =
    658                                         (((uint8_t*) change_bitmap)[port / 8] >> (port % 8)) % 2;
    659                         if (interrupt) {
    660                                 usb_hub_process_interrupt(
    661                                         hub_info, port);
    662                         }
    663                 }
    664                 usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
    665                 free(change_bitmap);
    666                
    667 
    668                 //async_hangup(hc);
    669                 fibril_mutex_lock(&usb_hub_list_lock);
    670         }
    671         fibril_mutex_unlock(&usb_hub_list_lock);
    672 }
    673 
    674 
     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}
    675702
    676703
Note: See TracChangeset for help on using the changeset viewer.