Changeset 20eaa82 in mainline for uspace/lib/usbhost/src/ddf_helpers.c


Ignore:
Timestamp:
2017-10-15T13:44:39Z (7 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2770b66
Parents:
867b375
Message:

usbhost refactoring: introduced bus→enumerate_device

File:
1 edited

Legend:

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

    r867b375 r20eaa82  
    3535
    3636#include <usb/classes/classes.h>
     37#include <usb/host/bus.h>
    3738#include <usb/debug.h>
    3839#include <usb/descriptor.h>
     
    5051#include <fibril_synch.h>
    5152#include <macros.h>
    52 #include <stdio.h>
    5353#include <stdlib.h>
    5454#include <str_error.h>
     
    5656
    5757#include "ddf_helpers.h"
    58 
    59 #define CTRL_PIPE_MIN_PACKET_SIZE 8
    60 
    61 typedef struct usb_dev {
    62         link_t link;
    63         list_t devices;
    64         fibril_mutex_t guard;
    65         usb_address_t address;
    66         usb_speed_t speed;
    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;
    71 } usb_dev_t;
    7258
    7359typedef struct hc_dev {
     
    9278
    9379
    94 static int hcd_ddf_new_device(hcd_t *hcd, ddf_dev_t *hc, usb_dev_t *hub_dev, unsigned port);
    95 static int hcd_ddf_remove_device(ddf_dev_t *device, usb_dev_t *hub, unsigned port);
     80static int hcd_ddf_new_device(hcd_t *hcd, ddf_dev_t *hc, device_t *hub_dev, unsigned port);
     81static int hcd_ddf_remove_device(ddf_dev_t *device, device_t *hub, unsigned port);
    9682
    9783
     
    115101        assert(fun);
    116102        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    117         usb_dev_t *dev = ddf_fun_data_get(fun);
     103        device_t *dev = ddf_fun_data_get(fun);
    118104        assert(hcd);
     105        assert(hcd->bus);
    119106        assert(dev);
    120107        const size_t size = max_packet_size;
    121         const usb_target_t target =
    122             {{.address = dev->address, .endpoint = endpoint}};
    123108
    124109        usb_log_debug("Register endpoint %d:%d %s-%s %zuB %ums.\n",
     
    126111            usb_str_direction(direction), max_packet_size, interval);
    127112
    128         return hcd_add_ep(hcd, target, direction, transfer_type,
    129             max_packet_size, packets, size, dev->tt);
     113        return bus_add_ep(hcd->bus, dev, endpoint, direction, transfer_type,
     114            max_packet_size, packets, size);
    130115}
    131116
     
    142127        assert(fun);
    143128        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    144         usb_dev_t *dev = ddf_fun_data_get(fun);
     129        device_t *dev = ddf_fun_data_get(fun);
    145130        assert(hcd);
     131        assert(hcd->bus);
    146132        assert(dev);
    147         const usb_target_t target =
    148             {{.address = dev->address, .endpoint = endpoint}};
     133        const usb_target_t target = {{
     134                .address = dev->address,
     135                .endpoint = endpoint
     136        }};
    149137        usb_log_debug("Unregister endpoint %d:%d %s.\n",
    150138            dev->address, endpoint, usb_str_direction(direction));
    151         return hcd_remove_ep(hcd, target, direction);
     139        return bus_remove_ep(hcd->bus, target, direction);
    152140}
    153141
     
    156144        assert(fun);
    157145        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    158         usb_dev_t *dev = ddf_fun_data_get(fun);
     146        device_t *dev = ddf_fun_data_get(fun);
    159147        assert(hcd);
     148        assert(hcd->bus);
    160149        assert(dev);
    161150
    162151        usb_log_debug("Device %d requested default address at %s speed\n",
    163152            dev->address, usb_str_speed(speed));
    164         return hcd_reserve_default_address(hcd, speed);
     153        return bus_reserve_default_address(hcd->bus, speed);
    165154}
    166155
     
    169158        assert(fun);
    170159        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    171         usb_dev_t *dev = ddf_fun_data_get(fun);
     160        device_t *dev = ddf_fun_data_get(fun);
    172161        assert(hcd);
     162        assert(hcd->bus);
    173163        assert(dev);
    174164
    175165        usb_log_debug("Device %d released default address\n", dev->address);
    176         return hcd_release_default_address(hcd);
     166        return bus_release_default_address(hcd->bus);
    177167}
    178168
     
    184174        hcd_t *hcd = dev_to_hcd(hc);
    185175        assert(hcd);
    186         usb_dev_t *hub = ddf_fun_data_get(fun);
     176        device_t *hub = ddf_fun_data_get(fun);
    187177        assert(hub);
    188178
     
    196186        assert(fun);
    197187        ddf_dev_t *ddf_dev = ddf_fun_get_dev(fun);
    198         usb_dev_t *dev = ddf_fun_data_get(fun);
     188        device_t *dev = ddf_fun_data_get(fun);
    199189        assert(ddf_dev);
    200190        assert(dev);
     
    233223{
    234224        assert(fun);
    235         usb_dev_t *usb_dev = ddf_fun_data_get(fun);
    236         assert(usb_dev);
     225        device_t *dev = ddf_fun_data_get(fun);
     226        assert(dev);
    237227        const usb_target_t target = {{
    238             .address =  usb_dev->address,
     228            .address  = dev->address,
    239229            .endpoint = endpoint,
    240230        }};
     
    259249{
    260250        assert(fun);
    261         usb_dev_t *usb_dev = ddf_fun_data_get(fun);
    262         assert(usb_dev);
     251        device_t *dev = ddf_fun_data_get(fun);
     252        assert(dev);
    263253        const usb_target_t target = {{
    264             .address =  usb_dev->address,
     254            .address  = dev->address,
    265255            .endpoint = endpoint,
    266256        }};
     
    343333}
    344334
    345 static int hcd_ddf_remove_device(ddf_dev_t *device, usb_dev_t *hub,
     335static int hcd_ddf_remove_device(ddf_dev_t *device, device_t *hub,
    346336    unsigned port)
    347337{
     
    350340        hcd_t *hcd = dev_to_hcd(device);
    351341        assert(hcd);
     342        assert(hcd->bus);
    352343
    353344        hc_dev_t *hc_dev = dev_to_hc_dev(device);
     
    356347        fibril_mutex_lock(&hub->guard);
    357348
    358         usb_dev_t *victim = NULL;
    359 
    360         list_foreach(hub->devices, link, usb_dev_t, it) {
    361                 if (it->tt.port == port) {
     349        device_t *victim = NULL;
     350
     351        list_foreach(hub->devices, link, device_t, it) {
     352                if (it->port == port) {
    362353                        victim = it;
    363354                        break;
     
    366357        if (victim) {
    367358                assert(victim->fun);
    368                 assert(victim->tt.port == port);
     359                assert(victim->port == port);
     360                assert(victim->hub == hub);
    369361                list_remove(&victim->link);
    370362                fibril_mutex_unlock(&hub->guard);
     
    372364                if (ret == EOK) {
    373365                        usb_address_t address = victim->address;
     366                        bus_remove_device(hcd->bus, hcd, victim);
    374367                        ddf_fun_destroy(victim->fun);
    375                         hcd_release_address(hcd, address);
     368                        bus_release_address(hcd->bus, address);
    376369                } else {
    377370                        usb_log_warning("Failed to unbind device `%s': %s\n",
     
    384377}
    385378
    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 
    408 static 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;
    412 
    413         static const usb_target_t default_target = {{
    414                 .address = USB_ADDRESS_DEFAULT,
    415                 .endpoint = 0,
    416         }};
    417 
    418         /** Reserve address early, we want pretty log messages */
    419         const usb_address_t address = hcd_request_address(hcd, speed);
    420         if (address < 0) {
    421                 usb_log_error("Failed to reserve new address: %s.",
    422                     str_error(address));
    423                 return address;
    424         }
    425         usb_log_debug("Device(%d): Reserved new address.", address);
    426 
    427         /* Add default pipe on default address */
    428         usb_log_debug("Device(%d): Adding default target (0:0)", address);
    429         err = hcd_add_ep(hcd,
    430             default_target, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL,
    431             CTRL_PIPE_MIN_PACKET_SIZE, CTRL_PIPE_MIN_PACKET_SIZE, 1, tt);
    432         if (err != EOK) {
    433                 usb_log_error("Device(%d): Failed to add default target: %s.",
    434                     address, str_error(err));
    435                 goto err_address;
    436         }
    437 
    438         /* Get max packet size for default pipe */
    439         usb_standard_device_descriptor_t desc = { 0 };
    440         const usb_device_request_setup_packet_t get_device_desc_8 =
    441             GET_DEVICE_DESC(CTRL_PIPE_MIN_PACKET_SIZE);
    442 
    443         usb_log_debug("Device(%d): Requesting first 8B of device descriptor.",
    444             address);
    445         ssize_t got = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_IN,
    446             &desc, CTRL_PIPE_MIN_PACKET_SIZE, *(uint64_t *)&get_device_desc_8,
    447             "read first 8 bytes of dev descriptor");
    448 
    449         if (got != CTRL_PIPE_MIN_PACKET_SIZE) {
    450                 err = got < 0 ? got : EOVERFLOW;
    451                 usb_log_error("Device(%d): Failed to get 8B of dev descr: %s.",
    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         };
    474 
    475         /* Register EP on the new address */
    476         usb_log_debug("Device(%d): Registering control EP.", address);
    477         err = hcd_add_ep(hcd, control_ep, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL,
    478             ED_MPS_PACKET_SIZE_GET(uint16_usb2host(desc.max_packet_size)),
    479             ED_MPS_TRANS_OPPORTUNITIES_GET(uint16_usb2host(desc.max_packet_size)),
    480             ED_MPS_PACKET_SIZE_GET(uint16_usb2host(desc.max_packet_size)), tt);
    481         if (err != EOK) {
    482                 usb_log_error("Device(%d): Failed to register EP0: %s",
    483                     address, str_error(err));
    484                 goto err_default_target;
    485         }
    486 
    487         hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH);
    488         return EOK;
    489 
    490 
    491 err_default_target:
    492         hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH);
    493 err_address:
    494         hcd_release_address(hcd, address);
    495         return err;
    496 }
    497 
    498 static 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 
    511 static usb_dev_t *usb_dev_create(ddf_dev_t *hc, usb_speed_t speed)
     379device_t *hcd_ddf_device_create(ddf_dev_t *hc, size_t device_size)
    512380{
    513381        /* Create DDF function for the new device */
     
    519387
    520388        /* 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) {
     389        device_t *dev = ddf_fun_data_alloc(fun, device_size);
     390        if (!dev) {
    523391                ddf_fun_destroy(fun);
    524392                return NULL;
    525393        }
    526394
    527         usb_dev_init(usb_dev, speed);
    528         usb_dev->fun = fun;
    529         return usb_dev;
    530 }
    531 
    532 static void usb_dev_destroy(usb_dev_t *dev)
     395        device_init(dev);
     396        dev->fun = fun;
     397        return dev;
     398}
     399
     400void hcd_ddf_device_destroy(device_t *dev)
    533401{
    534402        assert(dev);
     
    537405}
    538406
    539 static 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 
    550 static int usb_dev_explore(hcd_t *hcd, usb_dev_t *usb_dev)
     407int hcd_ddf_device_explore(hcd_t *hcd, device_t *device)
    551408{
    552409        int err;
     
    556413        init_match_ids(&mids);
    557414
    558         usb_target_t control_ep = {
    559                 .address = usb_dev->address,
     415        usb_target_t control_ep = {{
     416                .address = device->address,
    560417                .endpoint = 0
    561         };
     418        }};
    562419
    563420        /* Get std device descriptor */
     
    566423
    567424        usb_log_debug("Device(%d): Requesting full device descriptor.",
    568             usb_dev->address);
     425            device->address);
    569426        ssize_t got = hcd_send_batch_sync(hcd, control_ep, USB_DIRECTION_IN,
    570427            &desc, sizeof(desc), *(uint64_t *)&get_device_desc,
     
    573430                err = got < 0 ? got : EOVERFLOW;
    574431                usb_log_error("Device(%d): Failed to set get dev descriptor: %s",
    575                     usb_dev->address, str_error(err));
     432                    device->address, str_error(err));
    576433                goto out;
    577434        }
    578435
    579436        /* Create match ids from the device descriptor */
    580         usb_log_debug("Device(%d): Creating match IDs.", usb_dev->address);
     437        usb_log_debug("Device(%d): Creating match IDs.", device->address);
    581438        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));
     439                usb_log_error("Device(%d): Failed to create match ids: %s", device->address, str_error(err));
    583440                goto out;
    584441        }
    585442
    586443        list_foreach(mids.ids, link, const match_id_t, mid) {
    587                 ddf_fun_add_match_id(usb_dev->fun, mid->id, mid->score);
     444                ddf_fun_add_match_id(device->fun, mid->id, mid->score);
    588445        }
    589446
     
    593450}
    594451
    595 static 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 
    603 static int hcd_ddf_new_device(hcd_t *hcd, ddf_dev_t *hc, usb_dev_t *hub_dev, unsigned port)
     452static int hcd_ddf_new_device(hcd_t *hcd, ddf_dev_t *hc, device_t *hub, unsigned port)
    604453{
    605454        int err;
    606455        assert(hcd);
    607         assert(hub_dev);
     456        assert(hcd->bus);
     457        assert(hub);
    608458        assert(hc);
    609459
    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.
     460        device_t *dev = hcd_ddf_device_create(hc, hcd->bus->device_size);
     461        if (!dev) {
     462                usb_log_error("Failed to create USB device function.");
     463                return ENOMEM;
     464        }
     465
     466        dev->hub = hub;
     467        dev->port = port;
     468
     469        if ((err = bus_enumerate_device(hcd->bus, hcd, dev))) {
     470                usb_log_error("Failed to initialize USB dev memory structures.");
     471                return err;
     472        }
     473
     474        /* If the driver didn't name the dev when enumerating,
     475         * do it in some generic way.
    613476         */
    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));
     477        if (!ddf_fun_get_name(dev->fun)) {
     478                device_set_default_name(dev);
     479        }
     480
     481        if ((err = ddf_fun_bind(dev->fun))) {
     482                usb_log_error("Device(%d): Failed to register: %s.", dev->address, str_error(err));
    640483                goto err_usb_dev;
    641484        }
    642485
    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);
     486        fibril_mutex_lock(&hub->guard);
     487        list_append(&dev->link, &hub->devices);
     488        fibril_mutex_unlock(&hub->guard);
    664489
    665490        return EOK;
    666491
    667492err_usb_dev:
    668         usb_dev_destroy(usb_dev);
     493        hcd_ddf_device_destroy(dev);
    669494        return err;
    670495}
     
    681506        assert(hc);
    682507        assert(hcd);
    683 
    684         if ((err = hcd_reserve_default_address(hcd, USB_SPEED_MAX))) {
     508        assert(hcd->bus);
     509
     510        if ((err = bus_reserve_default_address(hcd->bus, USB_SPEED_MAX))) {
    685511                usb_log_error("Failed to reserve default address for roothub setup: %s", str_error(err));
    686512                return err;
    687513        }
    688514
    689         usb_dev_t *usb_dev = usb_dev_create(hc, USB_SPEED_MAX);
    690         if (!usb_dev) {
     515        device_t *dev = hcd_ddf_device_create(hc, USB_SPEED_MAX);
     516        if (!dev) {
    691517                usb_log_error("Failed to create function for the root hub.");
    692518                goto err_default_address;
    693519        }
    694520
    695         usb_dev->tt.address = -1;
    696         usb_dev->tt.port = 0;
     521        ddf_fun_set_name(dev->fun, "roothub");
     522
     523        dev->tt = (usb_tt_address_t) {
     524                .address = -1,
     525                .port = 0,
     526        };
    697527
    698528        /* 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));
     529        if ((err = bus_enumerate_device(hcd->bus, hcd, dev))) {
     530                usb_log_error("Failed to enumerate roothub device: %s", str_error(err));
    701531                goto err_usb_dev;
    702532        }
    703533
    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))) {
     534        if ((err = ddf_fun_bind(dev->fun))) {
    713535                usb_log_error("Failed to register roothub: %s.", str_error(err));
    714536                goto err_usb_dev;
    715537        }
    716538
    717         hcd_release_default_address(hcd);
     539        bus_release_default_address(hcd->bus);
    718540        return EOK;
    719541
    720542err_usb_dev:
    721         usb_dev_destroy(usb_dev);
     543        hcd_ddf_device_destroy(dev);
    722544err_default_address:
    723         hcd_release_default_address(hcd);
     545        bus_release_default_address(hcd->bus);
    724546        return err;
    725547}
     
    1043865}
    1044866
    1045 struct hcd_roothub {
    1046         hcd_t *hcd;
    1047         ddf_dev_t *hc_dev;
    1048         usb_dev_t rh_usb;
    1049 };
    1050 
    1051 hcd_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 
    1063 int 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 }
    1066867/**
    1067868 * @}
Note: See TracChangeset for help on using the changeset viewer.