Ignore:
File:
1 edited

Legend:

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

    rbe11749 r361fcec  
    149149
    150150
    151 static void usb_create_serialized_hub_descriptor(rh_t *instance,
    152         uint8_t ** out_result,
    153         size_t * out_size);
    154 
    155 static void rh_init_descriptors(rh_t *instance);
     151static int create_serialized_hub_descriptor(rh_t *instance);
     152
     153static int rh_init_descriptors(rh_t *instance);
    156154
    157155static int process_get_port_status_request(rh_t *instance, uint16_t port,
     
    164162        usb_transfer_batch_t * request);
    165163
    166 static void create_interrupt_mask(rh_t *instance, void ** buffer,
    167         size_t * buffer_size);
     164static void create_interrupt_mask_in_instance(rh_t *instance);
    168165
    169166static int process_get_descriptor_request(rh_t *instance,
     
    198195static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request);
    199196
    200 static int process_interrupt(rh_t *instance, usb_transfer_batch_t * request,
    201     void * change_buffer, size_t buffe_size);
     197static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request);
    202198
    203199static bool is_zeros(void * buffer, size_t size);
     
    213209        instance->port_count =
    214210            (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
    215         rh_init_descriptors(instance);
     211        int opResult = rh_init_descriptors(instance);
     212        if(opResult != EOK){
     213                return opResult;
     214        }
    216215        // set port power mode to no-power-switching
    217216        instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
    218217        instance->unfinished_interrupt_transfer = NULL;
     218        instance->interrupt_mask_size = (instance->port_count + 8)/8;
     219        instance->interrupt_buffer = malloc(instance->interrupt_mask_size);
     220        if(!instance->interrupt_buffer)
     221                return ENOMEM;
     222       
     223
    219224        usb_log_info("OHCI root hub with %d ports.\n", instance->port_count);
    220225        return EOK;
     
    239244        } else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) {
    240245                usb_log_info("Root hub got INTERRUPT packet\n");
    241                 void * buffer;
    242                 size_t buffer_size;
    243                 create_interrupt_mask(instance, &buffer,
    244                         &buffer_size);
    245                 if(is_zeros(buffer,buffer_size)){
    246                         usb_log_debug("no changes..");
    247                         instance->unfinished_interrupt_transfer=
    248                             request;
     246                create_interrupt_mask_in_instance(instance);
     247                if(is_zeros(instance->interrupt_buffer,
     248                    instance->interrupt_mask_size)){
     249                        usb_log_debug("no changes..\n");
     250                        instance->unfinished_interrupt_transfer = request;
    249251                        //will be finished later
    250252                }else{
    251                         usb_log_debug("processing changes..");
    252                         process_interrupt(instance, request,
    253                             buffer, buffer_size);
    254                 }
    255                 free(buffer);
     253                        usb_log_debug("processing changes..\n");
     254                        process_interrupt_mask_in_instance(instance, request);
     255                }
    256256                opResult = EOK;
    257257        } else {
     
    264264/*----------------------------------------------------------------------------*/
    265265
    266 
     266/**
     267 * process interrupt on a hub
     268 *
     269 * If there is no pending interrupt transfer, nothing happens.
     270 * @param instance
     271 */
    267272void rh_interrupt(rh_t *instance) {
    268         //usb_log_info("Whoa whoa wait, I`m not supposed to receive any "
    269         //      "interrupts, am I?\n");
    270273        if(!instance->unfinished_interrupt_transfer){
    271274                return;
    272275        }
    273         size_t size;
    274         void * buffer;
    275         create_interrupt_mask(instance, &buffer,
    276                         &size);
    277         process_interrupt(instance,instance->unfinished_interrupt_transfer,
    278             buffer,size);
    279         free(buffer);
     276        usb_log_debug("finalizing interrupt transfer\n");
     277        create_interrupt_mask_in_instance(instance);
     278        process_interrupt_mask_in_instance(instance,
     279            instance->unfinished_interrupt_transfer);
    280280}
    281281/*----------------------------------------------------------------------------*/
     
    288288 *
    289289 * @param instance root hub instance
    290  * @param@out out_result pointer to resultant serialized descriptor
    291  * @param@out out_size size of serialized descriptor
    292  */
    293 static void usb_create_serialized_hub_descriptor(rh_t *instance,
    294         uint8_t ** out_result,
    295         size_t * out_size) {
    296         //base size
    297         size_t size = 7;
    298         //variable size according to port count
    299         size_t var_size = instance->port_count / 8 +
    300                 ((instance->port_count % 8 > 0) ? 1 : 0);
    301         size += 2 * var_size;
     290 * @return error code
     291 */
     292static int create_serialized_hub_descriptor(rh_t *instance) {
     293        size_t size = 7 +
     294            ((instance->port_count +7 )/ 8) * 2;
     295        size_t var_size = (instance->port_count +7 )/ 8;
    302296        uint8_t * result = (uint8_t*) malloc(size);
     297        if(!result) return ENOMEM;
     298
    303299        bzero(result, size);
    304300        //size
     
    329325                result[7 + var_size + i] = 255;
    330326        }
    331         (*out_result) = result;
    332         (*out_size) = size;
     327        instance->hub_descriptor = result;
     328        instance->descriptor_size = size;
     329        return EOK;
    333330}
    334331/*----------------------------------------------------------------------------*/
     
    339336 * be initialized only once per hub.
    340337 * @instance root hub instance
    341  */
    342 static void rh_init_descriptors(rh_t *instance) {
     338 * @return error code
     339 */
     340static int rh_init_descriptors(rh_t *instance) {
    343341        memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor,
    344342                sizeof (ohci_rh_device_descriptor)
     
    347345        memcpy(&descriptor, &ohci_rh_conf_descriptor,
    348346                sizeof (ohci_rh_conf_descriptor));
    349         uint8_t * hub_descriptor;
    350         size_t hub_desc_size;
    351         usb_create_serialized_hub_descriptor(instance, &hub_descriptor,
    352                 &hub_desc_size);
    353 
     347
     348        int opResult = create_serialized_hub_descriptor(instance);
     349        if(opResult != EOK){
     350                return opResult;
     351        }
    354352        descriptor.total_length =
    355353                sizeof (usb_standard_configuration_descriptor_t) +
    356354                sizeof (usb_standard_endpoint_descriptor_t) +
    357355                sizeof (usb_standard_interface_descriptor_t) +
    358                 hub_desc_size;
     356                instance->descriptor_size;
    359357
    360358        uint8_t * full_config_descriptor =
    361359                (uint8_t*) malloc(descriptor.total_length);
     360        if(!full_config_descriptor){
     361                return ENOMEM;
     362        }
    362363        memcpy(full_config_descriptor, &descriptor, sizeof (descriptor));
    363364        memcpy(full_config_descriptor + sizeof (descriptor),
     
    369370                sizeof (ohci_rh_iface_descriptor) +
    370371                sizeof (ohci_rh_ep_descriptor),
    371                 hub_descriptor, hub_desc_size);
    372 
     372                instance->hub_descriptor, instance->descriptor_size);
     373       
    373374        instance->descriptors.configuration = full_config_descriptor;
    374375        instance->descriptors.configuration_size = descriptor.total_length;
     376        return EOK;
    375377}
    376378/*----------------------------------------------------------------------------*/
     
    463465 * bit i indicates change on i`th port (i>0). For more info see
    464466 * Hub and Port status bitmap specification in USB specification
    465  * (chapter 11.13.4)
    466  * @param instance root hub instance
    467  * @param@out buffer pointer to created interrupt mas
    468  * @param@out buffer_size size of created interrupt mask
    469  */
    470 static void create_interrupt_mask(rh_t *instance, void ** buffer,
    471         size_t * buffer_size) {
    472         int bit_count = instance->port_count + 1;
    473         (*buffer_size) = (bit_count / 8) + ((bit_count % 8 == 0) ? 0 : 1);
    474 
    475         (*buffer) = malloc(*buffer_size);
    476         uint8_t * bitmap = (uint8_t*) (*buffer);
     467 * (chapter 11.13.4).
     468 * Uses instance`s interrupt buffer to store the interrupt information.
     469 * @param instance root hub instance
     470 */
     471static void create_interrupt_mask_in_instance(rh_t * instance) {
     472        uint8_t * bitmap = (uint8_t*) (instance->interrupt_buffer);
    477473        uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16))
    478474                | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16));
    479         bzero(bitmap, (*buffer_size));
     475        bzero(bitmap, instance->interrupt_mask_size);
    480476        if (instance->registers->rh_status & mask) {
    481477                bitmap[0] = 1;
     
    508504        const uint16_t setup_request_value = setup_request->value_high;
    509505        //(setup_request->value_low << 8);
    510         bool del = false;
    511506        switch (setup_request_value) {
    512507                case USB_DESCTYPE_HUB:
    513508                {
    514                         uint8_t * descriptor;
    515                         usb_create_serialized_hub_descriptor(
    516                                 instance, &descriptor, &size);
    517                         result_descriptor = descriptor;
    518                         if (result_descriptor) del = true;
     509                        usb_log_debug("USB_DESCTYPE_HUB\n");
     510                        result_descriptor = instance->hub_descriptor;
     511                        size = instance->descriptor_size;
    519512                        break;
    520513                }
     
    567560        request->transfered_size = size;
    568561        memcpy(request->data_buffer, result_descriptor, size);
    569         if (del)
    570                 free(result_descriptor);
    571562        return EOK;
    572563}
     
    894885 * @param instance hub instance
    895886 * @param request batch request to be processed
    896  * @param change_buffer chages on hub
    897  * @param buffer_size size of change buffer
    898887 *
    899888 * @return
    900889 */
    901 static int process_interrupt(rh_t *instance, usb_transfer_batch_t * request,
    902     void * change_buffer, size_t buffe_size){
    903         create_interrupt_mask(instance, &change_buffer,
    904             &(request->transfered_size));
    905         memcpy(request->data_buffer, change_buffer,request->transfered_size);
     890static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request){
     891        memcpy(request->data_buffer, instance->interrupt_buffer,
     892            instance->interrupt_mask_size);
     893        request->transfered_size = instance->interrupt_mask_size;
    906894        instance->unfinished_interrupt_transfer = NULL;
    907895        usb_transfer_batch_finish_error(request, EOK);
Note: See TracChangeset for help on using the changeset viewer.