Changeset 299d53e in mainline for uspace/drv/usbhub/usbhub.c


Ignore:
Timestamp:
2011-02-27T02:54:49Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
4abc304
Parents:
8e1eb4d0 (diff), 81c508c (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:

Development branch changes

File:
1 edited

Legend:

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

    r8e1eb4d0 r299d53e  
    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
     
    249253        usb_endpoint_pipe_start_session(&result->endpoints.control);
    250254        opResult = usb_request_get_descriptor(&result->endpoints.control,
    251                         USB_REQUEST_TYPE_CLASS,
    252                         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,
    253258                        USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size);
    254259        usb_endpoint_pipe_end_session(&result->endpoints.control);
     
    267272        }
    268273
    269        
    270274        dprintf(USB_LOG_LEVEL_INFO, "setting port count to %d",descriptor->ports_count);
    271275        result->port_count = descriptor->ports_count;
     
    329333
    330334        //add the hub to list
     335        //is this needed now?
    331336        fibril_mutex_lock(&usb_hub_list_lock);
    332337        usb_lst_append(&usb_hub_list, hub_info);
    333338        fibril_mutex_unlock(&usb_hub_list_lock);
    334 
    335339        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");
    336360        //(void)hub_info;
    337         usb_hub_check_hub_changes();
     361        //usb_hub_check_hub_changes();
    338362       
    339363        dprintf(USB_LOG_LEVEL_INFO, "hub dev added");
     
    368392        //opResult = usb_drv_reserve_default_address(hc);
    369393        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");
     394       
     395        if (opResult != EOK) {
     396                dprintf(USB_LOG_LEVEL_WARNING,
     397                                "cannot assign default address, it is probably used %d",opResult);
    373398                return;
    374399        }
     
    381406                        );
    382407        if (opResult != EOK) {
    383                 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);
    384410                //usb_hub_release_default_address(hc);
    385411                usb_hc_release_default_address(&hub->connection);
     
    394420 */
    395421static void usb_hub_finalize_add_device( usb_hub_info_t * hub,
    396                 uint16_t port) {
     422                uint16_t port, bool isLowSpeed) {
    397423
    398424        int opResult;
     
    417443                        &new_device_connection);
    418444        /// \TODO get highspeed info
    419 
    420 
    421 
     445        usb_speed_t speed = isLowSpeed?USB_SPEED_LOW:USB_SPEED_FULL;
    422446
    423447
     
    425449        usb_address_t new_device_address = usb_hc_request_address(
    426450                        &hub->connection,
    427                         USB_SPEED_LOW/// \TODO fullspeed??
     451                        speed/// \TODO fullspeed??
    428452                        );
    429453        if (new_device_address < 0) {
     
    436460        //opResult = usb_drv_req_set_address(hc, USB_ADDRESS_DEFAULT,
    437461        //    new_device_address);
     462        usb_endpoint_pipe_start_session(&new_device_pipe);
    438463        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");
     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);
    442468                usb_hc_release_default_address(&hub->connection);
    443469                return;
     
    458484
    459485        if (opResult != EOK) {
    460                 dprintf(USB_LOG_LEVEL_ERROR, "could not start driver for new device");
     486                dprintf(USB_LOG_LEVEL_ERROR,
     487                                "could not start driver for new device %d",opResult);
    461488                return;
    462489        }
     
    469496                        &hub->attached_devs[port]);
    470497        if (opResult != EOK) {
    471                 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);
    472500                return;
    473501        }
     
    511539}
    512540
     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
    513561/**
    514562 * Process interrupts on given hub port
     
    522570        //determine type of change
    523571        usb_endpoint_pipe_t *pipe = &hub->endpoints.control;
    524         int opResult = usb_endpoint_pipe_start_session(pipe);
    525572       
    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         */
     573        int opResult;
    535574
    536575        usb_port_status_t status;
     
    547586                        );
    548587        if (opResult != EOK) {
    549                 dprintf(USB_LOG_LEVEL_ERROR, "ERROR: could not get port status");
     588                dprintf(USB_LOG_LEVEL_ERROR, "could not get port status");
    550589                return;
    551590        }
    552591        if (rcvd_size != sizeof (usb_port_status_t)) {
    553                 dprintf(USB_LOG_LEVEL_ERROR, "ERROR: received status has incorrect size");
     592                dprintf(USB_LOG_LEVEL_ERROR, "received status has incorrect size");
    554593                return;
    555594        }
     
    566605                }
    567606        }
     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        }
    568617        //port reset
    569618        if (usb_port_reset_completed(&status)) {
    570619                dprintf(USB_LOG_LEVEL_INFO, "port reset complete");
    571620                if (usb_port_enabled(&status)) {
    572                         usb_hub_finalize_add_device(hub, port);
     621                        usb_hub_finalize_add_device(hub, port, usb_port_low_speed(&status));
    573622                } else {
    574                         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");
    575624                }
    576625        }
     
    585634        }
    586635        /// \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) {
     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
    597658        /*
    598          * Iterate through all hubs.
     659         * Send the request.
    599660         */
    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;
     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);
    612696                }
    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 
     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}
    675703
    676704
Note: See TracChangeset for help on using the changeset viewer.