Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changes in / [b2995c3:f58154c5] in mainline


Ignore:
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • .bzrignore

    rb2995c3 rf58154c5  
    5353./uspace/app/klog/klog
    5454./uspace/app/lsusb/lsusb
     55./uspace/app/mkbd/mkbd
    5556./uspace/app/mkfat/mkfat
    5657./uspace/app/netstart/netstart
  • uspace/drv/ohci/batch.c

    rb2995c3 rf58154c5  
    4444#include "hw_struct/transfer_descriptor.h"
    4545
     46/** OHCI specific data required for USB transfer */
    4647typedef struct ohci_transfer_batch {
     48        /** Endpoint descriptor of the target endpoint. */
    4749        ed_t *ed;
     50        /** List of TDs needed for the transfer */
    4851        td_t **tds;
     52        /** Number of TDs used by the transfer */
    4953        size_t td_count;
     54        /** Dummy TD to be left at the ED and used by the next transfer */
    5055        size_t leave_td;
    51         char *device_buffer;
     56        /** Data buffer, must be accessible byb the OHCI hw. */
     57        void *device_buffer;
    5258} ohci_transfer_batch_t;
    53 
     59/*----------------------------------------------------------------------------*/
     60static void batch_control(usb_transfer_batch_t *instance,
     61    usb_direction_t data_dir, usb_direction_t status_dir);
     62static void batch_data(usb_transfer_batch_t *instance);
     63/*----------------------------------------------------------------------------*/
     64/** Safely destructs ohci_transfer_batch_t structure
     65 *
     66 * @param[in] ohci_batch Instance to destroy.
     67 */
    5468static void ohci_transfer_batch_dispose(void *ohci_batch)
    5569{
     
    6983}
    7084/*----------------------------------------------------------------------------*/
    71 static void batch_control(usb_transfer_batch_t *instance,
    72     usb_direction_t data_dir, usb_direction_t status_dir);
    73 static void batch_data(usb_transfer_batch_t *instance);
    74 /*----------------------------------------------------------------------------*/
     85/** Allocate memory initialize internal structures
     86 *
     87 * @param[in] fun DDF function to pass to callback.
     88 * @param[in] ep Communication target
     89 * @param[in] buffer Data source/destination.
     90 * @param[in] buffer_size Size of the buffer.
     91 * @param[in] setup_buffer Setup data source (if not NULL)
     92 * @param[in] setup_size Size of setup_buffer (should be always 8)
     93 * @param[in] func_in function to call on inbound transfer completion
     94 * @param[in] func_out function to call on outbound transfer completion
     95 * @param[in] arg additional parameter to func_in or func_out
     96 * @return Valid pointer if all structures were successfully created,
     97 * NULL otherwise.
     98 *
     99 * Allocates and initializes structures needed by the OHCI hw for the transfer.
     100 */
    75101usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
    76102    char *buffer, size_t buffer_size, char* setup_buffer, size_t setup_size,
     
    107133        }
    108134
    109         /* we need one extra place for td that is currently assigned to hcd_ep*/
     135        /* We need an extra place for TD that is currently assigned to hcd_ep*/
    110136        data->tds = calloc(sizeof(td_t*), data->td_count + 1);
    111137        CHECK_NULL_DISPOSE_RETURN(data->tds,
    112138            "Failed to allocate transfer descriptors.\n");
    113139
     140        /* Add TD left over by the previous transfer */
    114141        data->tds[0] = hcd_ep->td;
    115142        data->leave_td = 0;
     
    123150        data->ed = hcd_ep->ed;
    124151
     152        /* NOTE: OHCI is capable of handling buffer that crosses page boundaries
     153         * it is, however, not capable of handling buffer that occupies more
     154         * than two pages (the first page is computed using start pointer, the
     155         * other using the end pointer) */
    125156        if (setup_size + buffer_size > 0) {
    126157                data->device_buffer = malloc32(setup_size + buffer_size);
     
    135166}
    136167/*----------------------------------------------------------------------------*/
     168/** Check batch TDs' status.
     169 *
     170 * @param[in] instance Batch structure to use.
     171 * @return False, if there is an active TD, true otherwise.
     172 *
     173 * Walk all TDs (usually there is just one). Stop with false if there is an
     174 * active TD. Stop with true if an error is found. Return true if the walk
     175 * completes with the last TD.
     176 */
    137177bool batch_is_complete(usb_transfer_batch_t *instance)
    138178{
     
    140180        ohci_transfer_batch_t *data = instance->private_data;
    141181        assert(data);
    142         size_t tds = data->td_count;
    143182        usb_log_debug("Batch(%p) checking %zu td(s) for completion.\n",
    144             instance, tds);
     183            instance, data->td_count);
    145184        usb_log_debug("ED: %x:%x:%x:%x.\n",
    146185            data->ed->status, data->ed->td_head, data->ed->td_tail,
     
    148187        size_t i = 0;
    149188        instance->transfered_size = instance->buffer_size;
    150         for (; i < tds; ++i) {
     189        for (; i < data->td_count; ++i) {
    151190                assert(data->tds[i] != NULL);
    152191                usb_log_debug("TD %zu: %x:%x:%x:%x.\n", i,
     
    173212        assert(hcd_ep);
    174213        hcd_ep->td = data->tds[i];
    175         if (i > 0)
    176                 instance->transfered_size -= td_remain_size(data->tds[i - 1]);
     214        assert(i > 0);
     215        for (--i;i < data->td_count; ++i)
     216                instance->transfered_size -= td_remain_size(data->tds[i]);
    177217
    178218        /* Clear possible ED HALT */
    179219        data->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG;
    180         uint32_t pa = addr_to_phys(hcd_ep->td);
     220        const uint32_t pa = addr_to_phys(hcd_ep->td);
    181221        assert(pa == (data->ed->td_head & ED_TDHEAD_PTR_MASK));
    182222        assert(pa == (data->ed->td_tail & ED_TDTAIL_PTR_MASK));
     
    185225}
    186226/*----------------------------------------------------------------------------*/
     227/** Starts execution of the TD list
     228 *
     229 * @param[in] instance Batch structure to use
     230 */
    187231void batch_commit(usb_transfer_batch_t *instance)
    188232{
     
    193237}
    194238/*----------------------------------------------------------------------------*/
     239/** Prepares control write transfer.
     240 *
     241 * @param[in] instance Batch structure to use.
     242 *
     243 * Uses generic control transfer using direction OUT(data stage) and
     244 * IN(status stage).
     245 */
    195246void batch_control_write(usb_transfer_batch_t *instance)
    196247{
     
    203254}
    204255/*----------------------------------------------------------------------------*/
     256/** Prepares control read transfer.
     257 *
     258 * @param[in] instance Batch structure to use.
     259 *
     260 * Uses generic control transfer using direction IN(data stage) and
     261 * OUT(status stage).
     262 */
    205263void batch_control_read(usb_transfer_batch_t *instance)
    206264{
     
    211269}
    212270/*----------------------------------------------------------------------------*/
     271/** Prepare interrupt in transfer.
     272 *
     273 * @param[in] instance Batch structure to use.
     274 *
     275 * Data transfer.
     276 */
    213277void batch_interrupt_in(usb_transfer_batch_t *instance)
    214278{
     
    219283}
    220284/*----------------------------------------------------------------------------*/
     285/** Prepare interrupt out transfer.
     286 *
     287 * @param[in] instance Batch structure to use.
     288 *
     289 * Data transfer.
     290 */
    221291void batch_interrupt_out(usb_transfer_batch_t *instance)
    222292{
     
    229299}
    230300/*----------------------------------------------------------------------------*/
     301/** Prepare bulk in transfer.
     302 *
     303 * @param[in] instance Batch structure to use.
     304 *
     305 * Data transfer.
     306 */
    231307void batch_bulk_in(usb_transfer_batch_t *instance)
    232308{
     
    237313}
    238314/*----------------------------------------------------------------------------*/
     315/** Prepare bulk out transfer.
     316 *
     317 * @param[in] instance Batch structure to use.
     318 *
     319 * Data transfer.
     320 */
    239321void batch_bulk_out(usb_transfer_batch_t *instance)
    240322{
     
    247329}
    248330/*----------------------------------------------------------------------------*/
    249 ed_t * batch_ed(usb_transfer_batch_t *instance)
    250 {
    251         assert(instance);
    252         ohci_transfer_batch_t *data = instance->private_data;
    253         assert(data);
    254         return data->ed;
    255 }
    256 /*----------------------------------------------------------------------------*/
     331/** Prepare generic control transfer
     332 *
     333 * @param[in] instance Batch structure to use.
     334 * @param[in] data_dir Direction to use for data stage.
     335 * @param[in] status_dir Direction to use for status stage.
     336 *
     337 * Setup stage with toggle 0 and direction BOTH(SETUP_PID)
     338 * Data stage with alternating toggle and direction supplied by parameter.
     339 * Status stage with toggle 1 and direction supplied by parameter.
     340 */
    257341void batch_control(usb_transfer_batch_t *instance,
    258342    usb_direction_t data_dir, usb_direction_t status_dir)
     
    303387}
    304388/*----------------------------------------------------------------------------*/
     389/** Prepare generic data transfer
     390 *
     391 * @param[in] instance Batch structure to use.
     392 *
     393 * Direction is supplied by the associated ep and toggle is maintained by the
     394 * OHCI hw in ED.
     395 */
    305396void batch_data(usb_transfer_batch_t *instance)
    306397{
  • uspace/drv/ohci/batch.h

    rb2995c3 rf58154c5  
    4141#include <usb/host/batch.h>
    4242
    43 #include "hw_struct/endpoint_descriptor.h"
    44 
    4543usb_transfer_batch_t * batch_get(
    4644    ddf_fun_t *fun, endpoint_t *ep, char *buffer, size_t size,
     
    6563
    6664void batch_bulk_out(usb_transfer_batch_t *instance);
    67 
    68 ed_t * batch_ed(usb_transfer_batch_t *instance);
    6965#endif
    7066/**
  • uspace/drv/ohci/endpoint_list.c

    rb2995c3 rf58154c5  
    3434#include <errno.h>
    3535#include <usb/debug.h>
     36#include <arch/barrier.h>
    3637
    3738#include "endpoint_list.h"
     
    4344 * @return Error code
    4445 *
    45  * Allocates memory for internal qh_t structure.
     46 * Allocates memory for internal ed_t structure.
    4647 */
    4748int endpoint_list_init(endpoint_list_t *instance, const char *name)
     
    6869 * @param[in] instance List to lead.
    6970 * @param[in] next List to append.
    70  * @return Error code
    7171 *
    72  * Does not check whether this replaces an existing list .
     72 * Does not check whether this replaces an existing list.
    7373 */
    7474void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next)
     
    7979}
    8080/*----------------------------------------------------------------------------*/
    81 /** Submit transfer endpoint to the list and queue.
     81/** Add endpoint to the list and queue.
    8282 *
    8383 * @param[in] instance List to use.
    84  * @param[in] endpoint Transfer endpoint to submit.
    85  * @return Error code
     84 * @param[in] endpoint Endpoint to add.
    8685 *
    8786 * The endpoint is added to the end of the list and queue.
     
    9998        /* Add to the hardware queue. */
    10099        if (list_empty(&instance->endpoint_list)) {
    101                 /* There is nothing scheduled */
     100                /* There are no active EDs */
    102101                last_ed = instance->list_head;
    103102        } else {
    104                 /* There is something scheduled */
     103                /* There are active EDs, get the last one */
    105104                hcd_endpoint_t *last = list_get_instance(
    106105                    instance->endpoint_list.prev, hcd_endpoint_t, link);
     106                assert(last);
    107107                last_ed = last->ed;
    108108        }
    109         /* keep link */
     109        /* Keep link */
    110110        hcd_ep->ed->next = last_ed->next;
     111        /* Make sure ED is written to the memory */
     112        write_barrier();
     113
     114        /* Add ed to the hw queue */
    111115        ed_append_ed(last_ed, hcd_ep->ed);
     116        /* Make sure ED is updated */
     117        write_barrier();
    112118
    113         asm volatile ("": : :"memory");
    114 
    115         /* Add to the driver list */
     119        /* Add to the sw list */
    116120        list_append(&hcd_ep->link, &instance->endpoint_list);
    117121
     
    129133}
    130134/*----------------------------------------------------------------------------*/
    131 #if 0
    132 /** Create list for finished endpoints.
     135/** Remove endpoint from the list and queue.
    133136 *
    134137 * @param[in] instance List to use.
    135  * @param[in] done list to fill
    136  */
    137 void endpoint_list_remove_finished(endpoint_list_t *instance, link_t *done)
    138 {
    139         assert(instance);
    140         assert(done);
    141 
    142         fibril_mutex_lock(&instance->guard);
    143         usb_log_debug2("Checking list %s for completed endpointes(%d).\n",
    144             instance->name, list_count(&instance->endpoint_list));
    145         link_t *current = instance->endpoint_list.next;
    146         while (current != &instance->endpoint_list) {
    147                 link_t *next = current->next;
    148                 hcd_endpoint_t *endpoint =
    149                     list_get_instance(current, hcd_endpoint_t, link);
    150 
    151                 if (endpoint_is_complete(endpoint)) {
    152                         /* Save for post-processing */
    153                         endpoint_list_remove_endpoint(instance, endpoint);
    154                         list_append(current, done);
    155                 }
    156                 current = next;
    157         }
    158         fibril_mutex_unlock(&instance->guard);
    159 }
    160 /*----------------------------------------------------------------------------*/
    161 /** Walk the list and abort all endpointes.
    162  *
    163  * @param[in] instance List to use.
    164  */
    165 void endpoint_list_abort_all(endpoint_list_t *instance)
    166 {
    167         fibril_mutex_lock(&instance->guard);
    168         while (!list_empty(&instance->endpoint_list)) {
    169                 link_t *current = instance->endpoint_list.next;
    170                 hcd_endpoint_t *endpoint =
    171                     list_get_instance(current, hcd_endpoint_t, link);
    172                 endpoint_list_remove_endpoint(instance, endpoint);
    173                 hcd_endpoint_finish_error(endpoint, EIO);
    174         }
    175         fibril_mutex_unlock(&instance->guard);
    176 }
    177 #endif
    178 /*----------------------------------------------------------------------------*/
    179 /** Remove a transfer endpoint from the list and queue.
    180  *
    181  * @param[in] instance List to use.
    182  * @param[in] endpoint Transfer endpoint to remove.
    183  * @return Error code
    184  *
    185  * Does not lock the transfer list, caller is responsible for that.
     138 * @param[in] endpoint Endpoint to remove.
    186139 */
    187140void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)
     
    212165        assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys(hcd_ep->ed));
    213166        prev_ed->next = hcd_ep->ed->next;
     167        /* Make sure ED is updated */
     168        write_barrier();
    214169
    215         asm volatile ("": : :"memory");
    216170        usb_log_debug("HCD EP(%p) removed (%s) from %s, next %x.\n",
    217171            hcd_ep, qpos, instance->name, hcd_ep->ed->next);
  • uspace/drv/ohci/endpoint_list.h

    rb2995c3 rf58154c5  
    4141#include "utils/malloc32.h"
    4242
    43 typedef struct endpoint_list {
     43/** Structure maintains both OHCI queue and software list of active endpoints.*/
     44typedef struct endpoint_list
     45{
     46        /** Guard against add/remove races */
    4447        fibril_mutex_t guard;
     48        /** OHCI hw structure at the beginning of the queue */
    4549        ed_t *list_head;
     50        /** Physical address of the first(dummy) ED */
    4651        uint32_t list_head_pa;
     52        /** Assigned name, provides nicer debug output */
    4753        const char *name;
     54        /** Sw list of all active EDs */
    4855        link_t endpoint_list;
    4956} endpoint_list_t;
     
    5360 * @param[in] instance Memory place to use.
    5461 *
    55  * Frees memory for internal qh_t structure.
     62 * Frees memory of the internal ed_t structure.
    5663 */
    5764static inline void endpoint_list_fini(endpoint_list_t *instance)
     
    6875
    6976void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep);
    70 #if 0
    71 void endpoint_list_remove_finished(endpoint_list_t *instance, link_t *done);
    72 
    73 void endpoint_list_abort_all(endpoint_list_t *instance);
    74 #endif
    7577#endif
    7678/**
  • uspace/drv/ohci/hc.c

    rb2995c3 rf58154c5  
    293293                rh_interrupt(&instance->rh);
    294294
    295 
    296295        if (status & I_WDH) {
    297296                fibril_mutex_lock(&instance->guard);
     
    316315                fibril_mutex_unlock(&instance->guard);
    317316        }
     317
     318        if (status & I_UE) {
     319                hc_start_hw(instance);
     320        }
     321
    318322}
    319323/*----------------------------------------------------------------------------*/
     
    450454{
    451455        assert(instance);
    452 
    453456#define SETUP_ENDPOINT_LIST(type) \
    454457do { \
     
    458461                usb_log_error("Failed(%d) to setup %s endpoint list.\n", \
    459462                    ret, name); \
    460                 endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]); \
     463                endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]);\
    461464                endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \
    462465                endpoint_list_fini(&instance->lists[USB_TRANSFER_CONTROL]); \
  • uspace/drv/ohci/hcd_endpoint.h

    rb2995c3 rf58154c5  
    3737#include <assert.h>
    3838#include <adt/list.h>
    39 
    4039#include <usb/host/endpoint.h>
    4140
     
    4342#include "hw_struct/transfer_descriptor.h"
    4443
    45 typedef struct hcd_endpoint {
     44typedef struct hcd_endpoint
     45{
    4646        ed_t *ed;
    4747        td_t *td;
  • uspace/drv/ohci/hw_struct/transfer_descriptor.c

    rb2995c3 rf58154c5  
    4444        assert(instance);
    4545        bzero(instance, sizeof(td_t));
    46         instance-> status = 0
     46        instance->status = 0
    4747            | ((dp[dir] & TD_STATUS_DP_MASK) << TD_STATUS_DP_SHIFT)
    4848            | ((CC_NOACCESS2 & TD_STATUS_CC_MASK) << TD_STATUS_CC_SHIFT);
  • uspace/drv/ohci/hw_struct/transfer_descriptor.h

    rb2995c3 rf58154c5  
    4141#include "completion_codes.h"
    4242
    43 /* OHCI TDs can handle up to 8KB buffers */
    44 #define OHCI_TD_MAX_TRANSFER (8 * 1024)
     43/* OHCI TDs can handle up to 8KB buffers, however, it can use max 2 pages.
     44 * Using 4KB buffers guarantees the page count condition.
     45 * (OHCI assumes 4KB pages) */
     46#define OHCI_TD_MAX_TRANSFER (4 * 1024)
    4547
    4648typedef struct td {
  • uspace/drv/uhci-hcd/batch.c

    rb2995c3 rf58154c5  
    4545#define DEFAULT_ERROR_COUNT 3
    4646
     47/** UHCI specific data required for USB transfer */
    4748typedef struct uhci_transfer_batch {
     49        /** Queue head
     50         * This QH is used to maintain UHCI schedule structure and the element
     51         * pointer points to the first TD of this batch.
     52         */
    4853        qh_t *qh;
     54        /** List of TDs needed for the transfer */
    4955        td_t *tds;
     56        /** Number of TDs used by the transfer */
     57        size_t td_count;
     58        /** Data buffer, must be accessible by the UHCI hw */
    5059        void *device_buffer;
    51         size_t td_count;
    5260} uhci_transfer_batch_t;
    5361/*----------------------------------------------------------------------------*/
    54 static void uhci_transfer_batch_dispose(void *uhci_batch)
    55 {
    56         uhci_transfer_batch_t *instance = uhci_batch;
    57         assert(instance);
    58         free32(instance->device_buffer);
    59         free(instance);
    60 }
    61 /*----------------------------------------------------------------------------*/
    62 
    6362static void batch_control(usb_transfer_batch_t *instance,
    6463    usb_packet_id data_stage, usb_packet_id status_stage);
    6564static void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid);
    66 
     65/*----------------------------------------------------------------------------*/
     66/** Safely destructs uhci_transfer_batch_t structure
     67 *
     68 * @param[in] uhci_batch Instance to destroy.
     69 */
     70static void uhci_transfer_batch_dispose(void *uhci_batch)
     71{
     72        uhci_transfer_batch_t *instance = uhci_batch;
     73        assert(instance);
     74        free32(instance->device_buffer);
     75        free(instance);
     76}
     77/*----------------------------------------------------------------------------*/
    6778/** Allocate memory and initialize internal data structure.
    6879 *
     
    173184                instance->error = td_status(&data->tds[i]);
    174185                if (instance->error != EOK) {
    175                         usb_log_debug("Batch(%p) found error TD(%zu):%" PRIx32 ".\n",
    176                             instance, i, data->tds[i].status);
     186                        usb_log_debug("Batch(%p) found error TD(%zu):%"
     187                            PRIx32 ".\n", instance, i, data->tds[i].status);
    177188                        td_print_status(&data->tds[i]);
    178189
     
    397408/*----------------------------------------------------------------------------*/
    398409/** Provides access to QH data structure.
     410 *
    399411 * @param[in] instance Batch pointer to use.
    400412 * @return Pointer to the QH used by the batch.
  • uspace/drv/uhci-hcd/transfer_list.c

    rb2995c3 rf58154c5  
    3434#include <errno.h>
    3535#include <usb/debug.h>
     36#include <arch/barrier.h>
    3637
    3738#include "transfer_list.h"
     
    7172 * @param[in] instance Memory place to use.
    7273 *
    73  * Frees memory for internal qh_t structure.
     74 * Frees memory of the internal qh_t structure.
    7475 */
    7576void transfer_list_fini(transfer_list_t *instance)
     
    126127        assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
    127128
     129        /* Make sure all data in the batch are written */
     130        write_barrier();
     131
    128132        /* keep link */
    129133        batch_qh(batch)->next = last_qh->next;
    130134        qh_set_next_qh(last_qh, batch_qh(batch));
    131135
    132         asm volatile ("": : :"memory");
     136        /* Make sure the pointer is updated */
     137        write_barrier();
    133138
    134139        /* Add to the driver list */
     
    222227            == addr_to_phys(batch_qh(batch)));
    223228        prev_qh->next = batch_qh(batch)->next;
    224         asm volatile ("": : :"memory");
     229
     230        /* Make sure the pointer is updated */
     231        write_barrier();
     232
    225233        /* Remove from the batch list */
    226234        list_remove(&batch->link);
  • uspace/drv/uhci-hcd/utils/malloc32.h

    rb2995c3 rf58154c5  
    7474        if (size <= SLAB_ELEMENT_SIZE)
    7575                return slab_malloc_g();
    76         assert(false);
     76        usb_log_warning("Requested %zu bytes, current allocator can't handle "
     77            "that amount, pray that the standard malloc will suffice.", size);
    7778        return memalign(UHCI_STRCUTURES_ALIGNMENT, size);
    7879}
  • uspace/drv/uhci-rhd/port.c

    rb2995c3 rf58154c5  
    227227                while (uhci_port_read_status(port) & STATUS_IN_RESET);
    228228        }
     229        /* PIO delay, should not be longer than 3ms as the device might
     230         * enter suspend state. */
    229231        udelay(10);
    230232        /* Enable the port. */
    231233        uhci_port_set_enabled(port, true);
    232 
    233         /* Reset recovery period,
    234          * devices do not have to respond during this period
    235          */
    236         async_usleep(10000);
    237234        return EOK;
    238235}
  • uspace/lib/usbdev/src/hub.c

    rb2995c3 rf58154c5  
    4141#include <assert.h>
    4242#include <usb/debug.h>
     43#include <time.h>
    4344
    4445/** How much time to wait between attempts to register endpoint 0:0.
     
    218219
    219220        int rc;
     221        struct timeval start_time;
     222
     223        rc = gettimeofday(&start_time, NULL);
     224        if (rc != EOK) {
     225                return rc;
     226        }
    220227
    221228        rc = usb_hc_connection_open(&hc_conn);
     
    264271                }
    265272        } while (rc != EOK);
     273        struct timeval end_time;
     274
     275        rc = gettimeofday(&end_time, NULL);
     276        if (rc != EOK) {
     277                goto leave_release_default_address;
     278        }
     279
     280        /* According to the USB spec part 9.1.2 host allows 100ms time for
     281         * the insertion process to complete. According to 7.1.7.1 this is the
     282         * time between attach detected and port reset. However, the setup done
     283         * above might use much of this time so we should only wait to fill
     284         * up the 100ms quota*/
     285        suseconds_t elapsed = tv_sub(&end_time, &start_time);
     286        if (elapsed < 100000) {
     287                async_usleep(100000 - elapsed);
     288        }
    266289
    267290        /*
     
    273296                goto leave_release_default_address;
    274297        }
     298        /* USB spec 7.1.7.1: The USB System Software guarantees a minimum of
     299         * 10ms for reset recovery. Device response to any bus transactions
     300         * addressed to the default device address during the reset recovery
     301         * time is undefined.
     302         */
     303        async_usleep(10000);
    275304
    276305        rc = usb_pipe_probe_default_control(&ctrl_pipe);
Note: See TracChangeset for help on using the changeset viewer.