Ignore:
Timestamp:
2010-10-20T23:15:48Z (14 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
34586183
Parents:
b8507a1
Message:

Add virtual hub state machine

The virtual hub provided by vhcd now simulates a state machine for
each of its ports. Some of the transitions are not implemented but
basic port handling through port features shall work. Will add
comments later.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/hw/bus/usb/hcd/virtual/hubops.c

    rb8507a1 r6c741e1d  
    4343#include "hubintern.h"
    4444
     45#define MAKE_BYTE(b0, b1, b2, b3, b4, b5, b6, b7) \
     46        (( \
     47                ((b0) << 0) \
     48                | ((b1) << 1) \
     49                | ((b2) << 2) \
     50                | ((b3) << 3) \
     51                | ((b4) << 4) \
     52                | ((b5) << 5) \
     53                | ((b6) << 6) \
     54                | ((b7) << 7) \
     55        ))
     56
    4557static int on_get_descriptor(struct usbvirt_device *dev,
    4658    usb_device_request_setup_packet_t *request, uint8_t *data);
     
    8294}
    8395
     96/** Change port status and updates status change status fields.
     97 */
     98static void set_port_state(hub_port_t *port, hub_port_state_t state)
     99{
     100        port->state = state;
     101        if (state == HUB_PORT_STATE_POWERED_OFF) {
     102                clear_port_status_change(port, HUB_STATUS_C_PORT_CONNECTION);
     103                clear_port_status_change(port, HUB_STATUS_C_PORT_ENABLE);
     104                clear_port_status_change(port, HUB_STATUS_C_PORT_RESET);
     105        }
     106        if (state == HUB_PORT_STATE_RESUMING) {
     107                async_usleep(10*1000);
     108                if (port->state == state) {
     109                        set_port_state(port, HUB_PORT_STATE_ENABLED);
     110                }
     111        }
     112        if (state == HUB_PORT_STATE_RESETTING) {
     113                async_usleep(10*1000);
     114                if (port->state == state) {
     115                        set_port_status_change(port, HUB_STATUS_C_PORT_RESET);
     116                        set_port_state(port, HUB_PORT_STATE_ENABLED);
     117                }
     118        }
     119}
     120
     121#define _GET_PORT(portvar, index) \
     122        do { \
     123                if (virthub_dev.state != USBVIRT_STATE_CONFIGURED) { \
     124                        return EINVAL; \
     125                } \
     126                if (((index) == 0) || ((index) > HUB_PORT_COUNT)) { \
     127                        return EINVAL; \
     128                } \
     129        } while (false); \
     130        hub_port_t *portvar = &hub_dev.ports[index]
     131
     132
    84133static int clear_hub_feature(uint16_t feature)
    85134{
     
    88137
    89138static int clear_port_feature(uint16_t feature, uint16_t portindex)
    90 {
     139{       
     140        _GET_PORT(port, portindex);
     141       
     142        switch (feature) {
     143                case USB_HUB_FEATURE_PORT_ENABLE:
     144                        if ((port->state != HUB_PORT_STATE_NOT_CONFIGURED)
     145                            && (port->state != HUB_PORT_STATE_POWERED_OFF)) {
     146                                set_port_state(port, HUB_PORT_STATE_DISABLED);
     147                        }
     148                        return EOK;
     149               
     150                case USB_HUB_FEATURE_PORT_SUSPEND:
     151                        if (port->state != HUB_PORT_STATE_SUSPENDED) {
     152                                return EOK;
     153                        }
     154                        set_port_state(port, HUB_PORT_STATE_RESUMING);
     155                        return EOK;
     156                       
     157                case USB_HUB_FEATURE_PORT_POWER:
     158                        if (port->state != HUB_PORT_STATE_NOT_CONFIGURED) {
     159                                set_port_state(port, HUB_PORT_STATE_POWERED_OFF);
     160                        }
     161                        return EOK;
     162               
     163                case USB_HUB_FEATURE_C_PORT_CONNECTION:
     164                        clear_port_status_change(port, HUB_STATUS_C_PORT_CONNECTION);
     165                        return EOK;
     166               
     167                case USB_HUB_FEATURE_C_PORT_ENABLE:
     168                        clear_port_status_change(port, HUB_STATUS_C_PORT_ENABLE);
     169                        return EOK;
     170               
     171                case USB_HUB_FEATURE_C_PORT_SUSPEND:
     172                        clear_port_status_change(port, HUB_STATUS_C_PORT_SUSPEND);
     173                        return EOK;
     174                       
     175                case USB_HUB_FEATURE_C_PORT_OVER_CURRENT:
     176                        clear_port_status_change(port, HUB_STATUS_C_PORT_OVER_CURRENT);
     177                        return EOK;
     178        }
     179       
    91180        return ENOTSUP;
    92181}
     
    105194static int get_hub_status(void)
    106195{
    107         return ENOTSUP;
     196        uint32_t hub_status = 0;
     197       
     198        return virthub_dev.send_data(&virthub_dev, 0, &hub_status, 4);
    108199}
    109200
    110201static int get_port_status(uint16_t portindex)
    111202{
    112         return ENOTSUP;
     203        _GET_PORT(port, portindex);
     204       
     205        uint32_t status;
     206        status = MAKE_BYTE(
     207            /* Current connect status. */
     208            port->device == NULL ? 0 : 1,
     209            /* Port enabled/disabled. */
     210            port->state == HUB_PORT_STATE_ENABLED ? 1 : 0,
     211            /* Suspend. */
     212            (port->state == HUB_PORT_STATE_SUSPENDED)
     213                || (port->state == HUB_PORT_STATE_RESUMING) ? 1 : 0,
     214            /* Over-current. */
     215            0,
     216            /* Reset. */
     217            port->state == HUB_PORT_STATE_RESETTING ? 1 : 0,
     218            /* Reserved. */
     219            0, 0, 0)
     220           
     221            | (MAKE_BYTE(
     222            /* Port power. */
     223            port->state == HUB_PORT_STATE_POWERED_OFF ? 0 : 1,
     224            /* Full-speed device. */
     225            0,
     226            /* Reserved. */
     227            0, 0, 0, 0, 0, 0
     228            )) << 8;
     229           
     230        status |= (port->status_change << 16);
     231       
     232        return virthub_dev.send_data(&virthub_dev, 0, &status, 4);
    113233}
    114234
     
    121241static int set_port_feature(uint16_t feature, uint16_t portindex)
    122242{
    123         return ENOTSUP;
    124 }
     243        _GET_PORT(port, portindex);
     244       
     245        switch (feature) {
     246                case USB_HUB_FEATURE_PORT_RESET:
     247                        if (port->state != HUB_PORT_STATE_POWERED_OFF) {
     248                                set_port_state(port, HUB_PORT_STATE_RESETTING);
     249                        }
     250                        return EOK;
     251               
     252                case USB_HUB_FEATURE_PORT_SUSPEND:
     253                        if (port->state == HUB_PORT_STATE_ENABLED) {
     254                                set_port_state(port, HUB_PORT_STATE_SUSPENDED);
     255                        }
     256                        return EOK;
     257               
     258                case USB_HUB_FEATURE_PORT_POWER:
     259                        if (port->state == HUB_PORT_STATE_POWERED_OFF) {
     260                                set_port_state(port, HUB_PORT_STATE_DISCONNECTED);
     261                        }
     262                        return EOK;
     263        }
     264        return ENOTSUP;
     265}
     266
     267#undef _GET_PORT
     268
     269
    125270
    126271
     
    186331}
    187332
     333void clear_port_status_change(hub_port_t *port, uint16_t change)
     334{
     335        port->status_change &= (~change);
     336        hub_check_port_changes();
     337}
     338
     339void set_port_status_change(hub_port_t *port, uint16_t change)
     340{
     341        port->status_change |= change;
     342}
     343
    188344/**
    189345 * @}
Note: See TracChangeset for help on using the changeset viewer.