Changes in uspace/drv/vhc/hub.c [774afaae:ee0d8a8] in mainline


Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/vhc/hub.c

    r774afaae ree0d8a8  
    4040#include <stdlib.h>
    4141#include <driver.h>
    42 #include <usb/usbdrv.h>
    43 
     42
     43#include "vhcd.h"
    4444#include "hub.h"
    45 #include "hub/virthub.h"
    46 #include "vhcd.h"
    47 
    48 usbvirt_device_t virtual_hub_device;
    49 
    50 static int hub_register_in_devman_fibril(void *arg);
    51 
    52 void virtual_hub_device_init(device_t *hc_dev)
    53 {
    54         virthub_init(&virtual_hub_device);
    55 
    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");
     45#include "hubintern.h"
     46#include "conn.h"
     47
     48
     49/** Standard device descriptor. */
     50usb_standard_device_descriptor_t std_device_descriptor = {
     51        .length = sizeof(usb_standard_device_descriptor_t),
     52        .descriptor_type = USB_DESCTYPE_DEVICE,
     53        .usb_spec_version = 0x110,
     54        .device_class = USB_CLASS_HUB,
     55        .device_subclass = 0,
     56        .device_protocol = 0,
     57        .max_packet_size = 64,
     58        .configuration_count = 1
     59};
     60
     61/** Standard interface descriptor. */
     62usb_standard_interface_descriptor_t std_interface_descriptor = {
     63        .length = sizeof(usb_standard_interface_descriptor_t),
     64        .descriptor_type = USB_DESCTYPE_INTERFACE,
     65        .interface_number = 0,
     66        .alternate_setting = 0,
     67        .endpoint_count = 1,
     68        .interface_class = USB_CLASS_HUB,
     69        .interface_subclass = 0,
     70        .interface_protocol = 0,
     71        .str_interface = 0
     72};
     73
     74hub_descriptor_t hub_descriptor = {
     75        .length = sizeof(hub_descriptor_t),
     76        .type = USB_DESCTYPE_HUB,
     77        .port_count = HUB_PORT_COUNT,
     78        .characteristics = 0,
     79        .power_on_warm_up = 50, /* Huh? */
     80        .max_current = 100, /* Huh again. */
     81        .removable_device = { 0 },
     82        .port_power = { 0xFF }
     83};
     84
     85/** Endpoint descriptor. */
     86usb_standard_endpoint_descriptor_t endpoint_descriptor = {
     87        .length = sizeof(usb_standard_endpoint_descriptor_t),
     88        .descriptor_type = USB_DESCTYPE_ENDPOINT,
     89        .endpoint_address = HUB_STATUS_CHANGE_PIPE | 128,
     90        .attributes = USB_TRANSFER_INTERRUPT,
     91        .max_packet_size = 8,
     92        .poll_interval = 0xFF
     93};
     94
     95/** Standard configuration descriptor. */
     96usb_standard_configuration_descriptor_t std_configuration_descriptor = {
     97        .length = sizeof(usb_standard_configuration_descriptor_t),
     98        .descriptor_type = USB_DESCTYPE_CONFIGURATION,
     99        .total_length =
     100                sizeof(usb_standard_configuration_descriptor_t)
     101                + sizeof(std_interface_descriptor)
     102                + sizeof(hub_descriptor)
     103                + sizeof(endpoint_descriptor)
     104                ,
     105        .interface_count = 1,
     106        .configuration_number = HUB_CONFIGURATION_ID,
     107        .str_configuration = 0,
     108        .attributes = 128, /* denotes bus-powered device */
     109        .max_power = 50
     110};
     111
     112/** All hub configuration descriptors. */
     113static usbvirt_device_configuration_extras_t extra_descriptors[] = {
     114        {
     115                .data = (uint8_t *) &std_interface_descriptor,
     116                .length = sizeof(std_interface_descriptor)
     117        },
     118        {
     119                .data = (uint8_t *) &hub_descriptor,
     120                .length = sizeof(hub_descriptor)
     121        },
     122        {
     123                .data = (uint8_t *) &endpoint_descriptor,
     124                .length = sizeof(endpoint_descriptor)
     125        }
     126};
     127
     128/** Hub configuration. */
     129usbvirt_device_configuration_t configuration = {
     130        .descriptor = &std_configuration_descriptor,
     131        .extra = extra_descriptors,
     132        .extra_count = sizeof(extra_descriptors)/sizeof(extra_descriptors[0])
     133};
     134
     135/** Hub standard descriptors. */
     136usbvirt_descriptors_t descriptors = {
     137        .device = &std_device_descriptor,
     138        .configuration = &configuration,
     139        .configuration_count = 1,
     140};
     141
     142/** Hub as a virtual device. */
     143usbvirt_device_t virthub_dev = {
     144        .ops = &hub_ops,
     145        .descriptors = &descriptors,
     146        .lib_debug_level = 4,
     147        .lib_debug_enabled_tags = USBVIRT_DEBUGTAG_ALL
     148};
     149
     150/** Hub device. */
     151hub_device_t hub_dev;
     152
     153static usb_address_t hub_set_address(usbvirt_device_t *hub)
     154{
     155        usb_address_t new_address;
     156        int rc = vhc_iface.request_address(NULL, &new_address);
     157        if (rc != EOK) {
     158                return rc;
     159        }
     160       
     161        usb_device_request_setup_packet_t setup_packet = {
     162                .request_type = 0,
     163                .request = USB_DEVREQ_SET_ADDRESS,
     164                .index = 0,
     165                .length = 0,
     166        };
     167        setup_packet.value = new_address;
     168
     169        hub->transaction_setup(hub, 0, &setup_packet, sizeof(setup_packet));
     170        hub->transaction_in(hub, 0, NULL, 0, NULL);
     171       
     172        return new_address;
     173}
     174
     175/** Initialize virtual hub. */
     176void hub_init(device_t *hc_dev)
     177{
     178        size_t i;
     179        for (i = 0; i < HUB_PORT_COUNT; i++) {
     180                hub_port_t *port = &hub_dev.ports[i];
     181               
     182                port->device = NULL;
     183                port->state = HUB_PORT_STATE_NOT_CONFIGURED;
     184                port->status_change = 0;
     185        }
     186       
     187        usbvirt_connect_local(&virthub_dev);
     188       
     189        dprintf(1, "virtual hub (%d ports) created", HUB_PORT_COUNT);
     190
     191        usb_address_t hub_address = hub_set_address(&virthub_dev);
     192        if (hub_address < 0) {
     193                dprintf(1, "problem changing hub address (%s)",
     194                    str_error(hub_address));
     195        }
     196
     197        dprintf(2, "virtual hub address changed to %d", hub_address);
     198
     199        char *id;
     200        int rc = asprintf(&id, "usb&hub");
     201        if (rc <= 0) {
    66202                return;
    67203        }
    68 
    69         fibril_add_ready(root_hub_registration);
    70 }
    71 
    72 /** Register root hub in devman.
    73  *
    74  * @param arg Host controller device (type <code>device_t *</code>).
    75  * @return Error code.
    76  */
    77 int hub_register_in_devman_fibril(void *arg)
    78 {
    79         device_t *hc_dev = (device_t *) arg;
    80 
    81         int hc = usb_drv_hc_connect(hc_dev, IPC_FLAG_BLOCKING);
    82         if (hc < 0) {
    83                 printf(NAME ": failed to register root hub\n");
    84                 return hc;
    85         }
    86 
    87         usb_drv_reserve_default_address(hc);
    88 
    89         usb_address_t hub_address = usb_drv_request_address(hc);
    90         usb_drv_req_set_address(hc, USB_ADDRESS_DEFAULT, hub_address);
    91 
    92         usb_drv_release_default_address(hc);
    93 
    94204        devman_handle_t hub_handle;
    95         usb_drv_register_child_in_devman(hc, hc_dev, hub_address, &hub_handle);
    96         usb_drv_bind_address(hc, hub_address, hub_handle);
    97 
    98         return EOK;
    99 }
    100        
     205        rc = child_device_register_wrapper(hc_dev, "hub", id, 10, &hub_handle);
     206        if (rc != EOK) {
     207                free(id);
     208        }
     209
     210        vhc_iface.bind_address(NULL, hub_address, hub_handle); 
     211
     212        dprintf(2, "virtual hub has devman handle %d", (int) hub_handle);
     213}
     214
     215/** Connect device to the hub.
     216 *
     217 * @param device Device to be connected.
     218 * @return Port where the device was connected to.
     219 */
     220size_t hub_add_device(virtdev_connection_t *device)
     221{
     222        size_t i;
     223        for (i = 0; i < HUB_PORT_COUNT; i++) {
     224                hub_port_t *port = &hub_dev.ports[i];
     225               
     226                if (port->device != NULL) {
     227                        continue;
     228                }
     229               
     230                port->device = device;
     231               
     232                /*
     233                 * TODO:
     234                 * If the hub was configured, we can normally
     235                 * announce the plug-in.
     236                 * Otherwise, we will wait until hub is configured
     237                 * and announce changes in single burst.
     238                 */
     239                //if (port->state == HUB_PORT_STATE_DISCONNECTED) {
     240                        port->state = HUB_PORT_STATE_DISABLED;
     241                        set_port_status_change(port, HUB_STATUS_C_PORT_CONNECTION);
     242                //}
     243               
     244                return i;
     245        }
     246       
     247        return (size_t)-1;
     248}
     249
     250/** Disconnect device from the hub. */
     251void hub_remove_device(virtdev_connection_t *device)
     252{
     253        size_t i;
     254        for (i = 0; i < HUB_PORT_COUNT; i++) {
     255                hub_port_t *port = &hub_dev.ports[i];
     256               
     257                if (port->device != device) {
     258                        continue;
     259                }
     260               
     261                port->device = NULL;
     262                port->state = HUB_PORT_STATE_DISCONNECTED;
     263               
     264                set_port_status_change(port, HUB_STATUS_C_PORT_CONNECTION);
     265        }
     266}
     267
     268/** Tell whether device port is open.
     269 *
     270 * @return Whether communication to and from the device can go through the hub.
     271 */
     272bool hub_can_device_signal(virtdev_connection_t * device)
     273{
     274        size_t i;
     275        for (i = 0; i < HUB_PORT_COUNT; i++) {
     276                if (hub_dev.ports[i].device == device) {
     277                        return hub_dev.ports[i].state == HUB_PORT_STATE_ENABLED;
     278                }
     279        }
     280       
     281        return false;
     282}
     283
     284/** Format hub port status.
     285 *
     286 * @param result Buffer where to store status string.
     287 * @param len Number of characters that is possible to store in @p result
     288 *      (excluding trailing zero).
     289 */
     290void hub_get_port_statuses(char *result, size_t len)
     291{
     292        if (len > HUB_PORT_COUNT) {
     293                len = HUB_PORT_COUNT;
     294        }
     295        size_t i;
     296        for (i = 0; i < len; i++) {
     297                result[i] = hub_port_state_as_char(hub_dev.ports[i].state);
     298        }
     299        result[len] = 0;
     300}
    101301
    102302/**
Note: See TracChangeset for help on using the changeset viewer.