Ignore:
File:
1 edited

Legend:

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

    r361fcec rbe11749  
    149149
    150150
    151 static int create_serialized_hub_descriptor(rh_t *instance);
    152 
    153 static int rh_init_descriptors(rh_t *instance);
     151static void usb_create_serialized_hub_descriptor(rh_t *instance,
     152        uint8_t ** out_result,
     153        size_t * out_size);
     154
     155static void rh_init_descriptors(rh_t *instance);
    154156
    155157static int process_get_port_status_request(rh_t *instance, uint16_t port,
     
    162164        usb_transfer_batch_t * request);
    163165
    164 static void create_interrupt_mask_in_instance(rh_t *instance);
     166static void create_interrupt_mask(rh_t *instance, void ** buffer,
     167        size_t * buffer_size);
    165168
    166169static int process_get_descriptor_request(rh_t *instance,
     
    195198static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request);
    196199
    197 static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request);
     200static int process_interrupt(rh_t *instance, usb_transfer_batch_t * request,
     201    void * change_buffer, size_t buffe_size);
    198202
    199203static bool is_zeros(void * buffer, size_t size);
     
    209213        instance->port_count =
    210214            (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
    211         int opResult = rh_init_descriptors(instance);
    212         if(opResult != EOK){
    213                 return opResult;
    214         }
     215        rh_init_descriptors(instance);
    215216        // set port power mode to no-power-switching
    216217        instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
    217218        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 
    224219        usb_log_info("OHCI root hub with %d ports.\n", instance->port_count);
    225220        return EOK;
     
    244239        } else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) {
    245240                usb_log_info("Root hub got INTERRUPT packet\n");
    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;
     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;
    251249                        //will be finished later
    252250                }else{
    253                         usb_log_debug("processing changes..\n");
    254                         process_interrupt_mask_in_instance(instance, request);
    255                 }
     251                        usb_log_debug("processing changes..");
     252                        process_interrupt(instance, request,
     253                            buffer, buffer_size);
     254                }
     255                free(buffer);
    256256                opResult = EOK;
    257257        } else {
     
    264264/*----------------------------------------------------------------------------*/
    265265
    266 /**
    267  * process interrupt on a hub
    268  *
    269  * If there is no pending interrupt transfer, nothing happens.
    270  * @param instance
    271  */
     266
    272267void rh_interrupt(rh_t *instance) {
     268        //usb_log_info("Whoa whoa wait, I`m not supposed to receive any "
     269        //      "interrupts, am I?\n");
    273270        if(!instance->unfinished_interrupt_transfer){
    274271                return;
    275272        }
    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);
     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);
    280280}
    281281/*----------------------------------------------------------------------------*/
     
    288288 *
    289289 * @param instance root hub instance
    290  * @return error code
    291  */
    292 static 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;
     290 * @param@out out_result pointer to resultant serialized descriptor
     291 * @param@out out_size size of serialized descriptor
     292 */
     293static 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;
    296302        uint8_t * result = (uint8_t*) malloc(size);
    297         if(!result) return ENOMEM;
    298 
    299303        bzero(result, size);
    300304        //size
     
    325329                result[7 + var_size + i] = 255;
    326330        }
    327         instance->hub_descriptor = result;
    328         instance->descriptor_size = size;
    329         return EOK;
     331        (*out_result) = result;
     332        (*out_size) = size;
    330333}
    331334/*----------------------------------------------------------------------------*/
     
    336339 * be initialized only once per hub.
    337340 * @instance root hub instance
    338  * @return error code
    339  */
    340 static int rh_init_descriptors(rh_t *instance) {
     341 */
     342static void rh_init_descriptors(rh_t *instance) {
    341343        memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor,
    342344                sizeof (ohci_rh_device_descriptor)
     
    345347        memcpy(&descriptor, &ohci_rh_conf_descriptor,
    346348                sizeof (ohci_rh_conf_descriptor));
    347 
    348         int opResult = create_serialized_hub_descriptor(instance);
    349         if(opResult != EOK){
    350                 return opResult;
    351         }
     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
    352354        descriptor.total_length =
    353355                sizeof (usb_standard_configuration_descriptor_t) +
    354356                sizeof (usb_standard_endpoint_descriptor_t) +
    355357                sizeof (usb_standard_interface_descriptor_t) +
    356                 instance->descriptor_size;
     358                hub_desc_size;
    357359
    358360        uint8_t * full_config_descriptor =
    359361                (uint8_t*) malloc(descriptor.total_length);
    360         if(!full_config_descriptor){
    361                 return ENOMEM;
    362         }
    363362        memcpy(full_config_descriptor, &descriptor, sizeof (descriptor));
    364363        memcpy(full_config_descriptor + sizeof (descriptor),
     
    370369                sizeof (ohci_rh_iface_descriptor) +
    371370                sizeof (ohci_rh_ep_descriptor),
    372                 instance->hub_descriptor, instance->descriptor_size);
    373        
     371                hub_descriptor, hub_desc_size);
     372
    374373        instance->descriptors.configuration = full_config_descriptor;
    375374        instance->descriptors.configuration_size = descriptor.total_length;
    376         return EOK;
    377375}
    378376/*----------------------------------------------------------------------------*/
     
    465463 * bit i indicates change on i`th port (i>0). For more info see
    466464 * Hub and Port status bitmap specification in USB specification
    467  * (chapter 11.13.4).
    468  * Uses instance`s interrupt buffer to store the interrupt information.
    469  * @param instance root hub instance
    470  */
    471 static void create_interrupt_mask_in_instance(rh_t * instance) {
    472         uint8_t * bitmap = (uint8_t*) (instance->interrupt_buffer);
     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 */
     470static 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);
    473477        uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16))
    474478                | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16));
    475         bzero(bitmap, instance->interrupt_mask_size);
     479        bzero(bitmap, (*buffer_size));
    476480        if (instance->registers->rh_status & mask) {
    477481                bitmap[0] = 1;
     
    504508        const uint16_t setup_request_value = setup_request->value_high;
    505509        //(setup_request->value_low << 8);
     510        bool del = false;
    506511        switch (setup_request_value) {
    507512                case USB_DESCTYPE_HUB:
    508513                {
    509                         usb_log_debug("USB_DESCTYPE_HUB\n");
    510                         result_descriptor = instance->hub_descriptor;
    511                         size = instance->descriptor_size;
     514                        uint8_t * descriptor;
     515                        usb_create_serialized_hub_descriptor(
     516                                instance, &descriptor, &size);
     517                        result_descriptor = descriptor;
     518                        if (result_descriptor) del = true;
    512519                        break;
    513520                }
     
    560567        request->transfered_size = size;
    561568        memcpy(request->data_buffer, result_descriptor, size);
     569        if (del)
     570                free(result_descriptor);
    562571        return EOK;
    563572}
     
    885894 * @param instance hub instance
    886895 * @param request batch request to be processed
     896 * @param change_buffer chages on hub
     897 * @param buffer_size size of change buffer
    887898 *
    888899 * @return
    889900 */
    890 static 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;
     901static 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);
    894906        instance->unfinished_interrupt_transfer = NULL;
    895907        usb_transfer_batch_finish_error(request, EOK);
Note: See TracChangeset for help on using the changeset viewer.