Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/ohci/root_hub.c

    rccbcd895 r0368669c  
    4040#include "root_hub.h"
    4141#include "usb/classes/classes.h"
    42 #include "usb/devdrv.h"
    4342#include <usb/request.h>
    4443#include <usb/classes/hub.h>
     
    6261                /// \TODO these values migt be different
    6362                .str_serial_number = 0,
    64                 .usb_spec_version = 0x110,
     63                .usb_spec_version = 0,
    6564};
    6665
     
    111110};
    112111
    113 static const uint32_t hub_clear_feature_valid_mask =
    114         (1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER) +
    115         (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);
    116 
    117 static const uint32_t hub_clear_feature_by_writing_one_mask =
    118         1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER;
    119 
    120 static const uint32_t hub_set_feature_valid_mask =
    121         (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);
    122 
     112/** Root hub initialization
     113 * @return Error code.
     114 */
     115int rh_init(rh_t *instance, ddf_dev_t *dev, ohci_regs_t *regs)
     116{
     117        assert(instance);
     118        instance->address = -1;
     119        instance->registers = regs;
     120        instance->device = dev;
     121
     122
     123        usb_log_info("OHCI root hub with %d ports.\n", regs->rh_desc_a & 0xff);
     124
     125        //start generic usb hub driver
    123126       
    124 static const uint32_t hub_set_feature_direct_mask =
    125         (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);
    126 
    127 static const uint32_t port_set_feature_valid_mask =
    128         (1 << USB_HUB_FEATURE_PORT_ENABLE) +
    129         (1 << USB_HUB_FEATURE_PORT_SUSPEND) +
    130         (1 << USB_HUB_FEATURE_PORT_RESET) +
    131         (1 << USB_HUB_FEATURE_PORT_POWER);
    132 
    133 static const uint32_t port_clear_feature_valid_mask =
    134         (1 << USB_HUB_FEATURE_PORT_CONNECTION) +
    135         (1 << USB_HUB_FEATURE_PORT_SUSPEND) +
    136         (1 << USB_HUB_FEATURE_PORT_OVER_CURRENT) +
    137         (1 << USB_HUB_FEATURE_PORT_POWER) +
    138         (1 << USB_HUB_FEATURE_C_PORT_CONNECTION) +
    139         (1 << USB_HUB_FEATURE_C_PORT_ENABLE) +
    140         (1 << USB_HUB_FEATURE_C_PORT_SUSPEND) +
    141         (1 << USB_HUB_FEATURE_C_PORT_OVER_CURRENT) +
    142         (1 << USB_HUB_FEATURE_C_PORT_RESET);
    143 //note that USB_HUB_FEATURE_PORT_POWER bit is translated into USB_HUB_FEATURE_PORT_LOW_SPEED
    144 
    145 
    146 
     127        /* TODO: implement */
     128        return EOK;
     129}
     130/*----------------------------------------------------------------------------*/
     131
     132/**
     133 * create answer to port status_request
     134 *
     135 * Copy content of corresponding port status register to answer buffer.
     136 *
     137 * @param instance root hub instance
     138 * @param port port number, counted from 1
     139 * @param request structure containing both request and response information
     140 * @return error code
     141 */
     142static int process_get_port_status_request(rh_t *instance, uint16_t port,
     143                usb_transfer_batch_t * request){
     144        if(port<1 || port>instance->port_count)
     145                return EINVAL;
     146        uint32_t * uint32_buffer = (uint32_t*)request->buffer;
     147        request->transfered_size = 4;
     148        uint32_buffer[0] = instance->registers->rh_port_status[port -1];
     149        return EOK;
     150}
     151
     152/**
     153 * create answer to port status_request
     154 *
     155 * Copy content of hub status register to answer buffer.
     156 *
     157 * @param instance root hub instance
     158 * @param request structure containing both request and response information
     159 * @return error code
     160 */
     161static int process_get_hub_status_request(rh_t *instance,
     162                usb_transfer_batch_t * request){
     163        uint32_t * uint32_buffer = (uint32_t*)request->buffer;
     164        //bits, 0,1,16,17
     165        request->transfered_size = 4;
     166        uint32_t mask = 1 & (1<<1) & (1<<16) & (1<<17);
     167        uint32_buffer[0] = mask & instance->registers->rh_status;
     168        return EOK;
     169
     170}
    147171
    148172/**
    149173 * Create hub descriptor used in hub-driver <-> hub communication
    150  *
     174 * 
    151175 * This means creating byt array from data in root hub registers. For more
    152176 * info see usb hub specification.
     
    173197        result[2] = instance->port_count;
    174198        uint32_t hub_desc_reg = instance->registers->rh_desc_a;
    175         result[3] =
     199        result[3] = 
    176200                        ((hub_desc_reg >> 8) %2) +
    177201                        (((hub_desc_reg >> 9) %2) << 1) +
     
    195219        (*out_size) = size;
    196220}
    197 
    198 
    199 /** initialize hub descriptors
    200  *
    201  * Initialized are device and full configuration descriptor. These need to
    202  * be initialized only once per hub.
    203  * @instance root hub instance
    204  */
    205 static void rh_init_descriptors(rh_t *instance){
    206         memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor,
    207                 sizeof(ohci_rh_device_descriptor)
    208         );
    209         usb_standard_configuration_descriptor_t descriptor;
    210         memcpy(&descriptor,&ohci_rh_conf_descriptor,
    211                         sizeof(ohci_rh_conf_descriptor));
    212         uint8_t * hub_descriptor;
    213         size_t hub_desc_size;
    214         usb_create_serialized_hub_descriptor(instance, &hub_descriptor,
    215                         &hub_desc_size);
    216 
    217         descriptor.total_length =
    218                         sizeof(usb_standard_configuration_descriptor_t)+
    219                         sizeof(usb_standard_endpoint_descriptor_t)+
    220                         sizeof(usb_standard_interface_descriptor_t)+
    221                         hub_desc_size;
    222        
    223         uint8_t * full_config_descriptor =
    224                         (uint8_t*) malloc(descriptor.total_length);
    225         memcpy(full_config_descriptor, &descriptor, sizeof(descriptor));
    226         memcpy(full_config_descriptor + sizeof(descriptor),
    227                         &ohci_rh_iface_descriptor, sizeof(ohci_rh_iface_descriptor));
    228         memcpy(full_config_descriptor + sizeof(descriptor) +
    229                                 sizeof(ohci_rh_iface_descriptor),
    230                         &ohci_rh_ep_descriptor, sizeof(ohci_rh_ep_descriptor));
    231         memcpy(full_config_descriptor + sizeof(descriptor) +
    232                                 sizeof(ohci_rh_iface_descriptor) +
    233                                 sizeof(ohci_rh_ep_descriptor),
    234                         hub_descriptor, hub_desc_size);
    235        
    236         instance->descriptors.configuration = full_config_descriptor;
    237         instance->descriptors.configuration_size = descriptor.total_length;
    238 }
    239 
    240 /** Root hub initialization
    241  * @return Error code.
    242  */
    243 int rh_init(rh_t *instance, ddf_dev_t *dev, ohci_regs_t *regs)
    244 {
    245         assert(instance);
    246         instance->address = -1;
    247         instance->registers = regs;
    248         instance->device = dev;
    249         instance->port_count = instance->registers->rh_desc_a & 0xff;
    250         rh_init_descriptors(instance);
    251         /// \TODO set port power mode
    252 
    253 
    254         usb_log_info("OHCI root hub with %d ports.\n", instance->port_count);
    255 
    256         //start generic usb hub driver
    257        
    258         /* TODO: implement */
    259         return EOK;
    260 }
    261 /*----------------------------------------------------------------------------*/
    262 
    263 /**
    264  * create answer to port status_request
    265  *
    266  * Copy content of corresponding port status register to answer buffer.
    267  *
    268  * @param instance root hub instance
    269  * @param port port number, counted from 1
    270  * @param request structure containing both request and response information
    271  * @return error code
    272  */
    273 static int process_get_port_status_request(rh_t *instance, uint16_t port,
    274                 usb_transfer_batch_t * request){
    275         if(port<1 || port>instance->port_count)
    276                 return EINVAL;
    277         uint32_t * uint32_buffer = (uint32_t*)request->transport_buffer;
    278         request->transfered_size = 4;
    279         uint32_buffer[0] = instance->registers->rh_port_status[port -1];
    280         return EOK;
    281 }
    282 
    283 /**
    284  * create answer to port status_request
    285  *
    286  * Copy content of hub status register to answer buffer.
    287  *
    288  * @param instance root hub instance
    289  * @param request structure containing both request and response information
    290  * @return error code
    291  */
    292 static int process_get_hub_status_request(rh_t *instance,
    293                 usb_transfer_batch_t * request){
    294         uint32_t * uint32_buffer = (uint32_t*)request->transport_buffer;
    295         //bits, 0,1,16,17
    296         request->transfered_size = 4;
    297         uint32_t mask = 1 & (1<<1) & (1<<16) & (1<<17);
    298         uint32_buffer[0] = mask & instance->registers->rh_status;
    299         return EOK;
    300 
    301 }
    302 
    303221
    304222
     
    366284        }
    367285}
    368  
     286
     287/**
     288 * create standart configuration descriptor for the root hub instance
     289 * @param instance root hub instance
     290 * @return newly allocated descriptor
     291 */
     292static usb_standard_configuration_descriptor_t *
     293usb_ohci_rh_create_standart_configuration_descriptor(rh_t *instance){
     294        usb_standard_configuration_descriptor_t * descriptor =
     295                        malloc(sizeof(usb_standard_configuration_descriptor_t));
     296        memcpy(descriptor, &ohci_rh_conf_descriptor,
     297                sizeof(usb_standard_configuration_descriptor_t));
     298        /// \TODO should this include device descriptor?
     299        const size_t hub_descriptor_size = 7 +
     300                        2* (instance->port_count / 8 +
     301                        ((instance->port_count % 8 > 0) ? 1 : 0));
     302        descriptor->total_length =
     303                        sizeof(usb_standard_configuration_descriptor_t)+
     304                        sizeof(usb_standard_endpoint_descriptor_t)+
     305                        sizeof(usb_standard_interface_descriptor_t)+
     306                        hub_descriptor_size;
     307        return descriptor;
     308}
     309
    369310/**
    370311 * create answer to a descriptor request
     
    403344                case USB_DESCTYPE_CONFIGURATION: {
    404345                        usb_log_debug("USB_DESCTYPE_CONFIGURATION\n");
    405                         result_descriptor = instance->descriptors.configuration;
    406                         size = instance->descriptors.configuration_size;
     346                        usb_standard_configuration_descriptor_t * descriptor =
     347                                        usb_ohci_rh_create_standart_configuration_descriptor(
     348                                                instance);
     349                        result_descriptor = descriptor;
     350                        size = sizeof(usb_standard_configuration_descriptor_t);
     351                        del = true;
    407352                        break;
    408353                }
     
    435380        }
    436381        request->transfered_size = size;
    437         memcpy(request->transport_buffer,result_descriptor,size);
    438         usb_log_debug("sent desctiptor: %s\n",
    439                         usb_debug_str_buffer((uint8_t*)request->transport_buffer,size,size));
     382        memcpy(request->buffer,result_descriptor,size);
    440383        if (del)
    441384                free(result_descriptor);
     
    457400        if(request->buffer_size != 1)
    458401                return EINVAL;
    459         request->transport_buffer[0] = 1;
     402        request->buffer[0] = 1;
    460403        request->transfered_size = 1;
    461404        return EOK;
     
    463406
    464407/**
    465  * process feature-enabling request on hub
     408 * process feature-enabling/disabling request on hub
    466409 *
    467410 * @param instance root hub instance
    468411 * @param feature feature selector
     412 * @param enable enable or disable specified feature
    469413 * @return error code
    470414 */
    471415static int process_hub_feature_set_request(rh_t *instance,
    472                 uint16_t feature){
    473         if(! ((1<<feature) & hub_set_feature_valid_mask))
     416                uint16_t feature, bool enable){
     417        if(feature > USB_HUB_FEATURE_C_HUB_OVER_CURRENT)
    474418                return EINVAL;
    475419        instance->registers->rh_status =
     420                        enable ?
    476421                        (instance->registers->rh_status | (1<<feature))
    477                         & (~ hub_clear_feature_by_writing_one_mask);
    478         return EOK;
    479 }
    480 
    481 /**
    482  * process feature-disabling request on hub
    483  *
    484  * @param instance root hub instance
    485  * @param feature feature selector
    486  * @return error code
    487  */
    488 static int process_hub_feature_clear_request(rh_t *instance,
    489                 uint16_t feature){
    490         if(! ((1<<feature) & hub_clear_feature_valid_mask))
    491                 return EINVAL;
    492         //is the feature cleared directly?
    493         if ((1<<feature) & hub_set_feature_direct_mask){
    494                 instance->registers->rh_status =
    495                         (instance->registers->rh_status & (~(1<<feature)))
    496                         & (~ hub_clear_feature_by_writing_one_mask);
    497         }else{//the feature is cleared by writing '1'
    498                 instance->registers->rh_status =
    499                                 (instance->registers->rh_status
    500                                 & (~ hub_clear_feature_by_writing_one_mask))
    501                                 | (1<<feature);
    502         }
    503         return EOK;
    504 }
    505 
    506 
    507 
    508 /**
    509  * process feature-enabling request on hub
     422                        :
     423                        (instance->registers->rh_status & (~(1<<feature)));
     424        /// \TODO any error?
     425        return EOK;
     426}
     427
     428/**
     429 * process feature-enabling/disabling request on hub
    510430 *
    511431 * @param instance root hub instance
     
    516436 */
    517437static int process_port_feature_set_request(rh_t *instance,
    518                 uint16_t feature, uint16_t port){
    519         if(!((1<<feature) & port_set_feature_valid_mask))
     438                uint16_t feature, uint16_t port, bool enable){
     439        if(feature > USB_HUB_FEATURE_C_PORT_RESET)
    520440                return EINVAL;
    521441        if(port<1 || port>instance->port_count)
    522442                return EINVAL;
    523443        instance->registers->rh_port_status[port - 1] =
     444                        enable ?
    524445                        (instance->registers->rh_port_status[port - 1] | (1<<feature))
    525                         & (~port_clear_feature_valid_mask);
     446                        :
     447                        (instance->registers->rh_port_status[port - 1] & (~(1<<feature)));
    526448        /// \TODO any error?
    527449        return EOK;
    528450}
    529 
    530 /**
    531  * process feature-disabling request on hub
    532  *
    533  * @param instance root hub instance
    534  * @param feature feature selector
    535  * @param port port number, counted from 1
    536  * @param enable enable or disable the specified feature
    537  * @return error code
    538  */
    539 static int process_port_feature_clear_request(rh_t *instance,
    540                 uint16_t feature, uint16_t port){
    541         if(!((1<<feature) & port_clear_feature_valid_mask))
    542                 return EINVAL;
    543         if(port<1 || port>instance->port_count)
    544                 return EINVAL;
    545         if(feature == USB_HUB_FEATURE_PORT_POWER)
    546                 feature = USB_HUB_FEATURE_PORT_LOW_SPEED;
    547         if(feature == USB_HUB_FEATURE_PORT_SUSPEND)
    548                 feature = USB_HUB_FEATURE_PORT_OVER_CURRENT;
    549         instance->registers->rh_port_status[port - 1] =
    550                         (instance->registers->rh_port_status[port - 1]
    551                         & (~port_clear_feature_valid_mask))
    552                         | (1<<feature);
    553         /// \TODO any error?
    554         return EOK;
    555 }
    556 
    557451
    558452/**
     
    636530                        (usb_device_request_setup_packet_t*)request->setup_buffer;
    637531        request->transfered_size = 0;
    638         if(setup_request->request == USB_DEVREQ_CLEAR_FEATURE){
     532        if(setup_request->request == USB_DEVREQ_CLEAR_FEATURE
     533                                || setup_request->request == USB_DEVREQ_SET_FEATURE){
    639534                if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE){
    640535                        usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
    641                         return process_hub_feature_clear_request(instance,
    642                                         setup_request->value);
     536                        return process_hub_feature_set_request(instance, setup_request->value,
     537                                        setup_request->request == USB_DEVREQ_SET_FEATURE);
    643538                }
    644539                if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE){
    645540                        usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
    646                         return process_port_feature_clear_request(instance,
    647                                         setup_request->value,
    648                                         setup_request->index);
    649                 }
    650                 usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",
    651                                 setup_request->request_type);
    652                 return EINVAL;
    653         }
    654         if(setup_request->request == USB_DEVREQ_SET_FEATURE){
    655                 if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE){
    656                         usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
    657                         return process_hub_feature_set_request(instance,
    658                                         setup_request->value);
    659                 }
    660                 if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE){
    661                         usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
    662                         return process_port_feature_set_request(instance,
    663                                         setup_request->value,
    664                                         setup_request->index);
     541                        return process_port_feature_set_request(instance, setup_request->value,
     542                                        setup_request->index,
     543                                        setup_request->request == USB_DEVREQ_SET_FEATURE);
    665544                }
    666545                usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",setup_request->request_type);
Note: See TracChangeset for help on using the changeset viewer.