Ignore:
File:
1 edited

Legend:

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

    r4547f11 ra6afb4c  
    3131 */
    3232/** @file
    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>
     33 * Helpers to work with the DDF interface.
     34 */
    4135
    4236#include <adt/list.h>
     
    4741#include <device/hw_res_parsed.h>
    4842#include <errno.h>
    49 #include <fibril_synch.h>
    50 #include <macros.h>
    51 #include <stdio.h>
    52 #include <stdlib.h>
    5343#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>
    5448#include <usb_iface.h>
     49#include <usbhc_iface.h>
     50
     51#include "bus.h"
     52#include "endpoint.h"
    5553
    5654#include "ddf_helpers.h"
    5755
    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 
    71 typedef struct hc_dev {
    72         ddf_fun_t *ctl_fun;
    73         hcd_t hcd;
    74         usb_dev_t *root_hub;
    75 } hc_dev_t;
    76 
    77 static hc_dev_t *dev_to_hc_dev(ddf_dev_t *dev)
    78 {
    79         return ddf_dev_data_get(dev);
    80 }
    81 
    82 hcd_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 
    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);
    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.
     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.
    10763 * @return Error code.
    10864 */
    109 static 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)
    113 {
    114         assert(fun);
    115         hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    116         usb_dev_t *dev = ddf_fun_data_get(fun);
     65static int register_endpoint(ddf_fun_t *fun, usb_pipe_desc_t *pipe_desc,
     66     const usb_endpoint_descriptors_t *ep_desc)
     67{
     68        assert(fun);
     69        hc_device_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
     70        device_t *dev = ddf_fun_data_get(fun);
    11771        assert(hcd);
    118         assert(dev);
    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.
     72        assert(hcd->bus);
     73        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  */
     99static int unregister_endpoint(ddf_fun_t *fun, const usb_pipe_desc_t *pipe_desc)
     100{
     101        assert(fun);
     102        hc_device_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
     103        device_t *dev = ddf_fun_data_get(fun);
     104        assert(hcd);
     105        assert(hcd->bus);
     106        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 */
     120static int default_address_reservation(ddf_fun_t *fun, bool reserve)
     121{
     122        assert(fun);
     123        hc_device_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
     124        device_t *dev = ddf_fun_data_get(fun);
     125        assert(hcd);
     126        assert(hcd->bus);
     127        assert(dev);
     128
     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 */
     144static int device_enumerate(ddf_fun_t *fun, unsigned port, usb_speed_t speed)
     145{
     146        assert(fun);
     147        ddf_dev_t *hc = ddf_fun_get_dev(fun);
     148        assert(hc);
     149        hc_device_t *hcd = dev_to_hcd(hc);
     150        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
     192err_usb_dev:
     193        hcd_ddf_fun_destroy(dev);
     194        return err;
     195}
     196
     197static int device_remove(ddf_fun_t *fun, unsigned port)
     198{
     199        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",
     203            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.
     232 *
     233 * @param[in] fun Device function.
     234 * @param[out] desc Device descriptor to be filled.
    136235 * @return Error code.
    137236 */
    138 static int unregister_endpoint(
    139     ddf_fun_t *fun, usb_endpoint_t endpoint, usb_direction_t direction)
    140 {
    141         assert(fun);
    142         hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    143         usb_dev_t *dev = ddf_fun_data_get(fun);
    144         assert(hcd);
    145         assert(dev);
    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 
    153 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed)
    154 {
    155         assert(fun);
    156         hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    157         usb_dev_t *dev = ddf_fun_data_get(fun);
    158         assert(hcd);
    159         assert(dev);
    160 
    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 
    166 static int release_default_address(ddf_fun_t *fun)
    167 {
    168         assert(fun);
    169         hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    170         usb_dev_t *dev = ddf_fun_data_get(fun);
    171         assert(hcd);
    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 
    178 static 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);
    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);
    195         assert(ddf_dev);
    196         assert(dev);
    197         usb_log_debug("Hub `%s' reported removal of device on port %u\n",
    198             ddf_fun_get_name(fun), port);
    199         return hcd_ddf_remove_device(ddf_dev, dev, port);
    200 }
    201 
    202 /** Gets handle of the respective device.
    203  *
    204  * @param[in] fun Device function.
    205  * @param[out] handle Place to write the handle.
    206  * @return Error code.
    207  */
    208 static int get_my_device_handle(ddf_fun_t *fun, devman_handle_t *handle)
    209 {
    210         assert(fun);
    211         if (handle)
    212                 *handle = ddf_fun_get_handle(fun);
     237static int get_device_description(ddf_fun_t *fun, usb_device_desc_t *desc)
     238{
     239        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        };
    213253        return EOK;
    214254}
     
    224264 * @return Error code.
    225265 */
    226 static 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)
    229 {
    230         assert(fun);
    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");
     266static 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)
     269{
     270        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");
    240288}
    241289
     
    250298 * @return Error code.
    251299 */
    252 static 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)
    255 {
    256         assert(fun);
    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,
     300static 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)
     303{
     304        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,
    265321            callback, arg, "WRITE");
    266322}
     
    268324/** USB device interface */
    269325static usb_iface_t usb_iface = {
    270         .get_my_device_handle = get_my_device_handle,
    271 
    272         .reserve_default_address = reserve_default_address,
    273         .release_default_address = release_default_address,
     326        .get_my_description = get_device_description,
     327};
     328
     329/** USB host controller interface */
     330static usbhc_iface_t usbhc_iface = {
     331        .default_address_reservation = default_address_reservation,
    274332
    275333        .device_enumerate = device_enumerate,
     
    286344static ddf_dev_ops_t usb_ops = {
    287345        .interfaces[USB_DEV_IFACE] = &usb_iface,
     346        .interfaces[USBHC_DEV_IFACE] = &usbhc_iface,
    288347};
    289348
    290349
    291350/* 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 }
    370351
    371352#define ADD_MATCHID_OR_RETURN(list, sc, str, ...) \
     
    394375        assert(l);
    395376        assert(d);
    396        
     377
    397378        if (d->vendor_id != 0) {
    398379                /* First, with release number. */
     
    401382                    d->vendor_id, d->product_id, (d->device_version >> 8),
    402383                    (d->device_version & 0xff));
    403        
     384
    404385                /* Next, without release number. */
    405386                ADD_MATCHID_OR_RETURN(l, 90, "usb&vendor=%#04x&product=%#04x",
     
    415396
    416397        return EOK;
    417 
    418 }
    419 
    420 static 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 
    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,
    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         }
     398}
     399
     400device_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
     422void hcd_ddf_fun_destroy(device_t *dev)
     423{
     424        assert(dev);
     425        assert(dev->fun);
     426        ddf_fun_destroy(dev->fun);
     427}
     428
     429int hcd_ddf_setup_match_ids(device_t *device, usb_standard_device_descriptor_t *desc)
     430{
     431        int err;
     432        match_id_list_t mids;
     433
     434        init_match_ids(&mids);
    589435
    590436        /* Create match ids from the device descriptor */
    591         match_id_list_t mids;
    592         init_match_ids(&mids);
    593 
    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  */
    623 int 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;
     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;
    633447}
    634448
     
    643457 * This function does all the ddf work for hc driver.
    644458 */
    645 int hcd_ddf_setup_hc(ddf_dev_t *device, usb_speed_t max_speed,
    646     size_t bw, bw_count_func_t bw_count)
     459int hcd_ddf_setup_hc(ddf_dev_t *device, size_t size)
    647460{
    648461        assert(device);
    649462
    650         hc_dev_t *instance = ddf_dev_data_alloc(device, sizeof(hc_dev_t));
     463        hc_device_t *instance = ddf_dev_data_alloc(device, size);
    651464        if (instance == NULL) {
    652                 usb_log_error("Failed to allocate HCD ddf structure.\n");
     465                usb_log_error("Failed to allocate HCD ddf structure.");
    653466                return ENOMEM;
    654467        }
    655         instance->root_hub = NULL;
    656         hcd_init(&instance->hcd, max_speed, bw, bw_count);
     468        instance->ddf_dev = device;
    657469
    658470        int ret = ENOMEM;
    659471        instance->ctl_fun = ddf_fun_create(device, fun_exposed, "ctl");
    660472        if (!instance->ctl_fun) {
    661                 usb_log_error("Failed to create HCD ddf fun.\n");
     473                usb_log_error("Failed to create HCD ddf fun.");
    662474                goto err_destroy_fun;
    663475        }
     
    665477        ret = ddf_fun_bind(instance->ctl_fun);
    666478        if (ret != EOK) {
    667                 usb_log_error("Failed to bind ctl_fun: %s.\n", str_error(ret));
     479                usb_log_error("Failed to bind ctl_fun: %s.", str_error(ret));
    668480                goto err_destroy_fun;
    669481        }
     
    671483        ret = ddf_fun_add_to_category(instance->ctl_fun, USB_HC_CATEGORY);
    672484        if (ret != EOK) {
    673                 usb_log_error("Failed to add fun to category: %s.\n",
     485                usb_log_error("Failed to add fun to category: %s.",
    674486                    str_error(ret));
    675487                ddf_fun_unbind(instance->ctl_fun);
     
    686498}
    687499
    688 void 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
     500void 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
    699506/** Call the parent driver with a request to enable interrupt
    700507 *
     
    703510 * @return Error code.
    704511 */
    705 int hcd_ddf_enable_interrupt(ddf_dev_t *device, int inum)
    706 {
    707         async_sess_t *parent_sess = ddf_dev_parent_sess_get(device);
     512int 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);
    708515        if (parent_sess == NULL)
    709516                return EIO;
     
    712519}
    713520
    714 //TODO: Cache parent session in HCD
    715 int 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);
     521int 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);
    718524        if (parent_sess == NULL)
    719525                return EIO;
     
    726532}
    727533
    728 // TODO: move this someplace else
    729 static 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  */
    753 int 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  */
    799 void 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 
    811 static 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  */
    849 int 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));
    934 irq_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 }
    945534/**
    946535 * @}
Note: See TracChangeset for help on using the changeset viewer.