Ignore:
File:
1 edited

Legend:

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

    ra6afb4c r4547f11  
    3131 */
    3232/** @file
    33  * Helpers to work with the DDF interface.
    34  */
     33 *
     34 */
     35
     36#include <usb/classes/classes.h>
     37#include <usb/debug.h>
     38#include <usb/descriptor.h>
     39#include <usb/request.h>
     40#include <usb/usb.h>
    3541
    3642#include <adt/list.h>
     
    4147#include <device/hw_res_parsed.h>
    4248#include <errno.h>
     49#include <fibril_synch.h>
     50#include <macros.h>
     51#include <stdio.h>
     52#include <stdlib.h>
    4353#include <str_error.h>
    44 #include <usb/classes/classes.h>
    45 #include <usb/debug.h>
    46 #include <usb/descriptor.h>
    47 #include <usb/usb.h>
    4854#include <usb_iface.h>
    49 #include <usbhc_iface.h>
    50 
    51 #include "bus.h"
    52 #include "endpoint.h"
    5355
    5456#include "ddf_helpers.h"
    5557
    56 /**
    57  * DDF usbhc_iface callback. Passes the endpoint descriptors, fills the pipe
    58  * descriptor according to the contents of the endpoint.
    59  *
    60  * @param[in] fun DDF function of the device in question.
    61  * @param[out] pipe_desc The pipe descriptor to be filled.
    62  * @param[in] endpoint_desc Endpoint descriptors from the device.
     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
     71typedef struct hc_dev {
     72        ddf_fun_t *ctl_fun;
     73        hcd_t hcd;
     74        usb_dev_t *root_hub;
     75} hc_dev_t;
     76
     77static hc_dev_t *dev_to_hc_dev(ddf_dev_t *dev)
     78{
     79        return ddf_dev_data_get(dev);
     80}
     81
     82hcd_t *dev_to_hcd(ddf_dev_t *dev)
     83{
     84        hc_dev_t *hc_dev = dev_to_hc_dev(dev);
     85        if (!hc_dev) {
     86                usb_log_error("Invalid HCD device.\n");
     87                return NULL;
     88        }
     89        return &hc_dev->hcd;
     90}
     91
     92
     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);
     95
     96
     97/* DDF INTERFACE */
     98
     99/** Register endpoint interface function.
     100 * @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.
    63107 * @return Error code.
    64108 */
    65 static int register_endpoint(ddf_fun_t *fun, usb_pipe_desc_t *pipe_desc,
    66      const usb_endpoint_descriptors_t *ep_desc)
     109static 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)
    67113{
    68114        assert(fun);
    69         hc_device_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    70         device_t *dev = ddf_fun_data_get(fun);
     115        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
     116        usb_dev_t *dev = ddf_fun_data_get(fun);
    71117        assert(hcd);
    72         assert(hcd->bus);
    73118        assert(dev);
    74 
    75         endpoint_t *ep;
    76         const int err = bus_endpoint_add(dev, ep_desc, &ep);
    77         if (err)
    78                 return err;
    79 
    80         if (pipe_desc) {
    81                 pipe_desc->endpoint_no = ep->endpoint;
    82                 pipe_desc->direction = ep->direction;
    83                 pipe_desc->transfer_type = ep->transfer_type;
    84                 pipe_desc->max_transfer_size = ep->max_transfer_size;
    85         }
    86         endpoint_del_ref(ep);
    87 
    88         return EOK;
    89 }
    90 
    91  /**
    92   * DDF usbhc_iface callback. Unregister endpoint that makes the other end of
    93   * the pipe described.
    94   *
    95   * @param fun DDF function of the device in question.
    96   * @param pipe_desc Pipe description.
    97   * @return Error code.
    98   */
    99 static int unregister_endpoint(ddf_fun_t *fun, const usb_pipe_desc_t *pipe_desc)
     119        const size_t size = max_packet_size;
     120        const usb_target_t target =
     121            {{.address = dev->address, .endpoint = endpoint}};
     122
     123        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 */
     138static int unregister_endpoint(
     139    ddf_fun_t *fun, usb_endpoint_t endpoint, usb_direction_t direction)
    100140{
    101141        assert(fun);
    102         hc_device_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    103         device_t *dev = ddf_fun_data_get(fun);
     142        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
     143        usb_dev_t *dev = ddf_fun_data_get(fun);
    104144        assert(hcd);
    105         assert(hcd->bus);
    106145        assert(dev);
    107 
    108         endpoint_t *ep = bus_find_endpoint(dev, pipe_desc->endpoint_no, pipe_desc->direction);
    109         if (!ep)
    110                 return ENOENT;
    111 
    112         return bus_endpoint_remove(ep);
    113 }
    114 
    115 /**
    116  * DDF usbhc_iface callback. Calls the respective bus operation directly.
    117  *
    118  * @param fun DDF function of the device (hub) requesting the address.
    119  */
    120 static int default_address_reservation(ddf_fun_t *fun, bool reserve)
     146        const usb_target_t target =
     147            {{.address = dev->address, .endpoint = endpoint}};
     148        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);
     151}
     152
     153static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed)
    121154{
    122155        assert(fun);
    123         hc_device_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    124         device_t *dev = ddf_fun_data_get(fun);
     156        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
     157        usb_dev_t *dev = ddf_fun_data_get(fun);
    125158        assert(hcd);
    126         assert(hcd->bus);
    127159        assert(dev);
    128160
    129         usb_log_debug("Device %d %s default address", dev->address, reserve ? "requested" : "releasing");
    130         if (reserve) {
    131                 return bus_reserve_default_address(hcd->bus, dev);
    132         } else {
    133                 bus_release_default_address(hcd->bus, dev);
    134                 return EOK;
    135         }
    136 }
    137 
    138 /**
    139  * DDF usbhc_iface callback. Calls the bus operation directly.
    140  *
    141  * @param fun DDF function of the device (hub) requesting the address.
    142  * @param speed USB speed of the new device
    143  */
    144 static int device_enumerate(ddf_fun_t *fun, unsigned port, usb_speed_t speed)
     161        usb_log_debug("Device %d requested default address at %s speed\n",
     162            dev->address, usb_str_speed(speed));
     163        return hcd_reserve_default_address(hcd, speed);
     164}
     165
     166static int release_default_address(ddf_fun_t *fun)
    145167{
    146168        assert(fun);
    147         ddf_dev_t *hc = ddf_fun_get_dev(fun);
    148         assert(hc);
    149         hc_device_t *hcd = dev_to_hcd(hc);
     169        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
     170        usb_dev_t *dev = ddf_fun_data_get(fun);
    150171        assert(hcd);
    151         device_t *hub = ddf_fun_data_get(fun);
    152         assert(hub);
    153 
    154         int err;
    155 
    156         if (!usb_speed_is_valid(speed))
    157                 return EINVAL;
    158 
    159         usb_log_debug("Hub %d reported a new %s speed device on port: %u",
    160             hub->address, usb_str_speed(speed), port);
    161 
    162         device_t *dev = hcd_ddf_fun_create(hcd, speed);
    163         if (!dev) {
    164                 usb_log_error("Failed to create USB device function.");
    165                 return ENOMEM;
    166         }
    167 
    168         dev->hub = hub;
    169         dev->tier = hub->tier + 1;
    170         dev->port = port;
    171         dev->speed = speed;
    172 
    173         if ((err = bus_device_enumerate(dev))) {
    174                 usb_log_error("Failed to initialize USB dev memory structures.");
    175                 goto err_usb_dev;
    176         }
    177 
    178         /* If the driver didn't name the dev when enumerating,
    179          * do it in some generic way.
    180          */
    181         if (!ddf_fun_get_name(dev->fun)) {
    182                 bus_device_set_default_name(dev);
    183         }
    184 
    185         if ((err = ddf_fun_bind(dev->fun))) {
    186                 usb_log_error("Device(%d): Failed to register: %s.", dev->address, str_error(err));
    187                 goto err_usb_dev;
    188         }
    189 
    190         return EOK;
    191 
    192 err_usb_dev:
    193         hcd_ddf_fun_destroy(dev);
    194         return err;
     172        assert(dev);
     173
     174        usb_log_debug("Device %d released default address\n", dev->address);
     175        return hcd_release_default_address(hcd);
     176}
     177
     178static int device_enumerate(ddf_fun_t *fun, unsigned port)
     179{
     180        assert(fun);
     181        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);
    195188}
    196189
     
    198191{
    199192        assert(fun);
    200         device_t *hub = ddf_fun_data_get(fun);
    201         assert(hub);
    202         usb_log_debug("Hub `%s' reported removal of device on port %u",
     193        ddf_dev_t *ddf_dev = ddf_fun_get_dev(fun);
     194        usb_dev_t *dev = ddf_fun_data_get(fun);
     195        assert(ddf_dev);
     196        assert(dev);
     197        usb_log_debug("Hub `%s' reported removal of device on port %u\n",
    203198            ddf_fun_get_name(fun), port);
    204 
    205         device_t *victim = NULL;
    206 
    207         fibril_mutex_lock(&hub->guard);
    208         list_foreach(hub->devices, link, device_t, it) {
    209                 if (it->port == port) {
    210                         victim = it;
    211                         break;
    212                 }
    213         }
    214         fibril_mutex_unlock(&hub->guard);
    215 
    216         if (!victim) {
    217                 usb_log_warning("Hub '%s' tried to remove non-existent"
    218                     " device.", ddf_fun_get_name(fun));
    219                 return ENOENT;
    220         }
    221 
    222         assert(victim->fun);
    223         assert(victim->port == port);
    224         assert(victim->hub == hub);
    225 
    226         bus_device_gone(victim);
    227         return EOK;
    228 }
    229 
    230 /**
    231  * Gets description of the device that is calling.
     199        return hcd_ddf_remove_device(ddf_dev, dev, port);
     200}
     201
     202/** Gets handle of the respective device.
    232203 *
    233204 * @param[in] fun Device function.
    234  * @param[out] desc Device descriptor to be filled.
     205 * @param[out] handle Place to write the handle.
    235206 * @return Error code.
    236207 */
    237 static int get_device_description(ddf_fun_t *fun, usb_device_desc_t *desc)
     208static int get_my_device_handle(ddf_fun_t *fun, devman_handle_t *handle)
    238209{
    239210        assert(fun);
    240         device_t *dev = ddf_fun_data_get(fun);
    241         assert(dev);
    242 
    243         if (!desc)
    244                 return EOK;
    245 
    246         *desc = (usb_device_desc_t) {
    247                 .address = dev->address,
    248                 .depth = dev->tier,
    249                 .speed = dev->speed,
    250                 .handle = ddf_fun_get_handle(fun),
    251                 .iface = -1,
    252         };
     211        if (handle)
     212                *handle = ddf_fun_get_handle(fun);
    253213        return EOK;
    254214}
     
    264224 * @return Error code.
    265225 */
    266 static int dev_read(ddf_fun_t *fun, usb_target_t target,
    267     uint64_t setup_data, char *data, size_t size,
    268     usbhc_iface_transfer_callback_t callback, void *arg)
     226static int dev_read(ddf_fun_t *fun, usb_endpoint_t endpoint,
     227    uint64_t setup_data, uint8_t *data, size_t size,
     228    usbhc_iface_transfer_in_callback_t callback, void *arg)
    269229{
    270230        assert(fun);
    271         device_t *dev = ddf_fun_data_get(fun);
    272         assert(dev);
    273 
    274         target.address = dev->address;
    275 
    276         if (!usb_target_is_valid(&target))
    277                 return EINVAL;
    278 
    279         if (size > 0 && data == NULL)
    280                 return EBADMEM;
    281 
    282         if (!callback && arg)
    283                 return EBADMEM;
    284 
    285         return bus_device_send_batch(dev, target, USB_DIRECTION_IN,
    286             data, size, setup_data,
    287             callback, arg, "READ");
     231        usb_dev_t *usb_dev = ddf_fun_data_get(fun);
     232        assert(usb_dev);
     233        const usb_target_t target = {{
     234            .address =  usb_dev->address,
     235            .endpoint = endpoint,
     236        }};
     237        return hcd_send_batch(dev_to_hcd(ddf_fun_get_dev(fun)), target,
     238            USB_DIRECTION_IN, data, size, setup_data, callback, NULL, arg,
     239            "READ");
    288240}
    289241
     
    298250 * @return Error code.
    299251 */
    300 static int dev_write(ddf_fun_t *fun, usb_target_t target,
    301     uint64_t setup_data, const char *data, size_t size,
    302     usbhc_iface_transfer_callback_t callback, void *arg)
     252static int dev_write(ddf_fun_t *fun, usb_endpoint_t endpoint,
     253    uint64_t setup_data, const uint8_t *data, size_t size,
     254    usbhc_iface_transfer_out_callback_t callback, void *arg)
    303255{
    304256        assert(fun);
    305         device_t *dev = ddf_fun_data_get(fun);
    306         assert(dev);
    307 
    308         target.address = dev->address;
    309 
    310         if (!usb_target_is_valid(&target))
    311                 return EINVAL;
    312 
    313         if (size > 0 && data == NULL)
    314                 return EBADMEM;
    315 
    316         if (!callback && arg)
    317                 return EBADMEM;
    318 
    319         return bus_device_send_batch(dev, target, USB_DIRECTION_OUT,
    320             (char *) data, size, setup_data,
     257        usb_dev_t *usb_dev = ddf_fun_data_get(fun);
     258        assert(usb_dev);
     259        const usb_target_t target = {{
     260            .address =  usb_dev->address,
     261            .endpoint = endpoint,
     262        }};
     263        return hcd_send_batch(dev_to_hcd(ddf_fun_get_dev(fun)),
     264            target, USB_DIRECTION_OUT, (uint8_t*)data, size, setup_data, NULL,
    321265            callback, arg, "WRITE");
    322266}
     
    324268/** USB device interface */
    325269static usb_iface_t usb_iface = {
    326         .get_my_description = get_device_description,
    327 };
    328 
    329 /** USB host controller interface */
    330 static usbhc_iface_t usbhc_iface = {
    331         .default_address_reservation = default_address_reservation,
     270        .get_my_device_handle = get_my_device_handle,
     271
     272        .reserve_default_address = reserve_default_address,
     273        .release_default_address = release_default_address,
    332274
    333275        .device_enumerate = device_enumerate,
     
    344286static ddf_dev_ops_t usb_ops = {
    345287        .interfaces[USB_DEV_IFACE] = &usb_iface,
    346         .interfaces[USBHC_DEV_IFACE] = &usbhc_iface,
    347288};
    348289
    349290
    350291/* 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}
    351370
    352371#define ADD_MATCHID_OR_RETURN(list, sc, str, ...) \
     
    375394        assert(l);
    376395        assert(d);
    377 
     396       
    378397        if (d->vendor_id != 0) {
    379398                /* First, with release number. */
     
    382401                    d->vendor_id, d->product_id, (d->device_version >> 8),
    383402                    (d->device_version & 0xff));
    384 
     403       
    385404                /* Next, without release number. */
    386405                ADD_MATCHID_OR_RETURN(l, 90, "usb&vendor=%#04x&product=%#04x",
     
    396415
    397416        return EOK;
    398 }
    399 
    400 device_t *hcd_ddf_fun_create(hc_device_t *hc, usb_speed_t speed)
    401 {
    402         /* Create DDF function for the new device */
    403         ddf_fun_t *fun = ddf_fun_create(hc->ddf_dev, fun_inner, NULL);
    404         if (!fun)
    405                 return NULL;
    406 
    407         ddf_fun_set_ops(fun, &usb_ops);
    408 
    409         /* Create USB device node for the new device */
    410         device_t *dev = ddf_fun_data_alloc(fun, hc->bus->device_size);
    411         if (!dev) {
    412                 ddf_fun_destroy(fun);
    413                 return NULL;
    414         }
    415 
    416         bus_device_init(dev, hc->bus);
    417         dev->fun = fun;
    418         dev->speed = speed;
    419         return dev;
    420 }
    421 
    422 void hcd_ddf_fun_destroy(device_t *dev)
    423 {
    424         assert(dev);
    425         assert(dev->fun);
    426         ddf_fun_destroy(dev->fun);
    427 }
    428 
    429 int hcd_ddf_setup_match_ids(device_t *device, usb_standard_device_descriptor_t *desc)
    430 {
    431         int err;
     417
     418}
     419
     420static int hcd_ddf_remove_device(ddf_dev_t *device, usb_dev_t *hub,
     421    unsigned port)
     422{
     423        assert(device);
     424
     425        hcd_t *hcd = dev_to_hcd(device);
     426        assert(hcd);
     427
     428        hc_dev_t *hc_dev = dev_to_hc_dev(device);
     429        assert(hc_dev);
     430
     431        fibril_mutex_lock(&hub->guard);
     432
     433        usb_dev_t *victim = NULL;
     434
     435        list_foreach(hub->devices, link, usb_dev_t, it) {
     436                if (it->port == port) {
     437                        victim = it;
     438                        break;
     439                }
     440        }
     441        if (victim) {
     442                assert(victim->port == port);
     443                list_remove(&victim->link);
     444                fibril_mutex_unlock(&hub->guard);
     445                const int ret = ddf_fun_unbind(victim->fun);
     446                if (ret == EOK) {
     447                        usb_address_t address = victim->address;
     448                        ddf_fun_destroy(victim->fun);
     449                        hcd_release_address(hcd, address);
     450                } else {
     451                        usb_log_warning("Failed to unbind device `%s': %s\n",
     452                            ddf_fun_get_name(victim->fun), str_error(ret));
     453                }
     454                return EOK;
     455        }
     456        fibril_mutex_unlock(&hub->guard);
     457        return ENOENT;
     458}
     459
     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        usb_address_t address;
     484        ret = hcd_request_address(hcd, speed, &address);
     485        if (ret != EOK) {
     486                usb_log_error("Failed to reserve new address: %s.",
     487                    str_error(ret));
     488                return ret;
     489        }
     490
     491        usb_log_debug("Reserved new address: %d\n", address);
     492
     493        const usb_target_t target = {{
     494                .address = address,
     495                .endpoint = 0,
     496        }};
     497
     498        const usb_address_t tt_address = hub ? hub->tt_address : -1;
     499
     500        /* Add default pipe on default address */
     501        usb_log_debug("Device(%d): Adding default target(0:0)\n", address);
     502        ret = hcd_add_ep(hcd,
     503            default_target, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL,
     504            CTRL_PIPE_MIN_PACKET_SIZE, CTRL_PIPE_MIN_PACKET_SIZE, 1,
     505            tt_address, port);
     506        if (ret != EOK) {
     507                usb_log_error("Device(%d): Failed to add default target: %s.",
     508                    address, str_error(ret));
     509                hcd_release_address(hcd, address);
     510                return ret;
     511        }
     512
     513        /* Get max packet size for default pipe */
     514        usb_standard_device_descriptor_t desc = { 0 };
     515        const usb_device_request_setup_packet_t get_device_desc_8 =
     516            GET_DEVICE_DESC(CTRL_PIPE_MIN_PACKET_SIZE);
     517
     518        // TODO CALLBACKS
     519        usb_log_debug("Device(%d): Requesting first 8B of device descriptor.",
     520            address);
     521        size_t got;
     522        ret = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_IN,
     523            &desc, CTRL_PIPE_MIN_PACKET_SIZE, *(uint64_t *)&get_device_desc_8,
     524            "read first 8 bytes of dev descriptor", &got);
     525
     526        if (ret == EOK && got != CTRL_PIPE_MIN_PACKET_SIZE) {
     527                ret = EOVERFLOW;
     528        }
     529
     530        if (ret != EOK) {
     531                usb_log_error("Device(%d): Failed to get 8B of dev descr: %s.",
     532                    address, str_error(ret));
     533                hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH);
     534                hcd_release_address(hcd, address);
     535                return ret;
     536        }
     537
     538        /* Register EP on the new address */
     539        usb_log_debug("Device(%d): Registering control EP.", address);
     540        ret = hcd_add_ep(hcd, target, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL,
     541            ED_MPS_PACKET_SIZE_GET(uint16_usb2host(desc.max_packet_size)),
     542            ED_MPS_TRANS_OPPORTUNITIES_GET(uint16_usb2host(desc.max_packet_size)),
     543            ED_MPS_PACKET_SIZE_GET(uint16_usb2host(desc.max_packet_size)),
     544            tt_address, port);
     545        if (ret != EOK) {
     546                usb_log_error("Device(%d): Failed to register EP0: %s",
     547                    address, str_error(ret));
     548                hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH);
     549                hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
     550                hcd_release_address(hcd, address);
     551                return ret;
     552        }
     553
     554        /* Set new address */
     555        const usb_device_request_setup_packet_t set_address =
     556            SET_ADDRESS(target.address);
     557
     558        usb_log_debug("Device(%d): Setting USB address.", address);
     559        ret = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_OUT,
     560            NULL, 0, *(uint64_t *)&set_address, "set address", &got);
     561
     562        usb_log_debug("Device(%d): Removing default (0:0) EP.", address);
     563        hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH);
     564
     565        if (ret != EOK) {
     566                usb_log_error("Device(%d): Failed to set new address: %s.",
     567                    address, str_error(ret));
     568                hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
     569                hcd_release_address(hcd, address);
     570                return ret;
     571        }
     572
     573        /* Get std device descriptor */
     574        const usb_device_request_setup_packet_t get_device_desc =
     575            GET_DEVICE_DESC(sizeof(desc));
     576
     577        usb_log_debug("Device(%d): Requesting full device descriptor.",
     578            address);
     579        ret = hcd_send_batch_sync(hcd, target, USB_DIRECTION_IN,
     580            &desc, sizeof(desc), *(uint64_t *)&get_device_desc,
     581            "read device descriptor", &got);
     582        if (ret != EOK) {
     583                usb_log_error("Device(%d): Failed to set get dev descriptor: %s",
     584                    address, str_error(ret));
     585                hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
     586                hcd_release_address(hcd, target.address);
     587                return ret;
     588        }
     589
     590        /* Create match ids from the device descriptor */
    432591        match_id_list_t mids;
    433 
    434592        init_match_ids(&mids);
    435593
    436         /* Create match ids from the device descriptor */
    437         usb_log_debug("Device(%d): Creating match IDs.", device->address);
    438         if ((err = create_match_ids(&mids, desc))) {
    439                 return err;
    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         return EOK;
     594        usb_log_debug("Device(%d): Creating match IDs.", address);
     595        ret = create_match_ids(&mids, &desc);
     596        if (ret != EOK) {
     597                usb_log_error("Device(%d): Failed to create match ids: %s",
     598                    address, str_error(ret));
     599                hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
     600                hcd_release_address(hcd, target.address);
     601                return ret;
     602        }
     603
     604        /* Register device */
     605        usb_log_debug("Device(%d): Registering DDF device.", address);
     606        ret = hcd_ddf_add_device(device, hub, port, address, speed, NULL, &mids);
     607        clean_match_ids(&mids);
     608        if (ret != EOK) {
     609                usb_log_error("Device(%d): Failed to register: %s.",
     610                    address, str_error(ret));
     611                hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
     612                hcd_release_address(hcd, target.address);
     613        }
     614
     615        return ret;
     616}
     617
     618/** Announce root hub to the DDF
     619 *
     620 * @param[in] device Host controller ddf device
     621 * @return Error code
     622 */
     623int hcd_ddf_setup_root_hub(ddf_dev_t *device)
     624{
     625        assert(device);
     626        hcd_t *hcd = dev_to_hcd(device);
     627        assert(hcd);
     628
     629        hcd_reserve_default_address(hcd, hcd->bus.max_speed);
     630        const int ret = hcd_ddf_new_device(device, NULL, 0);
     631        hcd_release_default_address(hcd);
     632        return ret;
    447633}
    448634
     
    457643 * This function does all the ddf work for hc driver.
    458644 */
    459 int hcd_ddf_setup_hc(ddf_dev_t *device, size_t size)
     645int hcd_ddf_setup_hc(ddf_dev_t *device, usb_speed_t max_speed,
     646    size_t bw, bw_count_func_t bw_count)
    460647{
    461648        assert(device);
    462649
    463         hc_device_t *instance = ddf_dev_data_alloc(device, size);
     650        hc_dev_t *instance = ddf_dev_data_alloc(device, sizeof(hc_dev_t));
    464651        if (instance == NULL) {
    465                 usb_log_error("Failed to allocate HCD ddf structure.");
     652                usb_log_error("Failed to allocate HCD ddf structure.\n");
    466653                return ENOMEM;
    467654        }
    468         instance->ddf_dev = device;
     655        instance->root_hub = NULL;
     656        hcd_init(&instance->hcd, max_speed, bw, bw_count);
    469657
    470658        int ret = ENOMEM;
    471659        instance->ctl_fun = ddf_fun_create(device, fun_exposed, "ctl");
    472660        if (!instance->ctl_fun) {
    473                 usb_log_error("Failed to create HCD ddf fun.");
     661                usb_log_error("Failed to create HCD ddf fun.\n");
    474662                goto err_destroy_fun;
    475663        }
     
    477665        ret = ddf_fun_bind(instance->ctl_fun);
    478666        if (ret != EOK) {
    479                 usb_log_error("Failed to bind ctl_fun: %s.", str_error(ret));
     667                usb_log_error("Failed to bind ctl_fun: %s.\n", str_error(ret));
    480668                goto err_destroy_fun;
    481669        }
     
    483671        ret = ddf_fun_add_to_category(instance->ctl_fun, USB_HC_CATEGORY);
    484672        if (ret != EOK) {
    485                 usb_log_error("Failed to add fun to category: %s.",
     673                usb_log_error("Failed to add fun to category: %s.\n",
    486674                    str_error(ret));
    487675                ddf_fun_unbind(instance->ctl_fun);
     
    498686}
    499687
    500 void hcd_ddf_clean_hc(hc_device_t *hcd)
    501 {
    502         if (ddf_fun_unbind(hcd->ctl_fun) == EOK)
    503                 ddf_fun_destroy(hcd->ctl_fun);
    504 }
    505 
     688void hcd_ddf_clean_hc(ddf_dev_t *device)
     689{
     690        assert(device);
     691        hc_dev_t *hc = dev_to_hc_dev(device);
     692        assert(hc);
     693        const int ret = ddf_fun_unbind(hc->ctl_fun);
     694        if (ret == EOK)
     695                ddf_fun_destroy(hc->ctl_fun);
     696}
     697
     698//TODO: Cache parent session in HCD
    506699/** Call the parent driver with a request to enable interrupt
    507700 *
     
    510703 * @return Error code.
    511704 */
    512 int hcd_ddf_enable_interrupt(hc_device_t *hcd, int inum)
    513 {
    514         async_sess_t *parent_sess = ddf_dev_parent_sess_get(hcd->ddf_dev);
     705int hcd_ddf_enable_interrupt(ddf_dev_t *device, int inum)
     706{
     707        async_sess_t *parent_sess = ddf_dev_parent_sess_get(device);
    515708        if (parent_sess == NULL)
    516709                return EIO;
     
    519712}
    520713
    521 int hcd_ddf_get_registers(hc_device_t *hcd, hw_res_list_parsed_t *hw_res)
    522 {
    523         async_sess_t *parent_sess = ddf_dev_parent_sess_get(hcd->ddf_dev);
     714//TODO: Cache parent session in HCD
     715int hcd_ddf_get_registers(ddf_dev_t *device, hw_res_list_parsed_t *hw_res)
     716{
     717        async_sess_t *parent_sess = ddf_dev_parent_sess_get(device);
    524718        if (parent_sess == NULL)
    525719                return EIO;
     
    532726}
    533727
     728// TODO: move this someplace else
     729static inline void irq_code_clean(irq_code_t *code)
     730{
     731        if (code) {
     732                free(code->ranges);
     733                free(code->cmds);
     734                code->ranges = NULL;
     735                code->cmds = NULL;
     736                code->rangecount = 0;
     737                code->cmdcount = 0;
     738        }
     739}
     740
     741/** Register interrupt handler
     742 *
     743 * @param[in] device Host controller DDF device
     744 * @param[in] regs Register range
     745 * @param[in] irq Interrupt number
     746 * @paran[in] handler Interrupt handler
     747 * @param[in] gen_irq_code IRQ code generator.
     748 *
     749 * @param[out] handle  IRQ capability handle on success.
     750 *
     751 * @return Error code.
     752 */
     753int hcd_ddf_setup_interrupts(ddf_dev_t *device,
     754    const hw_res_list_parsed_t *hw_res,
     755    interrupt_handler_t handler,
     756    int (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *, int *),
     757    cap_handle_t *handle)
     758{
     759
     760        assert(device);
     761        if (!handler || !gen_irq_code)
     762                return ENOTSUP;
     763
     764        irq_code_t irq_code = {0};
     765
     766        int irq;
     767        int ret = gen_irq_code(&irq_code, hw_res, &irq);
     768        if (ret != EOK) {
     769                usb_log_error("Failed to generate IRQ code: %s.\n",
     770                    str_error(ret));
     771                return ret;
     772        }
     773
     774        /* Register handler to avoid interrupt lockup */
     775        ret = register_interrupt_handler(device, irq, handler,
     776            &irq_code, handle);
     777        irq_code_clean(&irq_code);
     778        if (ret != EOK) {
     779                usb_log_error("Failed to register interrupt handler: %s.\n",
     780                    str_error(ret));
     781                return ret;
     782        }
     783
     784        /* Enable interrupts */
     785        ret = hcd_ddf_enable_interrupt(device, irq);
     786        if (ret != EOK) {
     787                usb_log_error("Failed to register interrupt handler: %s.\n",
     788                    str_error(ret));
     789                unregister_interrupt_handler(device, *handle);
     790        }
     791        return ret;
     792}
     793
     794/** IRQ handling callback, forward status from call to diver structure.
     795 *
     796 * @param[in] dev DDF instance of the device to use.
     797 * @param[in] call Pointer to the call from kernel.
     798 */
     799void ddf_hcd_gen_irq_handler(ipc_call_t *call, ddf_dev_t *dev)
     800{
     801        assert(dev);
     802        hcd_t *hcd = dev_to_hcd(dev);
     803        if (!hcd || !hcd->ops.irq_hook) {
     804                usb_log_error("Interrupt on not yet initialized device.\n");
     805                return;
     806        }
     807        const uint32_t status = IPC_GET_ARG1(*call);
     808        hcd->ops.irq_hook(hcd, status);
     809}
     810
     811static int interrupt_polling(void *arg)
     812{
     813        hcd_t *hcd = arg;
     814        assert(hcd);
     815        if (!hcd->ops.status_hook || !hcd->ops.irq_hook)
     816                return ENOTSUP;
     817        uint32_t status = 0;
     818        while (hcd->ops.status_hook(hcd, &status) == EOK) {
     819                hcd->ops.irq_hook(hcd, status);
     820                status = 0;
     821                /* We should wait 1 frame - 1ms here, but this polling is a
     822                 * lame crutch anyway so don't hog the system. 10ms is still
     823                 * good enough for emergency mode */
     824                async_usleep(10000);
     825        }
     826        return EOK;
     827}
     828
     829/** Initialize hc and rh DDF structures and their respective drivers.
     830 *
     831 * @param device DDF instance of the device to use
     832 * @param speed Maximum supported speed
     833 * @param bw Available bandwidth (arbitrary units)
     834 * @param bw_count Bandwidth computing function
     835 * @param irq_handler IRQ handling function
     836 * @param gen_irq_code Function to generate IRQ pseudocode
     837 *                     (it needs to return used irq number)
     838 * @param driver_init Function to initialize HC driver
     839 * @param driver_fini Function to cleanup HC driver
     840 * @return Error code
     841 *
     842 * This function does all the preparatory work for hc and rh drivers:
     843 *  - gets device's hw resources
     844 *  - attempts to enable interrupts
     845 *  - registers interrupt handler
     846 *  - calls driver specific initialization
     847 *  - registers root hub
     848 */
     849int hcd_ddf_add_hc(ddf_dev_t *device, const ddf_hc_driver_t *driver)
     850{
     851        assert(driver);
     852        static const struct { size_t bw; bw_count_func_t bw_count; }bw[] = {
     853            [USB_SPEED_FULL] = { .bw = BANDWIDTH_AVAILABLE_USB11,
     854                                 .bw_count = bandwidth_count_usb11 },
     855            [USB_SPEED_HIGH] = { .bw = BANDWIDTH_AVAILABLE_USB11,
     856                                 .bw_count = bandwidth_count_usb11 },
     857        };
     858
     859        int ret = EOK;
     860        const usb_speed_t speed = driver->hc_speed;
     861        if (speed >= ARRAY_SIZE(bw) || bw[speed].bw == 0) {
     862                usb_log_error("Driver `%s' reported unsupported speed: %s",
     863                    driver->name, usb_str_speed(speed));
     864                return ENOTSUP;
     865        }
     866
     867        hw_res_list_parsed_t hw_res;
     868        ret = hcd_ddf_get_registers(device, &hw_res);
     869        if (ret != EOK) {
     870                usb_log_error("Failed to get register memory addresses "
     871                    "for `%s': %s.\n", ddf_dev_get_name(device),
     872                    str_error(ret));
     873                return ret;
     874        }
     875
     876        ret = hcd_ddf_setup_hc(device, speed, bw[speed].bw, bw[speed].bw_count);
     877        if (ret != EOK) {
     878                usb_log_error("Failed to setup generic HCD.\n");
     879                hw_res_list_parsed_clean(&hw_res);
     880                return ret;
     881        }
     882
     883        interrupt_handler_t *irq_handler =
     884            driver->irq_handler ? driver->irq_handler : ddf_hcd_gen_irq_handler;
     885        int irq_cap;
     886        int irq_ret = hcd_ddf_setup_interrupts(device, &hw_res,
     887            irq_handler, driver->irq_code_gen, &irq_cap);
     888        bool irqs_enabled = (irq_ret == EOK);
     889        if (irqs_enabled) {
     890                usb_log_debug("Hw interrupts enabled.\n");
     891        }
     892
     893        if (driver->claim) {
     894                ret = driver->claim(device);
     895                if (ret != EOK) {
     896                        usb_log_error("Failed to claim `%s' for driver `%s'",
     897                            ddf_dev_get_name(device), driver->name);
     898                        return ret;
     899                }
     900        }
     901
     902
     903        /* Init hw driver */
     904        hcd_t *hcd = dev_to_hcd(device);
     905        ret = driver->init(hcd, &hw_res, irqs_enabled);
     906        hw_res_list_parsed_clean(&hw_res);
     907        if (ret != EOK) {
     908                usb_log_error("Failed to init HCD: %s.\n", str_error(ret));
     909                goto irq_unregister;
     910        }
     911
     912        /* Need working irq replacement to setup root hub */
     913        if (!irqs_enabled && hcd->ops.status_hook) {
     914                hcd->polling_fibril = fibril_create(interrupt_polling, hcd);
     915                if (hcd->polling_fibril == 0) {
     916                        usb_log_error("Failed to create polling fibril\n");
     917                        ret = ENOMEM;
     918                        goto irq_unregister;
     919                }
     920                fibril_add_ready(hcd->polling_fibril);
     921                usb_log_warning("Failed to enable interrupts: %s."
     922                    " Falling back to polling.\n", str_error(irq_ret));
     923        }
     924
     925        /*
     926         * Creating root hub registers a new USB device so HC
     927         * needs to be ready at this time.
     928         */
     929        ret = hcd_ddf_setup_root_hub(device);
     930        if (ret != EOK) {
     931                usb_log_error("Failed to setup HC root hub: %s.\n",
     932                    str_error(ret));
     933                driver->fini(dev_to_hcd(device));
     934irq_unregister:
     935                /* Unregistering non-existent should be ok */
     936                unregister_interrupt_handler(device, irq_cap);
     937                hcd_ddf_clean_hc(device);
     938                return ret;
     939        }
     940
     941        usb_log_info("Controlling new `%s' device `%s'.\n",
     942            driver->name, ddf_dev_get_name(device));
     943        return EOK;
     944}
    534945/**
    535946 * @}
Note: See TracChangeset for help on using the changeset viewer.