Ignore:
File:
1 edited

Legend:

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

    r816f5f4 rcccd60c3  
    3535
    3636#include <usb/classes/classes.h>
    37 #include <usb/host/bus.h>
    3837#include <usb/debug.h>
    3938#include <usb/descriptor.h>
     
    4746#include <ddf/interrupt.h>
    4847#include <device/hw_res_parsed.h>
    49 #include <devman.h>
    5048#include <errno.h>
    5149#include <fibril_synch.h>
    5250#include <macros.h>
     51#include <stdio.h>
    5352#include <stdlib.h>
    5453#include <str_error.h>
     
    5756#include "ddf_helpers.h"
    5857
     58#define CTRL_PIPE_MIN_PACKET_SIZE 8
     59
     60typedef 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
    5971typedef struct hc_dev {
    6072        ddf_fun_t *ctl_fun;
    6173        hcd_t hcd;
     74        usb_dev_t *root_hub;
    6275} hc_dev_t;
    6376
     
    7891
    7992
    80 static int hcd_ddf_new_device(hcd_t *hcd, ddf_dev_t *hc, device_t *hub_dev, unsigned port);
    81 static int hcd_ddf_remove_device(ddf_dev_t *device, device_t *hub, unsigned port);
     93static int hcd_ddf_new_device(ddf_dev_t *device, usb_dev_t *hub, unsigned port);
     94static int hcd_ddf_remove_device(ddf_dev_t *device, usb_dev_t *hub, unsigned port);
    8295
    8396
     
    8699/** Register endpoint interface function.
    87100 * @param fun DDF function.
    88  * @param endpoint_desc Endpoint description.
     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.
    89107 * @return Error code.
    90108 */
    91109static int register_endpoint(
    92         ddf_fun_t *fun, usb_endpoint_desc_t *endpoint_desc)
     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)
    93113{
    94114        assert(fun);
    95115        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    96         device_t *dev = ddf_fun_data_get(fun);
     116        usb_dev_t *dev = ddf_fun_data_get(fun);
    97117        assert(hcd);
    98         assert(hcd->bus);
    99118        assert(dev);
    100 
    101         const size_t size = endpoint_desc->max_packet_size;
     119        const size_t size = max_packet_size;
     120        const usb_target_t target =
     121            {{.address = dev->address, .endpoint = endpoint}};
    102122
    103123        usb_log_debug("Register endpoint %d:%d %s-%s %zuB %ums.\n",
    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   */
     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 */
    120138static int unregister_endpoint(
    121         ddf_fun_t *fun, usb_endpoint_desc_t *endpoint_desc)
     139    ddf_fun_t *fun, usb_endpoint_t endpoint, usb_direction_t direction)
    122140{
    123141        assert(fun);
    124142        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    125         device_t *dev = ddf_fun_data_get(fun);
     143        usb_dev_t *dev = ddf_fun_data_get(fun);
    126144        assert(hcd);
    127         assert(hcd->bus);
    128145        assert(dev);
    129 
    130         const usb_target_t target = {{
    131                 .address = dev->address,
    132                 .endpoint = endpoint_desc->endpoint_no
    133         }};
    134 
     146        const usb_target_t target =
     147            {{.address = dev->address, .endpoint = endpoint}};
    135148        usb_log_debug("Unregister endpoint %d:%d %s.\n",
    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);
     149            dev->address, endpoint, usb_str_direction(direction));
     150        return hcd_remove_ep(hcd, target, direction);
    139151}
    140152
     
    143155        assert(fun);
    144156        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    145         device_t *dev = ddf_fun_data_get(fun);
     157        usb_dev_t *dev = ddf_fun_data_get(fun);
    146158        assert(hcd);
    147         assert(hcd->bus);
    148159        assert(dev);
    149160
    150161        usb_log_debug("Device %d requested default address at %s speed\n",
    151162            dev->address, usb_str_speed(speed));
    152         return bus_reserve_default_address(hcd->bus, speed);
     163        return hcd_reserve_default_address(hcd, speed);
    153164}
    154165
     
    157168        assert(fun);
    158169        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    159         device_t *dev = ddf_fun_data_get(fun);
     170        usb_dev_t *dev = ddf_fun_data_get(fun);
    160171        assert(hcd);
    161         assert(hcd->bus);
    162172        assert(dev);
    163173
    164174        usb_log_debug("Device %d released default address\n", dev->address);
    165         return bus_release_default_address(hcd->bus);
     175        return hcd_release_default_address(hcd);
    166176}
    167177
    168178static 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 
    183 static int device_remove(ddf_fun_t *fun, unsigned port)
    184179{
    185180        assert(fun);
    186181        ddf_dev_t *ddf_dev = ddf_fun_get_dev(fun);
    187         device_t *dev = ddf_fun_data_get(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
     190static 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);
    188195        assert(ddf_dev);
    189196        assert(dev);
     
    222229{
    223230        assert(fun);
    224         device_t *dev = ddf_fun_data_get(fun);
    225         assert(dev);
     231        usb_dev_t *usb_dev = ddf_fun_data_get(fun);
     232        assert(usb_dev);
    226233        const usb_target_t target = {{
    227             .address  = dev->address,
     234            .address =  usb_dev->address,
    228235            .endpoint = endpoint,
    229236        }};
     
    248255{
    249256        assert(fun);
    250         device_t *dev = ddf_fun_data_get(fun);
    251         assert(dev);
     257        usb_dev_t *usb_dev = ddf_fun_data_get(fun);
     258        assert(usb_dev);
    252259        const usb_target_t target = {{
    253             .address  = dev->address,
     260            .address =  usb_dev->address,
    254261            .endpoint = endpoint,
    255262        }};
     
    283290
    284291/* 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
     315static 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}
    285370
    286371#define ADD_MATCHID_OR_RETURN(list, sc, str, ...) \
     
    309394        assert(l);
    310395        assert(d);
    311 
     396       
    312397        if (d->vendor_id != 0) {
    313398                /* First, with release number. */
     
    316401                    d->vendor_id, d->product_id, (d->device_version >> 8),
    317402                    (d->device_version & 0xff));
    318 
     403       
    319404                /* Next, without release number. */
    320405                ADD_MATCHID_OR_RETURN(l, 90, "usb&vendor=%#04x&product=%#04x",
     
    330415
    331416        return EOK;
    332 }
    333 
    334 static int hcd_ddf_remove_device(ddf_dev_t *device, device_t *hub,
     417
     418}
     419
     420static int hcd_ddf_remove_device(ddf_dev_t *device, usb_dev_t *hub,
    335421    unsigned port)
    336422{
     
    339425        hcd_t *hcd = dev_to_hcd(device);
    340426        assert(hcd);
    341         assert(hcd->bus);
    342427
    343428        hc_dev_t *hc_dev = dev_to_hc_dev(device);
     
    346431        fibril_mutex_lock(&hub->guard);
    347432
    348         device_t *victim = NULL;
    349 
    350         list_foreach(hub->devices, link, device_t, it) {
     433        usb_dev_t *victim = NULL;
     434
     435        list_foreach(hub->devices, link, usb_dev_t, it) {
    351436                if (it->port == port) {
    352437                        victim = it;
     
    355440        }
    356441        if (victim) {
    357                 assert(victim->fun);
    358442                assert(victim->port == port);
    359                 assert(victim->hub == hub);
    360443                list_remove(&victim->link);
    361444                fibril_mutex_unlock(&hub->guard);
     
    363446                if (ret == EOK) {
    364447                        usb_address_t address = victim->address;
    365                         bus_remove_device(hcd->bus, hcd, victim);
    366448                        ddf_fun_destroy(victim->fun);
    367                         bus_release_address(hcd->bus, address);
     449                        hcd_release_address(hcd, address);
    368450                } else {
    369451                        usb_log_warning("Failed to unbind device `%s': %s\n",
     
    376458}
    377459
    378 device_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 
    399 void hcd_ddf_device_destroy(device_t *dev)
    400 {
    401         assert(dev);
    402         assert(dev->fun);
    403         ddf_fun_destroy(dev->fun);
    404 }
    405 
    406 int hcd_ddf_device_explore(hcd_t *hcd, device_t *device)
    407 {
    408         int err;
    409         match_id_list_t mids;
     460static 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,
     481        }};
     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 */
    410513        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
    417         }};
     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        }
    418567
    419568        /* Get std device descriptor */
     
    422571
    423572        usb_log_debug("Device(%d): Requesting full device descriptor.",
    424             device->address);
    425         ssize_t got = hcd_send_batch_sync(hcd, control_ep, USB_DIRECTION_IN,
     573            address);
     574        got = hcd_send_batch_sync(hcd, target, USB_DIRECTION_IN,
    426575            &desc, sizeof(desc), *(uint64_t *)&get_device_desc,
    427576            "read device descriptor");
    428         if (got < 0) {
    429                 err = got < 0 ? got : EOVERFLOW;
     577        if (ret != EOK) {
    430578                usb_log_error("Device(%d): Failed to set get dev descriptor: %s",
    431                     device->address, str_error(err));
    432                 goto out;
     579                    address, str_error(ret));
     580                hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
     581                hcd_release_address(hcd, target.address);
     582                return ret;
    433583        }
    434584
    435585        /* Create match ids from the device descriptor */
    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 
    446 out:
     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);
    447602        clean_match_ids(&mids);
    448         return err;
    449 }
    450 
    451 static 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 
    491 err_usb_dev:
    492         hcd_ddf_device_destroy(dev);
    493         return err;
     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;
    494611}
    495612
     
    499616 * @return Error code
    500617 */
    501 int hcd_setup_virtual_root_hub(hcd_t *hcd, ddf_dev_t *hc)
    502 {
    503         int err;
    504 
    505         assert(hc);
     618int hcd_ddf_setup_root_hub(ddf_dev_t *device)
     619{
     620        assert(device);
     621        hcd_t *hcd = dev_to_hcd(device);
    506622        assert(hcd);
    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 
    541 err_usb_dev:
    542         hcd_ddf_device_destroy(dev);
    543 err_default_address:
    544         bus_release_default_address(hcd->bus);
    545         return err;
     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;
    546628}
    547629
     
    556638 * This function does all the ddf work for hc driver.
    557639 */
    558 int hcd_ddf_setup_hc(ddf_dev_t *device)
     640int hcd_ddf_setup_hc(ddf_dev_t *device, usb_speed_t max_speed,
     641    size_t bw, bw_count_func_t bw_count)
    559642{
    560643        assert(device);
     
    565648                return ENOMEM;
    566649        }
    567         hcd_init(&instance->hcd);
     650        instance->root_hub = NULL;
     651        hcd_init(&instance->hcd, max_speed, bw, bw_count);
    568652
    569653        int ret = ENOMEM;
     
    607691}
    608692
    609 //TODO: Move this to generic ddf?
    610 /** Call the parent driver with a request to enable interrupts
     693//TODO: Cache parent session in HCD
     694/** Call the parent driver with a request to enable interrupt
    611695 *
    612696 * @param[in] device Device asking for interrupts
     697 * @param[in] inum Interrupt number
    613698 * @return Error code.
    614699 */
    615 int 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?
     700int 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
    628710int hcd_ddf_get_registers(ddf_dev_t *device, hw_res_list_parsed_t *hw_res)
    629711{
    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);
     712        async_sess_t *parent_sess = ddf_dev_parent_sess_get(device);
     713        if (parent_sess == NULL)
     714                return EIO;
     715
    636716        hw_res_list_parsed_init(hw_res);
    637717        const int ret = hw_res_get_list_parsed(parent_sess, hw_res, 0);
    638         async_hangup(parent_sess);
    639718        if (ret != EOK)
    640719                hw_res_list_parsed_clean(hw_res);
     
    663742 * @param[in] gen_irq_code IRQ code generator.
    664743 *
    665  * @return EOK on success or negative error code
     744 * @return IRQ capability handle on success.
     745 * @return Negative error code.
    666746 */
    667747int hcd_ddf_setup_interrupts(ddf_dev_t *device,
    668748    const hw_res_list_parsed_t *hw_res,
    669749    interrupt_handler_t handler,
    670     irq_code_gen_t gen_irq_code)
    671 {
     750    int (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *hw_res))
     751{
     752
    672753        assert(device);
    673 
    674         hcd_t *hcd = dev_to_hcd(device);
    675 
    676754        if (!handler || !gen_irq_code)
    677755                return ENOTSUP;
     
    679757        irq_code_t irq_code = {0};
    680758
    681         const int irq = gen_irq_code(&irq_code, hcd, hw_res);
     759        const int irq = gen_irq_code(&irq_code, hw_res);
    682760        if (irq < 0) {
    683761                usb_log_error("Failed to generate IRQ code: %s.\n",
     
    687765
    688766        /* Register handler to avoid interrupt lockup */
    689         int ret = register_interrupt_handler(device, irq, handler, &irq_code);
     767        const int irq_cap = register_interrupt_handler(device, irq, handler,
     768            &irq_code);
    690769        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);
    691778        if (ret != EOK) {
    692779                usb_log_error("Failed to register interrupt handler: %s.\n",
    693780                    str_error(ret));
    694                 return ret;
    695         }
    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;
     781                unregister_interrupt_handler(device, irq_cap);
     782                return ret;
     783        }
     784        return irq_cap;
    707785}
    708786
     
    766844{
    767845        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        };
    768852
    769853        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        }
    770860
    771861        hw_res_list_parsed_t hw_res;
     
    778868        }
    779869
    780         ret = hcd_ddf_setup_hc(device);
     870        ret = hcd_ddf_setup_hc(device, speed, bw[speed].bw, bw[speed].bw_count);
    781871        if (ret != EOK) {
    782872                usb_log_error("Failed to setup generic HCD.\n");
    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  */
     873                hw_res_list_parsed_clean(&hw_res);
     874                return ret;
     875        }
     876
    796877        interrupt_handler_t *irq_handler =
    797878            driver->irq_handler ? driver->irq_handler : ddf_hcd_gen_irq_handler;
    798         const int irq = hcd_ddf_setup_interrupts(device, &hw_res, irq_handler, driver->irq_code_gen);
    799         if (!(irq < 0)) {
     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) {
    800883                usb_log_debug("Hw interrupts enabled.\n");
    801884        }
    802885
    803         /* Claim the device from BIOS */
    804886        if (driver->claim)
    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;
     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;
    818902        }
    819903
    820904        /* Need working irq replacement to setup root hub */
    821         if ((irq < 0) && hcd->ops.status_hook) {
     905        if (!irqs_enabled && hcd->ops.status_hook) {
    822906                hcd->polling_fibril = fibril_create(interrupt_polling, hcd);
    823907                if (hcd->polling_fibril == 0) {
    824908                        usb_log_error("Failed to create polling fibril\n");
    825909                        ret = ENOMEM;
    826                         goto err_started;
     910                        goto irq_unregister;
    827911                }
    828912                fibril_add_ready(hcd->polling_fibril);
    829913                usb_log_warning("Failed to enable interrupts: %s."
    830                     " Falling back to polling.\n", str_error(irq));
     914                    " Falling back to polling.\n", str_error(irq_cap));
    831915        }
    832916
     
    835919         * needs to be ready at this time.
    836920         */
    837         if (driver->setup_root_hub)
    838                 ret = driver->setup_root_hub(hcd, device);
     921        ret = hcd_ddf_setup_root_hub(device);
    839922        if (ret != EOK) {
    840923                usb_log_error("Failed to setup HC root hub: %s.\n",
    841924                    str_error(ret));
    842                 goto err_polling;
     925                driver->fini(dev_to_hcd(device));
     926irq_unregister:
     927                /* Unregistering non-existent should be ok */
     928                unregister_interrupt_handler(device, irq_cap);
     929                hcd_ddf_clean_hc(device);
     930                return ret;
    843931        }
    844932
     
    846934            driver->name, ddf_dev_get_name(device));
    847935        return EOK;
    848 
    849 err_polling:
    850         // TODO: Stop the polling fibril (refactor the interrupt_polling func)
    851         //
    852 err_started:
    853         if (driver->stop)
    854                 driver->stop(hcd);
    855 err_irq:
    856         unregister_interrupt_handler(device, irq);
    857         if (driver->fini)
    858                 driver->fini(hcd);
    859 err_hcd:
    860         hcd_ddf_clean_hc(device);
    861 err_hw_res:
    862         hw_res_list_parsed_clean(&hw_res);
    863         return ret;
    864 }
    865 
     936}
    866937/**
    867938 * @}
Note: See TracChangeset for help on using the changeset viewer.