Ignore:
File:
1 edited

Legend:

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

    rcccd60c3 r816f5f4  
    3535
    3636#include <usb/classes/classes.h>
     37#include <usb/host/bus.h>
    3738#include <usb/debug.h>
    3839#include <usb/descriptor.h>
     
    4647#include <ddf/interrupt.h>
    4748#include <device/hw_res_parsed.h>
     49#include <devman.h>
    4850#include <errno.h>
    4951#include <fibril_synch.h>
    5052#include <macros.h>
    51 #include <stdio.h>
    5253#include <stdlib.h>
    5354#include <str_error.h>
     
    5657#include "ddf_helpers.h"
    5758
    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 
    7159typedef struct hc_dev {
    7260        ddf_fun_t *ctl_fun;
    7361        hcd_t hcd;
    74         usb_dev_t *root_hub;
    7562} hc_dev_t;
    7663
     
    9178
    9279
    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);
     80static int hcd_ddf_new_device(hcd_t *hcd, ddf_dev_t *hc, device_t *hub_dev, unsigned port);
     81static int hcd_ddf_remove_device(ddf_dev_t *device, device_t *hub, unsigned port);
    9582
    9683
     
    9986/** Register endpoint interface function.
    10087 * @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.
     88 * @param endpoint_desc Endpoint description.
    10789 * @return Error code.
    10890 */
    10991static 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)
     92        ddf_fun_t *fun, usb_endpoint_desc_t *endpoint_desc)
    11393{
    11494        assert(fun);
    11595        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    116         usb_dev_t *dev = ddf_fun_data_get(fun);
     96        device_t *dev = ddf_fun_data_get(fun);
    11797        assert(hcd);
     98        assert(hcd->bus);
    11899        assert(dev);
    119         const size_t size = max_packet_size;
    120         const usb_target_t target =
    121             {{.address = dev->address, .endpoint = endpoint}};
     100
     101        const size_t size = endpoint_desc->max_packet_size;
    122102
    123103        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  */
     104                dev->address, endpoint_desc->endpoint_no,
     105                usb_str_transfer_type(endpoint_desc->transfer_type),
     106                usb_str_direction(endpoint_desc->direction),
     107                endpoint_desc->max_packet_size, endpoint_desc->usb2.polling_interval);
     108
     109        return bus_add_ep(hcd->bus, dev, endpoint_desc->endpoint_no,
     110                endpoint_desc->direction, endpoint_desc->transfer_type,
     111                endpoint_desc->max_packet_size, endpoint_desc->packets,
     112                size);
     113}
     114
     115 /** Unregister endpoint interface function.
     116  * @param fun DDF function.
     117  * @param endpoint_desc Endpoint description.
     118  * @return Error code.
     119  */
    138120static int unregister_endpoint(
    139     ddf_fun_t *fun, usb_endpoint_t endpoint, usb_direction_t direction)
     121        ddf_fun_t *fun, usb_endpoint_desc_t *endpoint_desc)
    140122{
    141123        assert(fun);
    142124        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    143         usb_dev_t *dev = ddf_fun_data_get(fun);
     125        device_t *dev = ddf_fun_data_get(fun);
    144126        assert(hcd);
     127        assert(hcd->bus);
    145128        assert(dev);
    146         const usb_target_t target =
    147             {{.address = dev->address, .endpoint = endpoint}};
     129
     130        const usb_target_t target = {{
     131                .address = dev->address,
     132                .endpoint = endpoint_desc->endpoint_no
     133        }};
     134
    148135        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);
     136                dev->address, endpoint_desc->endpoint_no,
     137                usb_str_direction(endpoint_desc->direction));
     138        return bus_remove_ep(hcd->bus, target, endpoint_desc->direction);
    151139}
    152140
     
    155143        assert(fun);
    156144        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    157         usb_dev_t *dev = ddf_fun_data_get(fun);
     145        device_t *dev = ddf_fun_data_get(fun);
    158146        assert(hcd);
     147        assert(hcd->bus);
    159148        assert(dev);
    160149
    161150        usb_log_debug("Device %d requested default address at %s speed\n",
    162151            dev->address, usb_str_speed(speed));
    163         return hcd_reserve_default_address(hcd, speed);
     152        return bus_reserve_default_address(hcd->bus, speed);
    164153}
    165154
     
    168157        assert(fun);
    169158        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    170         usb_dev_t *dev = ddf_fun_data_get(fun);
     159        device_t *dev = ddf_fun_data_get(fun);
    171160        assert(hcd);
     161        assert(hcd->bus);
    172162        assert(dev);
    173163
    174164        usb_log_debug("Device %d released default address\n", dev->address);
    175         return hcd_release_default_address(hcd);
     165        return bus_release_default_address(hcd->bus);
    176166}
    177167
    178168static int device_enumerate(ddf_fun_t *fun, unsigned port)
     169{
     170        assert(fun);
     171        ddf_dev_t *hc = ddf_fun_get_dev(fun);
     172        assert(hc);
     173        hcd_t *hcd = dev_to_hcd(hc);
     174        assert(hcd);
     175        device_t *hub = ddf_fun_data_get(fun);
     176        assert(hub);
     177
     178        usb_log_debug("Hub %d reported a new USB device on port: %u\n",
     179            hub->address, port);
     180        return hcd_ddf_new_device(hcd, hc, hub, port);
     181}
     182
     183static int device_remove(ddf_fun_t *fun, unsigned port)
    179184{
    180185        assert(fun);
    181186        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);
     187        device_t *dev = ddf_fun_data_get(fun);
    195188        assert(ddf_dev);
    196189        assert(dev);
     
    229222{
    230223        assert(fun);
    231         usb_dev_t *usb_dev = ddf_fun_data_get(fun);
    232         assert(usb_dev);
     224        device_t *dev = ddf_fun_data_get(fun);
     225        assert(dev);
    233226        const usb_target_t target = {{
    234             .address =  usb_dev->address,
     227            .address  = dev->address,
    235228            .endpoint = endpoint,
    236229        }};
     
    255248{
    256249        assert(fun);
    257         usb_dev_t *usb_dev = ddf_fun_data_get(fun);
    258         assert(usb_dev);
     250        device_t *dev = ddf_fun_data_get(fun);
     251        assert(dev);
    259252        const usb_target_t target = {{
    260             .address =  usb_dev->address,
     253            .address  = dev->address,
    261254            .endpoint = endpoint,
    262255        }};
     
    290283
    291284/* 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 }
    370285
    371286#define ADD_MATCHID_OR_RETURN(list, sc, str, ...) \
     
    394309        assert(l);
    395310        assert(d);
    396        
     311
    397312        if (d->vendor_id != 0) {
    398313                /* First, with release number. */
     
    401316                    d->vendor_id, d->product_id, (d->device_version >> 8),
    402317                    (d->device_version & 0xff));
    403        
     318
    404319                /* Next, without release number. */
    405320                ADD_MATCHID_OR_RETURN(l, 90, "usb&vendor=%#04x&product=%#04x",
     
    415330
    416331        return EOK;
    417 
    418 }
    419 
    420 static int hcd_ddf_remove_device(ddf_dev_t *device, usb_dev_t *hub,
     332}
     333
     334static int hcd_ddf_remove_device(ddf_dev_t *device, device_t *hub,
    421335    unsigned port)
    422336{
     
    425339        hcd_t *hcd = dev_to_hcd(device);
    426340        assert(hcd);
     341        assert(hcd->bus);
    427342
    428343        hc_dev_t *hc_dev = dev_to_hc_dev(device);
     
    431346        fibril_mutex_lock(&hub->guard);
    432347
    433         usb_dev_t *victim = NULL;
    434 
    435         list_foreach(hub->devices, link, usb_dev_t, it) {
     348        device_t *victim = NULL;
     349
     350        list_foreach(hub->devices, link, device_t, it) {
    436351                if (it->port == port) {
    437352                        victim = it;
     
    440355        }
    441356        if (victim) {
     357                assert(victim->fun);
    442358                assert(victim->port == port);
     359                assert(victim->hub == hub);
    443360                list_remove(&victim->link);
    444361                fibril_mutex_unlock(&hub->guard);
     
    446363                if (ret == EOK) {
    447364                        usb_address_t address = victim->address;
     365                        bus_remove_device(hcd->bus, hcd, victim);
    448366                        ddf_fun_destroy(victim->fun);
    449                         hcd_release_address(hcd, address);
     367                        bus_release_address(hcd->bus, address);
    450368                } else {
    451369                        usb_log_warning("Failed to unbind device `%s': %s\n",
     
    458376}
    459377
    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,
     378device_t *hcd_ddf_device_create(ddf_dev_t *hc, size_t device_size)
     379{
     380        /* Create DDF function for the new device */
     381        ddf_fun_t *fun = ddf_fun_create(hc, fun_inner, NULL);
     382        if (!fun)
     383                return NULL;
     384
     385        ddf_fun_set_ops(fun, &usb_ops);
     386
     387        /* Create USB device node for the new device */
     388        device_t *dev = ddf_fun_data_alloc(fun, device_size);
     389        if (!dev) {
     390                ddf_fun_destroy(fun);
     391                return NULL;
     392        }
     393
     394        device_init(dev);
     395        dev->fun = fun;
     396        return dev;
     397}
     398
     399void hcd_ddf_device_destroy(device_t *dev)
     400{
     401        assert(dev);
     402        assert(dev->fun);
     403        ddf_fun_destroy(dev->fun);
     404}
     405
     406int hcd_ddf_device_explore(hcd_t *hcd, device_t *device)
     407{
     408        int err;
     409        match_id_list_t mids;
     410        usb_standard_device_descriptor_t desc = { 0 };
     411
     412        init_match_ids(&mids);
     413
     414        usb_target_t control_ep = {{
     415                .address = device->address,
     416                .endpoint = 0
    481417        }};
    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         }
    567418
    568419        /* Get std device descriptor */
     
    571422
    572423        usb_log_debug("Device(%d): Requesting full device descriptor.",
    573             address);
    574         got = hcd_send_batch_sync(hcd, target, USB_DIRECTION_IN,
     424            device->address);
     425        ssize_t got = hcd_send_batch_sync(hcd, control_ep, USB_DIRECTION_IN,
    575426            &desc, sizeof(desc), *(uint64_t *)&get_device_desc,
    576427            "read device descriptor");
    577         if (ret != EOK) {
     428        if (got < 0) {
     429                err = got < 0 ? got : EOVERFLOW;
    578430                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;
     431                    device->address, str_error(err));
     432                goto out;
    583433        }
    584434
    585435        /* 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);
     436        usb_log_debug("Device(%d): Creating match IDs.", device->address);
     437        if ((err = create_match_ids(&mids, &desc))) {
     438                usb_log_error("Device(%d): Failed to create match ids: %s", device->address, str_error(err));
     439                goto out;
     440        }
     441
     442        list_foreach(mids.ids, link, const match_id_t, mid) {
     443                ddf_fun_add_match_id(device->fun, mid->id, mid->score);
     444        }
     445
     446out:
    602447        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;
     448        return err;
     449}
     450
     451static int hcd_ddf_new_device(hcd_t *hcd, ddf_dev_t *hc, device_t *hub, unsigned port)
     452{
     453        int err;
     454        assert(hcd);
     455        assert(hcd->bus);
     456        assert(hub);
     457        assert(hc);
     458
     459        device_t *dev = hcd_ddf_device_create(hc, hcd->bus->device_size);
     460        if (!dev) {
     461                usb_log_error("Failed to create USB device function.");
     462                return ENOMEM;
     463        }
     464
     465        dev->hub = hub;
     466        dev->port = port;
     467
     468        if ((err = bus_enumerate_device(hcd->bus, hcd, dev))) {
     469                usb_log_error("Failed to initialize USB dev memory structures.");
     470                return err;
     471        }
     472
     473        /* If the driver didn't name the dev when enumerating,
     474         * do it in some generic way.
     475         */
     476        if (!ddf_fun_get_name(dev->fun)) {
     477                device_set_default_name(dev);
     478        }
     479
     480        if ((err = ddf_fun_bind(dev->fun))) {
     481                usb_log_error("Device(%d): Failed to register: %s.", dev->address, str_error(err));
     482                goto err_usb_dev;
     483        }
     484
     485        fibril_mutex_lock(&hub->guard);
     486        list_append(&dev->link, &hub->devices);
     487        fibril_mutex_unlock(&hub->guard);
     488
     489        return EOK;
     490
     491err_usb_dev:
     492        hcd_ddf_device_destroy(dev);
     493        return err;
    611494}
    612495
     
    616499 * @return Error code
    617500 */
    618 int hcd_ddf_setup_root_hub(ddf_dev_t *device)
    619 {
    620         assert(device);
    621         hcd_t *hcd = dev_to_hcd(device);
     501int hcd_setup_virtual_root_hub(hcd_t *hcd, ddf_dev_t *hc)
     502{
     503        int err;
     504
     505        assert(hc);
    622506        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;
     507        assert(hcd->bus);
     508
     509        if ((err = bus_reserve_default_address(hcd->bus, USB_SPEED_MAX))) {
     510                usb_log_error("Failed to reserve default address for roothub setup: %s", str_error(err));
     511                return err;
     512        }
     513
     514        device_t *dev = hcd_ddf_device_create(hc, USB_SPEED_MAX);
     515        if (!dev) {
     516                usb_log_error("Failed to create function for the root hub.");
     517                goto err_default_address;
     518        }
     519
     520        ddf_fun_set_name(dev->fun, "roothub");
     521
     522        dev->tt = (usb_tt_address_t) {
     523                .address = -1,
     524                .port = 0,
     525        };
     526
     527        /* Assign an address to the device */
     528        if ((err = bus_enumerate_device(hcd->bus, hcd, dev))) {
     529                usb_log_error("Failed to enumerate roothub device: %s", str_error(err));
     530                goto err_usb_dev;
     531        }
     532
     533        if ((err = ddf_fun_bind(dev->fun))) {
     534                usb_log_error("Failed to register roothub: %s.", str_error(err));
     535                goto err_usb_dev;
     536        }
     537
     538        bus_release_default_address(hcd->bus);
     539        return EOK;
     540
     541err_usb_dev:
     542        hcd_ddf_device_destroy(dev);
     543err_default_address:
     544        bus_release_default_address(hcd->bus);
     545        return err;
    628546}
    629547
     
    638556 * This function does all the ddf work for hc driver.
    639557 */
    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)
     558int hcd_ddf_setup_hc(ddf_dev_t *device)
    642559{
    643560        assert(device);
     
    648565                return ENOMEM;
    649566        }
    650         instance->root_hub = NULL;
    651         hcd_init(&instance->hcd, max_speed, bw, bw_count);
     567        hcd_init(&instance->hcd);
    652568
    653569        int ret = ENOMEM;
     
    691607}
    692608
    693 //TODO: Cache parent session in HCD
    694 /** Call the parent driver with a request to enable interrupt
     609//TODO: Move this to generic ddf?
     610/** Call the parent driver with a request to enable interrupts
    695611 *
    696612 * @param[in] device Device asking for interrupts
    697  * @param[in] inum Interrupt number
    698613 * @return Error code.
    699614 */
    700 int hcd_ddf_enable_interrupt(ddf_dev_t *device, int inum)
    701 {
    702         async_sess_t *parent_sess = ddf_dev_parent_sess_get(device);
    703         if (parent_sess == NULL)
    704                 return EIO;
    705 
    706         return hw_res_enable_interrupt(parent_sess, inum);
    707 }
    708 
    709 //TODO: Cache parent session in HCD
     615int hcd_ddf_enable_interrupts(ddf_dev_t *device)
     616{
     617        assert(device);
     618        async_sess_t *parent_sess =
     619            devman_parent_device_connect(ddf_dev_get_handle(device),
     620            IPC_FLAG_BLOCKING);
     621        const bool enabled = hw_res_enable_interrupt(parent_sess);
     622        async_hangup(parent_sess);
     623
     624        return enabled ? EOK : EIO;
     625}
     626
     627//TODO: Move this to generic ddf?
    710628int hcd_ddf_get_registers(ddf_dev_t *device, hw_res_list_parsed_t *hw_res)
    711629{
    712         async_sess_t *parent_sess = ddf_dev_parent_sess_get(device);
    713         if (parent_sess == NULL)
    714                 return EIO;
    715 
     630        assert(device);
     631        assert(hw_res);
     632
     633        async_sess_t *parent_sess =
     634            devman_parent_device_connect(ddf_dev_get_handle(device),
     635            IPC_FLAG_BLOCKING);
    716636        hw_res_list_parsed_init(hw_res);
    717637        const int ret = hw_res_get_list_parsed(parent_sess, hw_res, 0);
     638        async_hangup(parent_sess);
    718639        if (ret != EOK)
    719640                hw_res_list_parsed_clean(hw_res);
     
    742663 * @param[in] gen_irq_code IRQ code generator.
    743664 *
    744  * @return IRQ capability handle on success.
    745  * @return Negative error code.
     665 * @return EOK on success or negative error code
    746666 */
    747667int hcd_ddf_setup_interrupts(ddf_dev_t *device,
    748668    const hw_res_list_parsed_t *hw_res,
    749669    interrupt_handler_t handler,
    750     int (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *hw_res))
    751 {
    752 
     670    irq_code_gen_t gen_irq_code)
     671{
    753672        assert(device);
     673
     674        hcd_t *hcd = dev_to_hcd(device);
     675
    754676        if (!handler || !gen_irq_code)
    755677                return ENOTSUP;
     
    757679        irq_code_t irq_code = {0};
    758680
    759         const int irq = gen_irq_code(&irq_code, hw_res);
     681        const int irq = gen_irq_code(&irq_code, hcd, hw_res);
    760682        if (irq < 0) {
    761683                usb_log_error("Failed to generate IRQ code: %s.\n",
     
    765687
    766688        /* Register handler to avoid interrupt lockup */
    767         const int irq_cap = register_interrupt_handler(device, irq, handler,
    768             &irq_code);
     689        int ret = register_interrupt_handler(device, irq, handler, &irq_code);
    769690        irq_code_clean(&irq_code);
    770         if (irq_cap < 0) {
    771                 usb_log_error("Failed to register interrupt handler: %s.\n",
    772                     str_error(irq_cap));
    773                 return irq_cap;
    774         }
    775 
    776         /* Enable interrupts */
    777         int ret = hcd_ddf_enable_interrupt(device, irq);
    778691        if (ret != EOK) {
    779692                usb_log_error("Failed to register interrupt handler: %s.\n",
    780693                    str_error(ret));
    781                 unregister_interrupt_handler(device, irq_cap);
    782694                return ret;
    783695        }
    784         return irq_cap;
     696
     697        /* Enable interrupts */
     698        ret = hcd_ddf_enable_interrupts(device);
     699        if (ret != EOK) {
     700                usb_log_error("Failed to enable interrupts: %s.\n",
     701                    str_error(ret));
     702                unregister_interrupt_handler(device, irq);
     703                return ret;
     704        }
     705        assert(irq > 0);
     706        return irq;
    785707}
    786708
     
    844766{
    845767        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         };
    852768
    853769        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         }
    860770
    861771        hw_res_list_parsed_t hw_res;
     
    868778        }
    869779
    870         ret = hcd_ddf_setup_hc(device, speed, bw[speed].bw, bw[speed].bw_count);
     780        ret = hcd_ddf_setup_hc(device);
    871781        if (ret != EOK) {
    872782                usb_log_error("Failed to setup generic HCD.\n");
    873                 hw_res_list_parsed_clean(&hw_res);
    874                 return ret;
    875         }
    876 
     783                goto err_hw_res;
     784        }
     785
     786        hcd_t *hcd = dev_to_hcd(device);
     787
     788        if (driver->init)
     789                ret = driver->init(hcd, &hw_res);
     790        if (ret != EOK) {
     791                usb_log_error("Failed to init HCD.\n");
     792                goto err_hcd;
     793        }
     794
     795        /* Setup interrupts  */
    877796        interrupt_handler_t *irq_handler =
    878797            driver->irq_handler ? driver->irq_handler : ddf_hcd_gen_irq_handler;
    879         const int irq_cap = hcd_ddf_setup_interrupts(device, &hw_res,
    880             irq_handler, driver->irq_code_gen);
    881         bool irqs_enabled = !(irq_cap < 0);
    882         if (irqs_enabled) {
     798        const int irq = hcd_ddf_setup_interrupts(device, &hw_res, irq_handler, driver->irq_code_gen);
     799        if (!(irq < 0)) {
    883800                usb_log_debug("Hw interrupts enabled.\n");
    884801        }
    885802
     803        /* Claim the device from BIOS */
    886804        if (driver->claim)
    887                 ret = driver->claim(device);
    888         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);
    899         if (ret != EOK) {
    900                 usb_log_error("Failed to init HCD: %s.\n", str_error(ret));
    901                 goto irq_unregister;
     805                ret = driver->claim(hcd, device);
     806        if (ret != EOK) {
     807                usb_log_error("Failed to claim `%s' for driver `%s': %s",
     808                    ddf_dev_get_name(device), driver->name, str_error(ret));
     809                goto err_irq;
     810        }
     811
     812        /* Start hw driver */
     813        if (driver->start)
     814                ret = driver->start(hcd, !(irq < 0));
     815        if (ret != EOK) {
     816                usb_log_error("Failed to start HCD: %s.\n", str_error(ret));
     817                goto err_irq;
    902818        }
    903819
    904820        /* Need working irq replacement to setup root hub */
    905         if (!irqs_enabled && hcd->ops.status_hook) {
     821        if ((irq < 0) && hcd->ops.status_hook) {
    906822                hcd->polling_fibril = fibril_create(interrupt_polling, hcd);
    907823                if (hcd->polling_fibril == 0) {
    908824                        usb_log_error("Failed to create polling fibril\n");
    909825                        ret = ENOMEM;
    910                         goto irq_unregister;
     826                        goto err_started;
    911827                }
    912828                fibril_add_ready(hcd->polling_fibril);
    913829                usb_log_warning("Failed to enable interrupts: %s."
    914                     " Falling back to polling.\n", str_error(irq_cap));
     830                    " Falling back to polling.\n", str_error(irq));
    915831        }
    916832
     
    919835         * needs to be ready at this time.
    920836         */
    921         ret = hcd_ddf_setup_root_hub(device);
     837        if (driver->setup_root_hub)
     838                ret = driver->setup_root_hub(hcd, device);
    922839        if (ret != EOK) {
    923840                usb_log_error("Failed to setup HC root hub: %s.\n",
    924841                    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;
     842                goto err_polling;
    931843        }
    932844
     
    934846            driver->name, ddf_dev_get_name(device));
    935847        return EOK;
    936 }
     848
     849err_polling:
     850        // TODO: Stop the polling fibril (refactor the interrupt_polling func)
     851        //
     852err_started:
     853        if (driver->stop)
     854                driver->stop(hcd);
     855err_irq:
     856        unregister_interrupt_handler(device, irq);
     857        if (driver->fini)
     858                driver->fini(hcd);
     859err_hcd:
     860        hcd_ddf_clean_hc(device);
     861err_hw_res:
     862        hw_res_list_parsed_clean(&hw_res);
     863        return ret;
     864}
     865
    937866/**
    938867 * @}
Note: See TracChangeset for help on using the changeset viewer.