Ignore:
File:
1 edited

Legend:

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

    r0368669c rccbcd895  
    4040#include "root_hub.h"
    4141#include "usb/classes/classes.h"
     42#include "usb/devdrv.h"
    4243#include <usb/request.h>
    4344#include <usb/classes/hub.h>
     
    6162                /// \TODO these values migt be different
    6263                .str_serial_number = 0,
    63                 .usb_spec_version = 0,
     64                .usb_spec_version = 0x110,
    6465};
    6566
     
    110111};
    111112
    112 /** Root hub initialization
    113  * @return Error code.
    114  */
    115 int 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
     113static 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
     117static const uint32_t hub_clear_feature_by_writing_one_mask =
     118        1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER;
     119
     120static const uint32_t hub_set_feature_valid_mask =
     121        (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);
     122
    126123       
    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  */
    142 static 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  */
    161 static 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 }
     124static const uint32_t hub_set_feature_direct_mask =
     125        (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);
     126
     127static 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
     133static 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
    171147
    172148/**
    173149 * Create hub descriptor used in hub-driver <-> hub communication
    174  * 
     150 *
    175151 * This means creating byt array from data in root hub registers. For more
    176152 * info see usb hub specification.
     
    197173        result[2] = instance->port_count;
    198174        uint32_t hub_desc_reg = instance->registers->rh_desc_a;
    199         result[3] = 
     175        result[3] =
    200176                        ((hub_desc_reg >> 8) %2) +
    201177                        (((hub_desc_reg >> 9) %2) << 1) +
     
    219195        (*out_size) = size;
    220196}
     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 */
     205static 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 */
     243int 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 */
     273static 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 */
     292static 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
    221303
    222304
     
    284366        }
    285367}
    286 
    287 /**
    288  * create standart configuration descriptor for the root hub instance
    289  * @param instance root hub instance
    290  * @return newly allocated descriptor
    291  */
    292 static usb_standard_configuration_descriptor_t *
    293 usb_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 
     368 
    310369/**
    311370 * create answer to a descriptor request
     
    344403                case USB_DESCTYPE_CONFIGURATION: {
    345404                        usb_log_debug("USB_DESCTYPE_CONFIGURATION\n");
    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;
     405                        result_descriptor = instance->descriptors.configuration;
     406                        size = instance->descriptors.configuration_size;
    352407                        break;
    353408                }
     
    380435        }
    381436        request->transfered_size = size;
    382         memcpy(request->buffer,result_descriptor,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));
    383440        if (del)
    384441                free(result_descriptor);
     
    400457        if(request->buffer_size != 1)
    401458                return EINVAL;
    402         request->buffer[0] = 1;
     459        request->transport_buffer[0] = 1;
    403460        request->transfered_size = 1;
    404461        return EOK;
     
    406463
    407464/**
    408  * process feature-enabling/disabling request on hub
     465 * process feature-enabling request on hub
    409466 *
    410467 * @param instance root hub instance
    411468 * @param feature feature selector
    412  * @param enable enable or disable specified feature
    413469 * @return error code
    414470 */
    415471static int process_hub_feature_set_request(rh_t *instance,
    416                 uint16_t feature, bool enable){
    417         if(feature > USB_HUB_FEATURE_C_HUB_OVER_CURRENT)
     472                uint16_t feature){
     473        if(! ((1<<feature) & hub_set_feature_valid_mask))
    418474                return EINVAL;
    419475        instance->registers->rh_status =
    420                         enable ?
    421476                        (instance->registers->rh_status | (1<<feature))
    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
     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 */
     488static 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
    430510 *
    431511 * @param instance root hub instance
     
    436516 */
    437517static int process_port_feature_set_request(rh_t *instance,
    438                 uint16_t feature, uint16_t port, bool enable){
    439         if(feature > USB_HUB_FEATURE_C_PORT_RESET)
     518                uint16_t feature, uint16_t port){
     519        if(!((1<<feature) & port_set_feature_valid_mask))
    440520                return EINVAL;
    441521        if(port<1 || port>instance->port_count)
    442522                return EINVAL;
    443523        instance->registers->rh_port_status[port - 1] =
    444                         enable ?
    445524                        (instance->registers->rh_port_status[port - 1] | (1<<feature))
    446                         :
    447                         (instance->registers->rh_port_status[port - 1] & (~(1<<feature)));
     525                        & (~port_clear_feature_valid_mask);
    448526        /// \TODO any error?
    449527        return EOK;
    450528}
     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 */
     539static 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
    451557
    452558/**
     
    530636                        (usb_device_request_setup_packet_t*)request->setup_buffer;
    531637        request->transfered_size = 0;
    532         if(setup_request->request == USB_DEVREQ_CLEAR_FEATURE
    533                                 || setup_request->request == USB_DEVREQ_SET_FEATURE){
     638        if(setup_request->request == USB_DEVREQ_CLEAR_FEATURE){
    534639                if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE){
    535640                        usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
    536                         return process_hub_feature_set_request(instance, setup_request->value,
    537                                         setup_request->request == USB_DEVREQ_SET_FEATURE);
     641                        return process_hub_feature_clear_request(instance,
     642                                        setup_request->value);
    538643                }
    539644                if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE){
    540645                        usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
    541                         return process_port_feature_set_request(instance, setup_request->value,
    542                                         setup_request->index,
    543                                         setup_request->request == USB_DEVREQ_SET_FEATURE);
     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);
    544665                }
    545666                usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",setup_request->request_type);
Note: See TracChangeset for help on using the changeset viewer.