Changeset 774afaae in mainline


Ignore:
Timestamp:
2010-12-15T21:56:14Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
e63a4e1
Parents:
1840e0d
Message:

Refactoring of virtual hub

The hub is now divided into two layers (one as a hub and the other
one as a virtual USB device) and separated into more files for better
readability.

Location:
uspace/drv/vhc
Files:
4 added
1 deleted
6 edited
1 moved

Legend:

Unmodified
Added
Removed
  • uspace/drv/vhc/Makefile

    r1840e0d r774afaae  
    3939
    4040SOURCES = \
     41        hub/hub.c \
     42        hub/virthub.c \
     43        hub/virthubops.c \
    4144        conndev.c \
    4245        connhost.c \
     
    4548        hc.c \
    4649        hcd.c \
    47         hub.c \
    48         hubops.c
     50        hub.c
    4951
    5052include $(USPACE_PREFIX)/Makefile.common
  • uspace/drv/vhc/devices.c

    r1840e0d r774afaae  
    4747#include "devices.h"
    4848#include "hub.h"
     49#include "hub/virthub.h"
    4950#include "vhcd.h"
    5051
     
    6970        list_append(&dev->link, &devices);
    7071       
    71         hub_add_device(dev);
     72        virthub_connect_device(&virtual_hub_device, dev);
    7273       
    7374        return dev;
     
    7879void virtdev_destroy_device(virtdev_connection_t *dev)
    7980{
    80         hub_remove_device(dev);
     81        virthub_disconnect_device(&virtual_hub_device, dev);
    8182        list_remove(&dev->link);
    8283        free(dev);
     
    9495                    = list_get_instance(pos, virtdev_connection_t, link);
    9596               
    96                 if (!hub_can_device_signal(dev)) {
     97                if (!virthub_is_device_enabled(&virtual_hub_device, dev)) {
    9798                        continue;
    9899                }
     
    145146         * (if the address matches).
    146147         */
    147         if (virthub_dev.address == transaction->target.address) {
     148        if (virtual_hub_device.address == transaction->target.address) {
    148149                size_t tmp;
    149150                dprintf(1, "sending `%s' transaction to hub",
     
    151152                switch (transaction->type) {
    152153                        case USBVIRT_TRANSACTION_SETUP:
    153                                 virthub_dev.transaction_setup(&virthub_dev,
     154                                virtual_hub_device.transaction_setup(
     155                                    &virtual_hub_device,
    154156                                    transaction->target.endpoint,
    155157                                    transaction->buffer, transaction->len);
     
    157159                               
    158160                        case USBVIRT_TRANSACTION_IN:
    159                                 virthub_dev.transaction_in(&virthub_dev,
     161                                virtual_hub_device.transaction_in(
     162                                    &virtual_hub_device,
    160163                                    transaction->target.endpoint,
    161164                                    transaction->buffer, transaction->len,
     
    167170                               
    168171                        case USBVIRT_TRANSACTION_OUT:
    169                                 virthub_dev.transaction_out(&virthub_dev,
     172                                virtual_hub_device.transaction_out(
     173                                    &virtual_hub_device,
    170174                                    transaction->target.endpoint,
    171175                                    transaction->buffer, transaction->len);
  • uspace/drv/vhc/hc.c

    r1840e0d r774afaae  
    7878        list_get_instance(lnk, transaction_t, link)
    7979
     80#define HUB_STATUS_MAX_LEN (HUB_PORT_COUNT + 64)
     81
    8082static inline unsigned int pseudo_random(unsigned int *seed)
    8183{
     
    115117                }
    116118               
    117                 char ports[HUB_PORT_COUNT + 2];
    118                 hub_get_port_statuses(ports, HUB_PORT_COUNT + 1);
    119                 dprintf(4, "virtual hub: addr=%d ports=%s",
    120                     virthub_dev.address, ports);
     119                char ports[HUB_STATUS_MAX_LEN + 1];
     120                virthub_get_status(&virtual_hub_device, ports, HUB_STATUS_MAX_LEN);
    121121               
    122122                link_t *first_transaction_link = transaction_list.next;
     
    126126               
    127127
    128                 dprintf(0, "about to process " TRANSACTION_FORMAT " (vhub:%s)",
     128                dprintf(0, "about to process " TRANSACTION_FORMAT " [%s]",
    129129                    TRANSACTION_PRINTF(*transaction), ports);
    130130
  • uspace/drv/vhc/hcd.c

    r1840e0d r774afaae  
    7979         * Initialize our hub and announce its presence.
    8080         */
    81         hub_init(dev);
     81        virtual_hub_device_init(dev);
    8282
    8383        printf("%s: virtual USB host controller ready.\n", NAME);
     
    108108int main(int argc, char * argv[])
    109109{       
    110         printf("%s: virtual USB host controller driver.\n", NAME);
     110        /*
     111         * Temporary workaround. Wait a little bit to be the last driver
     112         * in devman output.
     113         */
     114        sleep(4);
     115
     116        printf(NAME ": virtual USB host controller driver.\n");
    111117
    112118        usb_dprintf_enable(NAME, 0);
     
    114120        fid_t fid = fibril_create(hc_manager_fibril, NULL);
    115121        if (fid == 0) {
    116                 printf("%s: failed to start HC manager fibril\n", NAME);
     122                printf(NAME ": failed to start HC manager fibril\n");
    117123                return ENOMEM;
    118124        }
    119125        fibril_add_ready(fid);
    120126
    121         /*
    122          * Temporary workaround. Wait a little bit to be the last driver
    123          * in devman output.
    124          */
    125         sleep(4);
    126127
    127128        return driver_main(&vhc_driver);
  • uspace/drv/vhc/hub.c

    r1840e0d r774afaae  
    4242#include <usb/usbdrv.h>
    4343
     44#include "hub.h"
     45#include "hub/virthub.h"
    4446#include "vhcd.h"
    45 #include "hub.h"
    46 #include "hubintern.h"
    47 #include "conn.h"
    4847
     48usbvirt_device_t virtual_hub_device;
    4949
    50 /** Standard device descriptor. */
    51 usb_standard_device_descriptor_t std_device_descriptor = {
    52         .length = sizeof(usb_standard_device_descriptor_t),
    53         .descriptor_type = USB_DESCTYPE_DEVICE,
    54         .usb_spec_version = 0x110,
    55         .device_class = USB_CLASS_HUB,
    56         .device_subclass = 0,
    57         .device_protocol = 0,
    58         .max_packet_size = 64,
    59         .configuration_count = 1
    60 };
     50static int hub_register_in_devman_fibril(void *arg);
    6151
    62 /** Standard interface descriptor. */
    63 usb_standard_interface_descriptor_t std_interface_descriptor = {
    64         .length = sizeof(usb_standard_interface_descriptor_t),
    65         .descriptor_type = USB_DESCTYPE_INTERFACE,
    66         .interface_number = 0,
    67         .alternate_setting = 0,
    68         .endpoint_count = 1,
    69         .interface_class = USB_CLASS_HUB,
    70         .interface_subclass = 0,
    71         .interface_protocol = 0,
    72         .str_interface = 0
    73 };
     52void virtual_hub_device_init(device_t *hc_dev)
     53{
     54        virthub_init(&virtual_hub_device);
    7455
    75 hub_descriptor_t hub_descriptor = {
    76         .length = sizeof(hub_descriptor_t),
    77         .type = USB_DESCTYPE_HUB,
    78         .port_count = HUB_PORT_COUNT,
    79         .characteristics = 0,
    80         .power_on_warm_up = 50, /* Huh? */
    81         .max_current = 100, /* Huh again. */
    82         .removable_device = { 0 },
    83         .port_power = { 0xFF }
    84 };
     56        /*
     57         * We need to register the root hub.
     58         * This must be done in separate fibril because the device
     59         * we are connecting to are ourselves and we cannot connect
     60         * before leaving the add_device() function.
     61         */
     62        fid_t root_hub_registration
     63            = fibril_create(hub_register_in_devman_fibril, hc_dev);
     64        if (root_hub_registration == 0) {
     65                printf(NAME ": failed to register root hub\n");
     66                return;
     67        }
    8568
    86 /** Endpoint descriptor. */
    87 usb_standard_endpoint_descriptor_t endpoint_descriptor = {
    88         .length = sizeof(usb_standard_endpoint_descriptor_t),
    89         .descriptor_type = USB_DESCTYPE_ENDPOINT,
    90         .endpoint_address = HUB_STATUS_CHANGE_PIPE | 128,
    91         .attributes = USB_TRANSFER_INTERRUPT,
    92         .max_packet_size = 8,
    93         .poll_interval = 0xFF
    94 };
    95 
    96 /** Standard configuration descriptor. */
    97 usb_standard_configuration_descriptor_t std_configuration_descriptor = {
    98         .length = sizeof(usb_standard_configuration_descriptor_t),
    99         .descriptor_type = USB_DESCTYPE_CONFIGURATION,
    100         .total_length =
    101                 sizeof(usb_standard_configuration_descriptor_t)
    102                 + sizeof(std_interface_descriptor)
    103                 + sizeof(hub_descriptor)
    104                 + sizeof(endpoint_descriptor)
    105                 ,
    106         .interface_count = 1,
    107         .configuration_number = HUB_CONFIGURATION_ID,
    108         .str_configuration = 0,
    109         .attributes = 128, /* denotes bus-powered device */
    110         .max_power = 50
    111 };
    112 
    113 /** All hub configuration descriptors. */
    114 static usbvirt_device_configuration_extras_t extra_descriptors[] = {
    115         {
    116                 .data = (uint8_t *) &std_interface_descriptor,
    117                 .length = sizeof(std_interface_descriptor)
    118         },
    119         {
    120                 .data = (uint8_t *) &hub_descriptor,
    121                 .length = sizeof(hub_descriptor)
    122         },
    123         {
    124                 .data = (uint8_t *) &endpoint_descriptor,
    125                 .length = sizeof(endpoint_descriptor)
    126         }
    127 };
    128 
    129 /** Hub configuration. */
    130 usbvirt_device_configuration_t configuration = {
    131         .descriptor = &std_configuration_descriptor,
    132         .extra = extra_descriptors,
    133         .extra_count = sizeof(extra_descriptors)/sizeof(extra_descriptors[0])
    134 };
    135 
    136 /** Hub standard descriptors. */
    137 usbvirt_descriptors_t descriptors = {
    138         .device = &std_device_descriptor,
    139         .configuration = &configuration,
    140         .configuration_count = 1,
    141 };
    142 
    143 /** Hub as a virtual device. */
    144 usbvirt_device_t virthub_dev = {
    145         .ops = &hub_ops,
    146         .descriptors = &descriptors,
    147         .lib_debug_level = 0,
    148         .lib_debug_enabled_tags = USBVIRT_DEBUGTAG_ALL
    149 };
    150 
    151 /** Hub device. */
    152 hub_device_t hub_dev;
     69        fibril_add_ready(root_hub_registration);
     70}
    15371
    15472/** Register root hub in devman.
     
    15775 * @return Error code.
    15876 */
    159 static int hub_register_in_devman_fibril(void *arg)
     77int hub_register_in_devman_fibril(void *arg)
    16078{
    16179        device_t *hc_dev = (device_t *) arg;
     
    18098        return EOK;
    18199}
    182 
    183 /** Initialize virtual hub. */
    184 void hub_init(device_t *hc_dev)
    185 {
    186         size_t i;
    187100       
    188         for (i = 0; i < HUB_PORT_COUNT; i++) {
    189                 hub_port_t *port = &hub_dev.ports[i];
    190                
    191                 port->index = (int) i + 1;
    192                 port->device = NULL;
    193                 port->state = HUB_PORT_STATE_NOT_CONFIGURED;
    194                 port->status_change = 0;
    195                 fibril_mutex_initialize(&port->guard);
    196         }
    197        
    198         usbvirt_connect_local(&virthub_dev);
    199        
    200         /*
    201          * We need to register the root hub.
    202          * This must be done in separate fibril because the device
    203          * we are connecting to are ourselves and we cannot connect
    204          * before leaving the add_device() function.
    205          */
    206         fid_t root_hub_registration
    207             = fibril_create(hub_register_in_devman_fibril, hc_dev);
    208         if (root_hub_registration == 0) {
    209                 printf(NAME ": failed to register root hub\n");
    210                 return;
    211         }
    212 
    213         fibril_add_ready(root_hub_registration);
    214 }
    215 
    216 /** Connect device to the hub.
    217  *
    218  * @param device Device to be connected.
    219  * @return Port where the device was connected to.
    220  */
    221 size_t hub_add_device(virtdev_connection_t *device)
    222 {
    223         size_t i;
    224         for (i = 0; i < HUB_PORT_COUNT; i++) {
    225                 hub_port_t *port = &hub_dev.ports[i];
    226                 fibril_mutex_lock(&port->guard);
    227                
    228                 if (port->device != NULL) {
    229                         fibril_mutex_unlock(&port->guard);
    230                         continue;
    231                 }
    232                
    233                 port->device = device;
    234                
    235                 /*
    236                  * TODO:
    237                  * If the hub was configured, we can normally
    238                  * announce the plug-in.
    239                  * Otherwise, we will wait until hub is configured
    240                  * and announce changes in single burst.
    241                  */
    242                 //if (port->state == HUB_PORT_STATE_DISCONNECTED) {
    243                         port->state = HUB_PORT_STATE_DISABLED;
    244                         set_port_status_change_nl(port, HUB_STATUS_C_PORT_CONNECTION);
    245                 //}
    246                
    247                 fibril_mutex_unlock(&port->guard);
    248 
    249                 return i;
    250         }
    251        
    252         return (size_t)-1;
    253 }
    254 
    255 /** Disconnect device from the hub. */
    256 void hub_remove_device(virtdev_connection_t *device)
    257 {
    258         size_t i;
    259         for (i = 0; i < HUB_PORT_COUNT; i++) {
    260                 hub_port_t *port = &hub_dev.ports[i];
    261                
    262                 if (port->device != device) {
    263                         continue;
    264                 }
    265                
    266                 port->device = NULL;
    267                 port->state = HUB_PORT_STATE_DISCONNECTED;
    268                
    269                 set_port_status_change(port, HUB_STATUS_C_PORT_CONNECTION);
    270         }
    271 }
    272 
    273 /** Tell whether device port is open.
    274  *
    275  * @return Whether communication to and from the device can go through the hub.
    276  */
    277 bool hub_can_device_signal(virtdev_connection_t * device)
    278 {
    279         size_t i;
    280         for (i = 0; i < HUB_PORT_COUNT; i++) {
    281                 if (hub_dev.ports[i].device == device) {
    282                         return hub_dev.ports[i].state == HUB_PORT_STATE_ENABLED;
    283                 }
    284         }
    285        
    286         return false;
    287 }
    288 
    289 /** Format hub port status.
    290  *
    291  * @param result Buffer where to store status string.
    292  * @param len Number of characters that is possible to store in @p result
    293  *      (excluding trailing zero).
    294  */
    295 void hub_get_port_statuses(char *result, size_t len)
    296 {
    297         if (len > HUB_PORT_COUNT) {
    298                 len = HUB_PORT_COUNT;
    299         }
    300         size_t i;
    301         for (i = 0; i < len; i++) {
    302                 result[i] = hub_port_state_as_char(hub_dev.ports[i].state);
    303         }
    304         result[len] = 0;
    305 }
    306101
    307102/**
  • uspace/drv/vhc/hub.h

    r1840e0d r774afaae  
    4040
    4141#include "devices.h"
     42#include "hub/hub.h"
     43#include "hub/virthub.h"
    4244
    43 #define HUB_PORT_COUNT 2
     45extern usbvirt_device_t virtual_hub_device;
    4446
    45 #define BITS2BYTES(bits) \
    46     (bits ? ((((bits)-1)>>3)+1) : 0)
    47 
    48 extern usbvirt_device_t virthub_dev;
    49 
    50 void hub_init(device_t *);
    51 size_t hub_add_device(virtdev_connection_t *);
    52 void hub_remove_device(virtdev_connection_t *);
    53 bool hub_can_device_signal(virtdev_connection_t *);
    54 void hub_get_port_statuses(char *result, size_t len);
     47void virtual_hub_device_init(device_t *);
    5548
    5649#endif
  • uspace/drv/vhc/hub/virthub.h

    r1840e0d r774afaae  
    3333 * @brief
    3434 */
    35 #ifndef VHCD_HUBINTERN_H_
    36 #define VHCD_HUBINTERN_H_
     35#ifndef VHC_HUB_VIRTHUB_H_
     36#define VHC_HUB_VIRTHUB_H_
    3737
     38#include <usbvirt/device.h>
     39#include "../devices.h"
    3840#include "hub.h"
    39 #include <fibril_synch.h>
    4041
    4142/** Endpoint number for status change pipe. */
     
    4344/** Configuration value for hub configuration. */
    4445#define HUB_CONFIGURATION_ID 1
     46
    4547
    4648/** Hub descriptor.
     
    6971} __attribute__ ((packed)) hub_descriptor_t;
    7072
    71 /** Hub port internal state.
    72  * Some states (e.g. port over current) are not covered as they are not
    73  * simulated at all.
    74  */
    75 typedef enum {
    76         HUB_PORT_STATE_NOT_CONFIGURED,
    77         HUB_PORT_STATE_POWERED_OFF,
    78         HUB_PORT_STATE_DISCONNECTED,
    79         HUB_PORT_STATE_DISABLED,
    80         HUB_PORT_STATE_RESETTING,
    81         HUB_PORT_STATE_ENABLED,
    82         HUB_PORT_STATE_SUSPENDED,
    83         HUB_PORT_STATE_RESUMING,
    84         /* HUB_PORT_STATE_, */
    85 } hub_port_state_t;
    86 
    87 /** Convert hub port state to a char. */
    88 static inline char hub_port_state_as_char(hub_port_state_t state) {
    89         switch (state) {
    90                 case HUB_PORT_STATE_NOT_CONFIGURED:
    91                         return '-';
    92                 case HUB_PORT_STATE_POWERED_OFF:
    93                         return 'O';
    94                 case HUB_PORT_STATE_DISCONNECTED:
    95                         return 'X';
    96                 case HUB_PORT_STATE_DISABLED:
    97                         return 'D';
    98                 case HUB_PORT_STATE_RESETTING:
    99                         return 'R';
    100                 case HUB_PORT_STATE_ENABLED:
    101                         return 'E';
    102                 case HUB_PORT_STATE_SUSPENDED:
    103                         return 'S';
    104                 case HUB_PORT_STATE_RESUMING:
    105                         return 'F';
    106                 default:
    107                         return '?';
    108         }
    109 }
    110 
    111 /** Hub status change mask bits. */
    112 typedef enum {
    113         HUB_STATUS_C_PORT_CONNECTION = (1 << 0),
    114         HUB_STATUS_C_PORT_ENABLE = (1 << 1),
    115         HUB_STATUS_C_PORT_SUSPEND = (1 << 2),
    116         HUB_STATUS_C_PORT_OVER_CURRENT = (1 << 3),
    117         HUB_STATUS_C_PORT_RESET = (1 << 4),
    118         /* HUB_STATUS_C_ = (1 << ), */
    119 } hub_status_change_t;
    120 
    121 /** Hub port information. */
    122 typedef struct {
    123         virtdev_connection_t *device;
    124         int index;
    125         hub_port_state_t state;
    126         uint16_t status_change;
    127         fibril_mutex_t guard;
    128 } hub_port_t;
    129 
    130 /** Hub device type. */
    131 typedef struct {
    132         hub_port_t ports[HUB_PORT_COUNT];
    133 } hub_device_t;
    134 
    135 extern hub_device_t hub_dev;
    136 
     73extern usbvirt_device_ops_t hub_ops;
    13774extern hub_descriptor_t hub_descriptor;
    13875
    139 extern usbvirt_device_ops_t hub_ops;
    140 
    141 void clear_port_status_change(hub_port_t *, uint16_t);
    142 void set_port_status_change(hub_port_t *, uint16_t);
    143 void set_port_status_change_nl(hub_port_t *, uint16_t);
    144 
     76int virthub_init(usbvirt_device_t *);
     77int virthub_connect_device(usbvirt_device_t *, virtdev_connection_t *);
     78int virthub_disconnect_device(usbvirt_device_t *, virtdev_connection_t *);
     79bool virthub_is_device_enabled(usbvirt_device_t *, virtdev_connection_t *);
     80void virthub_get_status(usbvirt_device_t *, char *, size_t);
    14581
    14682#endif
Note: See TracChangeset for help on using the changeset viewer.