Ignore:
File:
1 edited

Legend:

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

    r1387692 rb3f655f  
    3939
    4040#include "root_hub.h"
     41#include "usb/classes/classes.h"
     42#include <usb/request.h>
     43#include <usb/classes/hub.h>
     44
     45static const usb_standard_device_descriptor_t ohci_rh_device_descriptor =
     46{
     47                .configuration_count = 1,
     48                .descriptor_type = USB_DESCTYPE_DEVICE,
     49                .device_class = USB_CLASS_HUB,
     50                .device_protocol = 0,
     51                .device_subclass = 0,
     52                .device_version = 0,
     53                .length = sizeof(usb_standard_device_descriptor_t),
     54                /// \TODO this value is guessed
     55                .max_packet_size = 8,
     56                .vendor_id = 0x16db,
     57                .product_id = 0x0001,
     58                /// \TODO these values migt be different
     59                .str_serial_number = 0,
     60                .usb_spec_version = 0,
     61};
     62
     63static const usb_standard_configuration_descriptor_t ohci_rh_conf_descriptor =
     64{
     65        /// \TODO some values are default or guessed
     66        .attributes = 1<<7,
     67        .configuration_number = 1,
     68        .descriptor_type = USB_DESCTYPE_CONFIGURATION,
     69        .interface_count = 1,
     70        .length = sizeof(usb_standard_configuration_descriptor_t),
     71        .max_power = 100,
     72        .str_configuration = 0,
     73};
     74
     75static const usb_standard_interface_descriptor_t ohci_rh_iface_descriptor =
     76{
     77        .alternate_setting = 0,
     78        .descriptor_type = USB_DESCTYPE_INTERFACE,
     79        .endpoint_count = 1,
     80        .interface_class = USB_CLASS_HUB,
     81        /// \TODO is this correct?
     82        .interface_number = 1,
     83        .interface_protocol = 0,
     84        .interface_subclass = 0,
     85        .length = sizeof(usb_standard_interface_descriptor_t),
     86        .str_interface = 0,
     87};
     88
     89static const usb_standard_endpoint_descriptor_t ohci_rh_ep_descriptor =
     90{
     91        .attributes = USB_TRANSFER_INTERRUPT,
     92        .descriptor_type = USB_DESCTYPE_ENDPOINT,
     93        .endpoint_address = 1 + (1<<7),
     94        .length = sizeof(usb_standard_endpoint_descriptor_t),
     95        .max_packet_size = 8,
     96        .poll_interval = 255,
     97};
    4198
    4299/** Root hub initialization
     
    50107        instance->device = dev;
    51108
     109
    52110        usb_log_info("OHCI root hub with %d ports.\n", regs->rh_desc_a & 0xff);
    53111
     112        //start generic usb hub driver
     113       
    54114        /* TODO: implement */
    55115        return EOK;
    56116}
    57117/*----------------------------------------------------------------------------*/
     118
     119
     120static int process_get_port_status_request(rh_t *instance, uint16_t port,
     121                usb_transfer_batch_t * request){
     122        if(port<1 || port>instance->port_count)
     123                return EINVAL;
     124        uint32_t * uint32_buffer = (uint32_t*)request->buffer;
     125        request->transfered_size = 4;
     126        uint32_buffer[0] = instance->registers->rh_port_status[port -1];
     127        return EOK;
     128}
     129
     130static int process_get_hub_status_request(rh_t *instance,
     131                usb_transfer_batch_t * request){
     132        uint32_t * uint32_buffer = (uint32_t*)request->buffer;
     133        //bits, 0,1,16,17
     134        request->transfered_size = 4;
     135        uint32_t mask = 1 & (1<<1) & (1<<16) & (1<<17);
     136        uint32_buffer[0] = mask & instance->registers->rh_status;
     137        return EOK;
     138
     139}
     140
     141static void usb_create_serialized_hub_descriptor(rh_t *instance, uint8_t ** out_result,
     142                size_t * out_size) {
     143        //base size
     144        size_t size = 7;
     145        //variable size according to port count
     146        size_t var_size = instance->port_count / 8 +
     147                        ((instance->port_count % 8 > 0) ? 1 : 0);
     148        size += 2 * var_size;
     149        uint8_t * result = (uint8_t*) malloc(size);
     150        bzero(result,size);
     151        //size
     152        result[0] = size;
     153        //descriptor type
     154        result[1] = USB_DESCTYPE_HUB;
     155        result[2] = instance->port_count;
     156        uint32_t hub_desc_reg = instance->registers->rh_desc_a;
     157        result[3] =
     158                        ((hub_desc_reg >> 8) %2) +
     159                        (((hub_desc_reg >> 9) %2) << 1) +
     160                        (((hub_desc_reg >> 10) %2) << 2) +
     161                        (((hub_desc_reg >> 11) %2) << 3) +
     162                        (((hub_desc_reg >> 12) %2) << 4);
     163        result[4] = 0;
     164        result[5] = /*descriptor->pwr_on_2_good_time*/ 50;
     165        result[6] = 50;
     166
     167        int port;
     168        for (port = 1; port <= instance->port_count; ++port) {
     169                result[7 + port/8] +=
     170                                ((instance->registers->rh_desc_b >> port)%2) << (port%8);
     171        }
     172        size_t i;
     173        for (i = 0; i < var_size; ++i) {
     174                result[7 + var_size + i] = 255;
     175        }
     176        (*out_result) = result;
     177        (*out_size) = size;
     178}
     179
     180
     181static int process_get_status_request(rh_t *instance,
     182                usb_transfer_batch_t * request)
     183{
     184        size_t buffer_size = request->buffer_size;
     185        usb_device_request_setup_packet_t * request_packet =
     186                        (usb_device_request_setup_packet_t*)
     187                        request->setup_buffer;
     188
     189        usb_hub_bm_request_type_t request_type = request_packet->request_type;
     190        if(buffer_size<4/*request_packet->length*/){///\TODO
     191                usb_log_warning("requested more data than buffer size\n");
     192                return EINVAL;
     193        }
     194
     195        if(request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS)
     196                return process_get_hub_status_request(instance, request);
     197        if(request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS)
     198                return process_get_port_status_request(instance, request_packet->index,
     199                                request);
     200        return ENOTSUP;
     201}
     202
     203static void create_interrupt_mask(rh_t *instance, void ** buffer,
     204                size_t * buffer_size){
     205        int bit_count = instance->port_count + 1;
     206        (*buffer_size) = (bit_count / 8) + (bit_count%8==0)?0:1;
     207        (*buffer) = malloc(*buffer_size);
     208        uint8_t * bitmap = (uint8_t*)(*buffer);
     209        uint32_t mask = (1<<16) + (1<<17);
     210        bzero(bitmap,(*buffer_size));
     211        if(instance->registers->rh_status & mask){
     212                bitmap[0] = 1;
     213        }
     214        int port;
     215        mask = 0;
     216        int i;
     217        for(i=16;i<=20;++i)
     218                mask += 1<<i;
     219        for(port = 1; port<=instance->port_count;++port){
     220                if(mask & instance->registers->rh_port_status[port-1]){
     221                        bitmap[(port+1)/8] += 1<<(port%8);
     222                }
     223        }
     224}
     225
     226
     227static int process_get_descriptor_request(rh_t *instance,
     228                usb_transfer_batch_t *request){
     229        /// \TODO
     230        usb_device_request_setup_packet_t * setup_request =
     231                        (usb_device_request_setup_packet_t*)request->setup_buffer;
     232        size_t size;
     233        const void * result_descriptor;
     234        const uint16_t setup_request_value = setup_request->value_high;
     235                        //(setup_request->value_low << 8);
     236        bool del = false;
     237
     238        switch (setup_request_value)
     239        {
     240        case USB_DESCTYPE_HUB: {
     241                uint8_t * descriptor;
     242                usb_create_serialized_hub_descriptor(
     243                    instance, &descriptor, &size);
     244                result_descriptor = descriptor;
     245                break;
     246        }
     247        case USB_DESCTYPE_DEVICE: {
     248                usb_log_debug("USB_DESCTYPE_DEVICE\n");
     249                result_descriptor = &ohci_rh_device_descriptor;
     250                size = sizeof(ohci_rh_device_descriptor);
     251                break;
     252        }
     253        case USB_DESCTYPE_CONFIGURATION: {
     254                usb_log_debug("USB_DESCTYPE_CONFIGURATION\n");
     255                usb_standard_configuration_descriptor_t * descriptor =
     256                                malloc(sizeof(usb_standard_configuration_descriptor_t));
     257                memcpy(descriptor, &ohci_rh_conf_descriptor,
     258                    sizeof(usb_standard_configuration_descriptor_t));
     259                /// \TODO should this include device descriptor?
     260                const size_t hub_descriptor_size = 7 +
     261                                2* (instance->port_count / 8 +
     262                                ((instance->port_count % 8 > 0) ? 1 : 0));
     263                descriptor->total_length =
     264                                sizeof(usb_standard_configuration_descriptor_t)+
     265                                sizeof(usb_standard_endpoint_descriptor_t)+
     266                                sizeof(usb_standard_interface_descriptor_t)+
     267                                hub_descriptor_size;
     268                result_descriptor = descriptor;
     269                size = sizeof(usb_standard_configuration_descriptor_t);
     270                del = true;
     271                break;
     272        }
     273        case USB_DESCTYPE_INTERFACE: {
     274                usb_log_debug("USB_DESCTYPE_INTERFACE\n");
     275                result_descriptor = &ohci_rh_iface_descriptor;
     276                size = sizeof(ohci_rh_iface_descriptor);
     277                break;
     278        }
     279        case USB_DESCTYPE_ENDPOINT: {
     280                usb_log_debug("USB_DESCTYPE_ENDPOINT\n");
     281                result_descriptor = &ohci_rh_ep_descriptor;
     282                size = sizeof(ohci_rh_ep_descriptor);
     283                break;
     284        }
     285        default: {
     286                usb_log_debug("USB_DESCTYPE_EINVAL %d \n",setup_request->value);
     287                usb_log_debug("\ttype %d\n\trequest %d\n\tvalue %d\n\tindex %d\n\tlen %d\n ",
     288                                setup_request->request_type,
     289                                setup_request->request,
     290                                setup_request_value,
     291                                setup_request->index,
     292                                setup_request->length
     293                                );
     294                return EINVAL;
     295        }
     296        }
     297#if 0
     298        if(setup_request_value == USB_DESCTYPE_HUB){
     299                usb_log_debug("USB_DESCTYPE_HUB\n");
     300                //create hub descriptor
     301                uint8_t * descriptor;
     302                usb_create_serialized_hub_descriptor(instance,
     303                                &descriptor, &size);
     304                result_descriptor = descriptor;
     305        }else if(setup_request_value == USB_DESCTYPE_DEVICE){
     306                //create std device descriptor
     307                usb_log_debug("USB_DESCTYPE_DEVICE\n");
     308                usb_standard_device_descriptor_t * descriptor =
     309                                (usb_standard_device_descriptor_t*)
     310                                malloc(sizeof(usb_standard_device_descriptor_t));
     311                descriptor->configuration_count = 1;
     312                descriptor->descriptor_type = USB_DESCTYPE_DEVICE;
     313                descriptor->device_class = USB_CLASS_HUB;
     314                descriptor->device_protocol = 0;
     315                descriptor->device_subclass = 0;
     316                descriptor->device_version = 0;
     317                descriptor->length = sizeof(usb_standard_device_descriptor_t);
     318                /// \TODO this value is guessed
     319                descriptor->max_packet_size = 8;
     320                descriptor->product_id = 0x0001;
     321                /// \TODO these values migt be different
     322                descriptor->str_serial_number = 0;
     323                descriptor->str_serial_number = 0;
     324                descriptor->usb_spec_version = 0;
     325                descriptor->vendor_id = 0x16db;
     326                result_descriptor = descriptor;
     327                size = sizeof(usb_standard_device_descriptor_t);
     328        }else if(setup_request_value == USB_DESCTYPE_CONFIGURATION){
     329                usb_log_debug("USB_DESCTYPE_CONFIGURATION\n");
     330                usb_standard_configuration_descriptor_t * descriptor =
     331                                (usb_standard_configuration_descriptor_t*)
     332                                malloc(sizeof(usb_standard_configuration_descriptor_t));
     333                /// \TODO some values are default or guessed
     334                descriptor->attributes = 1<<7;
     335                descriptor->configuration_number = 1;
     336                descriptor->descriptor_type = USB_DESCTYPE_CONFIGURATION;
     337                descriptor->interface_count = 1;
     338                descriptor->length = sizeof(usb_standard_configuration_descriptor_t);
     339                descriptor->max_power = 100;
     340                descriptor->str_configuration = 0;
     341                /// \TODO should this include device descriptor?
     342                size_t hub_descriptor_size = 7 +
     343                                2* (instance->port_count / 8 +
     344                                ((instance->port_count % 8 > 0) ? 1 : 0));
     345                descriptor->total_length =
     346                                sizeof(usb_standard_configuration_descriptor_t)+
     347                                sizeof(usb_standard_endpoint_descriptor_t)+
     348                                sizeof(usb_standard_interface_descriptor_t)+
     349                                hub_descriptor_size;
     350                result_descriptor = descriptor;
     351                size = sizeof(usb_standard_configuration_descriptor_t);
     352
     353        }else if(setup_request_value == USB_DESCTYPE_INTERFACE){
     354                usb_log_debug("USB_DESCTYPE_INTERFACE\n");
     355                usb_standard_interface_descriptor_t * descriptor =
     356                                (usb_standard_interface_descriptor_t*)
     357                                malloc(sizeof(usb_standard_interface_descriptor_t));
     358                descriptor->alternate_setting = 0;
     359                descriptor->descriptor_type = USB_DESCTYPE_INTERFACE;
     360                descriptor->endpoint_count = 1;
     361                descriptor->interface_class = USB_CLASS_HUB;
     362                /// \TODO is this correct?
     363                descriptor->interface_number = 1;
     364                descriptor->interface_protocol = 0;
     365                descriptor->interface_subclass = 0;
     366                descriptor->length = sizeof(usb_standard_interface_descriptor_t);
     367                descriptor->str_interface = 0;
     368                result_descriptor = descriptor;
     369                size = sizeof(usb_standard_interface_descriptor_t);
     370        }else if(setup_request_value == USB_DESCTYPE_ENDPOINT){
     371                usb_log_debug("USB_DESCTYPE_ENDPOINT\n");
     372                usb_standard_endpoint_descriptor_t * descriptor =
     373                                (usb_standard_endpoint_descriptor_t*)
     374                                malloc(sizeof(usb_standard_endpoint_descriptor_t));
     375                descriptor->attributes = USB_TRANSFER_INTERRUPT;
     376                descriptor->descriptor_type = USB_DESCTYPE_ENDPOINT;
     377                descriptor->endpoint_address = 1 + (1<<7);
     378                descriptor->length = sizeof(usb_standard_endpoint_descriptor_t);
     379                descriptor->max_packet_size = 8;
     380                descriptor->poll_interval = 255;
     381                result_descriptor = descriptor;
     382                size = sizeof(usb_standard_endpoint_descriptor_t);
     383        }else{
     384                usb_log_debug("USB_DESCTYPE_EINVAL %d \n",setup_request->value);
     385                usb_log_debug("\ttype %d\n\trequest %d\n\tvalue %d\n\tindex %d\n\tlen %d\n ",
     386                                setup_request->request_type,
     387                                setup_request->request,
     388                                setup_request_value,
     389                                setup_request->index,
     390                                setup_request->length
     391                                );
     392                return EINVAL;
     393        }
     394#endif
     395        if(request->buffer_size < size){
     396                size = request->buffer_size;
     397        }
     398        request->transfered_size = size;
     399        memcpy(request->buffer,result_descriptor,size);
     400        if (del)
     401                free(result_descriptor);
     402        return EOK;
     403}
     404
     405static int process_get_configuration_request(rh_t *instance,
     406                usb_transfer_batch_t *request){
     407        //set and get configuration requests do not have any meaning, only dummy
     408        //values are returned
     409        if(request->buffer_size != 1)
     410                return EINVAL;
     411        request->buffer[0] = 1;
     412        request->transfered_size = 1;
     413        return EOK;
     414}
     415
     416static int process_hub_feature_set_request(rh_t *instance,
     417                uint16_t feature, bool enable){
     418        if(feature > USB_HUB_FEATURE_C_HUB_OVER_CURRENT)
     419                return EINVAL;
     420        instance->registers->rh_status =
     421                        enable ?
     422                        (instance->registers->rh_status | (1<<feature))
     423                        :
     424                        (instance->registers->rh_status & (~(1<<feature)));
     425        /// \TODO any error?
     426        return EOK;
     427}
     428
     429static int process_port_feature_set_request(rh_t *instance,
     430                uint16_t feature, uint16_t port, bool enable){
     431        if(feature > USB_HUB_FEATURE_C_PORT_RESET)
     432                return EINVAL;
     433        if(port<1 || port>instance->port_count)
     434                return EINVAL;
     435        instance->registers->rh_port_status[port - 1] =
     436                        enable ?
     437                        (instance->registers->rh_port_status[port - 1] | (1<<feature))
     438                        :
     439                        (instance->registers->rh_port_status[port - 1] & (~(1<<feature)));
     440        /// \TODO any error?
     441        return EOK;
     442}
     443
     444static int process_address_set_request(rh_t *instance,
     445                uint16_t address){
     446        instance->address = address;
     447        return EOK;
     448}
     449
     450static int process_request_with_output(rh_t *instance,
     451                usb_transfer_batch_t *request){
     452        usb_device_request_setup_packet_t * setup_request =
     453                        (usb_device_request_setup_packet_t*)request->setup_buffer;
     454        if(setup_request->request == USB_DEVREQ_GET_STATUS){
     455                usb_log_debug("USB_DEVREQ_GET_STATUS\n");
     456                return process_get_status_request(instance, request);
     457        }
     458        if(setup_request->request == USB_DEVREQ_GET_DESCRIPTOR){
     459                usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n");
     460                return process_get_descriptor_request(instance, request);
     461        }
     462        if(setup_request->request == USB_DEVREQ_GET_CONFIGURATION){
     463                usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n");
     464                return process_get_configuration_request(instance, request);
     465        }
     466        return ENOTSUP;
     467}
     468
     469static int process_request_with_input(rh_t *instance,
     470                usb_transfer_batch_t *request){
     471        usb_device_request_setup_packet_t * setup_request =
     472                        (usb_device_request_setup_packet_t*)request->setup_buffer;
     473        request->transfered_size = 0;
     474        if(setup_request->request == USB_DEVREQ_SET_DESCRIPTOR){
     475                return ENOTSUP;
     476        }
     477        if(setup_request->request == USB_DEVREQ_SET_CONFIGURATION){
     478                //set and get configuration requests do not have any meaning,
     479                //only dummy values are returned
     480                return EOK;
     481        }
     482        return ENOTSUP;
     483}
     484
     485
     486static int process_request_without_data(rh_t *instance,
     487                usb_transfer_batch_t *request){
     488        usb_device_request_setup_packet_t * setup_request =
     489                        (usb_device_request_setup_packet_t*)request->setup_buffer;
     490        request->transfered_size = 0;
     491        if(setup_request->request == USB_DEVREQ_CLEAR_FEATURE
     492                                || setup_request->request == USB_DEVREQ_SET_FEATURE){
     493                if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE){
     494                        usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
     495                        return process_hub_feature_set_request(instance, setup_request->value,
     496                                        setup_request->request == USB_DEVREQ_SET_FEATURE);
     497                }
     498                if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE){
     499                        usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
     500                        return process_port_feature_set_request(instance, setup_request->value,
     501                                        setup_request->index,
     502                                        setup_request->request == USB_DEVREQ_SET_FEATURE);
     503                }
     504                usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",setup_request->request_type);
     505                return EINVAL;
     506        }
     507        if(setup_request->request == USB_DEVREQ_SET_ADDRESS){
     508                usb_log_debug("USB_DEVREQ_SET_ADDRESS\n");
     509                return process_address_set_request(instance, setup_request->value);
     510        }
     511        usb_log_debug("USB_DEVREQ_SET_ENOTSUP %d\n",setup_request->request_type);
     512        return ENOTSUP;
     513}
     514
     515
     516/**
     517 *
     518 * @param instance
     519 * @param request
     520 * @return
     521 */
    58522int rh_request(rh_t *instance, usb_transfer_batch_t *request)
    59523{
    60524        assert(instance);
    61525        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);
     526        int opResult;
     527        if(request->transfer_type == USB_TRANSFER_CONTROL){
     528                if (request->setup_buffer) {
     529                        usb_log_info("Root hub got CTRL packet: %s.\n",
     530                                usb_debug_str_buffer((const uint8_t *)request->setup_buffer, 8, 8));
     531                        if(sizeof(usb_device_request_setup_packet_t)>request->setup_size){
     532                                usb_log_error("setup packet too small\n");
     533                                return EINVAL;
     534                        }
     535                        usb_device_request_setup_packet_t * setup_request =
     536                                        (usb_device_request_setup_packet_t*)request->setup_buffer;
     537                        if(
     538                                setup_request->request == USB_DEVREQ_GET_STATUS
     539                                || setup_request->request == USB_DEVREQ_GET_DESCRIPTOR
     540                                || setup_request->request == USB_DEVREQ_GET_CONFIGURATION
     541                        ){
     542                                usb_log_debug("processing request with output\n");
     543                                opResult = process_request_with_output(instance,request);
     544                        }else if(
     545                                setup_request->request == USB_DEVREQ_CLEAR_FEATURE
     546                                || setup_request->request == USB_DEVREQ_SET_FEATURE
     547                                || setup_request->request == USB_DEVREQ_SET_ADDRESS
     548                        ){
     549                                usb_log_debug("processing request without additional data\n");
     550                                opResult = process_request_without_data(instance,request);
     551                        }else if(setup_request->request == USB_DEVREQ_SET_DESCRIPTOR
     552                                        || setup_request->request == USB_DEVREQ_SET_CONFIGURATION
     553                        ){
     554                                usb_log_debug("processing request with input\n");
     555                                opResult = process_request_with_input(instance,request);
     556                        }else{
     557                                usb_log_warning("received unsuported request: %d\n",
     558                                                setup_request->request
     559                                                );
     560                                opResult = ENOTSUP;
     561                        }
     562                }else{
     563                        usb_log_error("root hub received empty transaction?");
     564                        opResult = EINVAL;
     565                }
     566        }else if(request->transfer_type == USB_TRANSFER_INTERRUPT){
     567                usb_log_info("Root hub got INTERRUPT packet\n");
     568                void * buffer;
     569                create_interrupt_mask(instance, &buffer,
     570                        &(request->transfered_size));
     571                memcpy(request->transport_buffer,buffer, request->transfered_size);
     572                opResult = EOK;
     573        }else{
     574                opResult = EINVAL;
     575        }
     576        usb_transfer_batch_finish(request, opResult);
    69577        return EOK;
    70578}
    71579/*----------------------------------------------------------------------------*/
     580
     581
    72582void rh_interrupt(rh_t *instance)
    73583{
Note: See TracChangeset for help on using the changeset viewer.