Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usbhost/src/ddf_helpers.c

    rcccd60c3 r0f6b50f  
    3535
    3636#include <usb/classes/classes.h>
     37#include <usb/host/bus.h>
    3738#include <usb/debug.h>
    3839#include <usb/descriptor.h>
     
    4950#include <fibril_synch.h>
    5051#include <macros.h>
    51 #include <stdio.h>
    5252#include <stdlib.h>
    5353#include <str_error.h>
     
    5656#include "ddf_helpers.h"
    5757
    58 #define CTRL_PIPE_MIN_PACKET_SIZE 8
    59 
    60 typedef struct usb_dev {
    61         link_t link;
    62         list_t devices;
    63         fibril_mutex_t guard;
    64         ddf_fun_t *fun;
    65         usb_address_t address;
    66         usb_speed_t speed;
    67         usb_address_t tt_address;
    68         unsigned port;
    69 } usb_dev_t;
    70 
    7158typedef struct hc_dev {
    7259        ddf_fun_t *ctl_fun;
    7360        hcd_t hcd;
    74         usb_dev_t *root_hub;
    7561} hc_dev_t;
    7662
     
    9177
    9278
    93 static int hcd_ddf_new_device(ddf_dev_t *device, usb_dev_t *hub, unsigned port);
    94 static int hcd_ddf_remove_device(ddf_dev_t *device, usb_dev_t *hub, unsigned port);
     79static int hcd_ddf_new_device(hcd_t *hcd, ddf_dev_t *hc, device_t *hub_dev, unsigned port);
     80static int hcd_ddf_remove_device(ddf_dev_t *device, device_t *hub, unsigned port);
    9581
    9682
     
    9985/** Register endpoint interface function.
    10086 * @param fun DDF function.
    101  * @param address USB address of the device.
    102  * @param endpoint USB endpoint number to be registered.
    103  * @param transfer_type Endpoint's transfer type.
    104  * @param direction USB communication direction the endpoint is capable of.
    105  * @param max_packet_size Maximu size of packets the endpoint accepts.
    106  * @param interval Preferred timeout between communication.
     87 * @param endpoint_desc Endpoint description.
    10788 * @return Error code.
    10889 */
    10990static int register_endpoint(
    110     ddf_fun_t *fun, usb_endpoint_t endpoint,
    111     usb_transfer_type_t transfer_type, usb_direction_t direction,
    112     size_t max_packet_size, unsigned packets, unsigned interval)
     91        ddf_fun_t *fun, usb_endpoint_desc_t *endpoint_desc)
    11392{
    11493        assert(fun);
    11594        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    116         usb_dev_t *dev = ddf_fun_data_get(fun);
     95        device_t *dev = ddf_fun_data_get(fun);
    11796        assert(hcd);
     97        assert(hcd->bus);
    11898        assert(dev);
    119         const size_t size = max_packet_size;
    120         const usb_target_t target =
    121             {{.address = dev->address, .endpoint = endpoint}};
     99
     100        const size_t size = endpoint_desc->max_packet_size;
    122101
    123102        usb_log_debug("Register endpoint %d:%d %s-%s %zuB %ums.\n",
    124             dev->address, endpoint, usb_str_transfer_type(transfer_type),
    125             usb_str_direction(direction), max_packet_size, interval);
    126 
    127         return hcd_add_ep(hcd, target, direction, transfer_type,
    128             max_packet_size, packets, size, dev->tt_address, dev->port);
    129 }
    130 
    131 /** Unregister endpoint interface function.
    132  * @param fun DDF function.
    133  * @param address USB address of the endpoint.
    134  * @param endpoint USB endpoint number.
    135  * @param direction Communication direction of the enpdoint to unregister.
    136  * @return Error code.
    137  */
     103                dev->address, endpoint_desc->endpoint_no,
     104                usb_str_transfer_type(endpoint_desc->transfer_type),
     105                usb_str_direction(endpoint_desc->direction),
     106                endpoint_desc->max_packet_size, endpoint_desc->usb2.polling_interval);
     107
     108        return bus_add_ep(hcd->bus, dev, endpoint_desc->endpoint_no,
     109                endpoint_desc->direction, endpoint_desc->transfer_type,
     110                endpoint_desc->max_packet_size, endpoint_desc->packets,
     111                size);
     112}
     113
     114 /** Unregister endpoint interface function.
     115  * @param fun DDF function.
     116  * @param endpoint_desc Endpoint description.
     117  * @return Error code.
     118  */
    138119static int unregister_endpoint(
    139     ddf_fun_t *fun, usb_endpoint_t endpoint, usb_direction_t direction)
     120        ddf_fun_t *fun, usb_endpoint_desc_t *endpoint_desc)
    140121{
    141122        assert(fun);
    142123        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    143         usb_dev_t *dev = ddf_fun_data_get(fun);
     124        device_t *dev = ddf_fun_data_get(fun);
    144125        assert(hcd);
     126        assert(hcd->bus);
    145127        assert(dev);
    146         const usb_target_t target =
    147             {{.address = dev->address, .endpoint = endpoint}};
     128
     129        const usb_target_t target = {{
     130                .address = dev->address,
     131                .endpoint = endpoint_desc->endpoint_no
     132        }};
     133
    148134        usb_log_debug("Unregister endpoint %d:%d %s.\n",
    149             dev->address, endpoint, usb_str_direction(direction));
    150         return hcd_remove_ep(hcd, target, direction);
     135                dev->address, endpoint_desc->endpoint_no,
     136                usb_str_direction(endpoint_desc->direction));
     137        return bus_remove_ep(hcd->bus, target, endpoint_desc->direction);
    151138}
    152139
     
    155142        assert(fun);
    156143        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    157         usb_dev_t *dev = ddf_fun_data_get(fun);
     144        device_t *dev = ddf_fun_data_get(fun);
    158145        assert(hcd);
     146        assert(hcd->bus);
    159147        assert(dev);
    160148
    161149        usb_log_debug("Device %d requested default address at %s speed\n",
    162150            dev->address, usb_str_speed(speed));
    163         return hcd_reserve_default_address(hcd, speed);
     151        return bus_reserve_default_address(hcd->bus, speed);
    164152}
    165153
     
    168156        assert(fun);
    169157        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    170         usb_dev_t *dev = ddf_fun_data_get(fun);
     158        device_t *dev = ddf_fun_data_get(fun);
    171159        assert(hcd);
     160        assert(hcd->bus);
    172161        assert(dev);
    173162
    174163        usb_log_debug("Device %d released default address\n", dev->address);
    175         return hcd_release_default_address(hcd);
     164        return bus_release_default_address(hcd->bus);
    176165}
    177166
    178167static int device_enumerate(ddf_fun_t *fun, unsigned port)
     168{
     169        assert(fun);
     170        ddf_dev_t *hc = ddf_fun_get_dev(fun);
     171        assert(hc);
     172        hcd_t *hcd = dev_to_hcd(hc);
     173        assert(hcd);
     174        device_t *hub = ddf_fun_data_get(fun);
     175        assert(hub);
     176
     177        usb_log_debug("Hub %d reported a new USB device on port: %u\n",
     178            hub->address, port);
     179        return hcd_ddf_new_device(hcd, hc, hub, port);
     180}
     181
     182static int device_remove(ddf_fun_t *fun, unsigned port)
    179183{
    180184        assert(fun);
    181185        ddf_dev_t *ddf_dev = ddf_fun_get_dev(fun);
    182         usb_dev_t *dev = ddf_fun_data_get(fun);
    183         assert(ddf_dev);
    184         assert(dev);
    185         usb_log_debug("Hub %d reported a new USB device on port: %u\n",
    186             dev->address, port);
    187         return hcd_ddf_new_device(ddf_dev, dev, port);
    188 }
    189 
    190 static int device_remove(ddf_fun_t *fun, unsigned port)
    191 {
    192         assert(fun);
    193         ddf_dev_t *ddf_dev = ddf_fun_get_dev(fun);
    194         usb_dev_t *dev = ddf_fun_data_get(fun);
     186        device_t *dev = ddf_fun_data_get(fun);
    195187        assert(ddf_dev);
    196188        assert(dev);
     
    229221{
    230222        assert(fun);
    231         usb_dev_t *usb_dev = ddf_fun_data_get(fun);
    232         assert(usb_dev);
     223        device_t *dev = ddf_fun_data_get(fun);
     224        assert(dev);
    233225        const usb_target_t target = {{
    234             .address =  usb_dev->address,
     226            .address  = dev->address,
    235227            .endpoint = endpoint,
    236228        }};
     
    255247{
    256248        assert(fun);
    257         usb_dev_t *usb_dev = ddf_fun_data_get(fun);
    258         assert(usb_dev);
     249        device_t *dev = ddf_fun_data_get(fun);
     250        assert(dev);
    259251        const usb_target_t target = {{
    260             .address =  usb_dev->address,
     252            .address  = dev->address,
    261253            .endpoint = endpoint,
    262254        }};
     
    290282
    291283/* DDF HELPERS */
    292 
    293 #define GET_DEVICE_DESC(size) \
    294 { \
    295         .request_type = SETUP_REQUEST_TYPE_DEVICE_TO_HOST \
    296             | (USB_REQUEST_TYPE_STANDARD << 5) \
    297             | USB_REQUEST_RECIPIENT_DEVICE, \
    298         .request = USB_DEVREQ_GET_DESCRIPTOR, \
    299         .value = uint16_host2usb(USB_DESCTYPE_DEVICE << 8), \
    300         .index = uint16_host2usb(0), \
    301         .length = uint16_host2usb(size), \
    302 };
    303 
    304 #define SET_ADDRESS(address) \
    305 { \
    306         .request_type = SETUP_REQUEST_TYPE_HOST_TO_DEVICE \
    307             | (USB_REQUEST_TYPE_STANDARD << 5) \
    308             | USB_REQUEST_RECIPIENT_DEVICE, \
    309         .request = USB_DEVREQ_SET_ADDRESS, \
    310         .value = uint16_host2usb(address), \
    311         .index = uint16_host2usb(0), \
    312         .length = uint16_host2usb(0), \
    313 };
    314 
    315 static int hcd_ddf_add_device(ddf_dev_t *parent, usb_dev_t *hub_dev,
    316     unsigned port, usb_address_t address, usb_speed_t speed, const char *name,
    317     const match_id_list_t *mids)
    318 {
    319         assert(parent);
    320 
    321         char default_name[10] = { 0 }; /* usbxyz-ss */
    322         if (!name) {
    323                 snprintf(default_name, sizeof(default_name) - 1,
    324                     "usb%u-%cs", address, usb_str_speed(speed)[0]);
    325                 name = default_name;
    326         }
    327 
    328         ddf_fun_t *fun = ddf_fun_create(parent, fun_inner, name);
    329         if (!fun)
    330                 return ENOMEM;
    331         usb_dev_t *info = ddf_fun_data_alloc(fun, sizeof(usb_dev_t));
    332         if (!info) {
    333                 ddf_fun_destroy(fun);
    334                 return ENOMEM;
    335         }
    336         info->address = address;
    337         info->speed = speed;
    338         info->fun = fun;
    339         info->port = port;
    340         info->tt_address = hub_dev ? hub_dev->tt_address : -1;
    341         link_initialize(&info->link);
    342         list_initialize(&info->devices);
    343         fibril_mutex_initialize(&info->guard);
    344 
    345         if (hub_dev && hub_dev->speed == USB_SPEED_HIGH && usb_speed_is_11(speed))
    346                 info->tt_address = hub_dev->address;
    347 
    348         ddf_fun_set_ops(fun, &usb_ops);
    349         list_foreach(mids->ids, link, const match_id_t, mid) {
    350                 ddf_fun_add_match_id(fun, mid->id, mid->score);
    351         }
    352 
    353         int ret = ddf_fun_bind(fun);
    354         if (ret != EOK) {
    355                 ddf_fun_destroy(fun);
    356                 return ret;
    357         }
    358 
    359         if (hub_dev) {
    360                 fibril_mutex_lock(&hub_dev->guard);
    361                 list_append(&info->link, &hub_dev->devices);
    362                 fibril_mutex_unlock(&hub_dev->guard);
    363         } else {
    364                 hc_dev_t *hc_dev = dev_to_hc_dev(parent);
    365                 assert(hc_dev->root_hub == NULL);
    366                 hc_dev->root_hub = info;
    367         }
    368         return EOK;
    369 }
    370284
    371285#define ADD_MATCHID_OR_RETURN(list, sc, str, ...) \
     
    394308        assert(l);
    395309        assert(d);
    396        
     310
    397311        if (d->vendor_id != 0) {
    398312                /* First, with release number. */
     
    401315                    d->vendor_id, d->product_id, (d->device_version >> 8),
    402316                    (d->device_version & 0xff));
    403        
     317
    404318                /* Next, without release number. */
    405319                ADD_MATCHID_OR_RETURN(l, 90, "usb&vendor=%#04x&product=%#04x",
     
    415329
    416330        return EOK;
    417 
    418 }
    419 
    420 static int hcd_ddf_remove_device(ddf_dev_t *device, usb_dev_t *hub,
     331}
     332
     333static int hcd_ddf_remove_device(ddf_dev_t *device, device_t *hub,
    421334    unsigned port)
    422335{
     
    425338        hcd_t *hcd = dev_to_hcd(device);
    426339        assert(hcd);
     340        assert(hcd->bus);
    427341
    428342        hc_dev_t *hc_dev = dev_to_hc_dev(device);
     
    431345        fibril_mutex_lock(&hub->guard);
    432346
    433         usb_dev_t *victim = NULL;
    434 
    435         list_foreach(hub->devices, link, usb_dev_t, it) {
     347        device_t *victim = NULL;
     348
     349        list_foreach(hub->devices, link, device_t, it) {
    436350                if (it->port == port) {
    437351                        victim = it;
     
    440354        }
    441355        if (victim) {
     356                assert(victim->fun);
    442357                assert(victim->port == port);
     358                assert(victim->hub == hub);
    443359                list_remove(&victim->link);
    444360                fibril_mutex_unlock(&hub->guard);
     
    446362                if (ret == EOK) {
    447363                        usb_address_t address = victim->address;
     364                        bus_remove_device(hcd->bus, hcd, victim);
    448365                        ddf_fun_destroy(victim->fun);
    449                         hcd_release_address(hcd, address);
     366                        bus_release_address(hcd->bus, address);
    450367                } else {
    451368                        usb_log_warning("Failed to unbind device `%s': %s\n",
     
    458375}
    459376
    460 static int hcd_ddf_new_device(ddf_dev_t *device, usb_dev_t *hub, unsigned port)
    461 {
    462         assert(device);
    463 
    464         hcd_t *hcd = dev_to_hcd(device);
    465         assert(hcd);
    466 
    467         usb_speed_t speed = USB_SPEED_MAX;
    468 
    469         /* This checks whether the default address is reserved and gets speed */
    470         int ret = usb_bus_get_speed(&hcd->bus, USB_ADDRESS_DEFAULT, &speed);
    471         if (ret != EOK) {
    472                 usb_log_error("Failed to verify speed: %s.", str_error(ret));
    473                 return ret;
    474         }
    475 
    476         usb_log_debug("Found new %s speed USB device.", usb_str_speed(speed));
    477 
    478         static const usb_target_t default_target = {{
    479                 .address = USB_ADDRESS_DEFAULT,
    480                 .endpoint = 0,
     377device_t *hcd_ddf_device_create(ddf_dev_t *hc, size_t device_size)
     378{
     379        /* Create DDF function for the new device */
     380        ddf_fun_t *fun = ddf_fun_create(hc, fun_inner, NULL);
     381        if (!fun)
     382                return NULL;
     383
     384        ddf_fun_set_ops(fun, &usb_ops);
     385
     386        /* Create USB device node for the new device */
     387        device_t *dev = ddf_fun_data_alloc(fun, device_size);
     388        if (!dev) {
     389                ddf_fun_destroy(fun);
     390                return NULL;
     391        }
     392
     393        device_init(dev);
     394        dev->fun = fun;
     395        return dev;
     396}
     397
     398void hcd_ddf_device_destroy(device_t *dev)
     399{
     400        assert(dev);
     401        assert(dev->fun);
     402        ddf_fun_destroy(dev->fun);
     403}
     404
     405int hcd_ddf_device_explore(hcd_t *hcd, device_t *device)
     406{
     407        int err;
     408        match_id_list_t mids;
     409        usb_standard_device_descriptor_t desc = { 0 };
     410
     411        init_match_ids(&mids);
     412
     413        usb_target_t control_ep = {{
     414                .address = device->address,
     415                .endpoint = 0
    481416        }};
    482 
    483         const usb_address_t address = hcd_request_address(hcd, speed);
    484         if (address < 0) {
    485                 usb_log_error("Failed to reserve new address: %s.",
    486                     str_error(address));
    487                 return address;
    488         }
    489 
    490         usb_log_debug("Reserved new address: %d\n", address);
    491 
    492         const usb_target_t target = {{
    493                 .address = address,
    494                 .endpoint = 0,
    495         }};
    496 
    497         const usb_address_t tt_address = hub ? hub->tt_address : -1;
    498 
    499         /* Add default pipe on default address */
    500         usb_log_debug("Device(%d): Adding default target(0:0)\n", address);
    501         ret = hcd_add_ep(hcd,
    502             default_target, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL,
    503             CTRL_PIPE_MIN_PACKET_SIZE, CTRL_PIPE_MIN_PACKET_SIZE, 1,
    504             tt_address, port);
    505         if (ret != EOK) {
    506                 usb_log_error("Device(%d): Failed to add default target: %s.",
    507                     address, str_error(ret));
    508                 hcd_release_address(hcd, address);
    509                 return ret;
    510         }
    511 
    512         /* Get max packet size for default pipe */
    513         usb_standard_device_descriptor_t desc = { 0 };
    514         const usb_device_request_setup_packet_t get_device_desc_8 =
    515             GET_DEVICE_DESC(CTRL_PIPE_MIN_PACKET_SIZE);
    516 
    517         // TODO CALLBACKS
    518         usb_log_debug("Device(%d): Requesting first 8B of device descriptor.",
    519             address);
    520         ssize_t got = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_IN,
    521             &desc, CTRL_PIPE_MIN_PACKET_SIZE, *(uint64_t *)&get_device_desc_8,
    522             "read first 8 bytes of dev descriptor");
    523 
    524         if (got != CTRL_PIPE_MIN_PACKET_SIZE) {
    525                 ret = got < 0 ? got : EOVERFLOW;
    526                 usb_log_error("Device(%d): Failed to get 8B of dev descr: %s.",
    527                     address, str_error(ret));
    528                 hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH);
    529                 hcd_release_address(hcd, address);
    530                 return ret;
    531         }
    532 
    533         /* Register EP on the new address */
    534         usb_log_debug("Device(%d): Registering control EP.", address);
    535         ret = hcd_add_ep(hcd, target, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL,
    536             ED_MPS_PACKET_SIZE_GET(uint16_usb2host(desc.max_packet_size)),
    537             ED_MPS_TRANS_OPPORTUNITIES_GET(uint16_usb2host(desc.max_packet_size)),
    538             ED_MPS_PACKET_SIZE_GET(uint16_usb2host(desc.max_packet_size)),
    539             tt_address, port);
    540         if (ret != EOK) {
    541                 usb_log_error("Device(%d): Failed to register EP0: %s",
    542                     address, str_error(ret));
    543                 hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH);
    544                 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
    545                 hcd_release_address(hcd, address);
    546                 return ret;
    547         }
    548 
    549         /* Set new address */
    550         const usb_device_request_setup_packet_t set_address =
    551             SET_ADDRESS(target.address);
    552 
    553         usb_log_debug("Device(%d): Setting USB address.", address);
    554         got = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_OUT,
    555             NULL, 0, *(uint64_t *)&set_address, "set address");
    556 
    557         usb_log_debug("Device(%d): Removing default (0:0) EP.", address);
    558         hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH);
    559 
    560         if (got != 0) {
    561                 usb_log_error("Device(%d): Failed to set new address: %s.",
    562                     address, str_error(got));
    563                 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
    564                 hcd_release_address(hcd, address);
    565                 return got;
    566         }
    567417
    568418        /* Get std device descriptor */
     
    571421
    572422        usb_log_debug("Device(%d): Requesting full device descriptor.",
    573             address);
    574         got = hcd_send_batch_sync(hcd, target, USB_DIRECTION_IN,
     423            device->address);
     424        ssize_t got = hcd_send_batch_sync(hcd, control_ep, USB_DIRECTION_IN,
    575425            &desc, sizeof(desc), *(uint64_t *)&get_device_desc,
    576426            "read device descriptor");
    577         if (ret != EOK) {
     427        if (got < 0) {
     428                err = got < 0 ? got : EOVERFLOW;
    578429                usb_log_error("Device(%d): Failed to set get dev descriptor: %s",
    579                     address, str_error(ret));
    580                 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
    581                 hcd_release_address(hcd, target.address);
    582                 return ret;
     430                    device->address, str_error(err));
     431                goto out;
    583432        }
    584433
    585434        /* Create match ids from the device descriptor */
    586         match_id_list_t mids;
    587         init_match_ids(&mids);
    588 
    589         usb_log_debug("Device(%d): Creating match IDs.", address);
    590         ret = create_match_ids(&mids, &desc);
    591         if (ret != EOK) {
    592                 usb_log_error("Device(%d): Failed to create match ids: %s",
    593                     address, str_error(ret));
    594                 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
    595                 hcd_release_address(hcd, target.address);
    596                 return ret;
    597         }
    598 
    599         /* Register device */
    600         usb_log_debug("Device(%d): Registering DDF device.", address);
    601         ret = hcd_ddf_add_device(device, hub, port, address, speed, NULL, &mids);
     435        usb_log_debug("Device(%d): Creating match IDs.", device->address);
     436        if ((err = create_match_ids(&mids, &desc))) {
     437                usb_log_error("Device(%d): Failed to create match ids: %s", device->address, str_error(err));
     438                goto out;
     439        }
     440
     441        list_foreach(mids.ids, link, const match_id_t, mid) {
     442                ddf_fun_add_match_id(device->fun, mid->id, mid->score);
     443        }
     444
     445out:
    602446        clean_match_ids(&mids);
    603         if (ret != EOK) {
    604                 usb_log_error("Device(%d): Failed to register: %s.",
    605                     address, str_error(ret));
    606                 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
    607                 hcd_release_address(hcd, target.address);
    608         }
    609 
    610         return ret;
     447        return err;
     448}
     449
     450static int hcd_ddf_new_device(hcd_t *hcd, ddf_dev_t *hc, device_t *hub, unsigned port)
     451{
     452        int err;
     453        assert(hcd);
     454        assert(hcd->bus);
     455        assert(hub);
     456        assert(hc);
     457
     458        device_t *dev = hcd_ddf_device_create(hc, hcd->bus->device_size);
     459        if (!dev) {
     460                usb_log_error("Failed to create USB device function.");
     461                return ENOMEM;
     462        }
     463
     464        dev->hub = hub;
     465        dev->port = port;
     466
     467        if ((err = bus_enumerate_device(hcd->bus, hcd, dev))) {
     468                usb_log_error("Failed to initialize USB dev memory structures.");
     469                return err;
     470        }
     471
     472        /* If the driver didn't name the dev when enumerating,
     473         * do it in some generic way.
     474         */
     475        if (!ddf_fun_get_name(dev->fun)) {
     476                device_set_default_name(dev);
     477        }
     478
     479        if ((err = ddf_fun_bind(dev->fun))) {
     480                usb_log_error("Device(%d): Failed to register: %s.", dev->address, str_error(err));
     481                goto err_usb_dev;
     482        }
     483
     484        fibril_mutex_lock(&hub->guard);
     485        list_append(&dev->link, &hub->devices);
     486        fibril_mutex_unlock(&hub->guard);
     487
     488        return EOK;
     489
     490err_usb_dev:
     491        hcd_ddf_device_destroy(dev);
     492        return err;
    611493}
    612494
     
    616498 * @return Error code
    617499 */
    618 int hcd_ddf_setup_root_hub(ddf_dev_t *device)
    619 {
    620         assert(device);
    621         hcd_t *hcd = dev_to_hcd(device);
     500int hcd_setup_virtual_root_hub(hcd_t *hcd, ddf_dev_t *hc)
     501{
     502        int err;
     503
     504        assert(hc);
    622505        assert(hcd);
    623 
    624         hcd_reserve_default_address(hcd, hcd->bus.max_speed);
    625         const int ret = hcd_ddf_new_device(device, NULL, 0);
    626         hcd_release_default_address(hcd);
    627         return ret;
     506        assert(hcd->bus);
     507
     508        if ((err = bus_reserve_default_address(hcd->bus, USB_SPEED_MAX))) {
     509                usb_log_error("Failed to reserve default address for roothub setup: %s", str_error(err));
     510                return err;
     511        }
     512
     513        device_t *dev = hcd_ddf_device_create(hc, USB_SPEED_MAX);
     514        if (!dev) {
     515                usb_log_error("Failed to create function for the root hub.");
     516                goto err_default_address;
     517        }
     518
     519        ddf_fun_set_name(dev->fun, "roothub");
     520
     521        dev->tt = (usb_tt_address_t) {
     522                .address = -1,
     523                .port = 0,
     524        };
     525
     526        /* Assign an address to the device */
     527        if ((err = bus_enumerate_device(hcd->bus, hcd, dev))) {
     528                usb_log_error("Failed to enumerate roothub device: %s", str_error(err));
     529                goto err_usb_dev;
     530        }
     531
     532        if ((err = ddf_fun_bind(dev->fun))) {
     533                usb_log_error("Failed to register roothub: %s.", str_error(err));
     534                goto err_usb_dev;
     535        }
     536
     537        bus_release_default_address(hcd->bus);
     538        return EOK;
     539
     540err_usb_dev:
     541        hcd_ddf_device_destroy(dev);
     542err_default_address:
     543        bus_release_default_address(hcd->bus);
     544        return err;
    628545}
    629546
     
    638555 * This function does all the ddf work for hc driver.
    639556 */
    640 int hcd_ddf_setup_hc(ddf_dev_t *device, usb_speed_t max_speed,
    641     size_t bw, bw_count_func_t bw_count)
     557int hcd_ddf_setup_hc(ddf_dev_t *device)
    642558{
    643559        assert(device);
     
    648564                return ENOMEM;
    649565        }
    650         instance->root_hub = NULL;
    651         hcd_init(&instance->hcd, max_speed, bw, bw_count);
     566        hcd_init(&instance->hcd);
    652567
    653568        int ret = ENOMEM;
     
    748663    const hw_res_list_parsed_t *hw_res,
    749664    interrupt_handler_t handler,
    750     int (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *hw_res))
    751 {
    752 
     665    irq_code_gen_t gen_irq_code)
     666{
    753667        assert(device);
     668
     669        hcd_t *hcd = dev_to_hcd(device);
     670
    754671        if (!handler || !gen_irq_code)
    755672                return ENOTSUP;
     
    757674        irq_code_t irq_code = {0};
    758675
    759         const int irq = gen_irq_code(&irq_code, hw_res);
     676        const int irq = gen_irq_code(&irq_code, hcd, hw_res);
    760677        if (irq < 0) {
    761678                usb_log_error("Failed to generate IRQ code: %s.\n",
     
    777694        int ret = hcd_ddf_enable_interrupt(device, irq);
    778695        if (ret != EOK) {
    779                 usb_log_error("Failed to register interrupt handler: %s.\n",
     696                usb_log_error("Failed to enable interrupts: %s.\n",
    780697                    str_error(ret));
    781698                unregister_interrupt_handler(device, irq_cap);
     
    844761{
    845762        assert(driver);
    846         static const struct { size_t bw; bw_count_func_t bw_count; }bw[] = {
    847             [USB_SPEED_FULL] = { .bw = BANDWIDTH_AVAILABLE_USB11,
    848                                  .bw_count = bandwidth_count_usb11 },
    849             [USB_SPEED_HIGH] = { .bw = BANDWIDTH_AVAILABLE_USB11,
    850                                  .bw_count = bandwidth_count_usb11 },
    851         };
    852763
    853764        int ret = EOK;
    854         const usb_speed_t speed = driver->hc_speed;
    855         if (speed >= ARRAY_SIZE(bw) || bw[speed].bw == 0) {
    856                 usb_log_error("Driver `%s' reported unsupported speed: %s",
    857                     driver->name, usb_str_speed(speed));
    858                 return ENOTSUP;
    859         }
    860765
    861766        hw_res_list_parsed_t hw_res;
     
    868773        }
    869774
    870         ret = hcd_ddf_setup_hc(device, speed, bw[speed].bw, bw[speed].bw_count);
     775        ret = hcd_ddf_setup_hc(device);
    871776        if (ret != EOK) {
    872777                usb_log_error("Failed to setup generic HCD.\n");
    873                 hw_res_list_parsed_clean(&hw_res);
    874                 return ret;
    875         }
    876 
     778                goto err_hw_res;
     779        }
     780
     781        hcd_t *hcd = dev_to_hcd(device);
     782
     783        if (driver->init)
     784                ret = driver->init(hcd, &hw_res, device);
     785        if (ret != EOK) {
     786                usb_log_error("Failed to init HCD.\n");
     787                goto err_hcd;
     788        }
     789
     790        /* Setup interrupts  */
    877791        interrupt_handler_t *irq_handler =
    878792            driver->irq_handler ? driver->irq_handler : ddf_hcd_gen_irq_handler;
     
    884798        }
    885799
     800        /* Claim the device from BIOS */
    886801        if (driver->claim)
    887                 ret = driver->claim(device);
     802                ret = driver->claim(hcd, device);
    888803        if (ret != EOK) {
    889                 usb_log_error("Failed to claim `%s' for driver `%s'",
    890                     ddf_dev_get_name(device), driver->name);
    891                 return ret;
    892         }
    893 
    894 
    895         /* Init hw driver */
    896         hcd_t *hcd = dev_to_hcd(device);
    897         ret = driver->init(hcd, &hw_res, irqs_enabled);
    898         hw_res_list_parsed_clean(&hw_res);
     804                usb_log_error("Failed to claim `%s' for driver `%s': %s",
     805                    ddf_dev_get_name(device), driver->name, str_error(ret));
     806                goto err_irq;
     807        }
     808
     809        /* Start hw driver */
     810        if (driver->start)
     811                ret = driver->start(hcd, irqs_enabled);
    899812        if (ret != EOK) {
    900                 usb_log_error("Failed to init HCD: %s.\n", str_error(ret));
    901                 goto irq_unregister;
     813                usb_log_error("Failed to start HCD: %s.\n", str_error(ret));
     814                goto err_irq;
    902815        }
    903816
     
    908821                        usb_log_error("Failed to create polling fibril\n");
    909822                        ret = ENOMEM;
    910                         goto irq_unregister;
     823                        goto err_started;
    911824                }
    912825                fibril_add_ready(hcd->polling_fibril);
     
    919832         * needs to be ready at this time.
    920833         */
    921         ret = hcd_ddf_setup_root_hub(device);
     834        if (driver->setup_root_hub)
     835                ret = driver->setup_root_hub(hcd, device);
    922836        if (ret != EOK) {
    923837                usb_log_error("Failed to setup HC root hub: %s.\n",
    924838                    str_error(ret));
    925                 driver->fini(dev_to_hcd(device));
    926 irq_unregister:
    927                 /* Unregistering non-existent should be ok */
    928                 unregister_interrupt_handler(device, irq_cap);
    929                 hcd_ddf_clean_hc(device);
    930                 return ret;
     839                goto err_polling;
    931840        }
    932841
     
    934843            driver->name, ddf_dev_get_name(device));
    935844        return EOK;
    936 }
     845
     846err_polling:
     847        // TODO: Stop the polling fibril (refactor the interrupt_polling func)
     848        //
     849err_started:
     850        if (driver->stop)
     851                driver->stop(hcd);
     852err_irq:
     853        unregister_interrupt_handler(device, irq_cap);
     854        if (driver->fini)
     855                driver->fini(hcd);
     856err_hcd:
     857        hcd_ddf_clean_hc(device);
     858err_hw_res:
     859        hw_res_list_parsed_clean(&hw_res);
     860        return ret;
     861}
     862
    937863/**
    938864 * @}
Note: See TracChangeset for help on using the changeset viewer.