Changeset 867b375 in mainline


Ignore:
Timestamp:
2017-10-15T02:04:10Z (7 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
20eaa82
Parents:
d7869d7e
Message:

hcd_ddf_new_device refactoring

This long function is now split into parts. Instead of passing dozens of arguments, it now creates the usb_dev_t right away, and uses that to pass it along. The address_device part is now modifiable by drivers.

There is still a work to be done. The biggest problem I see is in the addressing - currently, there is usb_address_t, and for high speed transaction translating there is another address. For (near) future extensibility, we should pass address as a structure. Or even better, make a way how to reference a device, maybe in a similar way how we work with endpoints.

Location:
uspace
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/vhc/main.c

    rd7869d7e r867b375  
    111111         * needs to be ready at this time.
    112112         */
    113         ret = hcd_setup_virtual_root_hub(dev);
     113        ret = hcd_setup_virtual_root_hub(dev_to_hcd(dev), dev);
    114114        if (ret != EOK) {
    115115                usb_log_error("Failed to init VHC root hub: %s\n",
  • uspace/drv/bus/usb/xhci/main.c

    rd7869d7e r867b375  
    4242
    4343#include "hc.h"
     44#include "rh.h"
    4445#include "endpoint.h"
    4546
     
    5051static int hcd_claim(hcd_t *, ddf_dev_t *);
    5152static int hcd_start(hcd_t *, bool);
     53static int hcd_setup_root_hub(hcd_t *, ddf_dev_t *);
    5254static int hcd_status(hcd_t *, uint32_t *);
    5355static void hcd_interrupt(hcd_t *, uint32_t);
    5456static int hcd_schedule(hcd_t *, usb_transfer_batch_t *);
     57static int hcd_address_device(hcd_t *, usb_speed_t, usb_tt_address_t, usb_address_t *);
    5558static void hc_driver_fini(hcd_t *);
    5659
     
    6265        .claim = hcd_claim,
    6366        .start = hcd_start,
     67        .setup_root_hub = hcd_setup_root_hub,
    6468        .fini = hc_driver_fini,
    6569        .ops = {
     
    6771                .irq_hook       = hcd_interrupt,
    6872                .status_hook    = hcd_status,
     73                .address_device = hcd_address_device,
    6974        }
    7075};
     
    116121}
    117122
     123static int hcd_setup_root_hub(hcd_t *hcd, ddf_dev_t *dev)
     124{
     125        xhci_hc_t *hc = hcd_get_driver_data(hcd);
     126        assert(hc);
     127
     128        hc->rh.hcd_rh = hcd_roothub_create(hcd, dev, USB_SPEED_SUPER);
     129        return hc->rh.hcd_rh ? EOK : ENOMEM;
     130}
     131
    118132static int hcd_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
    119133{
     
    139153
    140154        hc_interrupt(hc, status);
     155}
     156
     157static int hcd_address_device(hcd_t *hcd, usb_speed_t speed, usb_tt_address_t tt, usb_address_t *address)
     158{
     159        xhci_hc_t *hc = hcd_get_driver_data(hcd);
     160        assert(hc);
     161
     162        return xhci_rh_address_device(&hc->rh, speed, tt, address);
    141163}
    142164
  • uspace/drv/bus/usb/xhci/rh.c

    rd7869d7e r867b375  
    3838#include <usb/debug.h>
    3939#include <usb/host/utils/malloc32.h>
     40#include <usb/host/ddf_helpers.h>
     41
    4042#include "debug.h"
    4143#include "commands.h"
     
    6971// TODO: Check device deallocation, we free device_ctx in hc.c, not
    7072//       sure about the other structs.
    71 static int alloc_dev(xhci_hc_t *hc, uint8_t port, uint32_t route_str)
     73// TODO: This currently assumes the device is attached to rh directly.
     74//       Also, we should consider moving a lot of functionailty to xhci bus
     75int xhci_rh_address_device(xhci_rh_t *rh, usb_speed_t unused_speed, usb_tt_address_t tt, usb_address_t *address)
    7276{
    7377        int err;
     78        xhci_hc_t *hc = rh->hc;
    7479
    7580        xhci_cmd_t cmd;
    7681        xhci_cmd_init(&cmd);
    7782
    78         const xhci_port_speed_t *speed = xhci_rh_get_port_speed(&hc->rh, port);
     83        uint8_t port = tt.port;
     84
     85        /* XXX Certainly not generic solution. */
     86        uint32_t route_str = 0;
     87
     88        const xhci_port_speed_t *speed = xhci_rh_get_port_speed(rh, port);
    7989
    8090        xhci_send_enable_slot_command(hc, &cmd);
     
    127137        XHCI_EP_ERROR_COUNT_SET(ictx->endpoint_ctx[0], 3);
    128138
    129         // TODO: What's the alignment?
    130         xhci_device_ctx_t *dctx = malloc(sizeof(xhci_device_ctx_t));
     139        xhci_device_ctx_t *dctx = malloc32(sizeof(xhci_device_ctx_t));
    131140        if (!dctx) {
    132141                err = ENOMEM;
     
    149158        xhci_cmd_fini(&cmd);
    150159
    151         usb_address_t address = XHCI_SLOT_DEVICE_ADDRESS(dctx->slot_ctx);
    152         usb_log_debug2("Obtained USB address: %d.\n", address);
     160        *address = XHCI_SLOT_DEVICE_ADDRESS(dctx->slot_ctx);
     161        usb_log_debug2("Obtained USB address: %d.\n", *address);
    153162
    154163        // TODO: Ask libusbhost to create a control endpoint for EP0.
     
    174183}
    175184
     185static int rh_setup_device(xhci_rh_t *rh, uint8_t port_id)
     186{
     187        /** This should ideally use the libusbhost in a clean and elegant way,
     188         * to create child function. The refactoring of libusbhost is not over
     189         * yet, so for now it is still quirky.
     190         */
     191
     192        return hcd_roothub_new_device(rh->hcd_rh, port_id);
     193}
     194
    176195static int handle_connected_device(xhci_rh_t *rh, uint8_t port_id)
    177196{
     
    186205                if (link_state == 0) {
    187206                        /* USB3 is automatically advanced to enabled. */
    188                         return alloc_dev(rh->hc, port_id, 0);
     207                        return rh_setup_device(rh, port_id);
    189208                }
    190209                else if (link_state == 5) {
     
    270289                                 * every time USB2 port is reset. This is a
    271290                                 * temporary workaround. */
    272                                 alloc_dev(rh->hc, i, 0);
     291                                rh_setup_device(rh, i);
    273292                        }
    274293                }
  • uspace/drv/bus/usb/xhci/rh.h

    rd7869d7e r867b375  
    5151} xhci_port_speed_t;
    5252
     53typedef struct hcd_roothub hcd_roothub_t;
     54
    5355/* XHCI root hub instance */
    5456typedef struct {
     
    6466        /* Number of hub ports. */
    6567        uint8_t max_ports;
     68
     69        /* We need this to create child devices */
     70        hcd_roothub_t *hcd_rh;
    6671} xhci_rh_t;
    6772
     
    7479void xhci_rh_handle_port_change(xhci_rh_t *);
    7580
     81int xhci_rh_address_device(xhci_rh_t *, usb_speed_t, usb_tt_address_t, usb_address_t *);
     82
    7683#endif
    7784
  • uspace/lib/usb/include/usb/usb.h

    rd7869d7e r867b375  
    114114typedef int16_t usb_address_t;
    115115
     116typedef struct {
     117        usb_address_t address;
     118        unsigned port;
     119} usb_tt_address_t;
     120
    116121/** Default USB address. */
    117122#define USB_ADDRESS_DEFAULT 0
  • uspace/lib/usbhost/include/usb/host/ddf_helpers.h

    rd7869d7e r867b375  
    4949typedef int (*claim_t)(hcd_t *, ddf_dev_t *);
    5050typedef int (*driver_start_t)(hcd_t *, bool irq);
    51 typedef int (*setup_root_hub_t)(ddf_dev_t *);
     51typedef int (*setup_root_hub_t)(hcd_t *, ddf_dev_t *);
    5252
    5353typedef void (*driver_stop_t)(hcd_t *);
     
    8181void hcd_ddf_clean_hc(ddf_dev_t *device);
    8282
    83 int hcd_setup_virtual_root_hub(ddf_dev_t *);
     83int hcd_setup_virtual_root_hub(hcd_t *, ddf_dev_t *);
    8484
    8585hcd_t *dev_to_hcd(ddf_dev_t *dev);
     
    9393void ddf_hcd_gen_irq_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev);
    9494
     95/* For xHCI, we need to drive the roothub without roothub having assigned an
     96 * address. Thus we cannot create function for it, and we have to carry the
     97 * usb_dev_t somewhere.
     98 *
     99 * This is sort of hacky, but at least does not expose the internals of ddf_helpers.
     100 */
     101typedef struct hcd_roothub hcd_roothub_t;
     102
     103hcd_roothub_t *hcd_roothub_create(hcd_t *, ddf_dev_t *, usb_speed_t);
     104int hcd_roothub_new_device(hcd_roothub_t *, unsigned port);
     105
    95106#endif
    96107
  • uspace/lib/usbhost/include/usb/host/endpoint.h

    rd7869d7e r867b375  
    7979        fibril_condvar_t avail;
    8080        /** High speed TT data */
    81         struct {
    82                 usb_address_t address;
    83                 unsigned port;
    84         } tt;
     81        usb_tt_address_t tt;
    8582
    8683        /* This structure is meant to be extended by overriding. */
  • uspace/lib/usbhost/include/usb/host/hcd.h

    rd7869d7e r867b375  
    5050
    5151typedef int (*schedule_hook_t)(hcd_t *, usb_transfer_batch_t *);
    52 typedef int (*ep_add_hook_t)(hcd_t *, endpoint_t *);
    53 typedef void (*ep_remove_hook_t)(hcd_t *, endpoint_t *);
    5452typedef void (*interrupt_hook_t)(hcd_t *, uint32_t);
    5553typedef int (*status_hook_t)(hcd_t *, uint32_t *);
     54typedef int (*address_device_hook_t)(hcd_t *, usb_speed_t, usb_tt_address_t, usb_address_t *);
    5655
    5756typedef struct {
     
    6261        /** Periodic polling hook */
    6362        status_hook_t status_hook;
     63        /** Hook to setup device address */
     64        address_device_hook_t address_device;
    6465} hcd_ops_t;
    6566
     
    112113
    113114extern int hcd_add_ep(hcd_t *, usb_target_t, usb_direction_t,
    114     usb_transfer_type_t, size_t, unsigned int, size_t, usb_address_t,
    115     unsigned int);
     115    usb_transfer_type_t, size_t, unsigned int, size_t, usb_tt_address_t);
    116116
    117117extern int hcd_remove_ep(hcd_t *, usb_target_t, usb_direction_t);
  • uspace/lib/usbhost/src/ddf_helpers.c

    rd7869d7e r867b375  
    6363        list_t devices;
    6464        fibril_mutex_t guard;
    65         ddf_fun_t *fun;
    6665        usb_address_t address;
    6766        usb_speed_t speed;
    68         usb_address_t tt_address;
    69         unsigned port;
     67        usb_tt_address_t tt;
     68
     69        /* This must be set iff the usb_dev is managed by ddf_fun. */
     70        ddf_fun_t *fun;
    7071} usb_dev_t;
    7172
     
    7374        ddf_fun_t *ctl_fun;
    7475        hcd_t hcd;
    75         usb_dev_t *root_hub;
    7676} hc_dev_t;
    7777
     
    9292
    9393
    94 static int hcd_ddf_new_device(ddf_dev_t *device, usb_dev_t *hub, unsigned port);
     94static int hcd_ddf_new_device(hcd_t *hcd, ddf_dev_t *hc, usb_dev_t *hub_dev, unsigned port);
    9595static int hcd_ddf_remove_device(ddf_dev_t *device, usb_dev_t *hub, unsigned port);
    9696
     
    127127
    128128        return hcd_add_ep(hcd, target, direction, transfer_type,
    129             max_packet_size, packets, size, dev->tt_address, dev->port);
     129            max_packet_size, packets, size, dev->tt);
    130130}
    131131
     
    180180{
    181181        assert(fun);
    182         ddf_dev_t *ddf_dev = ddf_fun_get_dev(fun);
    183         usb_dev_t *dev = ddf_fun_data_get(fun);
    184         assert(ddf_dev);
    185         assert(dev);
     182        ddf_dev_t *hc = ddf_fun_get_dev(fun);
     183        assert(hc);
     184        hcd_t *hcd = dev_to_hcd(hc);
     185        assert(hcd);
     186        usb_dev_t *hub = ddf_fun_data_get(fun);
     187        assert(hub);
     188
    186189        usb_log_debug("Hub %d reported a new USB device on port: %u\n",
    187             dev->address, port);
    188         return hcd_ddf_new_device(ddf_dev, dev, port);
     190            hub->address, port);
     191        return hcd_ddf_new_device(hcd, hc, hub, port);
    189192}
    190193
     
    291294
    292295/* DDF HELPERS */
    293 
    294 #define GET_DEVICE_DESC(size) \
    295 { \
    296         .request_type = SETUP_REQUEST_TYPE_DEVICE_TO_HOST \
    297             | (USB_REQUEST_TYPE_STANDARD << 5) \
    298             | USB_REQUEST_RECIPIENT_DEVICE, \
    299         .request = USB_DEVREQ_GET_DESCRIPTOR, \
    300         .value = uint16_host2usb(USB_DESCTYPE_DEVICE << 8), \
    301         .index = uint16_host2usb(0), \
    302         .length = uint16_host2usb(size), \
    303 };
    304 
    305 #define SET_ADDRESS(address) \
    306 { \
    307         .request_type = SETUP_REQUEST_TYPE_HOST_TO_DEVICE \
    308             | (USB_REQUEST_TYPE_STANDARD << 5) \
    309             | USB_REQUEST_RECIPIENT_DEVICE, \
    310         .request = USB_DEVREQ_SET_ADDRESS, \
    311         .value = uint16_host2usb(address), \
    312         .index = uint16_host2usb(0), \
    313         .length = uint16_host2usb(0), \
    314 };
    315 
    316 static int hcd_ddf_add_device(ddf_dev_t *parent, usb_dev_t *hub_dev,
    317     unsigned port, usb_address_t address, usb_speed_t speed, const char *name,
    318     const match_id_list_t *mids)
    319 {
    320         assert(parent);
    321 
    322         char default_name[10] = { 0 }; /* usbxyz-ss */
    323         if (!name) {
    324                 snprintf(default_name, sizeof(default_name) - 1,
    325                     "usb%u-%cs", address, usb_str_speed(speed)[0]);
    326                 name = default_name;
    327         }
    328 
    329         ddf_fun_t *fun = ddf_fun_create(parent, fun_inner, name);
    330         if (!fun)
    331                 return ENOMEM;
    332         usb_dev_t *info = ddf_fun_data_alloc(fun, sizeof(usb_dev_t));
    333         if (!info) {
    334                 ddf_fun_destroy(fun);
    335                 return ENOMEM;
    336         }
    337         info->address = address;
    338         info->speed = speed;
    339         info->fun = fun;
    340         info->port = port;
    341         info->tt_address = hub_dev ? hub_dev->tt_address : -1;
    342         link_initialize(&info->link);
    343         list_initialize(&info->devices);
    344         fibril_mutex_initialize(&info->guard);
    345 
    346         if (hub_dev && hub_dev->speed == USB_SPEED_HIGH && usb_speed_is_11(speed))
    347                 info->tt_address = hub_dev->address;
    348 
    349         ddf_fun_set_ops(fun, &usb_ops);
    350         list_foreach(mids->ids, link, const match_id_t, mid) {
    351                 ddf_fun_add_match_id(fun, mid->id, mid->score);
    352         }
    353 
    354         int ret = ddf_fun_bind(fun);
    355         if (ret != EOK) {
    356                 ddf_fun_destroy(fun);
    357                 return ret;
    358         }
    359 
    360         if (hub_dev) {
    361                 fibril_mutex_lock(&hub_dev->guard);
    362                 list_append(&info->link, &hub_dev->devices);
    363                 fibril_mutex_unlock(&hub_dev->guard);
    364         } else {
    365                 hc_dev_t *hc_dev = dev_to_hc_dev(parent);
    366                 assert(hc_dev->root_hub == NULL);
    367                 hc_dev->root_hub = info;
    368         }
    369         return EOK;
    370 }
    371296
    372297#define ADD_MATCHID_OR_RETURN(list, sc, str, ...) \
     
    416341
    417342        return EOK;
    418 
    419343}
    420344
     
    435359
    436360        list_foreach(hub->devices, link, usb_dev_t, it) {
    437                 if (it->port == port) {
     361                if (it->tt.port == port) {
    438362                        victim = it;
    439363                        break;
     
    441365        }
    442366        if (victim) {
    443                 assert(victim->port == port);
     367                assert(victim->fun);
     368                assert(victim->tt.port == port);
    444369                list_remove(&victim->link);
    445370                fibril_mutex_unlock(&hub->guard);
     
    459384}
    460385
    461 static int hcd_ddf_new_device(ddf_dev_t *device, usb_dev_t *hub, unsigned port)
    462 {
    463         assert(device);
    464 
    465         hcd_t *hcd = dev_to_hcd(device);
    466         assert(hcd);
    467 
    468         usb_speed_t speed = USB_SPEED_MAX;
    469 
    470         /* This checks whether the default address is reserved and gets speed */
    471         int ret = bus_get_speed(hcd->bus, USB_ADDRESS_DEFAULT, &speed);
    472         if (ret != EOK) {
    473                 usb_log_error("Failed to verify speed: %s.", str_error(ret));
    474                 return ret;
    475         }
    476 
    477         usb_log_debug("Found new %s speed USB device.", usb_str_speed(speed));
     386#define GET_DEVICE_DESC(size) \
     387{ \
     388        .request_type = SETUP_REQUEST_TYPE_DEVICE_TO_HOST \
     389            | (USB_REQUEST_TYPE_STANDARD << 5) \
     390            | USB_REQUEST_RECIPIENT_DEVICE, \
     391        .request = USB_DEVREQ_GET_DESCRIPTOR, \
     392        .value = uint16_host2usb(USB_DESCTYPE_DEVICE << 8), \
     393        .index = uint16_host2usb(0), \
     394        .length = uint16_host2usb(size), \
     395};
     396
     397#define SET_ADDRESS(address) \
     398{ \
     399        .request_type = SETUP_REQUEST_TYPE_HOST_TO_DEVICE \
     400            | (USB_REQUEST_TYPE_STANDARD << 5) \
     401            | USB_REQUEST_RECIPIENT_DEVICE, \
     402        .request = USB_DEVREQ_SET_ADDRESS, \
     403        .value = uint16_host2usb(address), \
     404        .index = uint16_host2usb(0), \
     405        .length = uint16_host2usb(0), \
     406};
     407
     408static int hcd_usb2_address_device(hcd_t *hcd, usb_speed_t speed,
     409    usb_tt_address_t tt, usb_address_t *out_address)
     410{
     411        int err;
    478412
    479413        static const usb_target_t default_target = {{
     
    482416        }};
    483417
     418        /** Reserve address early, we want pretty log messages */
    484419        const usb_address_t address = hcd_request_address(hcd, speed);
    485420        if (address < 0) {
     
    488423                return address;
    489424        }
    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;
     425        usb_log_debug("Device(%d): Reserved new address.", address);
    499426
    500427        /* 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,
     428        usb_log_debug("Device(%d): Adding default target (0:0)", address);
     429        err = hcd_add_ep(hcd,
    503430            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) {
     431            CTRL_PIPE_MIN_PACKET_SIZE, CTRL_PIPE_MIN_PACKET_SIZE, 1, tt);
     432        if (err != EOK) {
    507433                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;
     434                    address, str_error(err));
     435                goto err_address;
    511436        }
    512437
     
    516441            GET_DEVICE_DESC(CTRL_PIPE_MIN_PACKET_SIZE);
    517442
    518         // TODO CALLBACKS
    519443        usb_log_debug("Device(%d): Requesting first 8B of device descriptor.",
    520444            address);
     
    524448
    525449        if (got != CTRL_PIPE_MIN_PACKET_SIZE) {
    526                 ret = got < 0 ? got : EOVERFLOW;
     450                err = got < 0 ? got : EOVERFLOW;
    527451                usb_log_error("Device(%d): Failed to get 8B of dev descr: %s.",
    528                     address, str_error(ret));
    529                 hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH);
    530                 hcd_release_address(hcd, address);
    531                 return ret;
    532         }
     452                    address, str_error(err));
     453                goto err_default_target;
     454        }
     455
     456        /* Set new address */
     457        const usb_device_request_setup_packet_t set_address = SET_ADDRESS(address);
     458
     459        usb_log_debug("Device(%d): Setting USB address.", address);
     460        err = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_OUT,
     461            NULL, 0, *(uint64_t *)&set_address, "set address");
     462        if (err != 0) {
     463                usb_log_error("Device(%d): Failed to set new address: %s.",
     464                    address, str_error(got));
     465                goto err_default_target;
     466        }
     467
     468        *out_address = address;
     469
     470        usb_target_t control_ep = {
     471                .address = address,
     472                .endpoint = 0
     473        };
    533474
    534475        /* Register EP on the new address */
    535476        usb_log_debug("Device(%d): Registering control EP.", address);
    536         ret = hcd_add_ep(hcd, target, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL,
     477        err = hcd_add_ep(hcd, control_ep, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL,
    537478            ED_MPS_PACKET_SIZE_GET(uint16_usb2host(desc.max_packet_size)),
    538479            ED_MPS_TRANS_OPPORTUNITIES_GET(uint16_usb2host(desc.max_packet_size)),
    539             ED_MPS_PACKET_SIZE_GET(uint16_usb2host(desc.max_packet_size)),
    540             tt_address, port);
    541         if (ret != EOK) {
     480            ED_MPS_PACKET_SIZE_GET(uint16_usb2host(desc.max_packet_size)), tt);
     481        if (err != EOK) {
    542482                usb_log_error("Device(%d): Failed to register EP0: %s",
    543                     address, str_error(ret));
    544                 hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH);
    545                 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
    546                 hcd_release_address(hcd, address);
    547                 return ret;
    548         }
    549 
    550         /* Set new address */
    551         const usb_device_request_setup_packet_t set_address =
    552             SET_ADDRESS(target.address);
    553 
    554         usb_log_debug("Device(%d): Setting USB address.", address);
    555         got = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_OUT,
    556             NULL, 0, *(uint64_t *)&set_address, "set address");
    557 
    558         usb_log_debug("Device(%d): Removing default (0:0) EP.", address);
     483                    address, str_error(err));
     484                goto err_default_target;
     485        }
     486
    559487        hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH);
    560 
    561         if (got != 0) {
    562                 usb_log_error("Device(%d): Failed to set new address: %s.",
    563                     address, str_error(got));
    564                 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
    565                 hcd_release_address(hcd, address);
    566                 return got;
    567         }
     488        return EOK;
     489
     490
     491err_default_target:
     492        hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH);
     493err_address:
     494        hcd_release_address(hcd, address);
     495        return err;
     496}
     497
     498static int usb_dev_init(usb_dev_t *usb_dev, usb_speed_t speed)
     499{
     500        memset(usb_dev, 0, sizeof(*usb_dev));
     501
     502        link_initialize(&usb_dev->link);
     503        list_initialize(&usb_dev->devices);
     504        fibril_mutex_initialize(&usb_dev->guard);
     505
     506        usb_dev->speed = speed;
     507
     508        return EOK;
     509}
     510
     511static usb_dev_t *usb_dev_create(ddf_dev_t *hc, usb_speed_t speed)
     512{
     513        /* Create DDF function for the new device */
     514        ddf_fun_t *fun = ddf_fun_create(hc, fun_inner, NULL);
     515        if (!fun)
     516                return NULL;
     517
     518        ddf_fun_set_ops(fun, &usb_ops);
     519
     520        /* Create USB device node for the new device */
     521        usb_dev_t *usb_dev = ddf_fun_data_alloc(fun, sizeof(usb_dev_t));
     522        if (!usb_dev) {
     523                ddf_fun_destroy(fun);
     524                return NULL;
     525        }
     526
     527        usb_dev_init(usb_dev, speed);
     528        usb_dev->fun = fun;
     529        return usb_dev;
     530}
     531
     532static void usb_dev_destroy(usb_dev_t *dev)
     533{
     534        assert(dev);
     535        assert(dev->fun);
     536        ddf_fun_destroy(dev->fun);
     537}
     538
     539static int usb_dev_set_default_name(usb_dev_t *usb_dev)
     540{
     541        assert(usb_dev);
     542
     543        char buf[10] = { 0 }; /* usbxyz-ss */
     544        snprintf(buf, sizeof(buf) - 1, "usb%u-%cs",
     545            usb_dev->address, usb_str_speed(usb_dev->speed)[0]);
     546
     547        return ddf_fun_set_name(usb_dev->fun, buf);
     548}
     549
     550static int usb_dev_explore(hcd_t *hcd, usb_dev_t *usb_dev)
     551{
     552        int err;
     553        match_id_list_t mids;
     554        usb_standard_device_descriptor_t desc = { 0 };
     555
     556        init_match_ids(&mids);
     557
     558        usb_target_t control_ep = {
     559                .address = usb_dev->address,
     560                .endpoint = 0
     561        };
    568562
    569563        /* Get std device descriptor */
     
    572566
    573567        usb_log_debug("Device(%d): Requesting full device descriptor.",
    574             address);
    575         got = hcd_send_batch_sync(hcd, target, USB_DIRECTION_IN,
     568            usb_dev->address);
     569        ssize_t got = hcd_send_batch_sync(hcd, control_ep, USB_DIRECTION_IN,
    576570            &desc, sizeof(desc), *(uint64_t *)&get_device_desc,
    577571            "read device descriptor");
    578         if (ret != EOK) {
     572        if (got < 0) {
     573                err = got < 0 ? got : EOVERFLOW;
    579574                usb_log_error("Device(%d): Failed to set get dev descriptor: %s",
    580                     address, str_error(ret));
    581                 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
    582                 hcd_release_address(hcd, target.address);
    583                 return ret;
     575                    usb_dev->address, str_error(err));
     576                goto out;
    584577        }
    585578
    586579        /* Create match ids from the device descriptor */
    587         match_id_list_t mids;
    588         init_match_ids(&mids);
    589 
    590         usb_log_debug("Device(%d): Creating match IDs.", address);
    591         ret = create_match_ids(&mids, &desc);
    592         if (ret != EOK) {
    593                 usb_log_error("Device(%d): Failed to create match ids: %s",
    594                     address, str_error(ret));
    595                 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
    596                 hcd_release_address(hcd, target.address);
    597                 return ret;
    598         }
    599 
    600         /* Register device */
    601         usb_log_debug("Device(%d): Registering DDF device.", address);
    602         ret = hcd_ddf_add_device(device, hub, port, address, speed, NULL, &mids);
     580        usb_log_debug("Device(%d): Creating match IDs.", usb_dev->address);
     581        if ((err = create_match_ids(&mids, &desc))) {
     582                usb_log_error("Device(%d): Failed to create match ids: %s", usb_dev->address, str_error(err));
     583                goto out;
     584        }
     585
     586        list_foreach(mids.ids, link, const match_id_t, mid) {
     587                ddf_fun_add_match_id(usb_dev->fun, mid->id, mid->score);
     588        }
     589
     590out:
    603591        clean_match_ids(&mids);
    604         if (ret != EOK) {
    605                 usb_log_error("Device(%d): Failed to register: %s.",
    606                     address, str_error(ret));
    607                 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
    608                 hcd_release_address(hcd, target.address);
    609         }
    610 
    611         return ret;
     592        return err;
     593}
     594
     595static int hcd_address_device(hcd_t *hcd, usb_dev_t *usb_dev)
     596{
     597        if (hcd->ops.address_device)
     598                return hcd->ops.address_device(hcd, usb_dev->speed, usb_dev->tt, &usb_dev->address);
     599        else
     600                return hcd_usb2_address_device(hcd, usb_dev->speed, usb_dev->tt, &usb_dev->address);
     601}
     602
     603static int hcd_ddf_new_device(hcd_t *hcd, ddf_dev_t *hc, usb_dev_t *hub_dev, unsigned port)
     604{
     605        int err;
     606        assert(hcd);
     607        assert(hub_dev);
     608        assert(hc);
     609
     610        usb_speed_t speed = USB_SPEED_MAX;
     611        /* The speed of the new device was reported by the hub when reserving
     612         * default address.
     613         */
     614        if ((err = bus_get_speed(hcd->bus, USB_ADDRESS_DEFAULT, &speed))) {
     615                usb_log_error("Failed to verify speed: %s.", str_error(err));
     616                return err;
     617        }
     618        usb_log_debug("Found new %s speed USB device.", usb_str_speed(speed));
     619
     620        usb_dev_t *usb_dev = usb_dev_create(hc, speed);
     621        if (!usb_dev) {
     622                usb_log_error("Failed to create USB device function.");
     623                return err;
     624        }
     625
     626        /* For devices under HS hub */
     627        /* TODO: How about SS hubs? */
     628        if (hub_dev->speed == USB_SPEED_HIGH && usb_speed_is_11(speed)) {
     629                usb_dev->tt.address = hub_dev->address;
     630        }
     631        else {
     632                /* Inherit hub's TT */
     633                usb_dev->tt.address = hub_dev->tt.address;
     634        }
     635        usb_dev->tt.port = port;
     636
     637        /* Assign an address to the device */
     638        if ((err = hcd_address_device(hcd, usb_dev))) {
     639                usb_log_error("Failed to setup address of the new device: %s", str_error(err));
     640                goto err_usb_dev;
     641        }
     642
     643        /* Read the device descriptor, derive the match ids */
     644        if ((err = usb_dev_explore(hcd, usb_dev))) {
     645                usb_log_error("Device(%d): Failed to explore device: %s", usb_dev->address, str_error(err));
     646                goto err_usb_dev;
     647        }
     648
     649        /* If the driver didn't name the device when addressing/exploring,
     650         * do it insome generic way.
     651         */
     652        if (!ddf_fun_get_name(usb_dev->fun)) {
     653                usb_dev_set_default_name(usb_dev);
     654        }
     655
     656        if ((err = ddf_fun_bind(usb_dev->fun))) {
     657                usb_log_error("Device(%d): Failed to register: %s.", usb_dev->address, str_error(err));
     658                goto err_usb_dev;
     659        }
     660
     661        fibril_mutex_lock(&hub_dev->guard);
     662        list_append(&usb_dev->link, &hub_dev->devices);
     663        fibril_mutex_unlock(&hub_dev->guard);
     664
     665        return EOK;
     666
     667err_usb_dev:
     668        usb_dev_destroy(usb_dev);
     669        return err;
    612670}
    613671
     
    617675 * @return Error code
    618676 */
    619 int hcd_setup_virtual_root_hub(ddf_dev_t *device)
    620 {
    621         assert(device);
    622         hcd_t *hcd = dev_to_hcd(device);
     677int hcd_setup_virtual_root_hub(hcd_t *hcd, ddf_dev_t *hc)
     678{
     679        int err;
     680
     681        assert(hc);
    623682        assert(hcd);
    624683
    625         hcd_reserve_default_address(hcd, USB_SPEED_MAX);
    626         const int ret = hcd_ddf_new_device(device, NULL, 0);
     684        if ((err = hcd_reserve_default_address(hcd, USB_SPEED_MAX))) {
     685                usb_log_error("Failed to reserve default address for roothub setup: %s", str_error(err));
     686                return err;
     687        }
     688
     689        usb_dev_t *usb_dev = usb_dev_create(hc, USB_SPEED_MAX);
     690        if (!usb_dev) {
     691                usb_log_error("Failed to create function for the root hub.");
     692                goto err_default_address;
     693        }
     694
     695        usb_dev->tt.address = -1;
     696        usb_dev->tt.port = 0;
     697
     698        /* Assign an address to the device */
     699        if ((err = hcd_address_device(hcd, usb_dev))) {
     700                usb_log_error("Failed to setup roothub address: %s", str_error(err));
     701                goto err_usb_dev;
     702        }
     703
     704        /* Read the device descriptor, derive the match ids */
     705        if ((err = usb_dev_explore(hcd, usb_dev))) {
     706                usb_log_error("Failed to explore roothub: %s", str_error(err));
     707                goto err_usb_dev;
     708        }
     709
     710        ddf_fun_set_name(usb_dev->fun, "roothub");
     711
     712        if ((err = ddf_fun_bind(usb_dev->fun))) {
     713                usb_log_error("Failed to register roothub: %s.", str_error(err));
     714                goto err_usb_dev;
     715        }
     716
    627717        hcd_release_default_address(hcd);
    628         return ret;
     718        return EOK;
     719
     720err_usb_dev:
     721        usb_dev_destroy(usb_dev);
     722err_default_address:
     723        hcd_release_default_address(hcd);
     724        return err;
    629725}
    630726
     
    648744                return ENOMEM;
    649745        }
    650         instance->root_hub = NULL;
    651746        hcd_init(&instance->hcd);
    652747
     
    9201015         */
    9211016        if (driver->setup_root_hub)
    922                 ret = driver->setup_root_hub(device);
     1017                ret = driver->setup_root_hub(hcd, device);
    9231018        if (ret != EOK) {
    9241019                usb_log_error("Failed to setup HC root hub: %s.\n",
     
    9471042        return ret;
    9481043}
     1044
     1045struct hcd_roothub {
     1046        hcd_t *hcd;
     1047        ddf_dev_t *hc_dev;
     1048        usb_dev_t rh_usb;
     1049};
     1050
     1051hcd_roothub_t *hcd_roothub_create(hcd_t *hcd, ddf_dev_t *dev, usb_speed_t speed)
     1052{
     1053        hcd_roothub_t *rh = malloc(sizeof(*rh));
     1054
     1055        rh->hcd = hcd;
     1056        rh->hc_dev = dev;
     1057        usb_dev_init(&rh->rh_usb, speed);
     1058
     1059        rh->rh_usb.tt.address = -1;
     1060        return rh;
     1061}
     1062
     1063int hcd_roothub_new_device(hcd_roothub_t *rh, unsigned port) {
     1064        return hcd_ddf_new_device(rh->hcd, rh->hc_dev, &rh->rh_usb, port);
     1065}
    9491066/**
    9501067 * @}
  • uspace/lib/usbhost/src/hcd.c

    rd7869d7e r867b375  
    129129int hcd_add_ep(hcd_t *hcd, usb_target_t target, usb_direction_t dir,
    130130    usb_transfer_type_t type, size_t max_packet_size, unsigned packets,
    131     size_t size, usb_address_t tt_address, unsigned tt_port)
     131    size_t size, usb_tt_address_t tt)
    132132{
    133133        assert(hcd);
     
    143143        ep->max_packet_size = max_packet_size;
    144144        ep->packets = packets;
    145 
    146         ep->tt.address = tt_address;
    147         ep->tt.port = tt_port;
     145        ep->tt = tt;
    148146
    149147        ep->bandwidth = bus_count_bw(ep, size);
Note: See TracChangeset for help on using the changeset viewer.