Ignore:
File:
1 edited

Legend:

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

    r1387692 rd8421c4  
    3939
    4040#include "root_hub.h"
     41#include "usb/classes/classes.h"
     42#include <usb/request.h>
     43#include <usb/classes/hub.h>
     44
    4145
    4246/** Root hub initialization
     
    5054        instance->device = dev;
    5155
     56
    5257        usb_log_info("OHCI root hub with %d ports.\n", regs->rh_desc_a & 0xff);
    5358
     59        //start generic usb hub driver
     60       
    5461        /* TODO: implement */
    5562        return EOK;
    5663}
    5764/*----------------------------------------------------------------------------*/
     65
     66
     67static int process_get_port_status_request(rh_t *instance, uint16_t port,
     68                usb_transfer_batch_t * request){
     69        if(port<1 || port>instance->port_count)
     70                return EINVAL;
     71        uint32_t * uint32_buffer = (uint32_t*)request->buffer;
     72        request->transfered_size = 4;
     73        uint32_buffer[0] = instance->registers->rh_port_status[port -1];
     74        return EOK;
     75}
     76
     77static int process_get_hub_status_request(rh_t *instance,
     78                usb_transfer_batch_t * request){
     79        uint32_t * uint32_buffer = (uint32_t*)request->buffer;
     80        //bits, 0,1,16,17
     81        request->transfered_size = 4;
     82        uint32_t mask = 1 & (1<<1) & (1<<16) & (1<<17);
     83        uint32_buffer[0] = mask & instance->registers->rh_status;
     84        return EOK;
     85
     86}
     87
     88static void usb_create_serialized_hub_descriptor(rh_t *instance, uint8_t ** out_result,
     89                size_t * out_size) {
     90        //base size
     91        size_t size = 7;
     92        //variable size according to port count
     93        size_t var_size = instance->port_count / 8 +
     94                        ((instance->port_count % 8 > 0) ? 1 : 0);
     95        size += 2 * var_size;
     96        uint8_t * result = (uint8_t*) malloc(size);
     97        bzero(result,size);
     98        //size
     99        result[0] = size;
     100        //descriptor type
     101        result[1] = USB_DESCTYPE_HUB;
     102        result[2] = instance->port_count;
     103        uint32_t hub_desc_reg = instance->registers->rh_desc_a;
     104        result[3] =
     105                        ((hub_desc_reg >> 8) %2) +
     106                        (((hub_desc_reg >> 9) %2) << 1) +
     107                        (((hub_desc_reg >> 10) %2) << 2) +
     108                        (((hub_desc_reg >> 11) %2) << 3) +
     109                        (((hub_desc_reg >> 12) %2) << 4);
     110        result[4] = 0;
     111        result[5] = /*descriptor->pwr_on_2_good_time*/ 50;
     112        result[6] = 50;
     113
     114        int port;
     115        for (port = 1; port <= instance->port_count; ++port) {
     116                result[7 + port/8] +=
     117                                ((instance->registers->rh_desc_b >> port)%2) << (port%8);
     118        }
     119        size_t i;
     120        for (i = 0; i < var_size; ++i) {
     121                result[7 + var_size + i] = 255;
     122        }
     123        (*out_result) = result;
     124        (*out_size) = size;
     125}
     126
     127
     128static int process_get_status_request(rh_t *instance,
     129                usb_transfer_batch_t * request)
     130{
     131        size_t buffer_size = request->buffer_size;
     132        usb_device_request_setup_packet_t * request_packet =
     133                        (usb_device_request_setup_packet_t*)
     134                        request->setup_buffer;
     135
     136        usb_hub_bm_request_type_t request_type = request_packet->request_type;
     137        if(buffer_size<4/*request_packet->length*/){///\TODO
     138                usb_log_warning("requested more data than buffer size\n");
     139                return EINVAL;
     140        }
     141
     142        if(request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS)
     143                return process_get_hub_status_request(instance, request);
     144        if(request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS)
     145                return process_get_port_status_request(instance, request_packet->index,
     146                                request);
     147        return ENOTSUP;
     148}
     149
     150static void create_interrupt_mask(rh_t *instance, void ** buffer,
     151                size_t * buffer_size){
     152        int bit_count = instance->port_count + 1;
     153        (*buffer_size) = (bit_count / 8) + (bit_count%8==0)?0:1;
     154        (*buffer) = malloc(*buffer_size);
     155        uint8_t * bitmap = (uint8_t*)(*buffer);
     156        uint32_t mask = (1<<16) + (1<<17);
     157        bzero(bitmap,(*buffer_size));
     158        if(instance->registers->rh_status & mask){
     159                bitmap[0] = 1;
     160        }
     161        int port;
     162        mask = 0;
     163        int i;
     164        for(i=16;i<=20;++i)
     165                mask += 1<<i;
     166        for(port = 1; port<=instance->port_count;++port){
     167                if(mask & instance->registers->rh_port_status[port-1]){
     168                        bitmap[(port+1)/8] += 1<<(port%8);
     169                }
     170        }
     171}
     172
     173
     174static int process_get_descriptor_request(rh_t *instance,
     175                usb_transfer_batch_t *request){
     176        /// \TODO
     177        usb_device_request_setup_packet_t * setup_request =
     178                        (usb_device_request_setup_packet_t*)request->setup_buffer;
     179        size_t size;
     180        void * result_descriptor;
     181        uint16_t setup_request_value = setup_request->value_high;
     182                        //(setup_request->value_low << 8);
     183        if(setup_request_value == USB_DESCTYPE_HUB){
     184                usb_log_debug("USB_DESCTYPE_HUB\n");
     185                //create hub descriptor
     186                uint8_t * descriptor;
     187                usb_create_serialized_hub_descriptor(instance,
     188                                &descriptor, &size);
     189                result_descriptor = descriptor;
     190        }else if(setup_request_value == USB_DESCTYPE_DEVICE){
     191                //create std device descriptor
     192                usb_log_debug("USB_DESCTYPE_DEVICE\n");
     193                usb_standard_device_descriptor_t * descriptor =
     194                                (usb_standard_device_descriptor_t*)
     195                                malloc(sizeof(usb_standard_device_descriptor_t));
     196                descriptor->configuration_count = 1;
     197                descriptor->descriptor_type = USB_DESCTYPE_DEVICE;
     198                descriptor->device_class = USB_CLASS_HUB;
     199                descriptor->device_protocol = 0;
     200                descriptor->device_subclass = 0;
     201                descriptor->device_version = 0;
     202                descriptor->length = sizeof(usb_standard_device_descriptor_t);
     203                /// \TODO this value is guessed
     204                descriptor->max_packet_size = 8;
     205                descriptor->product_id = 0x0001;
     206                /// \TODO these values migt be different
     207                descriptor->str_serial_number = 0;
     208                descriptor->str_serial_number = 0;
     209                descriptor->usb_spec_version = 0;
     210                descriptor->vendor_id = 0x16db;
     211                result_descriptor = descriptor;
     212                size = sizeof(usb_standard_device_descriptor_t);
     213        }else if(setup_request_value == USB_DESCTYPE_CONFIGURATION){
     214                usb_log_debug("USB_DESCTYPE_CONFIGURATION\n");
     215                usb_standard_configuration_descriptor_t * descriptor =
     216                                (usb_standard_configuration_descriptor_t*)
     217                                malloc(sizeof(usb_standard_configuration_descriptor_t));
     218                /// \TODO some values are default or guessed
     219                descriptor->attributes = 1<<7;
     220                descriptor->configuration_number = 1;
     221                descriptor->descriptor_type = USB_DESCTYPE_CONFIGURATION;
     222                descriptor->interface_count = 1;
     223                descriptor->length = sizeof(usb_standard_configuration_descriptor_t);
     224                descriptor->max_power = 100;
     225                descriptor->str_configuration = 0;
     226                /// \TODO should this include device descriptor?
     227                size_t hub_descriptor_size = 7 +
     228                                2* (instance->port_count / 8 +
     229                                ((instance->port_count % 8 > 0) ? 1 : 0));
     230                descriptor->total_length =
     231                                sizeof(usb_standard_configuration_descriptor_t)+
     232                                sizeof(usb_standard_endpoint_descriptor_t)+
     233                                sizeof(usb_standard_interface_descriptor_t)+
     234                                hub_descriptor_size;
     235                result_descriptor = descriptor;
     236                size = sizeof(usb_standard_configuration_descriptor_t);
     237
     238        }else if(setup_request_value == USB_DESCTYPE_INTERFACE){
     239                usb_log_debug("USB_DESCTYPE_INTERFACE\n");
     240                usb_standard_interface_descriptor_t * descriptor =
     241                                (usb_standard_interface_descriptor_t*)
     242                                malloc(sizeof(usb_standard_interface_descriptor_t));
     243                descriptor->alternate_setting = 0;
     244                descriptor->descriptor_type = USB_DESCTYPE_INTERFACE;
     245                descriptor->endpoint_count = 1;
     246                descriptor->interface_class = USB_CLASS_HUB;
     247                /// \TODO is this correct?
     248                descriptor->interface_number = 1;
     249                descriptor->interface_protocol = 0;
     250                descriptor->interface_subclass = 0;
     251                descriptor->length = sizeof(usb_standard_interface_descriptor_t);
     252                descriptor->str_interface = 0;
     253                result_descriptor = descriptor;
     254                size = sizeof(usb_standard_interface_descriptor_t);
     255        }else if(setup_request_value == USB_DESCTYPE_ENDPOINT){
     256                usb_log_debug("USB_DESCTYPE_ENDPOINT\n");
     257                usb_standard_endpoint_descriptor_t * descriptor =
     258                                (usb_standard_endpoint_descriptor_t*)
     259                                malloc(sizeof(usb_standard_endpoint_descriptor_t));
     260                descriptor->attributes = USB_TRANSFER_INTERRUPT;
     261                descriptor->descriptor_type = USB_DESCTYPE_ENDPOINT;
     262                descriptor->endpoint_address = 1 + (1<<7);
     263                descriptor->length = sizeof(usb_standard_endpoint_descriptor_t);
     264                descriptor->max_packet_size = 8;
     265                descriptor->poll_interval = 255;
     266                result_descriptor = descriptor;
     267                size = sizeof(usb_standard_endpoint_descriptor_t);
     268        }else{
     269                usb_log_debug("USB_DESCTYPE_EINVAL %d \n",setup_request->value);
     270                usb_log_debug("\ttype %d\n\trequest %d\n\tvalue %d\n\tindex %d\n\tlen %d\n ",
     271                                setup_request->request_type,
     272                                setup_request->request,
     273                                setup_request_value,
     274                                setup_request->index,
     275                                setup_request->length
     276                                );
     277                return EINVAL;
     278        }
     279        if(request->buffer_size < size){
     280                size = request->buffer_size;
     281        }
     282        request->transfered_size = size;
     283        memcpy(request->buffer,result_descriptor,size);
     284        free(result_descriptor);
     285        return EOK;
     286}
     287
     288static int process_get_configuration_request(rh_t *instance,
     289                usb_transfer_batch_t *request){
     290        //set and get configuration requests do not have any meaning, only dummy
     291        //values are returned
     292        if(request->buffer_size != 1)
     293                return EINVAL;
     294        request->buffer[0] = 1;
     295        request->transfered_size = 1;
     296        return EOK;
     297}
     298
     299static int process_hub_feature_set_request(rh_t *instance,
     300                uint16_t feature, bool enable){
     301        if(feature > USB_HUB_FEATURE_C_HUB_OVER_CURRENT)
     302                return EINVAL;
     303        instance->registers->rh_status =
     304                        enable ?
     305                        (instance->registers->rh_status | (1<<feature))
     306                        :
     307                        (instance->registers->rh_status & (~(1<<feature)));
     308        /// \TODO any error?
     309        return EOK;
     310}
     311
     312static int process_port_feature_set_request(rh_t *instance,
     313                uint16_t feature, uint16_t port, bool enable){
     314        if(feature > USB_HUB_FEATURE_C_PORT_RESET)
     315                return EINVAL;
     316        if(port<1 || port>instance->port_count)
     317                return EINVAL;
     318        instance->registers->rh_port_status[port - 1] =
     319                        enable ?
     320                        (instance->registers->rh_port_status[port - 1] | (1<<feature))
     321                        :
     322                        (instance->registers->rh_port_status[port - 1] & (~(1<<feature)));
     323        /// \TODO any error?
     324        return EOK;
     325}
     326
     327static int process_address_set_request(rh_t *instance,
     328                uint16_t address){
     329        instance->address = address;
     330        return EOK;
     331}
     332
     333static int process_request_with_output(rh_t *instance,
     334                usb_transfer_batch_t *request){
     335        usb_device_request_setup_packet_t * setup_request =
     336                        (usb_device_request_setup_packet_t*)request->setup_buffer;
     337        if(setup_request->request == USB_DEVREQ_GET_STATUS){
     338                usb_log_debug("USB_DEVREQ_GET_STATUS\n");
     339                return process_get_status_request(instance, request);
     340        }
     341        if(setup_request->request == USB_DEVREQ_GET_DESCRIPTOR){
     342                usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n");
     343                return process_get_descriptor_request(instance, request);
     344        }
     345        if(setup_request->request == USB_DEVREQ_GET_CONFIGURATION){
     346                usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n");
     347                return process_get_configuration_request(instance, request);
     348        }
     349        return ENOTSUP;
     350}
     351
     352static int process_request_with_input(rh_t *instance,
     353                usb_transfer_batch_t *request){
     354        usb_device_request_setup_packet_t * setup_request =
     355                        (usb_device_request_setup_packet_t*)request->setup_buffer;
     356        request->transfered_size = 0;
     357        if(setup_request->request == USB_DEVREQ_SET_DESCRIPTOR){
     358                return ENOTSUP;
     359        }
     360        if(setup_request->request == USB_DEVREQ_SET_CONFIGURATION){
     361                //set and get configuration requests do not have any meaning,
     362                //only dummy values are returned
     363                return EOK;
     364        }
     365        return ENOTSUP;
     366}
     367
     368
     369static int process_request_without_data(rh_t *instance,
     370                usb_transfer_batch_t *request){
     371        usb_device_request_setup_packet_t * setup_request =
     372                        (usb_device_request_setup_packet_t*)request->setup_buffer;
     373        request->transfered_size = 0;
     374        if(setup_request->request == USB_DEVREQ_CLEAR_FEATURE
     375                                || setup_request->request == USB_DEVREQ_SET_FEATURE){
     376                if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE){
     377                        usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
     378                        return process_hub_feature_set_request(instance, setup_request->value,
     379                                        setup_request->request == USB_DEVREQ_SET_FEATURE);
     380                }
     381                if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE){
     382                        usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
     383                        return process_port_feature_set_request(instance, setup_request->value,
     384                                        setup_request->index,
     385                                        setup_request->request == USB_DEVREQ_SET_FEATURE);
     386                }
     387                usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",setup_request->request_type);
     388                return EINVAL;
     389        }
     390        if(setup_request->request == USB_DEVREQ_SET_ADDRESS){
     391                usb_log_debug("USB_DEVREQ_SET_ADDRESS\n");
     392                return process_address_set_request(instance, setup_request->value);
     393        }
     394        usb_log_debug("USB_DEVREQ_SET_ENOTSUP %d\n",setup_request->request_type);
     395        return ENOTSUP;
     396}
     397
     398
     399/**
     400 *
     401 * @param instance
     402 * @param request
     403 * @return
     404 */
    58405int rh_request(rh_t *instance, usb_transfer_batch_t *request)
    59406{
    60407        assert(instance);
    61408        assert(request);
    62         /* TODO: implement */
    63         if (request->setup_buffer) {
    64                 usb_log_info("Root hub got SETUP packet: %s.\n",
    65                     usb_debug_str_buffer((const uint8_t *)request->setup_buffer, 8, 8));
    66         }
    67         usb_log_error("Root hub request processing not implemented.\n");
    68         usb_transfer_batch_finish(request, ENOTSUP);
     409        int opResult;
     410        if(request->transfer_type == USB_TRANSFER_CONTROL){
     411                if (request->setup_buffer) {
     412                        usb_log_info("Root hub got CTRL packet: %s.\n",
     413                                usb_debug_str_buffer((const uint8_t *)request->setup_buffer, 8, 8));
     414                        if(sizeof(usb_device_request_setup_packet_t)>request->setup_size){
     415                                usb_log_error("setup packet too small\n");
     416                                return EINVAL;
     417                        }
     418                        usb_device_request_setup_packet_t * setup_request =
     419                                        (usb_device_request_setup_packet_t*)request->setup_buffer;
     420                        if(
     421                                setup_request->request == USB_DEVREQ_GET_STATUS
     422                                || setup_request->request == USB_DEVREQ_GET_DESCRIPTOR
     423                                || setup_request->request == USB_DEVREQ_GET_CONFIGURATION
     424                        ){
     425                                usb_log_debug("processing request with output\n");
     426                                opResult = process_request_with_output(instance,request);
     427                        }else if(
     428                                setup_request->request == USB_DEVREQ_CLEAR_FEATURE
     429                                || setup_request->request == USB_DEVREQ_SET_FEATURE
     430                                || setup_request->request == USB_DEVREQ_SET_ADDRESS
     431                        ){
     432                                usb_log_debug("processing request without additional data\n");
     433                                opResult = process_request_without_data(instance,request);
     434                        }else if(setup_request->request == USB_DEVREQ_SET_DESCRIPTOR
     435                                        || setup_request->request == USB_DEVREQ_SET_CONFIGURATION
     436                        ){
     437                                usb_log_debug("processing request with input\n");
     438                                opResult = process_request_with_input(instance,request);
     439                        }else{
     440                                usb_log_warning("received unsuported request: %d\n",
     441                                                setup_request->request
     442                                                );
     443                                opResult = ENOTSUP;
     444                        }
     445                }else{
     446                        usb_log_error("root hub received empty transaction?");
     447                        opResult = EINVAL;
     448                }
     449        }else if(request->transfer_type == USB_TRANSFER_INTERRUPT){
     450                usb_log_info("Root hub got INTERRUPT packet\n");
     451                void * buffer;
     452                create_interrupt_mask(instance, &buffer,
     453                        &(request->transfered_size));
     454                memcpy(request->transport_buffer,buffer, request->transfered_size);
     455                opResult = EOK;
     456        }else{
     457                opResult = EINVAL;
     458        }
     459        usb_transfer_batch_finish(request, opResult);
    69460        return EOK;
    70461}
    71462/*----------------------------------------------------------------------------*/
     463
     464
    72465void rh_interrupt(rh_t *instance)
    73466{
Note: See TracChangeset for help on using the changeset viewer.