Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 6c741e1d in mainline


Ignore:
Timestamp:
2010-10-20T23:15:48Z (10 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
master
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.

Location:
uspace/srv/hw/bus/usb/hcd/virtual
Files:
4 edited

Legend:

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

    rb8507a1 r6c741e1d  
    140140        .descriptors = &descriptors,
    141141};
    142 
     142 
    143143hub_device_t hub_dev;
    144144
     
    147147        size_t i;
    148148        for (i = 0; i < HUB_PORT_COUNT; i++) {
    149                 hub_dev.ports[i].device = NULL;
    150                 hub_dev.ports[i].state = HUB_PORT_STATE_NOT_CONFIGURED;
    151         }
    152         hub_dev.status_change_bitmap = 0;
     149                hub_port_t *port = &hub_dev.ports[i];
     150               
     151                port->device = NULL;
     152                port->state = HUB_PORT_STATE_NOT_CONFIGURED;
     153                port->status_change = 0;
     154        }
    153155       
    154156        usbvirt_connect_local(&virthub_dev);
     
    161163        size_t i;
    162164        for (i = 0; i < HUB_PORT_COUNT; i++) {
    163                 if (hub_dev.ports[i].device != NULL) {
     165                hub_port_t *port = &hub_dev.ports[i];
     166               
     167                if (port->device != NULL) {
    164168                        continue;
    165169                }
    166                 hub_dev.ports[i].device = device;
    167                 // TODO - notify the host about change
    168                 // bad, bad but it will work somehow at least
    169                 hub_dev.ports[i].state = HUB_PORT_STATE_ENABLED;
    170                 hub_dev.status_change_bitmap |= (1 << (i+1));
     170               
     171                port->device = device;
     172               
     173                /*
     174                 * TODO:
     175                 * If the hub was configured, we can normally
     176                 * announce the plug-in.
     177                 * Otherwise, we will wait until hub is configured
     178                 * and announce changes in single burst.
     179                 */
     180                //if (port->state == HUB_PORT_STATE_DISCONNECTED) {
     181                        port->state = HUB_PORT_STATE_DISABLED;
     182                        set_port_status_change(port, HUB_STATUS_C_PORT_CONNECTION);
     183                //}
     184               
    171185                return i;
    172186        }
     
    180194        size_t i;
    181195        for (i = 0; i < HUB_PORT_COUNT; i++) {
    182                 if (hub_dev.ports[i].device != device) {
     196                hub_port_t *port = &hub_dev.ports[i];
     197               
     198                if (port->device != device) {
    183199                        continue;
    184200                }
    185                 hub_dev.ports[i].device = NULL;
    186                 hub_dev.ports[i].state = HUB_PORT_STATE_DISCONNECTED;
    187                 hub_dev.status_change_bitmap |= (1 << (i+1));
    188                 // TODO - notify the host of the removal
     201               
     202                port->device = NULL;
     203                port->state = HUB_PORT_STATE_DISCONNECTED;
     204               
     205                set_port_status_change(port, HUB_STATUS_C_PORT_CONNECTION);
    189206        }
    190207}
     
    202219}
    203220
     221void hub_check_port_changes(void)
     222{
     223        /* FIXME - what if HUB_PORT_COUNT is greater than 8. */
     224        uint8_t change_map = 0;
     225       
     226        size_t i;
     227        for (i = 0; i < HUB_PORT_COUNT; i++) {
     228                hub_port_t *port = &hub_dev.ports[i];
     229               
     230                if (port->status_change != 0) {
     231                        change_map |= (1 << (i + 1));
     232                }
     233        }
     234       
     235        /* FIXME - do not send when it has not changed since previous run. */
     236        if (change_map != 0) {
     237                virthub_dev.send_data(&virthub_dev, HUB_STATUS_CHANGE_PIPE,
     238                    &change_map, 1);
     239        }
     240}
    204241
    205242/**
  • uspace/srv/hw/bus/usb/hcd/virtual/hub.h

    rb8507a1 r6c741e1d  
    5151void hub_remove_device(virtdev_connection_t *);
    5252bool hub_can_device_signal(virtdev_connection_t *);
     53void hub_check_port_changes(void);
    5354
    5455#endif
  • uspace/srv/hw/bus/usb/hcd/virtual/hubintern.h

    rb8507a1 r6c741e1d  
    7878} hub_port_state_t;
    7979
     80typedef enum {
     81        HUB_STATUS_C_PORT_CONNECTION = (1 << 0),
     82        HUB_STATUS_C_PORT_ENABLE = (1 << 1),
     83        HUB_STATUS_C_PORT_SUSPEND = (1 << 2),
     84        HUB_STATUS_C_PORT_OVER_CURRENT = (1 << 3),
     85        HUB_STATUS_C_PORT_RESET = (1 << 4),
     86        /* HUB_STATUS_C_ = (1 << ), */
     87} hub_status_change_t;
     88
    8089typedef struct {
    8190        virtdev_connection_t *device;
    8291        hub_port_state_t state;
     92        uint16_t status_change;
    8393} hub_port_t;
    8494
    8595typedef struct {
    8696        hub_port_t ports[HUB_PORT_COUNT];
    87         /* FIXME - assuming HUB_PORT_COUNT < 8 */
    88         uint8_t status_change_bitmap;
    8997} hub_device_t;
    9098
     
    95103extern usbvirt_device_ops_t hub_ops;
    96104
     105void clear_port_status_change(hub_port_t *, uint16_t);
     106void set_port_status_change(hub_port_t *, uint16_t);
     107
     108
    97109#endif
    98110/**
  • 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.