Changeset 4069f5c in mainline for uspace/drv/bus/usb/ohci/root_hub.c


Ignore:
Timestamp:
2011-07-17T09:52:42Z (13 years ago)
Author:
Petr Koupy <petr.koupy@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
64639256, ca1f1ec
Parents:
27eddb52 (diff), 4118f5f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

File:
1 edited

Legend:

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

    r27eddb52 r4069f5c  
    4040#include "root_hub.h"
    4141#include <usb/classes/classes.h>
     42#include <usb/classes/hub.h>
    4243#include <usb/dev/driver.h>
    4344#include "ohci_regs.h"
     
    5657        .device_subclass = 0,
    5758        .device_version = 0,
    58         .length = sizeof (usb_standard_device_descriptor_t),
    59         .max_packet_size = 8,
    60         .vendor_id = 0x16db,
     59        .length = sizeof(usb_standard_device_descriptor_t),
     60        .max_packet_size = 64,
     61        .vendor_id = 0x16db, /* HelenOS does not have USB vendor ID assigned.*/
    6162        .product_id = 0x0001,
    6263        .str_serial_number = 0,
     
    7374        .descriptor_type = USB_DESCTYPE_CONFIGURATION,
    7475        .interface_count = 1,
    75         .length = sizeof (usb_standard_configuration_descriptor_t),
    76         .max_power = 100,
     76        .length = sizeof(usb_standard_configuration_descriptor_t),
     77        .max_power = 0, /* root hubs don't need no power */
    7778        .str_configuration = 0,
    7879};
     
    8990        .interface_protocol = 0,
    9091        .interface_subclass = 0,
    91         .length = sizeof (usb_standard_interface_descriptor_t),
     92        .length = sizeof(usb_standard_interface_descriptor_t),
    9293        .str_interface = 0,
    9394};
     
    100101        .descriptor_type = USB_DESCTYPE_ENDPOINT,
    101102        .endpoint_address = 1 + (1 << 7),
    102         .length = sizeof (usb_standard_endpoint_descriptor_t),
    103         .max_packet_size = 8,
     103        .length = sizeof(usb_standard_endpoint_descriptor_t),
     104        .max_packet_size = 2,
    104105        .poll_interval = 255,
    105106};
    106107
    107 /**
    108  * bitmask of hub features that are valid to be cleared
    109  */
    110 static const uint32_t hub_clear_feature_valid_mask =
    111     RHS_OCIC_FLAG |
    112     RHS_CLEAR_PORT_POWER;
    113 
    114 /**
    115  * bitmask of hub features that are cleared by writing 1 (and not 0)
    116  */
    117 static const uint32_t hub_clear_feature_by_writing_one_mask =
    118     RHS_CLEAR_PORT_POWER;
    119 
    120 /**
    121  * bitmask of hub features that are valid to be set
    122  */
    123 static const uint32_t hub_set_feature_valid_mask =
    124     RHS_LPSC_FLAG |
    125     RHS_OCIC_FLAG;
    126 
    127 /**
    128  * bitmask of hub features that are set by writing 1 and cleared by writing 0
    129  */
    130 static const uint32_t hub_set_feature_direct_mask =
    131     RHS_SET_PORT_POWER;
    132 
    133 /**
    134  * bitmask of port features that are valid to be set
    135  */
    136 static const uint32_t port_set_feature_valid_mask =
    137     RHPS_SET_PORT_ENABLE |
    138     RHPS_SET_PORT_SUSPEND |
    139     RHPS_SET_PORT_RESET |
    140     RHPS_SET_PORT_POWER;
    141 
    142 /**
    143  * bitmask of port features that can be cleared
    144  */
    145 static const uint32_t port_clear_feature_valid_mask =
    146     RHPS_CCS_FLAG |
    147     RHPS_SET_PORT_SUSPEND |
    148     RHPS_POCI_FLAG |
    149     RHPS_SET_PORT_POWER |
    150     RHPS_CSC_FLAG |
    151     RHPS_PESC_FLAG |
    152     RHPS_PSSC_FLAG |
    153     RHPS_OCIC_FLAG |
    154     RHPS_PRSC_FLAG;
    155 
    156 //note that USB_HUB_FEATURE_PORT_POWER bit is translated into
    157 //USB_HUB_FEATURE_PORT_LOW_SPEED for port set feature request
    158 
    159 /**
    160  * bitmask with port status changes
    161  */
    162 static const uint32_t port_status_change_mask = RHPS_CHANGE_WC_MASK;
    163 
    164 static int create_serialized_hub_descriptor(rh_t *instance);
    165 
    166 static int rh_init_descriptors(rh_t *instance);
    167 
    168 static int process_get_port_status_request(rh_t *instance, uint16_t port,
    169     usb_transfer_batch_t * request);
    170 
    171 static int process_get_hub_status_request(rh_t *instance,
    172     usb_transfer_batch_t * request);
    173 
    174 static int process_get_status_request(rh_t *instance,
    175     usb_transfer_batch_t * request);
    176 
    177 static void create_interrupt_mask_in_instance(rh_t *instance);
    178 
    179 static int process_get_descriptor_request(rh_t *instance,
    180     usb_transfer_batch_t *request);
    181 
    182 static int process_get_configuration_request(rh_t *instance,
    183     usb_transfer_batch_t *request);
    184 
    185 static int process_hub_feature_set_request(rh_t *instance, uint16_t feature);
    186 
    187 static int process_hub_feature_clear_request(rh_t *instance,
    188     uint16_t feature);
    189 
    190 static int process_port_feature_set_request(rh_t *instance,
    191     uint16_t feature, uint16_t port);
    192 
    193 static int process_port_feature_clear_request(rh_t *instance,
    194     uint16_t feature, uint16_t port);
    195 
    196 static int process_address_set_request(rh_t *instance,
    197     uint16_t address);
    198 
    199 static int process_request_with_output(rh_t *instance,
    200     usb_transfer_batch_t *request);
    201 
    202 static int process_request_with_input(rh_t *instance,
    203     usb_transfer_batch_t *request);
    204 
    205 static int process_request_without_data(rh_t *instance,
    206     usb_transfer_batch_t *request);
    207 
    208 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request);
    209 
    210 static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request);
    211 
    212 static bool is_zeros(void * buffer, size_t size);
    213 
    214 /** Root hub initialization
    215  * @return Error code.
    216  */
    217 int rh_init(rh_t *instance, ohci_regs_t *regs) {
    218         assert(instance);
     108static void create_serialized_hub_descriptor(rh_t *instance);
     109static void rh_init_descriptors(rh_t *instance);
     110static uint16_t create_interrupt_mask(rh_t *instance);
     111static int get_status(rh_t *instance, usb_transfer_batch_t *request);
     112static int get_descriptor(rh_t *instance, usb_transfer_batch_t *request);
     113static int set_feature(rh_t *instance, usb_transfer_batch_t *request);
     114static int clear_feature(rh_t *instance, usb_transfer_batch_t *request);
     115static int set_feature_port(rh_t *instance, uint16_t feature, uint16_t port);
     116static int clear_feature_port(rh_t *instance, uint16_t feature, uint16_t port);
     117static int control_request(rh_t *instance, usb_transfer_batch_t *request);
     118static inline void interrupt_request(
     119    usb_transfer_batch_t *request, uint16_t mask, size_t size)
     120{
     121        assert(request);
     122
     123        memcpy(request->data_buffer, &mask, size);
     124        request->transfered_size = size;
     125        usb_transfer_batch_finish_error(request, EOK);
     126}
     127
     128#define TRANSFER_OK(bytes) \
     129do { \
     130        request->transfered_size = bytes; \
     131        return EOK; \
     132} while (0)
     133
     134/** Root Hub driver structure initialization.
     135 *
     136 * Reads info registers and prepares descriptors. Sets power mode.
     137 */
     138void rh_init(rh_t *instance, ohci_regs_t *regs)
     139{
     140        assert(instance);
     141        assert(regs);
     142
    219143        instance->registers = regs;
    220144        instance->port_count =
    221145            (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
    222         int opResult = rh_init_descriptors(instance);
    223         if (opResult != EOK) {
    224                 return opResult;
    225         }
    226         // set port power mode to no-power-switching
     146        if (instance->port_count > 15) {
     147                usb_log_warning("OHCI specification does not allow more than 15"
     148                    " ports. Max 15 ports will be used");
     149                instance->port_count = 15;
     150        }
     151
     152        /* Don't forget the hub status bit and round up */
     153        instance->interrupt_mask_size = 1 + (instance->port_count / 8);
     154        instance->unfinished_interrupt_transfer = NULL;
     155
     156#ifdef OHCI_POWER_SWITCH_no
     157        /* Set port power mode to no power-switching. (always on) */
    227158        instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
    228         instance->unfinished_interrupt_transfer = NULL;
    229         instance->interrupt_mask_size = (instance->port_count + 8) / 8;
    230         instance->interrupt_buffer = malloc(instance->interrupt_mask_size);
    231         if (!instance->interrupt_buffer)
    232                 return ENOMEM;
     159        /* Set to no over-current reporting */
     160        instance->registers->rh_desc_a |= RHDA_NOCP_FLAG;
     161#elif defined OHCI_POWER_SWITCH_ganged
     162        /* Set port power mode to no ganged power-switching. */
     163        instance->registers->rh_desc_a &= ~RHDA_NPS_FLAG;
     164        instance->registers->rh_desc_a &= ~RHDA_PSM_FLAG;
     165        instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
     166        /* Set to global over-current */
     167        instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;
     168        instance->registers->rh_desc_a &= ~RHDA_OCPM_FLAG;
     169#else
     170        /* Set port power mode to no per port power-switching. */
     171        instance->registers->rh_desc_a &= ~RHDA_NPS_FLAG;
     172        instance->registers->rh_desc_a |= RHDA_PSM_FLAG;
     173
     174        /* Control all ports by global switch and turn them off */
     175        instance->registers->rh_desc_b &= (RHDB_PCC_MASK << RHDB_PCC_SHIFT);
     176        instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
     177        /* Return control to per port state */
     178        instance->registers->rh_desc_b |=
     179                ((1 << (instance->port_count + 1)) - 1) << RHDB_PCC_SHIFT;
     180        /* Set per port over-current */
     181        instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;
     182        instance->registers->rh_desc_a |= RHDA_OCPM_FLAG;
     183#endif
     184
     185        rh_init_descriptors(instance);
    233186
    234187        usb_log_info("Root hub (%zu ports) initialized.\n",
    235188            instance->port_count);
    236 
    237         return EOK;
    238 }
    239 /*----------------------------------------------------------------------------*/
    240 
    241 /**
    242  * process root hub request
    243  *
    244  * @param instance root hub instance
    245  * @param request structure containing both request and response information
    246  * @return error code
    247  */
    248 int rh_request(rh_t *instance, usb_transfer_batch_t *request) {
     189}
     190/*----------------------------------------------------------------------------*/
     191/**
     192 * Process root hub request.
     193 *
     194 * @param instance Root hub instance
     195 * @param request Structure containing both request and response information
     196 * @return Error code
     197 */
     198void rh_request(rh_t *instance, usb_transfer_batch_t *request)
     199{
    249200        assert(instance);
    250201        assert(request);
    251         int opResult;
    252         if (request->ep->transfer_type == USB_TRANSFER_CONTROL) {
     202
     203        switch (request->ep->transfer_type)
     204        {
     205        case USB_TRANSFER_CONTROL:
    253206                usb_log_debug("Root hub got CONTROL packet\n");
    254                 opResult = process_ctrl_request(instance, request);
    255                 usb_transfer_batch_finish_error(request, opResult);
    256         } else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) {
     207                const int ret = control_request(instance, request);
     208                usb_transfer_batch_finish_error(request, ret);
     209                break;
     210        case USB_TRANSFER_INTERRUPT:
    257211                usb_log_debug("Root hub got INTERRUPT packet\n");
    258                 create_interrupt_mask_in_instance(instance);
    259                 if (is_zeros(instance->interrupt_buffer,
    260                     instance->interrupt_mask_size)) {
     212                const uint16_t mask = create_interrupt_mask(instance);
     213                if (mask == 0) {
    261214                        usb_log_debug("No changes..\n");
     215                        assert(instance->unfinished_interrupt_transfer == NULL);
    262216                        instance->unfinished_interrupt_transfer = request;
    263                         //will be finished later
    264                 } else {
    265                         usb_log_debug("Processing changes..\n");
    266                         process_interrupt_mask_in_instance(instance, request);
     217                        break;
    267218                }
    268                 opResult = EOK;
    269         } else {
    270 
    271                 opResult = EINVAL;
    272                 usb_transfer_batch_finish_error(request, opResult);
    273         }
    274         return EOK;
    275 }
    276 
    277 /*----------------------------------------------------------------------------*/
    278 
    279 /**
    280  * process interrupt on a hub
     219                usb_log_debug("Processing changes...\n");
     220                interrupt_request(request, mask, instance->interrupt_mask_size);
     221                break;
     222
     223        default:
     224                usb_log_error("Root hub got unsupported request.\n");
     225                usb_transfer_batch_finish_error(request, EINVAL);
     226        }
     227}
     228/*----------------------------------------------------------------------------*/
     229/**
     230 * Process interrupt on a hub device.
    281231 *
    282232 * If there is no pending interrupt transfer, nothing happens.
    283233 * @param instance
    284234 */
    285 void rh_interrupt(rh_t *instance) {
    286         if (!instance->unfinished_interrupt_transfer) {
     235void rh_interrupt(rh_t *instance)
     236{
     237        assert(instance);
     238
     239        if (!instance->unfinished_interrupt_transfer)
    287240                return;
    288         }
     241
    289242        usb_log_debug("Finalizing interrupt transfer\n");
    290         create_interrupt_mask_in_instance(instance);
    291         process_interrupt_mask_in_instance(instance,
    292             instance->unfinished_interrupt_transfer);
    293 }
    294 /*----------------------------------------------------------------------------*/
    295 
    296 /**
    297  * Create hub descriptor used in hub-driver <-> hub communication
    298  *
    299  * This means creating byt array from data in root hub registers. For more
    300  * info see usb hub specification.
    301  *
     243        const uint16_t mask = create_interrupt_mask(instance);
     244        interrupt_request(instance->unfinished_interrupt_transfer,
     245            mask, instance->interrupt_mask_size);
     246
     247        instance->unfinished_interrupt_transfer = NULL;
     248}
     249/*----------------------------------------------------------------------------*/
     250/**
     251 * Create hub descriptor.
     252 *
     253 * For descriptor format see USB hub specification (chapter 11.15.2.1, pg. 263)
     254 *
     255 * @param instance Root hub instance
     256 * @return Error code
     257 */
     258void create_serialized_hub_descriptor(rh_t *instance)
     259{
     260        assert(instance);
     261
     262        /* 7 bytes + 2 port bit fields (port count + global bit) */
     263        const size_t size = 7 + (instance->interrupt_mask_size * 2);
     264        assert(size <= HUB_DESCRIPTOR_MAX_SIZE);
     265        instance->hub_descriptor_size = size;
     266
     267        const uint32_t hub_desc = instance->registers->rh_desc_a;
     268        const uint32_t port_desc = instance->registers->rh_desc_b;
     269
     270        /* bDescLength */
     271        instance->descriptors.hub[0] = size;
     272        /* bDescriptorType */
     273        instance->descriptors.hub[1] = USB_DESCTYPE_HUB;
     274        /* bNmbrPorts */
     275        instance->descriptors.hub[2] = instance->port_count;
     276        /* wHubCharacteristics */
     277        instance->descriptors.hub[3] = 0 |
     278            /* The lowest 2 bits indicate power switching mode */
     279            (((hub_desc & RHDA_PSM_FLAG)  ? 1 : 0) << 0) |
     280            (((hub_desc & RHDA_NPS_FLAG)  ? 1 : 0) << 1) |
     281            /* Bit 3 indicates device type (compound device) */
     282            (((hub_desc & RHDA_DT_FLAG)   ? 1 : 0) << 2) |
     283            /* Bits 4,5 indicate over-current protection mode */
     284            (((hub_desc & RHDA_OCPM_FLAG) ? 1 : 0) << 3) |
     285            (((hub_desc & RHDA_NOCP_FLAG) ? 1 : 0) << 4);
     286
     287        /* Reserved */
     288        instance->descriptors.hub[4] = 0;
     289        /* bPwrOn2PwrGood */
     290        instance->descriptors.hub[5] =
     291            (hub_desc >> RHDA_POTPGT_SHIFT) & RHDA_POTPGT_MASK;
     292        /* bHubContrCurrent, root hubs don't need no power. */
     293        instance->descriptors.hub[6] = 0;
     294
     295        /* Device Removable and some legacy 1.0 stuff*/
     296        instance->descriptors.hub[7] =
     297            (port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK & 0xff;
     298        instance->descriptors.hub[8] = 0xff;
     299        if (instance->interrupt_mask_size == 2) {
     300                instance->descriptors.hub[8] =
     301                    (port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK >> 8;
     302                instance->descriptors.hub[9]  = 0xff;
     303                instance->descriptors.hub[10] = 0xff;
     304        }
     305}
     306/*----------------------------------------------------------------------------*/
     307/** Initialize hub descriptors.
     308 *
     309 * A full configuration descriptor is assembled. The configuration and endpoint
     310 * descriptors have local modifications.
     311 * @param instance Root hub instance
     312 * @return Error code
     313 */
     314void rh_init_descriptors(rh_t *instance)
     315{
     316        assert(instance);
     317
     318        instance->descriptors.configuration = ohci_rh_conf_descriptor;
     319        instance->descriptors.interface = ohci_rh_iface_descriptor;
     320        instance->descriptors.endpoint = ohci_rh_ep_descriptor;
     321        create_serialized_hub_descriptor(instance);
     322
     323        instance->descriptors.endpoint.max_packet_size =
     324            instance->interrupt_mask_size;
     325
     326        instance->descriptors.configuration.total_length =
     327            sizeof(usb_standard_configuration_descriptor_t) +
     328            sizeof(usb_standard_endpoint_descriptor_t) +
     329            sizeof(usb_standard_interface_descriptor_t) +
     330            instance->hub_descriptor_size;
     331}
     332/*----------------------------------------------------------------------------*/
     333/**
     334 * Create bitmap of changes to answer status interrupt.
     335 *
     336 * Result contains bitmap where bit 0 indicates change on hub and
     337 * bit i indicates change on i`th port (i>0). For more info see
     338 * Hub and Port status bitmap specification in USB specification
     339 * (chapter 11.13.4).
    302340 * @param instance root hub instance
    303  * @return error code
    304  */
    305 static int create_serialized_hub_descriptor(rh_t *instance) {
    306         size_t size = 7 +
    307             ((instance->port_count + 7) / 8) * 2;
    308         size_t var_size = (instance->port_count + 7) / 8;
    309         uint8_t * result = (uint8_t*) malloc(size);
    310         if (!result) return ENOMEM;
    311 
    312         bzero(result, size);
    313         //size
    314         result[0] = size;
    315         //descriptor type
    316         result[1] = USB_DESCTYPE_HUB;
    317         result[2] = instance->port_count;
    318         uint32_t hub_desc_reg = instance->registers->rh_desc_a;
    319         result[3] =
    320             ((hub_desc_reg >> 8) % 2) +
    321             (((hub_desc_reg >> 9) % 2) << 1) +
    322             (((hub_desc_reg >> 10) % 2) << 2) +
    323             (((hub_desc_reg >> 11) % 2) << 3) +
    324             (((hub_desc_reg >> 12) % 2) << 4);
    325         result[4] = 0;
    326         result[5] = /*descriptor->pwr_on_2_good_time*/ 50;
    327         result[6] = 50;
    328 
    329         size_t port;
    330         for (port = 1; port <= instance->port_count; ++port) {
    331                 uint8_t is_non_removable =
    332                     instance->registers->rh_desc_b >> port % 2;
    333                 result[7 + port / 8] +=
    334                     is_non_removable << (port % 8);
    335         }
    336         size_t i;
    337         for (i = 0; i < var_size; ++i) {
    338                 result[7 + var_size + i] = 255;
    339         }
    340         instance->hub_descriptor = result;
    341         instance->descriptor_size = size;
    342 
    343         return EOK;
    344 }
    345 /*----------------------------------------------------------------------------*/
    346 
    347 /** initialize hub descriptors
    348  *
    349  * Initialized are device and full configuration descriptor. These need to
    350  * be initialized only once per hub.
    351  * @instance root hub instance
    352  * @return error code
    353  */
    354 static int rh_init_descriptors(rh_t *instance) {
    355         memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor,
    356             sizeof (ohci_rh_device_descriptor)
    357             );
    358         usb_standard_configuration_descriptor_t descriptor;
    359         memcpy(&descriptor, &ohci_rh_conf_descriptor,
    360             sizeof (ohci_rh_conf_descriptor));
    361 
    362         int opResult = create_serialized_hub_descriptor(instance);
    363         if (opResult != EOK) {
    364                 return opResult;
    365         }
    366         descriptor.total_length =
    367             sizeof (usb_standard_configuration_descriptor_t) +
    368             sizeof (usb_standard_endpoint_descriptor_t) +
    369             sizeof (usb_standard_interface_descriptor_t) +
    370             instance->descriptor_size;
    371 
    372         uint8_t * full_config_descriptor =
    373             (uint8_t*) malloc(descriptor.total_length);
    374         if (!full_config_descriptor) {
    375                 return ENOMEM;
    376         }
    377         memcpy(full_config_descriptor, &descriptor, sizeof (descriptor));
    378         memcpy(full_config_descriptor + sizeof (descriptor),
    379             &ohci_rh_iface_descriptor, sizeof (ohci_rh_iface_descriptor));
    380         memcpy(full_config_descriptor + sizeof (descriptor) +
    381             sizeof (ohci_rh_iface_descriptor),
    382             &ohci_rh_ep_descriptor, sizeof (ohci_rh_ep_descriptor));
    383         memcpy(full_config_descriptor + sizeof (descriptor) +
    384             sizeof (ohci_rh_iface_descriptor) +
    385             sizeof (ohci_rh_ep_descriptor),
    386             instance->hub_descriptor, instance->descriptor_size);
    387 
    388         instance->descriptors.configuration = full_config_descriptor;
    389         instance->descriptors.configuration_size = descriptor.total_length;
    390 
    391         return EOK;
    392 }
    393 /*----------------------------------------------------------------------------*/
    394 
    395 /**
    396  * create answer to port status_request
    397  *
    398  * Copy content of corresponding port status register to answer buffer. The
    399  * format of the port status register and port status data is the same (
    400  * see OHCI root hub and USB hub documentation).
    401  *
    402  * @param instance root hub instance
    403  * @param port port number, counted from 1
    404  * @param request structure containing both request and response information
    405  * @return error code
    406  */
    407 static int process_get_port_status_request(rh_t *instance, uint16_t port,
    408     usb_transfer_batch_t * request) {
    409         if (port < 1 || port > instance->port_count)
    410                 return EINVAL;
    411         request->transfered_size = 4;
    412         uint32_t data = instance->registers->rh_port_status[port - 1];
    413         memcpy(request->data_buffer, &data, 4);
    414         return EOK;
    415 }
    416 /*----------------------------------------------------------------------------*/
    417 
    418 /**
    419  * create answer to port status_request
    420  *
    421  * This copies flags in hub status register into the buffer. The format of the
    422  * status register and status message is the same, according to USB hub
    423  * specification and OHCI root hub specification.
    424  *
    425  * @param instance root hub instance
    426  * @param request structure containing both request and response information
    427  * @return error code
    428  */
    429 static int process_get_hub_status_request(rh_t *instance,
    430     usb_transfer_batch_t * request) {
    431         request->transfered_size = 4;
    432         //bits, 0,1,16,17
    433         uint32_t mask = 1 | (1 << 1) | (1 << 16) | (1 << 17);
    434         uint32_t data = mask & instance->registers->rh_status;
    435         memcpy(request->data_buffer, &data, 4);
    436 
    437         return EOK;
    438 }
    439 /*----------------------------------------------------------------------------*/
    440 
    441 /**
    442  * create answer to status request
     341 * @return Mask of changes.
     342 */
     343uint16_t create_interrupt_mask(rh_t *instance)
     344{
     345        assert(instance);
     346        uint16_t mask = 0;
     347
     348        /* Only local power source change and over-current change can happen */
     349        if (instance->registers->rh_status & (RHS_LPSC_FLAG | RHS_OCIC_FLAG)) {
     350                mask |= 1;
     351        }
     352        size_t port = 1;
     353        for (; port <= instance->port_count; ++port) {
     354                /* Write-clean bits are those that indicate change */
     355                if (RHPS_CHANGE_WC_MASK
     356                    & instance->registers->rh_port_status[port - 1]) {
     357
     358                        mask |= (1 << port);
     359                }
     360        }
     361        /* USB is little endian */
     362        return host2uint32_t_le(mask);
     363}
     364/*----------------------------------------------------------------------------*/
     365/**
     366 * Create answer to status request.
    443367 *
    444368 * This might be either hub status or port status request. If neither,
     
    448372 * @return error code
    449373 */
    450 static int process_get_status_request(rh_t *instance,
    451     usb_transfer_batch_t * request) {
    452         size_t buffer_size = request->buffer_size;
    453         usb_device_request_setup_packet_t * request_packet =
    454             (usb_device_request_setup_packet_t*)
    455             request->setup_buffer;
    456 
    457         usb_hub_bm_request_type_t request_type = request_packet->request_type;
    458         if (buffer_size < 4) {
    459                 usb_log_warning("Requested more data than buffer size\n");
    460                 return EINVAL;
    461         }
    462 
    463         if (request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS)
    464                 return process_get_hub_status_request(instance, request);
    465         if (request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS)
    466                 return process_get_port_status_request(instance,
    467             request_packet->index,
    468             request);
     374int get_status(rh_t *instance, usb_transfer_batch_t *request)
     375{
     376        assert(instance);
     377        assert(request);
     378
     379        const usb_device_request_setup_packet_t *request_packet =
     380            (usb_device_request_setup_packet_t*)request->setup_buffer;
     381
     382        if (request->buffer_size < 4) {
     383                usb_log_error("Buffer too small for get status request.\n");
     384                return EOVERFLOW;
     385        }
     386
     387        /* Hub status: just filter relevant info from rh_status reg */
     388        if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS) {
     389                const uint32_t data = instance->registers->rh_status &
     390                    (RHS_LPS_FLAG | RHS_LPSC_FLAG | RHS_OCI_FLAG | RHS_OCIC_FLAG);
     391                memcpy(request->data_buffer, &data, 4);
     392                TRANSFER_OK(4);
     393        }
     394
     395        /* Copy appropriate rh_port_status register, OHCI designers were
     396         * kind enough to make those bit values match USB specification */
     397        if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS) {
     398                const unsigned port = request_packet->index;
     399                if (port < 1 || port > instance->port_count)
     400                        return EINVAL;
     401
     402                const uint32_t data =
     403                    instance->registers->rh_port_status[port - 1];
     404                memcpy(request->data_buffer, &data, 4);
     405                TRANSFER_OK(4);
     406        }
    469407
    470408        return ENOTSUP;
    471409}
    472410/*----------------------------------------------------------------------------*/
    473 
    474 /**
    475  * create answer to status interrupt consisting of change bitmap
    476  *
    477  * Result contains bitmap where bit 0 indicates change on hub and
    478  * bit i indicates change on i`th port (i>0). For more info see
    479  * Hub and Port status bitmap specification in USB specification
    480  * (chapter 11.13.4).
    481  * Uses instance`s interrupt buffer to store the interrupt information.
    482  * @param instance root hub instance
    483  */
    484 static void create_interrupt_mask_in_instance(rh_t * instance) {
    485         uint8_t * bitmap = (uint8_t*) (instance->interrupt_buffer);
    486         uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16))
    487             | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16));
    488         bzero(bitmap, instance->interrupt_mask_size);
    489         if ((instance->registers->rh_status & mask) != 0) {
    490                 bitmap[0] = 1;
    491         }
    492         size_t port;
    493         mask = port_status_change_mask;
    494         for (port = 1; port <= instance->port_count; ++port) {
    495                 if ((mask & instance->registers->rh_port_status[port - 1]) != 0) {
    496 
    497                         bitmap[(port) / 8] += 1 << (port % 8);
    498                 }
    499         }
    500 }
    501 /*----------------------------------------------------------------------------*/
    502 
    503 /**
    504  * create answer to a descriptor request
     411/**
     412 * Create answer to a descriptor request.
    505413 *
    506414 * This might be a request for standard (configuration, device, endpoint or
    507415 * interface) or device specific (hub) descriptor.
    508  * @param instance root hub instance
    509  * @param request structure containing both request and response information
    510  * @return error code
    511  */
    512 static int process_get_descriptor_request(rh_t *instance,
    513     usb_transfer_batch_t *request) {
    514         usb_device_request_setup_packet_t * setup_request =
    515             (usb_device_request_setup_packet_t*) request->setup_buffer;
     416 * @param instance Root hub instance
     417 * @param request Structure containing both request and response information
     418 * @return Error code
     419 */
     420int get_descriptor(rh_t *instance, usb_transfer_batch_t *request)
     421{
     422        assert(instance);
     423        assert(request);
     424
     425        const usb_device_request_setup_packet_t *setup_request =
     426            (usb_device_request_setup_packet_t *) request->setup_buffer;
    516427        size_t size;
    517         const void * result_descriptor = NULL;
     428        const void *descriptor = NULL;
    518429        const uint16_t setup_request_value = setup_request->value_high;
    519430        //(setup_request->value_low << 8);
    520         switch (setup_request_value) {
    521                 case USB_DESCTYPE_HUB:
    522                 {
    523                         usb_log_debug2("USB_DESCTYPE_HUB\n");
    524                         result_descriptor = instance->hub_descriptor;
    525                         size = instance->descriptor_size;
    526                         break;
    527                 }
    528                 case USB_DESCTYPE_DEVICE:
    529                 {
    530                         usb_log_debug2("USB_DESCTYPE_DEVICE\n");
    531                         result_descriptor = &ohci_rh_device_descriptor;
    532                         size = sizeof (ohci_rh_device_descriptor);
    533                         break;
    534                 }
    535                 case USB_DESCTYPE_CONFIGURATION:
    536                 {
    537                         usb_log_debug2("USB_DESCTYPE_CONFIGURATION\n");
    538                         result_descriptor = instance->descriptors.configuration;
    539                         size = instance->descriptors.configuration_size;
    540                         break;
    541                 }
    542                 case USB_DESCTYPE_INTERFACE:
    543                 {
    544                         usb_log_debug2("USB_DESCTYPE_INTERFACE\n");
    545                         result_descriptor = &ohci_rh_iface_descriptor;
    546                         size = sizeof (ohci_rh_iface_descriptor);
    547                         break;
    548                 }
    549                 case USB_DESCTYPE_ENDPOINT:
    550                 {
    551                         usb_log_debug2("USB_DESCTYPE_ENDPOINT\n");
    552                         result_descriptor = &ohci_rh_ep_descriptor;
    553                         size = sizeof (ohci_rh_ep_descriptor);
    554                         break;
    555                 }
    556                 default:
    557                 {
    558                         usb_log_debug2("USB_DESCTYPE_EINVAL %d \n",
    559                             setup_request->value);
    560                         usb_log_debug2("\ttype %d\n\trequest %d\n\tvalue "
    561                             "%d\n\tindex %d\n\tlen %d\n ",
    562                             setup_request->request_type,
    563                             setup_request->request,
    564                             setup_request_value,
    565                             setup_request->index,
    566                             setup_request->length
    567                             );
    568                         return EINVAL;
    569                 }
     431        switch (setup_request_value)
     432        {
     433        case USB_DESCTYPE_HUB:
     434                usb_log_debug2("USB_DESCTYPE_HUB\n");
     435                /* Hub descriptor was generated locally */
     436                descriptor = instance->descriptors.hub;
     437                size = instance->hub_descriptor_size;
     438                break;
     439
     440        case USB_DESCTYPE_DEVICE:
     441                usb_log_debug2("USB_DESCTYPE_DEVICE\n");
     442                /* Device descriptor is shared (No one should ask for it)*/
     443                descriptor = &ohci_rh_device_descriptor;
     444                size = sizeof(ohci_rh_device_descriptor);
     445                break;
     446
     447        case USB_DESCTYPE_CONFIGURATION:
     448                usb_log_debug2("USB_DESCTYPE_CONFIGURATION\n");
     449                /* Start with configuration and add others depending on
     450                 * request size */
     451                descriptor = &instance->descriptors;
     452                size = instance->descriptors.configuration.total_length;
     453                break;
     454
     455        case USB_DESCTYPE_INTERFACE:
     456                usb_log_debug2("USB_DESCTYPE_INTERFACE\n");
     457                /* Use local interface descriptor. There is one and it
     458                 * might be modified */
     459                descriptor = &instance->descriptors.interface;
     460                size = sizeof(instance->descriptors.interface);
     461                break;
     462
     463        case USB_DESCTYPE_ENDPOINT:
     464                /* Use local endpoint descriptor. There is one
     465                 * it might have max_packet_size field modified*/
     466                usb_log_debug2("USB_DESCTYPE_ENDPOINT\n");
     467                descriptor = &instance->descriptors.endpoint;
     468                size = sizeof(instance->descriptors.endpoint);
     469                break;
     470
     471        default:
     472                usb_log_debug2("USB_DESCTYPE_EINVAL %d \n"
     473                    "\ttype %d\n\trequest %d\n\tvalue "
     474                    "%d\n\tindex %d\n\tlen %d\n ",
     475                    setup_request->value,
     476                    setup_request->request_type, setup_request->request,
     477                    setup_request_value, setup_request->index,
     478                    setup_request->length);
     479                return EINVAL;
    570480        }
    571481        if (request->buffer_size < size) {
    572482                size = request->buffer_size;
    573483        }
    574         request->transfered_size = size;
    575         memcpy(request->data_buffer, result_descriptor, size);
    576 
    577         return EOK;
    578 }
    579 /*----------------------------------------------------------------------------*/
    580 
    581 /**
    582  * answer to get configuration request
    583  *
    584  * Root hub works independently on the configuration.
    585  * @param instance root hub instance
    586  * @param request structure containing both request and response information
    587  * @return error code
    588  */
    589 static int process_get_configuration_request(rh_t *instance,
    590     usb_transfer_batch_t *request) {
    591         //set and get configuration requests do not have any meaning, only dummy
    592         //values are returned
    593         if (request->buffer_size != 1)
    594                 return EINVAL;
    595         request->data_buffer[0] = 1;
    596         request->transfered_size = 1;
    597 
    598         return EOK;
    599 }
    600 /*----------------------------------------------------------------------------*/
    601 
    602 /**
    603  * process feature-enabling request on hub
    604  *
    605  * @param instance root hub instance
    606  * @param feature feature selector
    607  * @return error code
    608  */
    609 static int process_hub_feature_set_request(rh_t *instance,
    610     uint16_t feature) {
    611         if (!((1 << feature) & hub_set_feature_valid_mask))
    612                 return EINVAL;
    613         if (feature == USB_HUB_FEATURE_C_HUB_LOCAL_POWER)
    614                 feature = USB_HUB_FEATURE_C_HUB_LOCAL_POWER << 16;
    615         instance->registers->rh_status =
    616             (instance->registers->rh_status | (1 << feature))
    617             & (~hub_clear_feature_by_writing_one_mask);
    618 
    619         return EOK;
    620 }
    621 /*----------------------------------------------------------------------------*/
    622 
    623 /**
    624  * process feature-disabling request on hub
    625  *
    626  * @param instance root hub instance
    627  * @param feature feature selector
    628  * @return error code
    629  */
    630 static int process_hub_feature_clear_request(rh_t *instance,
    631     uint16_t feature) {
    632         if (!((1 << feature) & hub_clear_feature_valid_mask))
    633                 return EINVAL;
    634         //is the feature cleared directly?
    635         if ((1 << feature) & hub_set_feature_direct_mask) {
    636                 instance->registers->rh_status =
    637                     (instance->registers->rh_status & (~(1 << feature)))
    638                     & (~hub_clear_feature_by_writing_one_mask);
    639         } else {//the feature is cleared by writing '1'
    640 
    641                 instance->registers->rh_status =
    642                     (instance->registers->rh_status
    643                     & (~hub_clear_feature_by_writing_one_mask))
    644                     | (1 << feature);
    645         }
    646         return EOK;
    647 }
    648 /*----------------------------------------------------------------------------*/
    649 
     484
     485        memcpy(request->data_buffer, descriptor, size);
     486        TRANSFER_OK(size);
     487}
     488/*----------------------------------------------------------------------------*/
    650489/**
    651490 * process feature-enabling request on hub
     
    657496 * @return error code
    658497 */
    659 static int process_port_feature_set_request(rh_t *instance,
    660     uint16_t feature, uint16_t port) {
    661         if (!((1 << feature) & port_set_feature_valid_mask))
    662                 return EINVAL;
     498int set_feature_port(rh_t *instance, uint16_t feature, uint16_t port)
     499{
     500        assert(instance);
     501
    663502        if (port < 1 || port > instance->port_count)
    664503                return EINVAL;
    665         instance->registers->rh_port_status[port - 1] =
    666             (instance->registers->rh_port_status[port - 1] | (1 << feature))
    667             & (~port_clear_feature_valid_mask);
    668         return EOK;
    669 }
    670 /*----------------------------------------------------------------------------*/
    671 
    672 /**
    673  * process feature-disabling request on hub
     504
     505        switch (feature)
     506        {
     507        case USB_HUB_FEATURE_PORT_POWER:   //8
     508                /* No power switching */
     509                if (instance->registers->rh_desc_a & RHDA_NPS_FLAG)
     510                        return EOK;
     511                /* Ganged power switching */
     512                if (!(instance->registers->rh_desc_a & RHDA_PSM_FLAG)) {
     513                        instance->registers->rh_status = RHS_SET_GLOBAL_POWER;
     514                        return EOK;
     515                }
     516        case USB_HUB_FEATURE_PORT_ENABLE:  //1
     517        case USB_HUB_FEATURE_PORT_SUSPEND: //2
     518        case USB_HUB_FEATURE_PORT_RESET:   //4
     519                /* Nice thing is that these shifts correspond to the position
     520                 * of control bits in register */
     521                instance->registers->rh_port_status[port - 1] = (1 << feature);
     522                return EOK;
     523        default:
     524                return ENOTSUP;
     525        }
     526}
     527/*----------------------------------------------------------------------------*/
     528/**
     529 * Process feature clear request.
    674530 *
    675531 * @param instance root hub instance
     
    679535 * @return error code
    680536 */
    681 static int process_port_feature_clear_request(rh_t *instance,
    682     uint16_t feature, uint16_t port) {
    683         if (!((1 << feature) & port_clear_feature_valid_mask))
    684                 return EINVAL;
     537int clear_feature_port(rh_t *instance, uint16_t feature, uint16_t port)
     538{
     539        assert(instance);
     540
    685541        if (port < 1 || port > instance->port_count)
    686542                return EINVAL;
    687         if (feature == USB_HUB_FEATURE_PORT_POWER)
    688                 feature = USB_HUB_FEATURE_PORT_LOW_SPEED;
    689         if (feature == USB_HUB_FEATURE_PORT_SUSPEND)
    690                 feature = USB_HUB_FEATURE_PORT_OVER_CURRENT;
    691         instance->registers->rh_port_status[port - 1] =
    692             (instance->registers->rh_port_status[port - 1]
    693             & (~port_clear_feature_valid_mask))
    694             | (1 << feature);
    695 
    696         return EOK;
    697 }
    698 /*----------------------------------------------------------------------------*/
    699 
    700 /**
    701  * register address to this device
    702  *
    703  * @param instance root hub instance
    704  * @param address new address
    705  * @return error code
    706  */
    707 static int process_address_set_request(rh_t *instance,
    708     uint16_t address) {
    709         return ENOTSUP;
    710 }
    711 /*----------------------------------------------------------------------------*/
    712 
    713 /**
    714  * process one of requests that requere output data
    715  *
    716  * Request can be one of USB_DEVREQ_GET_STATUS, USB_DEVREQ_GET_DESCRIPTOR or
    717  * USB_DEVREQ_GET_CONFIGURATION.
    718  * @param instance root hub instance
    719  * @param request structure containing both request and response information
    720  * @return error code
    721  */
    722 static int process_request_with_output(rh_t *instance,
    723     usb_transfer_batch_t *request) {
    724         usb_device_request_setup_packet_t * setup_request =
    725             (usb_device_request_setup_packet_t*) request->setup_buffer;
    726         if (setup_request->request == USB_DEVREQ_GET_STATUS) {
    727                 usb_log_debug("USB_DEVREQ_GET_STATUS\n");
    728                 return process_get_status_request(instance, request);
    729         }
    730         if (setup_request->request == USB_DEVREQ_GET_DESCRIPTOR) {
    731                 usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n");
    732                 return process_get_descriptor_request(instance, request);
    733         }
    734         if (setup_request->request == USB_DEVREQ_GET_CONFIGURATION) {
    735                 usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n");
    736 
    737                 return process_get_configuration_request(instance, request);
    738         }
    739         return ENOTSUP;
    740 }
    741 /*----------------------------------------------------------------------------*/
    742 
    743 /**
    744  * process one of requests that carry input data
    745  *
    746  * Request can be one of USB_DEVREQ_SET_DESCRIPTOR or
    747  * USB_DEVREQ_SET_CONFIGURATION.
    748  * @param instance root hub instance
    749  * @param request structure containing both request and response information
    750  * @return error code
    751  */
    752 static int process_request_with_input(rh_t *instance,
    753     usb_transfer_batch_t *request) {
    754         usb_device_request_setup_packet_t * setup_request =
    755             (usb_device_request_setup_packet_t*) request->setup_buffer;
    756         request->transfered_size = 0;
    757         if (setup_request->request == USB_DEVREQ_SET_DESCRIPTOR) {
     543
     544        /* Enabled features to clear: see page 269 of USB specs */
     545        switch (feature)
     546        {
     547        case USB_HUB_FEATURE_PORT_POWER:          //8
     548                /* No power switching */
     549                if (instance->registers->rh_desc_a & RHDA_NPS_FLAG)
     550                        return ENOTSUP;
     551                /* Ganged power switching */
     552                if (!(instance->registers->rh_desc_a & RHDA_PSM_FLAG)) {
     553                        instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
     554                        return EOK;
     555                }
     556                instance->registers->rh_port_status[port - 1] =
     557                        RHPS_CLEAR_PORT_POWER;
     558                return EOK;
     559
     560        case USB_HUB_FEATURE_PORT_ENABLE:         //1
     561                instance->registers->rh_port_status[port - 1] =
     562                        RHPS_CLEAR_PORT_ENABLE;
     563                return EOK;
     564
     565        case USB_HUB_FEATURE_PORT_SUSPEND:        //2
     566                instance->registers->rh_port_status[port - 1] =
     567                        RHPS_CLEAR_PORT_SUSPEND;
     568                return EOK;
     569
     570        case USB_HUB_FEATURE_C_PORT_CONNECTION:   //16
     571        case USB_HUB_FEATURE_C_PORT_ENABLE:       //17
     572        case USB_HUB_FEATURE_C_PORT_SUSPEND:      //18
     573        case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: //19
     574        case USB_HUB_FEATURE_C_PORT_RESET:        //20
     575                /* Nice thing is that these shifts correspond to the position
     576                 * of control bits in register */
     577                instance->registers->rh_port_status[port - 1] = (1 << feature);
     578                return EOK;
     579
     580        default:
    758581                return ENOTSUP;
    759582        }
    760         if (setup_request->request == USB_DEVREQ_SET_CONFIGURATION) {
    761                 //set and get configuration requests do not have any meaning,
    762                 //only dummy values are returned
    763 
    764                 return EOK;
    765         }
    766         return ENOTSUP;
    767 }
    768 /*----------------------------------------------------------------------------*/
    769 
     583}
     584/*----------------------------------------------------------------------------*/
    770585/**
    771586 * process one of requests that do not request nor carry additional data
     
    777592 * @return error code
    778593 */
    779 static int process_request_without_data(rh_t *instance,
    780     usb_transfer_batch_t *request) {
    781         usb_device_request_setup_packet_t * setup_request =
    782             (usb_device_request_setup_packet_t*) request->setup_buffer;
    783         request->transfered_size = 0;
    784         if (setup_request->request == USB_DEVREQ_CLEAR_FEATURE) {
    785                 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE) {
    786                         usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
    787                         return process_hub_feature_clear_request(instance,
    788                             setup_request->value);
    789                 }
    790                 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) {
    791                         usb_log_debug2("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
    792                         return process_port_feature_clear_request(instance,
    793                             setup_request->value,
    794                             setup_request->index);
    795                 }
    796                 usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",
     594int set_feature(rh_t *instance, usb_transfer_batch_t *request)
     595{
     596        assert(instance);
     597        assert(request);
     598
     599        const usb_device_request_setup_packet_t *setup_request =
     600            (usb_device_request_setup_packet_t *) request->setup_buffer;
     601        switch (setup_request->request_type)
     602        {
     603        case USB_HUB_REQ_TYPE_SET_PORT_FEATURE:
     604                usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
     605                return set_feature_port(instance,
     606                    setup_request->value, setup_request->index);
     607
     608        case USB_HUB_REQ_TYPE_SET_HUB_FEATURE:
     609                /* Chapter 11.16.2 specifies that hub can be recipient
     610                 * only for C_HUB_LOCAL_POWER and C_HUB_OVER_CURRENT
     611                 * features. It makes no sense to SET either. */
     612                usb_log_error("Invalid HUB set feature request.\n");
     613                return ENOTSUP;
     614        default:
     615                usb_log_error("Invalid set feature request type: %d\n",
    797616                    setup_request->request_type);
    798617                return EINVAL;
    799618        }
    800         if (setup_request->request == USB_DEVREQ_SET_FEATURE) {
    801                 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE) {
    802                         usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
    803                         return process_hub_feature_set_request(instance,
    804                             setup_request->value);
     619}
     620/*----------------------------------------------------------------------------*/
     621/**
     622 * process one of requests that do not request nor carry additional data
     623 *
     624 * Request can be one of USB_DEVREQ_CLEAR_FEATURE, USB_DEVREQ_SET_FEATURE or
     625 * USB_DEVREQ_SET_ADDRESS.
     626 * @param instance root hub instance
     627 * @param request structure containing both request and response information
     628 * @return error code
     629 */
     630int clear_feature(rh_t *instance, usb_transfer_batch_t *request)
     631{
     632        assert(instance);
     633        assert(request);
     634
     635        const usb_device_request_setup_packet_t *setup_request =
     636            (usb_device_request_setup_packet_t *) request->setup_buffer;
     637        request->transfered_size = 0;
     638        switch (setup_request->request_type)
     639        {
     640        case USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE:
     641                usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE\n");
     642                return clear_feature_port(instance,
     643                    setup_request->value, setup_request->index);
     644
     645        case USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE:
     646                usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE\n");
     647                /*
     648                 * Chapter 11.16.2 specifies that only C_HUB_LOCAL_POWER and
     649                 * C_HUB_OVER_CURRENT are supported. C_HUB_OVER_CURRENT is represented
     650                 * by OHCI RHS_OCIC_FLAG. C_HUB_LOCAL_POWER is not supported
     651                 * as root hubs do not support local power status feature.
     652                 * (OHCI pg. 127) */
     653                if (setup_request->value == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) {
     654                        instance->registers->rh_status = RHS_OCIC_FLAG;
     655                        TRANSFER_OK(0);
    805656                }
    806                 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) {
    807                         usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
    808                         return process_port_feature_set_request(instance,
    809                             setup_request->value,
    810                             setup_request->index);
    811                 }
    812                 usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",
     657        default:
     658                usb_log_error("Invalid clear feature request type: %d\n",
    813659                    setup_request->request_type);
    814660                return EINVAL;
    815661        }
    816         if (setup_request->request == USB_DEVREQ_SET_ADDRESS) {
    817                 usb_log_debug("USB_DEVREQ_SET_ADDRESS\n");
    818                 return process_address_set_request(instance,
    819                     setup_request->value);
    820         }
    821         usb_log_debug("USB_DEVREQ_SET_ENOTSUP %d\n",
    822             setup_request->request_type);
    823 
    824         return ENOTSUP;
    825 }
    826 /*----------------------------------------------------------------------------*/
    827 
    828 /**
    829  * process hub control request
     662}
     663/*----------------------------------------------------------------------------*/
     664/**
     665 * Process hub control request.
    830666 *
    831667 * If needed, writes answer into the request structure.
     
    844680 * @return error code
    845681 */
    846 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request) {
     682int control_request(rh_t *instance, usb_transfer_batch_t *request)
     683{
     684        assert(instance);
     685        assert(request);
     686
    847687        if (!request->setup_buffer) {
    848                 usb_log_error("root hub received empty transaction?");
     688                usb_log_error("Root hub received empty transaction!");
    849689                return EINVAL;
    850690        }
    851         int opResult;
    852         if (sizeof (usb_device_request_setup_packet_t) > request->setup_size) {
     691
     692        if (sizeof(usb_device_request_setup_packet_t) > request->setup_size) {
    853693                usb_log_error("Setup packet too small\n");
    854                 return EINVAL;
    855         }
    856         usb_log_debug("CTRL packet: %s.\n",
    857             usb_debug_str_buffer(
    858             (const uint8_t *) request->setup_buffer, 8, 8));
    859         usb_device_request_setup_packet_t * setup_request =
    860             (usb_device_request_setup_packet_t*)
    861             request->setup_buffer;
    862         switch (setup_request->request) {
    863                 case USB_DEVREQ_GET_STATUS:
    864                 case USB_DEVREQ_GET_DESCRIPTOR:
    865                 case USB_DEVREQ_GET_CONFIGURATION:
    866                         usb_log_debug2("Processing request with output\n");
    867                         opResult = process_request_with_output(
    868                             instance, request);
    869                         break;
    870                 case USB_DEVREQ_CLEAR_FEATURE:
    871                 case USB_DEVREQ_SET_FEATURE:
    872                 case USB_DEVREQ_SET_ADDRESS:
    873                         usb_log_debug2("Processing request without "
    874                             "additional data\n");
    875                         opResult = process_request_without_data(
    876                             instance, request);
    877                         break;
    878                 case USB_DEVREQ_SET_DESCRIPTOR:
    879                 case USB_DEVREQ_SET_CONFIGURATION:
    880                         usb_log_debug2("Processing request with input\n");
    881                         opResult = process_request_with_input(
    882                             instance, request);
    883 
    884                         break;
    885                 default:
    886                         usb_log_warning("Received unsupported request: %d.\n",
    887                             setup_request->request);
    888                         opResult = ENOTSUP;
    889         }
    890         return opResult;
    891 }
    892 /*----------------------------------------------------------------------------*/
    893 
    894 /**
    895  * process hanging interrupt request
    896  *
    897  * If an interrupt transfer has been received and there was no change,
    898  * the driver stores the transfer information and waits for change to occcur.
    899  * This routine is called when that happens and it finalizes the interrupt
    900  * transfer.
    901  *
    902  * @param instance hub instance
    903  * @param request batch request to be processed
    904  *
    905  * @return
    906  */
    907 static int process_interrupt_mask_in_instance(rh_t *instance,
    908     usb_transfer_batch_t * request) {
    909         memcpy(request->data_buffer, instance->interrupt_buffer,
    910             instance->interrupt_mask_size);
    911         request->transfered_size = instance->interrupt_mask_size;
    912         instance->unfinished_interrupt_transfer = NULL;
    913         usb_transfer_batch_finish_error(request, EOK);
    914 
    915         return EOK;
    916 }
    917 
    918 /*----------------------------------------------------------------------------*/
    919 
    920 /**
    921  * return whether the buffer is full of zeros
    922  *
    923  * Convenience function.
    924  * @param buffer
    925  * @param size
    926  * @return
    927  */
    928 static bool is_zeros(void *buffer, size_t size) {
    929         if (!buffer) return true;
    930         if (!size) return true;
    931         size_t i;
    932         for (i = 0; i < size; ++i) {
    933                 if (((char*) buffer)[i])
    934                         return false;
    935         }
    936         return true;
     694                return EOVERFLOW;
     695        }
     696
     697        usb_log_debug2("CTRL packet: %s.\n",
     698            usb_debug_str_buffer((uint8_t *) request->setup_buffer, 8, 8));
     699        const usb_device_request_setup_packet_t *setup_request =
     700            (usb_device_request_setup_packet_t *) request->setup_buffer;
     701        switch (setup_request->request)
     702        {
     703        case USB_DEVREQ_GET_STATUS:
     704                usb_log_debug("USB_DEVREQ_GET_STATUS\n");
     705                return get_status(instance, request);
     706
     707        case USB_DEVREQ_GET_DESCRIPTOR:
     708                usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n");
     709                return get_descriptor(instance, request);
     710
     711        case USB_DEVREQ_GET_CONFIGURATION:
     712                usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n");
     713                if (request->buffer_size != 1)
     714                        return EINVAL;
     715                request->data_buffer[0] = 1;
     716                TRANSFER_OK(1);
     717
     718        case USB_DEVREQ_CLEAR_FEATURE:
     719                usb_log_debug2("Processing request without "
     720                    "additional data\n");
     721                return clear_feature(instance, request);
     722        case USB_DEVREQ_SET_FEATURE:
     723                usb_log_debug2("Processing request without "
     724                    "additional data\n");
     725                return set_feature(instance, request);
     726
     727        case USB_DEVREQ_SET_ADDRESS:
     728                usb_log_debug("USB_DEVREQ_SET_ADDRESS\n");
     729                instance->address = setup_request->value;
     730                TRANSFER_OK(0);
     731
     732        case USB_DEVREQ_SET_CONFIGURATION:
     733                usb_log_debug("USB_DEVREQ_SET_CONFIGURATION\n");
     734                /* We don't need to do anything */
     735                TRANSFER_OK(0);
     736
     737        case USB_DEVREQ_SET_DESCRIPTOR: /* Not supported by OHCI RH */
     738        default:
     739                usb_log_error("Received unsupported request: %d.\n",
     740                    setup_request->request);
     741                return ENOTSUP;
     742        }
    937743}
    938744
Note: See TracChangeset for help on using the changeset viewer.