Changes in / [367db39a:e160bfe8] in mainline


Ignore:
Files:
37 added
6 deleted
62 edited

Legend:

Unmodified
Added
Removed
  • .bzrignore

    r367db39a re160bfe8  
    234234uspace/dist/drv/virt/
    235235uspace/dist/drv/xtkbd/
     236uspace/dist/drv/xhci/
    236237uspace/dist/inc/_link.ld
    237238uspace/dist/inc/c/
     
    288289uspace/drv/bus/usb/usbmid/usbmid
    289290uspace/drv/bus/usb/vhc/vhc
     291uspace/drv/bus/usb/xhci/xhci
     292uspace/drv/bus/usb/xhci/test-xhci
    290293uspace/drv/char/atkbd/atkbd
    291294uspace/drv/char/i8042/i8042
  • boot/Makefile.common

    r367db39a re160bfe8  
    235235        $(USPACE_PATH)/lib/posix/test-libposix \
    236236        $(USPACE_PATH)/lib/uri/test-liburi \
     237        $(USPACE_PATH)/drv/bus/usb/xhci/test-xhci \
    237238        $(USPACE_PATH)/app/bdsh/test-bdsh \
    238239        $(USPACE_PATH)/srv/net/tcp/test-tcp
  • boot/arch/amd64/Makefile.inc

    r367db39a re160bfe8  
    5454        bus/usb/usbmast \
    5555        bus/usb/usbmid \
    56         bus/usb/vhc
     56        bus/usb/vhc \
     57        bus/usb/xhci
    5758
    5859RD_DRV_CFG += \
  • tools/ew.py

    r367db39a re160bfe8  
    160160        return ' -usb'
    161161
     162def qemu_xhci_options():
     163        if is_override('noxhci'):
     164                return ''
     165        return ' -device nec-usb-xhci,id=xhci'
     166
    162167def qemu_audio_options():
    163168        if is_override('nosnd'):
     
    180185        if (not 'usb' in cfg.keys()) or cfg['usb']:
    181186                cmdline += qemu_usb_options()
     187        if (not 'xhci' in cfg.keys()) or cfg['xhci']:
     188                cmdline += qemu_xhci_options()
    182189        if (not 'audio' in cfg.keys()) or cfg['audio']:
    183190                cmdline += qemu_audio_options()
     
    286293def usage():
    287294        print("%s - emulator wrapper for running HelenOS\n" % os.path.basename(sys.argv[0]))
    288         print("%s [-d] [-h] [-net e1k|rtl8139|ne2k] [-nohdd] [-nokvm] [-nonet] [-nosnd] [-nousb]\n" %
     295        print("%s [-d] [-h] [-net e1k|rtl8139|ne2k] [-nohdd] [-nokvm] [-nonet] [-nosnd] [-nousb] [-noxhci]\n" %
    289296            os.path.basename(sys.argv[0]))
    290297        print("-d\tDry run: do not run the emulation, just print the command line.")
     
    295302        print("-nosnd\tDisable sound, if applicable.")
    296303        print("-nousb\tDisable USB support, if applicable.")
     304        print("-noxhci\tDisable XHCI support, if applicable.")
    297305
    298306def fail(platform, machine):
     
    336344                elif sys.argv[i] == '-nousb':
    337345                        overrides['nousb'] = True
     346                elif sys.argv[i] == '-noxhci':
     347                        overrides['noxhci'] = True
    338348                else:
    339349                        usage()
  • uspace/Makefile

    r367db39a re160bfe8  
    156156        drv/bus/usb/usbmid \
    157157        drv/bus/usb/vhc \
     158        drv/bus/usb/xhci \
    158159        drv/char/i8042 \
    159160        drv/char/ns8250 \
  • uspace/drv/bus/usb/ehci/Makefile

    r367db39a re160bfe8  
    4646SOURCES = \
    4747        ehci_batch.c \
    48         ehci_endpoint.c \
     48        ehci_bus.c \
    4949        ehci_rh.c \
    5050        endpoint_list.c \
  • uspace/drv/bus/usb/ehci/ehci_batch.c

    r367db39a re160bfe8  
    4545
    4646#include "ehci_batch.h"
    47 #include "ehci_endpoint.h"
     47#include "ehci_bus.h"
    4848
    4949/* The buffer pointer list in the qTD is long enough to support a maximum
     
    5353#define EHCI_TD_MAX_TRANSFER   (16 * 1024)
    5454
    55 static void (*const batch_setup[])(ehci_transfer_batch_t*, usb_direction_t);
     55static void (*const batch_setup[])(ehci_transfer_batch_t*);
    5656
    5757/** Safely destructs ehci_transfer_batch_t structure
     
    5959 * @param[in] ehci_batch Instance to destroy.
    6060 */
    61 static void ehci_transfer_batch_dispose(ehci_transfer_batch_t *ehci_batch)
    62 {
    63         if (!ehci_batch)
    64                 return;
     61void ehci_transfer_batch_destroy(ehci_transfer_batch_t *ehci_batch)
     62{
     63        assert(ehci_batch);
    6564        if (ehci_batch->tds) {
    6665                for (size_t i = 0; i < ehci_batch->td_count; ++i) {
     
    6968                free(ehci_batch->tds);
    7069        }
    71         usb_transfer_batch_destroy(ehci_batch->usb_batch);
    7270        free32(ehci_batch->device_buffer);
    7371        free(ehci_batch);
     
    7573}
    7674
    77 /** Finishes usb_transfer_batch and destroys the structure.
    78  *
    79  * @param[in] uhci_batch Instance to finish and destroy.
    80  */
    81 void ehci_transfer_batch_finish_dispose(ehci_transfer_batch_t *ehci_batch)
    82 {
    83         assert(ehci_batch);
    84         assert(ehci_batch->usb_batch);
    85         usb_transfer_batch_finish(ehci_batch->usb_batch,
    86             ehci_batch->device_buffer + ehci_batch->usb_batch->setup_size);
    87         ehci_transfer_batch_dispose(ehci_batch);
    88 }
    89 
    9075/** Allocate memory and initialize internal data structure.
    9176 *
     
    9479 * NULL otherwise.
    9580 *
     81 */
     82ehci_transfer_batch_t * ehci_transfer_batch_create(endpoint_t *ep)
     83{
     84        assert(ep);
     85
     86        ehci_transfer_batch_t *ehci_batch = calloc(1, sizeof(ehci_transfer_batch_t));
     87        if (!ehci_batch) {
     88                usb_log_error("Failed to allocate EHCI batch data.");
     89                return NULL;
     90        }
     91
     92        usb_transfer_batch_init(&ehci_batch->base, ep);
     93        link_initialize(&ehci_batch->link);
     94
     95        return ehci_batch;
     96}
     97
     98/** Prepares a batch to be sent.
     99 *
    96100 * Determines the number of needed transfer descriptors (TDs).
    97101 * Prepares a transport buffer (that is accessible by the hardware).
    98102 * Initializes parameters needed for the transfer and callback.
    99103 */
    100 ehci_transfer_batch_t * ehci_transfer_batch_get(usb_transfer_batch_t *usb_batch)
    101 {
    102         assert(usb_batch);
    103 
    104         ehci_transfer_batch_t *ehci_batch =
    105             calloc(1, sizeof(ehci_transfer_batch_t));
    106         if (!ehci_batch) {
    107                 usb_log_error("Batch %p: Failed to allocate EHCI batch data.",
    108                     usb_batch);
    109                 goto dispose;
    110         }
    111         link_initialize(&ehci_batch->link);
    112         ehci_batch->td_count =
    113             (usb_batch->buffer_size + EHCI_TD_MAX_TRANSFER - 1)
    114             / EHCI_TD_MAX_TRANSFER;
     104int ehci_transfer_batch_prepare(ehci_transfer_batch_t *ehci_batch)
     105{
     106        assert(ehci_batch);
     107
     108        const size_t setup_size = (ehci_batch->base.ep->transfer_type == USB_TRANSFER_CONTROL)
     109                ? USB_SETUP_PACKET_SIZE
     110                : 0;
     111
     112        const size_t size = ehci_batch->base.buffer_size;
     113
     114        /* Mix setup stage and data together, we have enough space */
     115        if (size + setup_size > 0) {
     116                /* Use one buffer for setup and data stage */
     117                ehci_batch->device_buffer = malloc32(size + setup_size);
     118                if (!ehci_batch->device_buffer) {
     119                        usb_log_error("Batch %p: Failed to allocate device "
     120                            "buffer", ehci_batch);
     121                        return ENOMEM;
     122                }
     123                /* Copy setup data */
     124                memcpy(ehci_batch->device_buffer, ehci_batch->base.setup.buffer,
     125                    setup_size);
     126                /* Copy generic data */
     127                if (ehci_batch->base.dir != USB_DIRECTION_IN)
     128                        memcpy(ehci_batch->device_buffer + setup_size,
     129                            ehci_batch->base.buffer, ehci_batch->base.buffer_size);
     130        }
     131
     132        /* Add TD left over by the previous transfer */
     133        ehci_batch->qh = ehci_endpoint_get(ehci_batch->base.ep)->qh;
     134
     135        /* Determine number of TDs needed */
     136        ehci_batch->td_count = (size + EHCI_TD_MAX_TRANSFER - 1)
     137                / EHCI_TD_MAX_TRANSFER;
    115138
    116139        /* Control transfer need Setup and Status stage */
    117         if (usb_batch->ep->transfer_type == USB_TRANSFER_CONTROL) {
     140        if (ehci_batch->base.ep->transfer_type == USB_TRANSFER_CONTROL) {
    118141                ehci_batch->td_count += 2;
    119142        }
     
    122145        if (!ehci_batch->tds) {
    123146                usb_log_error("Batch %p: Failed to allocate EHCI transfer "
    124                     "descriptors.", usb_batch);
    125                 goto dispose;
    126         }
    127 
    128         /* Add TD left over by the previous transfer */
    129         ehci_batch->qh = ehci_endpoint_get(usb_batch->ep)->qh;
     147                    "descriptors.", ehci_batch);
     148                return ENOMEM;
     149        }
    130150
    131151        for (unsigned i = 0; i < ehci_batch->td_count; ++i) {
     
    133153                if (!ehci_batch->tds[i]) {
    134154                        usb_log_error("Batch %p: Failed to allocate TD %d.",
    135                             usb_batch, i);
    136                         goto dispose;
     155                            ehci_batch, i);
     156                        return ENOMEM;
    137157                }
    138158                memset(ehci_batch->tds[i], 0, sizeof(td_t));
    139159        }
    140160
    141 
    142         /* Mix setup stage and data together, we have enough space */
    143         if (usb_batch->setup_size + usb_batch->buffer_size > 0) {
    144                 /* Use one buffer for setup and data stage */
    145                 ehci_batch->device_buffer =
    146                     malloc32(usb_batch->setup_size + usb_batch->buffer_size);
    147                 if (!ehci_batch->device_buffer) {
    148                         usb_log_error("Batch %p: Failed to allocate device "
    149                             "buffer", usb_batch);
    150                         goto dispose;
    151                 }
    152                 /* Copy setup data */
    153                 memcpy(ehci_batch->device_buffer, usb_batch->setup_buffer,
    154                     usb_batch->setup_size);
    155                 /* Copy generic data */
    156                 if (usb_batch->ep->direction != USB_DIRECTION_IN)
    157                         memcpy(
    158                             ehci_batch->device_buffer + usb_batch->setup_size,
    159                             usb_batch->buffer, usb_batch->buffer_size);
    160         }
    161         ehci_batch->usb_batch = usb_batch;
    162 
    163         const usb_direction_t dir = usb_transfer_batch_direction(usb_batch);
    164         assert(batch_setup[usb_batch->ep->transfer_type]);
    165         batch_setup[usb_batch->ep->transfer_type](ehci_batch, dir);
     161        assert(batch_setup[ehci_batch->base.ep->transfer_type]);
     162        batch_setup[ehci_batch->base.ep->transfer_type](ehci_batch);
    166163
    167164        usb_log_debug("Batch %p %s " USB_TRANSFER_BATCH_FMT " initialized.\n",
    168             usb_batch, usb_str_direction(dir),
    169             USB_TRANSFER_BATCH_ARGS(*usb_batch));
    170 
    171         return ehci_batch;
    172 dispose:
    173         ehci_transfer_batch_dispose(ehci_batch);
    174         return NULL;
     165            ehci_batch, usb_str_direction(ehci_batch->base.dir),
     166            USB_TRANSFER_BATCH_ARGS(ehci_batch->base));
     167
     168        return EOK;
    175169}
    176170
     
    184178 * completes with the last TD.
    185179 */
    186 bool ehci_transfer_batch_is_complete(const ehci_transfer_batch_t *ehci_batch)
    187 {
    188         assert(ehci_batch);
    189         assert(ehci_batch->usb_batch);
     180bool ehci_transfer_batch_check_completed(ehci_transfer_batch_t *ehci_batch)
     181{
     182        assert(ehci_batch);
    190183
    191184        usb_log_debug("Batch %p: checking %zu td(s) for completion.\n",
    192             ehci_batch->usb_batch, ehci_batch->td_count);
     185            ehci_batch, ehci_batch->td_count);
    193186
    194187        usb_log_debug2("Batch %p: QH: %08x:%08x:%08x:%08x:%08x:%08x.\n",
    195             ehci_batch->usb_batch,
     188            ehci_batch,
    196189            ehci_batch->qh->ep_char, ehci_batch->qh->ep_cap,
    197190            ehci_batch->qh->status, ehci_batch->qh->current,
     
    206199
    207200        /* Assume all data got through */
    208         ehci_batch->usb_batch->transfered_size =
    209             ehci_batch->usb_batch->buffer_size;
     201        ehci_batch->base.transfered_size = ehci_batch->base.buffer_size;
    210202
    211203        /* Check all TDs */
     
    213205                assert(ehci_batch->tds[i] != NULL);
    214206                usb_log_debug("Batch %p: TD %zu: %08x:%08x:%08x.",
    215                     ehci_batch->usb_batch, i,
     207                    ehci_batch, i,
    216208                    ehci_batch->tds[i]->status, ehci_batch->tds[i]->next,
    217209                    ehci_batch->tds[i]->alternate);
    218210
    219                 ehci_batch->usb_batch->error = td_error(ehci_batch->tds[i]);
    220                 if (ehci_batch->usb_batch->error == EOK) {
     211                ehci_batch->base.error = td_error(ehci_batch->tds[i]);
     212                if (ehci_batch->base.error == EOK) {
    221213                        /* If the TD got all its data through, it will report
    222214                         * 0 bytes remain, the sole exception is INPUT with
     
    231223                         * we leave the very last(unused) TD behind.
    232224                         */
    233                         ehci_batch->usb_batch->transfered_size
     225                        ehci_batch->base.transfered_size
    234226                            -= td_remain_size(ehci_batch->tds[i]);
    235227                } else {
    236228                        usb_log_debug("Batch %p found error TD(%zu):%08x (%d).",
    237                             ehci_batch->usb_batch, i,
     229                            ehci_batch, i,
    238230                            ehci_batch->tds[i]->status,
    239                             ehci_batch->usb_batch->error);
     231                            ehci_batch->base.error);
    240232                        /* Clear possible ED HALT */
    241233                        qh_clear_halt(ehci_batch->qh);
     
    244236        }
    245237
    246         assert(ehci_batch->usb_batch->transfered_size <=
    247             ehci_batch->usb_batch->buffer_size);
     238        assert(ehci_batch->base.transfered_size <= ehci_batch->base.buffer_size);
     239
     240        if (ehci_batch->base.dir == USB_DIRECTION_IN)
     241                memcpy(ehci_batch->base.buffer, ehci_batch->device_buffer, ehci_batch->base.transfered_size);
     242
    248243        /* Clear TD pointers */
    249244        ehci_batch->qh->next = LINK_POINTER_TERM;
    250245        ehci_batch->qh->current = LINK_POINTER_TERM;
    251         usb_log_debug("Batch %p complete: %s", ehci_batch->usb_batch,
    252             str_error(ehci_batch->usb_batch->error));
     246        usb_log_debug("Batch %p complete: %s", ehci_batch,
     247            str_error(ehci_batch->base.error));
    253248
    254249        return true;
     
    268263 *
    269264 * @param[in] ehci_batch Batch structure to use.
    270  * @param[in] dir Communication direction
    271265 *
    272266 * Setup stage with toggle 0 and direction BOTH(SETUP_PID)
    273  * Data stage with alternating toggle and direction supplied by parameter.
    274  * Status stage with toggle 1 and direction supplied by parameter.
    275  */
    276 static void batch_control(ehci_transfer_batch_t *ehci_batch, usb_direction_t dir)
    277 {
    278         assert(ehci_batch);
    279         assert(ehci_batch->usb_batch);
     267 * Data stage with alternating toggle and direction
     268 * Status stage with toggle 1 and direction
     269 */
     270static void batch_control(ehci_transfer_batch_t *ehci_batch)
     271{
     272        assert(ehci_batch);
     273
     274        usb_direction_t dir = ehci_batch->base.dir;
    280275        assert(dir == USB_DIRECTION_IN || dir == USB_DIRECTION_OUT);
    281276
    282277        usb_log_debug2("Batch %p: Control QH(%"PRIxn"): "
    283             "%08x:%08x:%08x:%08x:%08x:%08x", ehci_batch->usb_batch,
     278            "%08x:%08x:%08x:%08x:%08x:%08x", ehci_batch,
    284279            addr_to_phys(ehci_batch->qh),
    285280            ehci_batch->qh->ep_char, ehci_batch->qh->ep_cap,
     
    298293        /* Setup stage */
    299294        td_init(ehci_batch->tds[0], ehci_batch->tds[1], USB_DIRECTION_BOTH,
    300             buffer, ehci_batch->usb_batch->setup_size, toggle, false);
     295            buffer, USB_SETUP_PACKET_SIZE, toggle, false);
    301296        usb_log_debug2("Batch %p: Created CONTROL SETUP TD(%"PRIxn"): "
    302             "%08x:%08x:%08x", ehci_batch->usb_batch,
     297            "%08x:%08x:%08x", ehci_batch,
    303298            addr_to_phys(ehci_batch->tds[0]),
    304299            ehci_batch->tds[0]->status, ehci_batch->tds[0]->next,
    305300            ehci_batch->tds[0]->alternate);
    306         buffer += ehci_batch->usb_batch->setup_size;
     301        buffer += USB_SETUP_PACKET_SIZE;
    307302
    308303        /* Data stage */
    309304        size_t td_current = 1;
    310         size_t remain_size = ehci_batch->usb_batch->buffer_size;
     305        size_t remain_size = ehci_batch->base.buffer_size;
    311306        while (remain_size > 0) {
    312307                const size_t transfer_size =
     
    318313                    transfer_size, toggle, false);
    319314                usb_log_debug2("Batch %p: Created CONTROL DATA TD(%"PRIxn"): "
    320                     "%08x:%08x:%08x", ehci_batch->usb_batch,
     315                    "%08x:%08x:%08x", ehci_batch,
    321316                    addr_to_phys(ehci_batch->tds[td_current]),
    322317                    ehci_batch->tds[td_current]->status,
     
    334329        td_init(ehci_batch->tds[td_current], NULL, status_dir, NULL, 0, 1, true);
    335330        usb_log_debug2("Batch %p: Created CONTROL STATUS TD(%"PRIxn"): "
    336             "%08x:%08x:%08x", ehci_batch->usb_batch,
     331            "%08x:%08x:%08x", ehci_batch,
    337332            addr_to_phys(ehci_batch->tds[td_current]),
    338333            ehci_batch->tds[td_current]->status,
     
    349344 * EHCI hw in ED.
    350345 */
    351 static void batch_data(ehci_transfer_batch_t *ehci_batch, usb_direction_t dir)
    352 {
    353         assert(ehci_batch);
    354         assert(ehci_batch->usb_batch);
    355         assert(dir == USB_DIRECTION_IN || dir == USB_DIRECTION_OUT);
     346static void batch_data(ehci_transfer_batch_t *ehci_batch)
     347{
     348        assert(ehci_batch);
    356349
    357350        usb_log_debug2("Batch %p: Data QH(%"PRIxn"): "
    358             "%08x:%08x:%08x:%08x:%08x:%08x", ehci_batch->usb_batch,
     351            "%08x:%08x:%08x:%08x:%08x:%08x", ehci_batch,
    359352            addr_to_phys(ehci_batch->qh),
    360353            ehci_batch->qh->ep_char, ehci_batch->qh->ep_cap,
     
    363356
    364357        size_t td_current = 0;
    365         size_t remain_size = ehci_batch->usb_batch->buffer_size;
     358        size_t remain_size = ehci_batch->base.buffer_size;
    366359        char *buffer = ehci_batch->device_buffer;
    367360        while (remain_size > 0) {
     
    373366                    ehci_batch->tds[td_current],
    374367                    last ? NULL : ehci_batch->tds[td_current + 1],
    375                     dir, buffer, transfer_size, -1, last);
     368                    ehci_batch->base.dir, buffer, transfer_size, -1, last);
    376369
    377370                usb_log_debug2("Batch %p: DATA TD(%"PRIxn": %08x:%08x:%08x",
    378                     ehci_batch->usb_batch,
     371                    ehci_batch,
    379372                    addr_to_phys(ehci_batch->tds[td_current]),
    380373                    ehci_batch->tds[td_current]->status,
     
    390383
    391384/** Transfer setup table. */
    392 static void (*const batch_setup[])(ehci_transfer_batch_t*, usb_direction_t) =
     385static void (*const batch_setup[])(ehci_transfer_batch_t*) =
    393386{
    394387        [USB_TRANSFER_CONTROL] = batch_control,
  • uspace/drv/bus/usb/ehci/ehci_batch.h

    r367db39a re160bfe8  
    4545/** EHCI specific data required for USB transfer */
    4646typedef struct ehci_transfer_batch {
     47        usb_transfer_batch_t base;
    4748        /** Link */
    4849        link_t link;
     
    5960} ehci_transfer_batch_t;
    6061
    61 ehci_transfer_batch_t * ehci_transfer_batch_get(usb_transfer_batch_t *batch);
    62 bool ehci_transfer_batch_is_complete(const ehci_transfer_batch_t *batch);
     62ehci_transfer_batch_t * ehci_transfer_batch_create(endpoint_t *ep);
     63int ehci_transfer_batch_prepare(ehci_transfer_batch_t *batch);
    6364void ehci_transfer_batch_commit(const ehci_transfer_batch_t *batch);
    64 void ehci_transfer_batch_finish_dispose(ehci_transfer_batch_t *batch);
     65bool ehci_transfer_batch_check_completed(ehci_transfer_batch_t *batch);
     66void ehci_transfer_batch_destroy(ehci_transfer_batch_t *batch);
    6567
    6668static inline ehci_transfer_batch_t *ehci_transfer_batch_from_link(link_t *l)
     
    6971        return list_get_instance(l, ehci_transfer_batch_t, link);
    7072}
     73
     74static inline ehci_transfer_batch_t * ehci_transfer_batch_get(usb_transfer_batch_t *usb_batch)
     75{
     76        assert(usb_batch);
     77
     78        return (ehci_transfer_batch_t *) usb_batch;
     79}
     80
    7181#endif
    7282/**
  • uspace/drv/bus/usb/ehci/ehci_rh.c

    r367db39a re160bfe8  
    144144        assert(instance);
    145145        assert(batch);
    146         const usb_target_t target = {{
    147                 .address = batch->ep->address,
    148                 .endpoint = batch->ep->endpoint,
    149         }};
     146        const usb_target_t target = batch->ep->target;
    150147        batch->error = virthub_base_request(&instance->base, target,
    151             usb_transfer_batch_direction(batch), (void*)batch->setup_buffer,
     148            batch->dir, (void*) batch->setup.buffer,
    152149            batch->buffer, batch->buffer_size, &batch->transfered_size);
    153150        if (batch->error == ENAK) {
     
    160157                instance->unfinished_interrupt_transfer = batch;
    161158        } else {
    162                 usb_transfer_batch_finish(batch, NULL);
    163                 usb_transfer_batch_destroy(batch);
    164159                usb_log_debug("RH(%p): BATCH(%p) virtual request complete: %s",
    165160                    instance, batch, str_error(batch->error));
     161                usb_transfer_batch_finish(batch);
    166162        }
    167163        return EOK;
     
    183179            instance, batch);
    184180        if (batch) {
    185                 const usb_target_t target = {{
    186                         .address = batch->ep->address,
    187                         .endpoint = batch->ep->endpoint,
    188                 }};
     181                const usb_target_t target = batch->ep->target;
    189182                batch->error = virthub_base_request(&instance->base, target,
    190                     usb_transfer_batch_direction(batch),
    191                     (void*)batch->setup_buffer,
     183                    batch->dir, (void*) batch->setup.buffer,
    192184                    batch->buffer, batch->buffer_size, &batch->transfered_size);
    193                 usb_transfer_batch_finish(batch, NULL);
    194                 usb_transfer_batch_destroy(batch);
     185                usb_transfer_batch_finish(batch);
    195186        }
    196187        return EOK;
  • uspace/drv/bus/usb/ehci/endpoint_list.h

    r367db39a re160bfe8  
    4040#include <usb/host/utils/malloc32.h>
    4141
    42 #include "ehci_endpoint.h"
     42#include "ehci_bus.h"
    4343#include "hw_struct/queue_head.h"
    4444
  • uspace/drv/bus/usb/ehci/hc.c

    r367db39a re160bfe8  
    8989};
    9090
    91 static void hc_start(hc_t *instance);
    9291static int hc_init_memory(hc_t *instance);
    9392
     
    9897 * @return Error code.
    9998 */
    100 int ehci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res)
     99int ehci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res)
    101100{
    102101        assert(code);
    103102        assert(hw_res);
     103
     104        hc_t *instance = hcd_get_driver_data(hcd);
    104105
    105106        if (hw_res->irqs.count != 1 || hw_res->mem_ranges.count != 1)
     
    128129
    129130        memcpy(code->cmds, ehci_irq_commands, sizeof(ehci_irq_commands));
    130         ehci_caps_regs_t *caps = NULL;
    131 
    132         int ret = pio_enable_range(&regs, (void**)&caps);
    133         if (ret != EOK) {
    134                 free(code->ranges);
    135                 free(code->cmds);
    136                 return ret;
    137         }
    138131
    139132        ehci_regs_t *registers =
    140             (ehci_regs_t *)(RNGABSPTR(regs) + EHCI_RD8(caps->caplength));
     133                (ehci_regs_t *)(RNGABSPTR(regs) + EHCI_RD8(instance->caps->caplength));
    141134        code->cmds[0].addr = (void *) &registers->usbsts;
    142135        code->cmds[3].addr = (void *) &registers->usbsts;
     
    156149 * @return Error code
    157150 */
    158 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts)
     151int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res)
    159152{
    160153        assert(instance);
     
    172165                return ret;
    173166        }
     167
    174168        usb_log_info("HC(%p): Device registers at %"PRIx64" (%zuB) accessible.",
    175169            instance, hw_res->mem_ranges.ranges[0].address.absolute,
     
    195189        ehci_rh_init(
    196190            &instance->rh, instance->caps, instance->registers, "ehci rh");
    197         usb_log_debug("HC(%p): Starting HW.", instance);
    198         hc_start(instance);
    199 
     191
     192        ehci_bus_init(&instance->bus, instance);
    200193        return EOK;
    201194}
     
    222215        ehci_endpoint_t *ehci_ep = ehci_endpoint_get(ep);
    223216        usb_log_debug("HC(%p) enqueue EP(%d:%d:%s:%s)\n", instance,
    224             ep->address, ep->endpoint,
     217            ep->target.address, ep->target.endpoint,
    225218            usb_str_transfer_type_short(ep->transfer_type),
    226219            usb_str_direction(ep->direction));
     
    246239        ehci_endpoint_t *ehci_ep = ehci_endpoint_get(ep);
    247240        usb_log_debug("HC(%p) dequeue EP(%d:%d:%s:%s)\n", instance,
    248             ep->address, ep->endpoint,
     241            ep->target.address, ep->target.endpoint,
    249242            usb_str_transfer_type_short(ep->transfer_type),
    250243            usb_str_direction(ep->direction));
     
    298291
    299292        /* Check for root hub communication */
    300         if (batch->ep->address == ehci_rh_get_address(&instance->rh)) {
     293        if (batch->ep->target.address == ehci_rh_get_address(&instance->rh)) {
    301294                usb_log_debug("HC(%p): Scheduling BATCH(%p) for RH(%p)",
    302295                    instance, batch, &instance->rh);
    303296                return ehci_rh_schedule(&instance->rh, batch);
    304297        }
     298
    305299        ehci_transfer_batch_t *ehci_batch = ehci_transfer_batch_get(batch);
    306         if (!ehci_batch)
    307                 return ENOMEM;
     300
     301        const int err = ehci_transfer_batch_prepare(ehci_batch);
     302        if (err)
     303                return err;
    308304
    309305        fibril_mutex_lock(&instance->guard);
     
    350346                            ehci_transfer_batch_from_link(current);
    351347
    352                         if (ehci_transfer_batch_is_complete(batch)) {
     348                        if (ehci_transfer_batch_check_completed(batch)) {
    353349                                list_remove(current);
    354                                 ehci_transfer_batch_finish_dispose(batch);
     350                                usb_transfer_batch_finish(&batch->base);
    355351                        }
    356352                }
     
    368364 * @param[in] instance EHCI hc driver structure.
    369365 */
    370 void hc_start(hc_t *instance)
    371 {
    372         assert(instance);
     366int hc_start(hc_t *instance, bool interrupts)
     367{
     368        assert(instance);
     369        usb_log_debug("HC(%p): Starting HW.", instance);
     370
    373371        /* Turn off the HC if it's running, Reseting a running device is
    374372         * undefined */
     
    435433        EHCI_WR(instance->registers->usbsts, EHCI_RD(instance->registers->usbsts));
    436434        EHCI_WR(instance->registers->usbintr, EHCI_USED_INTERRUPTS);
     435
     436        return EOK;
    437437}
    438438
  • uspace/drv/bus/usb/ehci/hc.h

    r367db39a re160bfe8  
    8080        /** USB hub emulation structure */
    8181        ehci_rh_t rh;
     82
     83        /** USB bookkeeping */
     84        ehci_bus_t bus;
    8285} hc_t;
    8386
    84 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts);
     87int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res);
     88int hc_start(hc_t *instance, bool interrupts);
    8589void hc_fini(hc_t *instance);
    8690
     
    8892void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep);
    8993
    90 int ehci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res);
     94int ehci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res);
    9195
    9296void ehci_hc_interrupt(hcd_t *hcd, uint32_t status);
  • uspace/drv/bus/usb/ehci/hw_struct/queue_head.c

    r367db39a re160bfe8  
    3737#include <mem.h>
    3838#include <macros.h>
     39#include <usb/host/bus.h>
    3940
    4041#include "mem_access.h"
     
    6566        assert(ep->speed < ARRAY_SIZE(speed));
    6667        EHCI_MEM32_WR(instance->ep_char,
    67             QH_EP_CHAR_ADDR_SET(ep->address) |
    68             QH_EP_CHAR_EP_SET(ep->endpoint) |
     68            QH_EP_CHAR_ADDR_SET(ep->target.address) |
     69            QH_EP_CHAR_EP_SET(ep->target.endpoint) |
    6970            speed[ep->speed] |
    7071            QH_EP_CHAR_MAX_LENGTH_SET(ep->max_packet_size)
     
    8182        if (ep->speed != USB_SPEED_HIGH) {
    8283                ep_cap |=
    83                     QH_EP_CAP_TT_PORT_SET(ep->tt.port) |
    84                     QH_EP_CAP_TT_ADDR_SET(ep->tt.address);
     84                    QH_EP_CAP_TT_PORT_SET(ep->device->tt.port) |
     85                    QH_EP_CAP_TT_ADDR_SET(ep->device->tt.address);
    8586        }
    8687        if (ep->transfer_type == USB_TRANSFER_INTERRUPT) {
  • uspace/drv/bus/usb/ehci/main.c

    r367db39a re160bfe8  
    4848#include "res.h"
    4949#include "hc.h"
    50 #include "ehci_endpoint.h"
    5150
    5251#define NAME "ehci"
    5352
    54 static int ehci_driver_init(hcd_t *, const hw_res_list_parsed_t *, bool);
     53static int ehci_driver_init(hcd_t *, const hw_res_list_parsed_t *, ddf_dev_t *);
     54static int ehci_driver_claim(hcd_t *, ddf_dev_t *);
     55static int ehci_driver_start(hcd_t *, bool);
    5556static void ehci_driver_fini(hcd_t *);
    5657
    5758static const ddf_hc_driver_t ehci_hc_driver = {
    58         .claim = disable_legacy,
    59         .hc_speed = USB_SPEED_HIGH,
     59        .name = "EHCI-PCI",
     60        .init = ehci_driver_init,
    6061        .irq_code_gen = ehci_hc_gen_irq_code,
    61         .init = ehci_driver_init,
     62        .claim = ehci_driver_claim,
     63        .start = ehci_driver_start,
     64        .setup_root_hub = hcd_setup_virtual_root_hub,
    6265        .fini = ehci_driver_fini,
    63         .name = "EHCI-PCI",
    6466        .ops = {
    6567                .schedule       = ehci_hc_schedule,
    66                 .ep_add_hook    = ehci_endpoint_init,
    67                 .ep_remove_hook = ehci_endpoint_fini,
    6868                .irq_hook       = ehci_hc_interrupt,
    6969                .status_hook    = ehci_hc_status,
     
    7272
    7373
    74 static int ehci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res,
    75     bool irq)
     74static int ehci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, ddf_dev_t *device)
    7675{
    7776        assert(hcd);
     
    8281                return ENOMEM;
    8382
    84         const int ret = hc_init(instance, res, irq);
     83        const int ret = hc_init(instance, res);
    8584        if (ret == EOK) {
    86                 hcd_set_implementation(hcd, instance, &ehci_hc_driver.ops);
     85                hcd_set_implementation(hcd, instance, &ehci_hc_driver.ops, &instance->bus.base.base);
    8786        } else {
    8887                free(instance);
    8988        }
    9089        return ret;
     90}
     91
     92static int ehci_driver_claim(hcd_t *hcd, ddf_dev_t *dev)
     93{
     94        hc_t *instance = hcd_get_driver_data(hcd);
     95        assert(instance);
     96
     97        return disable_legacy(instance, dev);
     98}
     99
     100static int ehci_driver_start(hcd_t *hcd, bool irq) {
     101        hc_t *instance = hcd_get_driver_data(hcd);
     102        assert(instance);
     103
     104        return hc_start(instance, irq);
    91105}
    92106
     
    99113
    100114        free(hc);
    101         hcd_set_implementation(hcd, NULL, NULL);
     115        hcd_set_implementation(hcd, NULL, NULL, NULL);
    102116}
    103117
  • uspace/drv/bus/usb/ehci/res.c

    r367db39a re160bfe8  
    172172}
    173173
    174 int disable_legacy(ddf_dev_t *device)
     174int disable_legacy(hc_t *hc, ddf_dev_t *device)
    175175{
    176176        assert(device);
     
    182182        usb_log_debug("Disabling EHCI legacy support.\n");
    183183
    184         hw_res_list_parsed_t res;
    185         hw_res_list_parsed_init(&res);
    186         int ret = hw_res_get_list_parsed(parent_sess, &res, 0);
    187         if (ret != EOK) {
    188                 usb_log_error("Failed to get resource list: %s\n",
    189                     str_error(ret));
    190                 goto clean;
    191         }
    192 
    193         if (res.mem_ranges.count < 1) {
    194                 usb_log_error("Incorrect mem range count: %zu",
    195                     res.mem_ranges.count);
    196                 ret = EINVAL;
    197                 goto clean;
    198         }
    199 
    200         /* Map EHCI registers */
    201         void *regs = NULL;
    202         ret = pio_enable_range(&res.mem_ranges.ranges[0], &regs);
    203         if (ret != EOK) {
    204                 usb_log_error("Failed to map registers %p: %s.\n",
    205                     RNGABSPTR(res.mem_ranges.ranges[0]), str_error(ret));
    206                 goto clean;
    207         }
    208 
    209         usb_log_debug("Registers mapped at: %p.\n", regs);
    210 
    211         ehci_caps_regs_t *ehci_caps = regs;
    212 
    213         const uint32_t hcc_params = EHCI_RD(ehci_caps->hccparams);
     184
     185        const uint32_t hcc_params = EHCI_RD(hc->caps->hccparams);
    214186        usb_log_debug2("Value of hcc params register: %x.\n", hcc_params);
    215187
     
    220192        usb_log_debug2("Value of EECP: %x.\n", eecp);
    221193
    222         ret = disable_extended_caps(parent_sess, eecp);
     194        int ret = disable_extended_caps(parent_sess, eecp);
    223195        if (ret != EOK) {
    224196                usb_log_error("Failed to disable extended capabilities: %s.\n",
     
    227199        }
    228200clean:
    229         //TODO unmap registers
    230         hw_res_list_parsed_clean(&res);
     201        async_hangup(parent_sess);
    231202        return ret;
    232203}
  • uspace/drv/bus/usb/ehci/res.h

    r367db39a re160bfe8  
    3939#include <device/hw_res_parsed.h>
    4040
    41 extern int disable_legacy(ddf_dev_t *);
     41#include "hc.h"
     42
     43extern int disable_legacy(hc_t *, ddf_dev_t *);
    4244
    4345#endif
  • uspace/drv/bus/usb/ohci/Makefile

    r367db39a re160bfe8  
    4949        main.c \
    5050        ohci_batch.c \
    51         ohci_endpoint.c \
     51        ohci_bus.c \
    5252        ohci_rh.c \
    5353        hw_struct/endpoint_descriptor.c \
  • uspace/drv/bus/usb/ohci/endpoint_list.h

    r367db39a re160bfe8  
    4141#include <usb/host/utils/malloc32.h>
    4242
    43 #include "ohci_endpoint.h"
     43#include "ohci_bus.h"
    4444#include "hw_struct/endpoint_descriptor.h"
    4545
  • uspace/drv/bus/usb/ohci/hc.c

    r367db39a re160bfe8  
    4747#include <usb/usb.h>
    4848
    49 #include "ohci_endpoint.h"
     49#include "ohci_bus.h"
    5050#include "ohci_batch.h"
    5151
     
    8989};
    9090
    91 static void hc_gain_control(hc_t *instance);
    92 static void hc_start(hc_t *instance);
    9391static int hc_init_transfer_lists(hc_t *instance);
    9492static int hc_init_memory(hc_t *instance);
     
    103101 * @return Error code.
    104102 */
    105 int ohci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res)
     103int ohci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res)
    106104{
    107105        assert(code);
     
    151149 * @return Error code
    152150 */
    153 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts)
     151int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res)
    154152{
    155153        assert(instance);
     
    172170        list_initialize(&instance->pending_batches);
    173171        fibril_mutex_initialize(&instance->guard);
    174         instance->hw_interrupts = interrupts;
    175172
    176173        ret = hc_init_memory(instance);
     
    181178                return ret;
    182179        }
    183 
    184         hc_gain_control(instance);
    185 
    186         ohci_rh_init(&instance->rh, instance->registers, "ohci rh");
    187         hc_start(instance);
    188180
    189181        return EOK;
     
    295287
    296288        /* Check for root hub communication */
    297         if (batch->ep->address == ohci_rh_get_address(&instance->rh)) {
     289        if (batch->ep->target.address == ohci_rh_get_address(&instance->rh)) {
    298290                usb_log_debug("OHCI root hub request.\n");
    299291                return ohci_rh_schedule(&instance->rh, batch);
     
    302294        if (!ohci_batch)
    303295                return ENOMEM;
     296
     297        const int err = ohci_transfer_batch_prepare(ohci_batch);
     298        if (err)
     299                return err;
    304300
    305301        fibril_mutex_lock(&instance->guard);
     
    354350                            ohci_transfer_batch_from_link(current);
    355351
    356                         if (ohci_transfer_batch_is_complete(batch)) {
     352                        if (ohci_transfer_batch_check_completed(batch)) {
    357353                                list_remove(current);
    358                                 ohci_transfer_batch_finish_dispose(batch);
     354                                usb_transfer_batch_finish(&batch->base);
    359355                        }
    360356
     
    443439void hc_start(hc_t *instance)
    444440{
     441        ohci_rh_init(&instance->rh, instance->registers, "ohci rh");
     442
    445443        /* OHCI guide page 42 */
    446444        assert(instance);
  • uspace/drv/bus/usb/ohci/hc.h

    r367db39a re160bfe8  
    5252#include "ohci_regs.h"
    5353#include "ohci_rh.h"
     54#include "ohci_bus.h"
    5455#include "endpoint_list.h"
    5556#include "hw_struct/hcca.h"
     
    5960        /** Memory mapped I/O registers area */
    6061        ohci_regs_t *registers;
     62       
    6163        /** Host controller communication area structure */
    6264        hcca_t *hcca;
     
    6466        /** Transfer schedules */
    6567        endpoint_list_t lists[4];
     68
    6669        /** List of active transfers */
    6770        list_t pending_batches;
     
    7881        /** USB hub emulation structure */
    7982        ohci_rh_t rh;
     83
     84        /** USB bookkeeping */
     85        ohci_bus_t bus;
    8086} hc_t;
    8187
    82 extern int hc_init(hc_t *, const hw_res_list_parsed_t *, bool);
     88extern int hc_init(hc_t *, const hw_res_list_parsed_t *);
     89extern void hc_gain_control(hc_t *instance);
     90extern void hc_start(hc_t *instance);
    8391extern void hc_fini(hc_t *);
    8492
     
    8694extern void hc_dequeue_endpoint(hc_t *, const endpoint_t *);
    8795
    88 int ohci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res);
     96int ohci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res);
    8997
    9098extern void ohci_hc_interrupt(hcd_t *, uint32_t);
  • uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.c

    r367db39a re160bfe8  
    7979        /* Status: address, endpoint nr, direction mask and max packet size. */
    8080        OHCI_MEM32_WR(instance->status,
    81             ((ep->address & ED_STATUS_FA_MASK) << ED_STATUS_FA_SHIFT)
    82             | ((ep->endpoint & ED_STATUS_EN_MASK) << ED_STATUS_EN_SHIFT)
     81            ((ep->target.address & ED_STATUS_FA_MASK) << ED_STATUS_FA_SHIFT)
     82            | ((ep->target.endpoint & ED_STATUS_EN_MASK) << ED_STATUS_EN_SHIFT)
    8383            | ((dir[ep->direction] & ED_STATUS_D_MASK) << ED_STATUS_D_SHIFT)
    8484            | ((ep->max_packet_size & ED_STATUS_MPS_MASK)
  • uspace/drv/bus/usb/ohci/main.c

    r367db39a re160bfe8  
    4545
    4646#include "hc.h"
     47#include "ohci_bus.h"
    4748
    4849#define NAME "ohci"
    49 static int ohci_driver_init(hcd_t *, const hw_res_list_parsed_t *, bool);
     50static int ohci_driver_init(hcd_t *, const hw_res_list_parsed_t *, ddf_dev_t *);
     51static int ohci_driver_start(hcd_t *, bool);
     52static int ohci_driver_claim(hcd_t *, ddf_dev_t *);
    5053static void ohci_driver_fini(hcd_t *);
    5154
    5255static const ddf_hc_driver_t ohci_hc_driver = {
    53         .hc_speed = USB_SPEED_FULL,
    5456        .irq_code_gen = ohci_hc_gen_irq_code,
    5557        .init = ohci_driver_init,
     58        .claim = ohci_driver_claim,
     59        .start = ohci_driver_start,
     60        .setup_root_hub = hcd_setup_virtual_root_hub,
    5661        .fini = ohci_driver_fini,
    5762        .name = "OHCI",
    5863        .ops = {
    5964                .schedule       = ohci_hc_schedule,
    60                 .ep_add_hook    = ohci_endpoint_init,
    61                 .ep_remove_hook = ohci_endpoint_fini,
    6265                .irq_hook       = ohci_hc_interrupt,
    6366                .status_hook    = ohci_hc_status,
     
    6669
    6770
    68 static int ohci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, bool irq)
     71static int ohci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, ddf_dev_t *device)
    6972{
     73        int err;
     74
    7075        assert(hcd);
    7176        assert(hcd_get_driver_data(hcd) == NULL);
     
    7580                return ENOMEM;
    7681
    77         const int ret = hc_init(instance, res, irq);
    78         if (ret == EOK) {
    79                 hcd_set_implementation(hcd, instance, &ohci_hc_driver.ops);
    80         } else {
    81                 free(instance);
    82         }
    83         return ret;
     82        if ((err = hc_init(instance, res)) != EOK)
     83                goto err;
     84
     85        if ((err = ohci_bus_init(&instance->bus, instance)))
     86                goto err;
     87
     88        hcd_set_implementation(hcd, instance, &ohci_hc_driver.ops, &instance->bus.base.base);
     89
     90        return EOK;
     91
     92err:
     93        free(instance);
     94        return err;
     95}
     96
     97static int ohci_driver_claim(hcd_t *hcd, ddf_dev_t *dev)
     98{
     99        hc_t *hc = hcd_get_driver_data(hcd);
     100        assert(hc);
     101
     102        hc_gain_control(hc);
     103
     104        return EOK;
     105}
     106
     107static int ohci_driver_start(hcd_t *hcd, bool interrupts)
     108{
     109        hc_t *hc = hcd_get_driver_data(hcd);
     110        assert(hc);
     111
     112        hc->hw_interrupts = interrupts;
     113        hc_start(hc);
     114        return EOK;
    84115}
    85116
     
    91122                hc_fini(hc);
    92123
    93         hcd_set_implementation(hcd, NULL, NULL);
     124        hcd_set_implementation(hcd, NULL, NULL, NULL);
    94125        free(hc);
    95126}
  • uspace/drv/bus/usb/ohci/ohci_batch.c

    r367db39a re160bfe8  
    4545
    4646#include "ohci_batch.h"
    47 #include "ohci_endpoint.h"
    48 
    49 static void (*const batch_setup[])(ohci_transfer_batch_t*, usb_direction_t);
     47#include "ohci_bus.h"
     48
     49static void (*const batch_setup[])(ohci_transfer_batch_t*);
    5050
    5151/** Safely destructs ohci_transfer_batch_t structure
     
    5353 * @param[in] ohci_batch Instance to destroy.
    5454 */
    55 static void ohci_transfer_batch_dispose(ohci_transfer_batch_t *ohci_batch)
    56 {
    57         if (!ohci_batch)
    58                 return;
     55void ohci_transfer_batch_destroy(ohci_transfer_batch_t *ohci_batch)
     56{
     57        assert(ohci_batch);
    5958        if (ohci_batch->tds) {
    6059                const ohci_endpoint_t *ohci_ep =
     
    6766                free(ohci_batch->tds);
    6867        }
    69         usb_transfer_batch_destroy(ohci_batch->usb_batch);
    7068        free32(ohci_batch->device_buffer);
    7169        free(ohci_batch);
    72 }
    73 
    74 /** Finishes usb_transfer_batch and destroys the structure.
    75  *
    76  * @param[in] uhci_batch Instance to finish and destroy.
    77  */
    78 void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *ohci_batch)
    79 {
    80         assert(ohci_batch);
    81         assert(ohci_batch->usb_batch);
    82         usb_transfer_batch_finish(ohci_batch->usb_batch,
    83             ohci_batch->device_buffer + ohci_batch->usb_batch->setup_size);
    84         ohci_transfer_batch_dispose(ohci_batch);
    8570}
    8671
     
    9075 * @return Valid pointer if all structures were successfully created,
    9176 * NULL otherwise.
    92  *
    93  * Determines the number of needed transfer descriptors (TDs).
    94  * Prepares a transport buffer (that is accessible by the hardware).
    95  * Initializes parameters needed for the transfer and callback.
    96  */
    97 ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *usb_batch)
    98 {
    99         assert(usb_batch);
     77 */
     78ohci_transfer_batch_t * ohci_transfer_batch_create(endpoint_t *ep)
     79{
     80        assert(ep);
    10081
    10182        ohci_transfer_batch_t *ohci_batch =
     
    10384        if (!ohci_batch) {
    10485                usb_log_error("Failed to allocate OHCI batch data.");
    105                 goto dispose;
    106         }
     86                return NULL;
     87        }
     88
     89        usb_transfer_batch_init(&ohci_batch->base, ep);
    10790        link_initialize(&ohci_batch->link);
    108         ohci_batch->td_count =
    109             (usb_batch->buffer_size + OHCI_TD_MAX_TRANSFER - 1)
     91
     92        return ohci_batch;
     93}
     94
     95/** Prepares a batch to be sent.
     96 *
     97 * Determines the number of needed transfer descriptors (TDs).
     98 * Prepares a transport buffer (that is accessible by the hardware).
     99 * Initializes parameters needed for the transfer and callback.
     100 */
     101int ohci_transfer_batch_prepare(ohci_transfer_batch_t *ohci_batch)
     102{
     103        assert(ohci_batch);
     104
     105        const size_t setup_size = (ohci_batch->base.ep->transfer_type == USB_TRANSFER_CONTROL)
     106                ? USB_SETUP_PACKET_SIZE
     107                : 0;
     108
     109        usb_transfer_batch_t *usb_batch = &ohci_batch->base;
     110
     111        ohci_batch->td_count = (usb_batch->buffer_size + OHCI_TD_MAX_TRANSFER - 1)
    110112            / OHCI_TD_MAX_TRANSFER;
    111113        /* Control transfer need Setup and Status stage */
     
    118120        if (!ohci_batch->tds) {
    119121                usb_log_error("Failed to allocate OHCI transfer descriptors.");
    120                 goto dispose;
     122                return ENOMEM;
    121123        }
    122124
     
    129131                if (!ohci_batch->tds[i]) {
    130132                        usb_log_error("Failed to allocate TD %d.", i);
    131                         goto dispose;
     133                        return ENOMEM;
    132134                }
    133135        }
    134 
    135136
    136137        /* NOTE: OHCI is capable of handling buffer that crosses page boundaries
     
    138139         * than two pages (the first page is computed using start pointer, the
    139140         * other using the end pointer) */
    140         if (usb_batch->setup_size + usb_batch->buffer_size > 0) {
     141        if (setup_size + usb_batch->buffer_size > 0) {
    141142                /* Use one buffer for setup and data stage */
    142143                ohci_batch->device_buffer =
    143                     malloc32(usb_batch->setup_size + usb_batch->buffer_size);
     144                    malloc32(setup_size + usb_batch->buffer_size);
    144145                if (!ohci_batch->device_buffer) {
    145146                        usb_log_error("Failed to allocate device buffer");
    146                         goto dispose;
     147                        return ENOMEM;
    147148                }
    148149                /* Copy setup data */
    149                 memcpy(ohci_batch->device_buffer, usb_batch->setup_buffer,
    150                     usb_batch->setup_size);
     150                memcpy(ohci_batch->device_buffer, usb_batch->setup.buffer, setup_size);
    151151                /* Copy generic data */
    152152                if (usb_batch->ep->direction != USB_DIRECTION_IN)
    153153                        memcpy(
    154                             ohci_batch->device_buffer + usb_batch->setup_size,
     154                            ohci_batch->device_buffer + setup_size,
    155155                            usb_batch->buffer, usb_batch->buffer_size);
    156156        }
    157         ohci_batch->usb_batch = usb_batch;
    158 
    159         const usb_direction_t dir = usb_transfer_batch_direction(usb_batch);
     157
    160158        assert(batch_setup[usb_batch->ep->transfer_type]);
    161         batch_setup[usb_batch->ep->transfer_type](ohci_batch, dir);
    162 
    163         return ohci_batch;
    164 dispose:
    165         ohci_transfer_batch_dispose(ohci_batch);
    166         return NULL;
     159        batch_setup[usb_batch->ep->transfer_type](ohci_batch);
     160
     161        return EOK;
    167162}
    168163
     
    176171 * completes with the last TD.
    177172 */
    178 bool ohci_transfer_batch_is_complete(const ohci_transfer_batch_t *ohci_batch)
    179 {
    180         assert(ohci_batch);
    181         assert(ohci_batch->usb_batch);
     173bool ohci_transfer_batch_check_completed(ohci_transfer_batch_t *ohci_batch)
     174{
     175        assert(ohci_batch);
    182176
    183177        usb_log_debug("Batch %p checking %zu td(s) for completion.\n",
     
    194188
    195189        /* Assume all data got through */
    196         ohci_batch->usb_batch->transfered_size =
    197             ohci_batch->usb_batch->buffer_size;
     190        ohci_batch->base.transfered_size = ohci_batch->base.buffer_size;
    198191
    199192        /* Assume we will leave the last(unused) TD behind */
     
    207200                    ohci_batch->tds[i]->next, ohci_batch->tds[i]->be);
    208201
    209                 ohci_batch->usb_batch->error = td_error(ohci_batch->tds[i]);
    210                 if (ohci_batch->usb_batch->error == EOK) {
     202                ohci_batch->base.error = td_error(ohci_batch->tds[i]);
     203                if (ohci_batch->base.error == EOK) {
    211204                        /* If the TD got all its data through, it will report
    212205                         * 0 bytes remain, the sole exception is INPUT with
     
    221214                         * we leave the very last(unused) TD behind.
    222215                         */
    223                         ohci_batch->usb_batch->transfered_size
     216                        ohci_batch->base.transfered_size
    224217                            -= td_remain_size(ohci_batch->tds[i]);
    225218                } else {
     
    252245                }
    253246        }
    254         assert(ohci_batch->usb_batch->transfered_size <=
    255             ohci_batch->usb_batch->buffer_size);
     247        assert(ohci_batch->base.transfered_size <=
     248            ohci_batch->base.buffer_size);
     249
     250        if (ohci_batch->base.dir == USB_DIRECTION_IN)
     251                memcpy(ohci_batch->base.buffer, ohci_batch->device_buffer, ohci_batch->base.transfered_size);
    256252
    257253        /* Store the remaining TD */
    258         ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ohci_batch->usb_batch->ep);
     254        ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ohci_batch->base.ep);
    259255        assert(ohci_ep);
    260256        ohci_ep->td = ohci_batch->tds[leave_td];
     
    286282 * Status stage with toggle 1 and direction supplied by parameter.
    287283 */
    288 static void batch_control(ohci_transfer_batch_t *ohci_batch, usb_direction_t dir)
    289 {
    290         assert(ohci_batch);
    291         assert(ohci_batch->usb_batch);
     284static void batch_control(ohci_transfer_batch_t *ohci_batch)
     285{
     286        assert(ohci_batch);
     287
     288        usb_direction_t dir = ohci_batch->base.dir;
    292289        assert(dir == USB_DIRECTION_IN || dir == USB_DIRECTION_OUT);
     290
    293291        usb_log_debug("Using ED(%p): %08x:%08x:%08x:%08x.\n", ohci_batch->ed,
    294292            ohci_batch->ed->status, ohci_batch->ed->td_tail,
     
    307305        td_init(
    308306            ohci_batch->tds[0], ohci_batch->tds[1], USB_DIRECTION_BOTH,
    309             buffer, ohci_batch->usb_batch->setup_size, toggle);
     307            buffer, USB_SETUP_PACKET_SIZE, toggle);
    310308        usb_log_debug("Created CONTROL SETUP TD: %08x:%08x:%08x:%08x.\n",
    311309            ohci_batch->tds[0]->status, ohci_batch->tds[0]->cbp,
    312310            ohci_batch->tds[0]->next, ohci_batch->tds[0]->be);
    313         buffer += ohci_batch->usb_batch->setup_size;
     311        buffer += USB_SETUP_PACKET_SIZE;
    314312
    315313        /* Data stage */
     
    361359 * OHCI hw in ED.
    362360 */
    363 static void batch_data(ohci_transfer_batch_t *ohci_batch, usb_direction_t dir)
    364 {
    365         assert(ohci_batch);
    366         assert(ohci_batch->usb_batch);
     361static void batch_data(ohci_transfer_batch_t *ohci_batch)
     362{
     363        assert(ohci_batch);
     364
     365        usb_direction_t dir = ohci_batch->base.dir;
    367366        assert(dir == USB_DIRECTION_IN || dir == USB_DIRECTION_OUT);
    368367        usb_log_debug("Using ED(%p): %08x:%08x:%08x:%08x.\n", ohci_batch->ed,
     
    401400
    402401/** Transfer setup table. */
    403 static void (*const batch_setup[])(ohci_transfer_batch_t*, usb_direction_t) =
     402static void (*const batch_setup[])(ohci_transfer_batch_t*) =
    404403{
    405404        [USB_TRANSFER_CONTROL] = batch_control,
  • uspace/drv/bus/usb/ohci/ohci_batch.h

    r367db39a re160bfe8  
    4545/** OHCI specific data required for USB transfer */
    4646typedef struct ohci_transfer_batch {
     47        usb_transfer_batch_t base;
     48
    4749        /** Link */
    4850        link_t link;
     
    5961} ohci_transfer_batch_t;
    6062
    61 ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *batch);
    62 bool ohci_transfer_batch_is_complete(const ohci_transfer_batch_t *batch);
     63ohci_transfer_batch_t * ohci_transfer_batch_create(endpoint_t *batch);
     64int ohci_transfer_batch_prepare(ohci_transfer_batch_t *ohci_batch);
    6365void ohci_transfer_batch_commit(const ohci_transfer_batch_t *batch);
    64 void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *batch);
     66bool ohci_transfer_batch_check_completed(ohci_transfer_batch_t *batch);
     67void ohci_transfer_batch_destroy(ohci_transfer_batch_t *ohci_batch);
    6568
    6669static inline ohci_transfer_batch_t *ohci_transfer_batch_from_link(link_t *l)
     
    6972        return list_get_instance(l, ohci_transfer_batch_t, link);
    7073}
     74
     75static inline ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *usb_batch)
     76{
     77        assert(usb_batch);
     78
     79        return (ohci_transfer_batch_t *) usb_batch;
     80}
     81
    7182#endif
    7283/**
  • uspace/drv/bus/usb/ohci/ohci_rh.c

    r367db39a re160bfe8  
    178178        assert(instance);
    179179        assert(batch);
    180         const usb_target_t target = {{
    181                 .address = batch->ep->address,
    182                 .endpoint = batch->ep->endpoint,
    183         }};
     180        const usb_target_t target = batch->ep->target;
    184181        batch->error = virthub_base_request(&instance->base, target,
    185             usb_transfer_batch_direction(batch), (void*)batch->setup_buffer,
     182            batch->dir, &batch->setup.packet,
    186183            batch->buffer, batch->buffer_size, &batch->transfered_size);
    187184        if (batch->error == ENAK) {
     
    192189                instance->unfinished_interrupt_transfer = batch;
    193190        } else {
    194                 usb_transfer_batch_finish(batch, NULL);
    195                 usb_transfer_batch_destroy(batch);
     191                usb_transfer_batch_finish(batch);
    196192        }
    197193        return EOK;
     
    211207        instance->unfinished_interrupt_transfer = NULL;
    212208        if (batch) {
    213                 const usb_target_t target = {{
    214                         .address = batch->ep->address,
    215                         .endpoint = batch->ep->endpoint,
    216                 }};
     209                const usb_target_t target = batch->ep->target;
    217210                batch->error = virthub_base_request(&instance->base, target,
    218                     usb_transfer_batch_direction(batch),
    219                     (void*)batch->setup_buffer,
     211                    batch->dir, &batch->setup.packet,
    220212                    batch->buffer, batch->buffer_size, &batch->transfered_size);
    221                 usb_transfer_batch_finish(batch, NULL);
    222                 usb_transfer_batch_destroy(batch);
     213                usb_transfer_batch_finish(batch);
    223214        }
    224215        return EOK;
  • uspace/drv/bus/usb/uhci/hc.c

    r367db39a re160bfe8  
    5050#include <usb/usb.h>
    5151#include <usb/host/utils/malloc32.h>
     52#include <usb/host/bandwidth.h>
    5253
    5354#include "uhci_batch.h"
     
    106107 * @return Error code.
    107108 */
    108 int uhci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res)
     109int uhci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res)
    109110{
    110111        assert(code);
     
    176177                        uhci_transfer_batch_t *batch =
    177178                            uhci_transfer_batch_from_link(current);
    178                         uhci_transfer_batch_finish_dispose(batch);
     179                        usb_transfer_batch_finish(&batch->base);
    179180                }
    180181        }
     
    214215 * interrupt fibrils.
    215216 */
    216 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts)
     217int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res)
    217218{
    218219        assert(instance);
     
    222223            return EINVAL;
    223224
    224         instance->hw_interrupts = interrupts;
    225225        instance->hw_failures = 0;
    226226
     
    246246        }
    247247
     248        return EOK;
     249}
     250
     251void hc_start(hc_t *instance)
     252{
    248253        hc_init_hw(instance);
    249254        (void)hc_debug_checker;
    250255
    251256        uhci_rh_init(&instance->rh, instance->registers->ports, "uhci");
    252 
    253         return EOK;
    254257}
    255258
     
    306309}
    307310
     311static usb_transfer_batch_t *create_transfer_batch(bus_t *bus, endpoint_t *ep)
     312{
     313        uhci_transfer_batch_t *batch = uhci_transfer_batch_create(ep);
     314        return &batch->base;
     315}
     316
     317static void destroy_transfer_batch(usb_transfer_batch_t *batch)
     318{
     319        uhci_transfer_batch_destroy(uhci_transfer_batch_get(batch));
     320}
     321
    308322/** Initialize UHCI hc memory structures.
    309323 *
     
    318332int hc_init_mem_structures(hc_t *instance)
    319333{
    320         assert(instance);
     334        int err;
     335        assert(instance);
     336
     337        if ((err = usb2_bus_init(&instance->bus, BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11)))
     338                return err;
     339
     340        instance->bus.base.ops.create_batch = create_transfer_batch;
     341        instance->bus.base.ops.destroy_batch = destroy_transfer_batch;
    321342
    322343        /* Init USB frame list page */
     
    440461        assert(batch);
    441462
    442         if (batch->ep->address == uhci_rh_get_address(&instance->rh))
     463        if (batch->ep->target.address == uhci_rh_get_address(&instance->rh))
    443464                return uhci_rh_schedule(&instance->rh, batch);
    444465
    445         uhci_transfer_batch_t *uhci_batch = uhci_transfer_batch_get(batch);
     466        uhci_transfer_batch_t *uhci_batch = (uhci_transfer_batch_t *) batch;
    446467        if (!uhci_batch) {
    447468                usb_log_error("Failed to create UHCI transfer structures.\n");
    448469                return ENOMEM;
    449470        }
     471
     472        const int err = uhci_transfer_batch_prepare(uhci_batch);
     473        if (err)
     474                return err;
    450475
    451476        transfer_list_t *list =
  • uspace/drv/bus/usb/uhci/hc.h

    r367db39a re160bfe8  
    4343#include <ddi.h>
    4444#include <usb/host/hcd.h>
     45#include <usb/host/usb2_bus.h>
    4546#include <usb/host/usb_transfer_batch.h>
    4647
     
    100101typedef struct hc {
    101102        uhci_rh_t rh;
     103        usb2_bus_t bus;
    102104        /** Addresses of I/O registers */
    103105        uhci_regs_t *registers;
     
    124126} hc_t;
    125127
    126 extern int hc_init(hc_t *, const hw_res_list_parsed_t *, bool);
     128extern int hc_init(hc_t *, const hw_res_list_parsed_t *);
     129extern void hc_start(hc_t *);
    127130extern void hc_fini(hc_t *);
    128131
    129 extern int uhci_hc_gen_irq_code(irq_code_t *, const hw_res_list_parsed_t *);
     132extern int uhci_hc_gen_irq_code(irq_code_t *, hcd_t *,const hw_res_list_parsed_t *);
    130133
    131134extern void uhci_hc_interrupt(hcd_t *, uint32_t);
  • uspace/drv/bus/usb/uhci/main.c

    r367db39a re160bfe8  
    4949#define NAME "uhci"
    5050
    51 static int uhci_driver_init(hcd_t *, const hw_res_list_parsed_t *, bool);
     51static int uhci_driver_init(hcd_t *, const hw_res_list_parsed_t *, ddf_dev_t *);
     52static int uhci_driver_start(hcd_t *, bool);
    5253static void uhci_driver_fini(hcd_t *);
    53 static int disable_legacy(ddf_dev_t *);
     54static int disable_legacy(hcd_t *, ddf_dev_t *);
    5455
    5556static const ddf_hc_driver_t uhci_hc_driver = {
    5657        .claim = disable_legacy,
    57         .hc_speed = USB_SPEED_FULL,
    5858        .irq_code_gen = uhci_hc_gen_irq_code,
    5959        .init = uhci_driver_init,
     60        .start = uhci_driver_start,
     61        .setup_root_hub = hcd_setup_virtual_root_hub,
    6062        .fini = uhci_driver_fini,
    6163        .name = "UHCI",
     
    6769};
    6870
    69 static int uhci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, bool irq)
     71static int uhci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, ddf_dev_t *device)
    7072{
     73        int err;
     74
    7175        assert(hcd);
    7276        assert(hcd_get_driver_data(hcd) == NULL);
     
    7680                return ENOMEM;
    7781
    78         const int ret = hc_init(instance, res, irq);
    79         if (ret == EOK) {
    80                 hcd_set_implementation(hcd, instance, &uhci_hc_driver.ops);
    81         } else {
    82                 free(instance);
    83         }
    84         return ret;
     82        if ((err = hc_init(instance, res)) != EOK)
     83                goto err;
     84
     85        hcd_set_implementation(hcd, instance, &uhci_hc_driver.ops, &instance->bus.base);
     86
     87        return EOK;
     88
     89err:
     90        free(instance);
     91        return err;
     92}
     93
     94static int uhci_driver_start(hcd_t *hcd, bool interrupts)
     95{
     96        assert(hcd);
     97        hc_t *hc = hcd_get_driver_data(hcd);
     98
     99        hc->hw_interrupts = interrupts;
     100        hc_start(hc);
     101        return EOK;
    85102}
    86103
     
    92109                hc_fini(hc);
    93110
    94         hcd_set_implementation(hcd, NULL, NULL);
     111        hcd_set_implementation(hcd, NULL, NULL, NULL);
    95112        free(hc);
    96113}
     
    101118 * @return Error code.
    102119 */
    103 static int disable_legacy(ddf_dev_t *device)
     120static int disable_legacy(hcd_t *hcd, ddf_dev_t *device)
    104121{
    105122        assert(device);
  • uspace/drv/bus/usb/uhci/transfer_list.c

    r367db39a re160bfe8  
    167167                    uhci_transfer_batch_from_link(current);
    168168
    169                 if (uhci_transfer_batch_is_complete(batch)) {
     169                if (uhci_transfer_batch_check_completed(batch)) {
    170170                        /* Save for processing */
    171171                        transfer_list_remove_batch(instance, batch);
  • uspace/drv/bus/usb/uhci/uhci_batch.c

    r367db39a re160bfe8  
    5050#define DEFAULT_ERROR_COUNT 3
    5151
    52 /** Safely destructs uhci_transfer_batch_t structure.
     52/** Transfer batch setup table. */
     53static void (*const batch_setup[])(uhci_transfer_batch_t*);
     54
     55/** Destroys uhci_transfer_batch_t structure.
    5356 *
    5457 * @param[in] uhci_batch Instance to destroy.
    5558 */
    56 static void uhci_transfer_batch_dispose(uhci_transfer_batch_t *uhci_batch)
    57 {
    58         if (uhci_batch) {
    59                 usb_transfer_batch_destroy(uhci_batch->usb_batch);
    60                 free32(uhci_batch->device_buffer);
    61                 free(uhci_batch);
    62         }
    63 }
    64 
    65 /** Finishes usb_transfer_batch and destroys the structure.
    66  *
    67  * @param[in] uhci_batch Instance to finish and destroy.
    68  */
    69 void uhci_transfer_batch_finish_dispose(uhci_transfer_batch_t *uhci_batch)
     59void uhci_transfer_batch_destroy(uhci_transfer_batch_t *uhci_batch)
    7060{
    7161        assert(uhci_batch);
    72         assert(uhci_batch->usb_batch);
    73         assert(!link_in_use(&uhci_batch->link));
    74         usb_transfer_batch_finish(uhci_batch->usb_batch,
    75             uhci_transfer_batch_data_buffer(uhci_batch));
    76         uhci_transfer_batch_dispose(uhci_batch);
    77 }
    78 
    79 /** Transfer batch setup table. */
    80 static void (*const batch_setup[])(uhci_transfer_batch_t*, usb_direction_t);
     62        free32(uhci_batch->device_buffer);
     63        free(uhci_batch);
     64}
    8165
    8266/** Allocate memory and initialize internal data structure.
     
    8569 * @return Valid pointer if all structures were successfully created,
    8670 * NULL otherwise.
     71 */
     72uhci_transfer_batch_t * uhci_transfer_batch_create(endpoint_t *ep)
     73{
     74        uhci_transfer_batch_t *uhci_batch =
     75            calloc(1, sizeof(uhci_transfer_batch_t));
     76        if (!uhci_batch) {
     77                usb_log_error("Failed to allocate UHCI batch.\n");
     78                return NULL;
     79        }
     80
     81        usb_transfer_batch_init(&uhci_batch->base, ep);
     82
     83        link_initialize(&uhci_batch->link);
     84        return uhci_batch;
     85}
     86
     87/* Prepares batch for commiting.
    8788 *
    8889 * Determines the number of needed transfer descriptors (TDs).
     
    9091 * Initializes parameters needed for the transfer and callback.
    9192 */
    92 uhci_transfer_batch_t * uhci_transfer_batch_get(usb_transfer_batch_t *usb_batch)
     93int uhci_transfer_batch_prepare(uhci_transfer_batch_t *uhci_batch)
    9394{
    9495        static_assert((sizeof(td_t) % 16) == 0);
    95 #define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \
    96         if (ptr == NULL) { \
    97                 usb_log_error(message); \
    98                 uhci_transfer_batch_dispose(uhci_batch); \
    99                 return NULL; \
    100         } else (void)0
    101 
    102         uhci_transfer_batch_t *uhci_batch =
    103             calloc(1, sizeof(uhci_transfer_batch_t));
    104         CHECK_NULL_DISPOSE_RETURN(uhci_batch,
    105             "Failed to allocate UHCI batch.\n");
    106         link_initialize(&uhci_batch->link);
    107         uhci_batch->td_count =
    108             (usb_batch->buffer_size + usb_batch->ep->max_packet_size - 1)
    109             / usb_batch->ep->max_packet_size;
     96
     97        usb_transfer_batch_t *usb_batch = &uhci_batch->base;
     98
     99        uhci_batch->td_count = (usb_batch->buffer_size + usb_batch->ep->max_packet_size - 1)
     100                / usb_batch->ep->max_packet_size;
     101
    110102        if (usb_batch->ep->transfer_type == USB_TRANSFER_CONTROL) {
    111103                uhci_batch->td_count += 2;
    112104        }
    113105
     106        const size_t setup_size = (uhci_batch->base.ep->transfer_type == USB_TRANSFER_CONTROL)
     107                ? USB_SETUP_PACKET_SIZE
     108                : 0;
     109
    114110        const size_t total_size = (sizeof(td_t) * uhci_batch->td_count)
    115             + sizeof(qh_t) + usb_batch->setup_size + usb_batch->buffer_size;
     111            + sizeof(qh_t) + setup_size + usb_batch->buffer_size;
    116112        uhci_batch->device_buffer = malloc32(total_size);
    117         CHECK_NULL_DISPOSE_RETURN(uhci_batch->device_buffer,
    118             "Failed to allocate UHCI buffer.\n");
     113        if (!uhci_batch->device_buffer) {
     114                usb_log_error("Failed to allocate UHCI buffer.\n");
     115                return ENOMEM;
     116        }
    119117        memset(uhci_batch->device_buffer, 0, total_size);
    120118
     
    130128            + sizeof(qh_t);
    131129        /* Copy SETUP packet data to the device buffer */
    132         memcpy(dest, usb_batch->setup_buffer, usb_batch->setup_size);
    133         dest += usb_batch->setup_size;
     130        memcpy(dest, usb_batch->setup.buffer, setup_size);
     131        dest += setup_size;
    134132        /* Copy generic data unless they are provided by the device */
    135133        if (usb_batch->ep->direction != USB_DIRECTION_IN) {
    136134                memcpy(dest, usb_batch->buffer, usb_batch->buffer_size);
    137135        }
    138         uhci_batch->usb_batch = usb_batch;
    139136        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT
    140137            " memory structures ready.\n", usb_batch,
    141138            USB_TRANSFER_BATCH_ARGS(*usb_batch));
    142139
    143         const usb_direction_t dir = usb_transfer_batch_direction(usb_batch);
    144 
    145140        assert(batch_setup[usb_batch->ep->transfer_type]);
    146         batch_setup[usb_batch->ep->transfer_type](uhci_batch, dir);
    147 
    148         return uhci_batch;
     141        batch_setup[usb_batch->ep->transfer_type](uhci_batch);
     142
     143        return EOK;
    149144}
    150145
     
    158153 * is reached.
    159154 */
    160 bool uhci_transfer_batch_is_complete(const uhci_transfer_batch_t *uhci_batch)
     155bool uhci_transfer_batch_check_completed(uhci_transfer_batch_t *uhci_batch)
    161156{
    162157        assert(uhci_batch);
    163         assert(uhci_batch->usb_batch);
    164158
    165159        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT
     
    168162            USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch),
    169163            uhci_batch->td_count);
    170         uhci_batch->usb_batch->transfered_size = 0;
     164        uhci_batch->base.transfered_size = 0;
    171165
    172166        for (size_t i = 0;i < uhci_batch->td_count; ++i) {
     
    175169                }
    176170
    177                 uhci_batch->usb_batch->error = td_status(&uhci_batch->tds[i]);
    178                 if (uhci_batch->usb_batch->error != EOK) {
    179                         assert(uhci_batch->usb_batch->ep != NULL);
     171                uhci_batch->base.error = td_status(&uhci_batch->tds[i]);
     172                if (uhci_batch->base.error != EOK) {
     173                        assert(uhci_batch->base.ep != NULL);
    180174
    181175                        usb_log_debug("Batch %p found error TD(%zu->%p):%"
     
    184178                        td_print_status(&uhci_batch->tds[i]);
    185179
    186                         endpoint_toggle_set(uhci_batch->usb_batch->ep,
     180                        endpoint_toggle_set(uhci_batch->base.ep,
    187181                            td_toggle(&uhci_batch->tds[i]));
    188182                        if (i > 0)
     
    191185                }
    192186
    193                 uhci_batch->usb_batch->transfered_size
     187                uhci_batch->base.transfered_size
    194188                    += td_act_size(&uhci_batch->tds[i]);
    195189                if (td_is_short(&uhci_batch->tds[i]))
     
    197191        }
    198192substract_ret:
    199         uhci_batch->usb_batch->transfered_size
    200             -= uhci_batch->usb_batch->setup_size;
     193        if (uhci_batch->base.ep->transfer_type == USB_TRANSFER_CONTROL)
     194                uhci_batch->base.transfered_size -= USB_SETUP_PACKET_SIZE;
    201195        return true;
    202196}
     
    216210 * The last transfer is marked with IOC flag.
    217211 */
    218 static void batch_data(uhci_transfer_batch_t *uhci_batch, usb_direction_t dir)
     212static void batch_data(uhci_transfer_batch_t *uhci_batch)
    219213{
    220214        assert(uhci_batch);
    221         assert(uhci_batch->usb_batch);
    222         assert(uhci_batch->usb_batch->ep);
     215
     216        usb_direction_t dir = uhci_batch->base.dir;
    223217        assert(dir == USB_DIRECTION_OUT || dir == USB_DIRECTION_IN);
    224218
     
    226220        const usb_packet_id pid = direction_pids[dir];
    227221        const bool low_speed =
    228             uhci_batch->usb_batch->ep->speed == USB_SPEED_LOW;
    229         const size_t mps = uhci_batch->usb_batch->ep->max_packet_size;
    230         const usb_target_t target = {{
    231             uhci_batch->usb_batch->ep->address,
    232             uhci_batch->usb_batch->ep->endpoint }};
    233 
    234         int toggle = endpoint_toggle_get(uhci_batch->usb_batch->ep);
     222            uhci_batch->base.ep->speed == USB_SPEED_LOW;
     223        const size_t mps = uhci_batch->base.ep->max_packet_size;
     224        const usb_target_t target = uhci_batch->base.ep->target;
     225
     226        int toggle = endpoint_toggle_get(uhci_batch->base.ep);
    235227        assert(toggle == 0 || toggle == 1);
    236228
    237229        size_t td = 0;
    238         size_t remain_size = uhci_batch->usb_batch->buffer_size;
     230        size_t remain_size = uhci_batch->base.buffer_size;
    239231        char *buffer = uhci_transfer_batch_data_buffer(uhci_batch);
    240232
     
    256248        }
    257249        td_set_ioc(&uhci_batch->tds[td - 1]);
    258         endpoint_toggle_set(uhci_batch->usb_batch->ep, toggle);
     250        endpoint_toggle_set(uhci_batch->base.ep, toggle);
    259251        usb_log_debug2(
    260252            "Batch %p %s %s " USB_TRANSFER_BATCH_FMT " initialized.\n", \
    261253            uhci_batch->usb_batch,
    262             usb_str_transfer_type(uhci_batch->usb_batch->ep->transfer_type),
    263             usb_str_direction(uhci_batch->usb_batch->ep->direction),
     254            usb_str_transfer_type(uhci_batch->base.ep->transfer_type),
     255            usb_str_direction(uhci_batch->base.ep->direction),
    264256            USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch));
    265257}
     
    276268 * The last transfer is marked with IOC.
    277269 */
    278 static void batch_control(uhci_transfer_batch_t *uhci_batch, usb_direction_t dir)
     270static void batch_control(uhci_transfer_batch_t *uhci_batch)
    279271{
    280272        assert(uhci_batch);
    281         assert(uhci_batch->usb_batch);
    282         assert(uhci_batch->usb_batch->ep);
     273
     274        usb_direction_t dir = uhci_batch->base.dir;
    283275        assert(dir == USB_DIRECTION_OUT || dir == USB_DIRECTION_IN);
    284276        assert(uhci_batch->td_count >= 2);
     
    291283        const usb_packet_id status_stage_pid = status_stage_pids[dir];
    292284        const bool low_speed =
    293             uhci_batch->usb_batch->ep->speed == USB_SPEED_LOW;
    294         const size_t mps = uhci_batch->usb_batch->ep->max_packet_size;
    295         const usb_target_t target = {{
    296             uhci_batch->usb_batch->ep->address,
    297             uhci_batch->usb_batch->ep->endpoint }};
     285            uhci_batch->base.ep->speed == USB_SPEED_LOW;
     286        const size_t mps = uhci_batch->base.ep->max_packet_size;
     287        const usb_target_t target = uhci_batch->base.ep->target;
    298288
    299289        /* setup stage */
    300290        td_init(
    301291            &uhci_batch->tds[0], DEFAULT_ERROR_COUNT,
    302             uhci_batch->usb_batch->setup_size, 0, false,
     292            USB_SETUP_PACKET_SIZE, 0, false,
    303293            low_speed, target, USB_PID_SETUP,
    304294            uhci_transfer_batch_setup_buffer(uhci_batch), &uhci_batch->tds[1]);
     
    307297        size_t td = 1;
    308298        unsigned toggle = 1;
    309         size_t remain_size = uhci_batch->usb_batch->buffer_size;
     299        size_t remain_size = uhci_batch->base.buffer_size;
    310300        char *buffer = uhci_transfer_batch_data_buffer(uhci_batch);
    311301
     
    337327}
    338328
    339 static void (*const batch_setup[])(uhci_transfer_batch_t*, usb_direction_t) =
     329static void (*const batch_setup[])(uhci_transfer_batch_t*) =
    340330{
    341331        [USB_TRANSFER_CONTROL] = batch_control,
  • uspace/drv/bus/usb/uhci/uhci_batch.h

    r367db39a re160bfe8  
    4343#include <stddef.h>
    4444#include <usb/host/usb_transfer_batch.h>
     45#include <usb/host/endpoint.h>
    4546
    4647#include "hw_struct/queue_head.h"
     
    4950/** UHCI specific data required for USB transfer */
    5051typedef struct uhci_transfer_batch {
     52        usb_transfer_batch_t base;
     53
    5154        /** Queue head
    5255         * This QH is used to maintain UHCI schedule structure and the element
     
    6669} uhci_transfer_batch_t;
    6770
    68 uhci_transfer_batch_t * uhci_transfer_batch_get(usb_transfer_batch_t *batch);
    69 void uhci_transfer_batch_finish_dispose(uhci_transfer_batch_t *uhci_batch);
    70 bool uhci_transfer_batch_is_complete(const uhci_transfer_batch_t *uhci_batch);
     71uhci_transfer_batch_t * uhci_transfer_batch_create(endpoint_t *ep);
     72int uhci_transfer_batch_prepare(uhci_transfer_batch_t *uhci_batch);
     73bool uhci_transfer_batch_check_completed(uhci_transfer_batch_t *uhci_batch);
     74void uhci_transfer_batch_destroy(uhci_transfer_batch_t *uhci_batch);
    7175
    7276/** Get offset to setup buffer accessible to the HC hw.
     
    9397        assert(uhci_batch->usb_batch);
    9498        return uhci_transfer_batch_setup_buffer(uhci_batch) +
    95             uhci_batch->usb_batch->setup_size;
     99            (uhci_batch->base.ep->transfer_type == USB_TRANSFER_CONTROL ? USB_SETUP_PACKET_SIZE : 0);
    96100}
    97101
     
    107111        uhci_batch->usb_batch->error = EINTR;
    108112        uhci_batch->usb_batch->transfered_size = 0;
    109         uhci_transfer_batch_finish_dispose(uhci_batch);
     113        usb_transfer_batch_finish(&uhci_batch->base);
    110114}
    111115
     
    120124}
    121125
     126static inline uhci_transfer_batch_t *uhci_transfer_batch_get(usb_transfer_batch_t *b)
     127{
     128        assert(b);
     129        return (uhci_transfer_batch_t *) b;
     130}
     131
    122132#endif
    123133
  • uspace/drv/bus/usb/uhci/uhci_rh.c

    r367db39a re160bfe8  
    3939#include <usb/classes/hub.h>
    4040#include <usb/request.h>
     41#include <usb/host/endpoint.h>
    4142#include <usb/usb.h>
    4243
     
    103104        assert(batch);
    104105
    105         const usb_target_t target = {{
    106                 .address = batch->ep->address,
    107                 .endpoint = batch->ep->endpoint
    108         }};
     106        const usb_target_t target = batch->ep->target;
    109107        do {
    110108                batch->error = virthub_base_request(&instance->base, target,
    111                     usb_transfer_batch_direction(batch), (void*)batch->setup_buffer,
     109                    batch->dir, (void*) batch->setup.buffer,
    112110                    batch->buffer, batch->buffer_size, &batch->transfered_size);
    113111                if (batch->error == ENAK)
     
    116114                //ENAK is technically an error condition
    117115        } while (batch->error == ENAK);
    118         usb_transfer_batch_finish(batch, NULL);
    119         usb_transfer_batch_destroy(batch);
     116        usb_transfer_batch_finish(batch);
    120117        return EOK;
    121118}
  • uspace/drv/bus/usb/usbhid/main.c

    r367db39a re160bfe8  
    9595           usb_hid_polling_callback,
    9696           /* How much data to request. */
    97            hid_dev->poll_pipe_mapping->pipe.max_packet_size,
     97           hid_dev->poll_pipe_mapping->pipe.desc.max_packet_size,
    9898           /* Delay */
    9999           -1,
  • uspace/drv/bus/usb/usbhub/status.h

    r367db39a re160bfe8  
    110110        if ((status & USB_HUB_PORT_STATUS_HIGH_SPEED) != 0)
    111111                return USB_SPEED_HIGH;
     112        /* TODO: add super speed */
    112113        return USB_SPEED_FULL;
    113114}
  • uspace/drv/bus/usb/usbmast/main.c

    r367db39a re160bfe8  
    172172            usb_device_get_name(dev));
    173173        usb_log_debug("Bulk in endpoint: %d [%zuB].\n",
    174             epm_in->pipe.endpoint_no, epm_in->pipe.max_packet_size);
     174            epm_in->pipe.desc.endpoint_no, epm_in->pipe.desc.max_packet_size);
    175175        usb_log_debug("Bulk out endpoint: %d [%zuB].\n",
    176             epm_out->pipe.endpoint_no, epm_out->pipe.max_packet_size);
     176            epm_out->pipe.desc.endpoint_no, epm_out->pipe.desc.max_packet_size);
    177177
    178178        usb_log_debug("Get LUN count...\n");
  • uspace/drv/bus/usb/vhc/main.c

    r367db39a re160bfe8  
    8989
    9090        /* Initialize generic structures */
    91         ret = hcd_ddf_setup_hc(dev, USB_SPEED_FULL,
    92             BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11);
     91        ret = hcd_ddf_setup_hc(dev);
    9392        if (ret != EOK) {
    9493                usb_log_error("Failed to init HCD structures: %s.\n",
     
    9897        }
    9998
    100         hcd_set_implementation(dev_to_hcd(dev), data, &vhc_hc_ops);
     99        hcd_set_implementation(dev_to_hcd(dev), data, &vhc_hc_ops, &data->bus.base);
    101100
    102101        /* Add virtual hub device */
     
    112111         * needs to be ready at this time.
    113112         */
    114         ret = hcd_ddf_setup_root_hub(dev);
     113        ret = hcd_setup_virtual_root_hub(dev_to_hcd(dev), dev);
    115114        if (ret != EOK) {
    116115                usb_log_error("Failed to init VHC root hub: %s\n",
  • uspace/drv/bus/usb/vhc/transfer.c

    r367db39a re160bfe8  
    3131#include <usb/debug.h>
    3232#include <usbvirt/device.h>
     33#include <usb/host/bandwidth.h>
    3334#include <usbvirt/ipc.h>
    3435#include "vhcd.h"
     
    3738static bool is_set_address_transfer(vhc_transfer_t *transfer)
    3839{
    39         if (transfer->batch->ep->endpoint != 0) {
     40        if (transfer->batch->ep->target.endpoint != 0) {
    4041                return false;
    4142        }
     
    4344                return false;
    4445        }
    45         if (usb_transfer_batch_direction(transfer->batch) != USB_DIRECTION_OUT) {
    46                 return false;
    47         }
    48         const usb_device_request_setup_packet_t *setup =
    49             (void*)transfer->batch->setup_buffer;
     46        if (transfer->batch->dir != USB_DIRECTION_OUT) {
     47                return false;
     48        }
     49        const usb_device_request_setup_packet_t *setup
     50                = &transfer->batch->setup.packet;
    5051        if (setup->request_type != 0) {
    5152                return false;
     
    6263{
    6364        int rc;
    64        
    65         const usb_direction_t dir = usb_transfer_batch_direction(batch);
     65
     66        const usb_direction_t dir = batch->dir;
    6667
    6768        if (batch->ep->transfer_type == USB_TRANSFER_CONTROL) {
    6869                if (dir == USB_DIRECTION_IN) {
    6970                        rc = usbvirt_control_read(dev,
    70                             batch->setup_buffer, batch->setup_size,
     71                            batch->setup.buffer, USB_SETUP_PACKET_SIZE,
    7172                            batch->buffer, batch->buffer_size,
    7273                            actual_data_size);
     
    7475                        assert(dir == USB_DIRECTION_OUT);
    7576                        rc = usbvirt_control_write(dev,
    76                             batch->setup_buffer, batch->setup_size,
     77                            batch->setup.buffer, USB_SETUP_PACKET_SIZE,
    7778                            batch->buffer, batch->buffer_size);
    7879                }
     
    8081                if (dir == USB_DIRECTION_IN) {
    8182                        rc = usbvirt_data_in(dev, batch->ep->transfer_type,
    82                             batch->ep->endpoint,
     83                            batch->ep->target.endpoint,
    8384                            batch->buffer, batch->buffer_size,
    8485                            actual_data_size);
     
    8687                        assert(dir == USB_DIRECTION_OUT);
    8788                        rc = usbvirt_data_out(dev, batch->ep->transfer_type,
    88                             batch->ep->endpoint,
     89                            batch->ep->target.endpoint,
    8990                            batch->buffer, batch->buffer_size);
    9091                }
     
    99100        int rc;
    100101
    101         const usb_direction_t dir = usb_transfer_batch_direction(batch);
     102        const usb_direction_t dir = batch->dir;
    102103
    103104        if (batch->ep->transfer_type == USB_TRANSFER_CONTROL) {
    104105                if (dir == USB_DIRECTION_IN) {
    105106                        rc = usbvirt_ipc_send_control_read(sess,
    106                             batch->setup_buffer, batch->setup_size,
     107                            batch->setup.buffer, USB_SETUP_PACKET_SIZE,
    107108                            batch->buffer, batch->buffer_size,
    108109                            actual_data_size);
     
    110111                        assert(dir == USB_DIRECTION_OUT);
    111112                        rc = usbvirt_ipc_send_control_write(sess,
    112                             batch->setup_buffer, batch->setup_size,
     113                            batch->setup.buffer, USB_SETUP_PACKET_SIZE,
    113114                            batch->buffer, batch->buffer_size);
    114115                }
    115116        } else {
    116117                if (dir == USB_DIRECTION_IN) {
    117                         rc = usbvirt_ipc_send_data_in(sess, batch->ep->endpoint,
     118                        rc = usbvirt_ipc_send_data_in(sess, batch->ep->target.endpoint,
    118119                            batch->ep->transfer_type,
    119120                            batch->buffer, batch->buffer_size,
     
    121122                } else {
    122123                        assert(dir == USB_DIRECTION_OUT);
    123                         rc = usbvirt_ipc_send_data_out(sess, batch->ep->endpoint,
     124                        rc = usbvirt_ipc_send_data_out(sess, batch->ep->target.endpoint,
    124125                            batch->ep->transfer_type,
    125126                            batch->buffer, batch->buffer_size);
     
    148149        assert(transfer);
    149150        assert(transfer->batch);
    150         usb_transfer_batch_finish_error(transfer->batch, NULL,
    151             data_transfer_size, outcome);
    152         usb_transfer_batch_destroy(transfer->batch);
     151        transfer->batch->error = outcome;
     152        transfer->batch->transfered_size = data_transfer_size;
     153        usb_transfer_batch_finish(transfer->batch);
    153154        free(transfer);
    154155}
     
    159160        list_initialize(&instance->devices);
    160161        fibril_mutex_initialize(&instance->guard);
     162        usb2_bus_init(&instance->bus, BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11);
    161163        instance->magic = 0xDEADBEEF;
    162164        return virthub_init(&instance->hub, "root hub");
     
    182184        list_foreach(vhc->devices, link, vhc_virtdev_t, dev) {
    183185                fibril_mutex_lock(&dev->guard);
    184                 if (dev->address == transfer->batch->ep->address) {
     186                if (dev->address == transfer->batch->ep->target.address) {
    185187                        if (!targets) {
    186188                                list_append(&transfer->link, &dev->transfer_queue);
     
    234236                        if (is_set_address_transfer(transfer)) {
    235237                                usb_device_request_setup_packet_t *setup =
    236                                     (void*) transfer->batch->setup_buffer;
     238                                    (void*) transfer->batch->setup.buffer;
    237239                                dev->address = setup->value;
    238240                                usb_log_debug2("Address changed to %d\n",
  • uspace/drv/bus/usb/vhc/vhcd.h

    r367db39a re160bfe8  
    4242
    4343#include <usb/host/hcd.h>
     44#include <usb/host/usb2_bus.h>
    4445
    4546#define NAME "vhc"
     
    6061        fibril_mutex_t guard;
    6162        usbvirt_device_t hub;
     63        usb2_bus_t bus;
    6264} vhc_data_t;
    6365
  • uspace/lib/c/include/bitops.h

    r367db39a re160bfe8  
    5454#define BIT_RANGE_EXTRACT(type, hi, lo, value) \
    5555    (((value) >> (lo)) & BIT_RRANGE(type, (hi) - (lo) + 1))
     56
     57/** Insert @a value between bits @a hi .. @a lo. */
     58#define BIT_RANGE_INSERT(type, hi, lo, value) \
     59    (((value) & BIT_RRANGE(type, (hi) - (lo) + 1)) << (lo))
    5660
    5761/** Return position of first non-zero bit from left (i.e. [log_2(arg)]).
  • uspace/lib/c/include/byteorder.h

    r367db39a re160bfe8  
    8585#define ntohl(n)  uint32_t_be2host((n))
    8686
     87#define uint8_t_be2host(n)  (n)
     88#define uint8_t_le2host(n)  (n)
     89#define host2uint8_t_be(n)  (n)
     90#define host2uint8_t_le(n)  (n)
     91
    8792static inline uint64_t uint64_t_byteorder_swap(uint64_t n)
    8893{
  • uspace/lib/drv/generic/remote_usb.c

    r367db39a re160bfe8  
    175175} pack8_t;
    176176
    177 int usb_register_endpoint(async_exch_t *exch, usb_endpoint_t endpoint,
    178     usb_transfer_type_t type, usb_direction_t direction,
    179     size_t mps, unsigned packets, unsigned interval)
    180 {
    181         if (!exch)
    182                 return EBADMEM;
    183         pack8_t pack;
    184         pack.arr[0] = type;
    185         pack.arr[1] = direction;
    186         pack.arr[2] = interval;
    187         pack.arr[3] = packets;
    188 
    189         return async_req_4_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    190             IPC_M_USB_REGISTER_ENDPOINT, endpoint, pack.arg, mps);
    191 
    192 }
    193 
    194 int usb_unregister_endpoint(async_exch_t *exch, usb_endpoint_t endpoint,
    195     usb_direction_t direction)
    196 {
    197         if (!exch)
    198                 return EBADMEM;
    199         return async_req_3_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    200             IPC_M_USB_UNREGISTER_ENDPOINT, endpoint, direction);
     177int usb_register_endpoint(async_exch_t *exch,
     178        usb_endpoint_desc_t *endpoint_desc)
     179{
     180        if (!exch)
     181                return EBADMEM;
     182
     183        aid_t opening_request = async_send_1(exch,
     184            DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_REGISTER_ENDPOINT, NULL);
     185
     186        if (opening_request == 0) {
     187                return ENOMEM;
     188        }
     189
     190        const int ret = async_data_write_start(exch, (void *) endpoint_desc,
     191                sizeof(usb_endpoint_desc_t));
     192
     193        if (ret != EOK) {
     194                async_forget(opening_request);
     195                return ret;
     196        }
     197
     198        /* Wait for the answer. */
     199        sysarg_t opening_request_rc;
     200        async_wait_for(opening_request, &opening_request_rc);
     201
     202        return (int) opening_request_rc;
     203}
     204
     205int usb_unregister_endpoint(async_exch_t *exch,
     206        usb_endpoint_desc_t *endpoint_desc)
     207{
     208        if (!exch)
     209                return EBADMEM;
     210
     211        aid_t opening_request = async_send_1(exch,
     212                DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_UNREGISTER_ENDPOINT, NULL);
     213
     214        if (opening_request == 0) {
     215                return ENOMEM;
     216        }
     217
     218        const int ret = async_data_write_start(exch, endpoint_desc,
     219                sizeof(usb_endpoint_desc_t));
     220        if (ret != EOK) {
     221                async_forget(opening_request);
     222                return ret;
     223        }
     224
     225        /* Wait for the answer. */
     226        sysarg_t opening_request_rc;
     227        async_wait_for(opening_request, &opening_request_rc);
     228
     229        return (int) opening_request_rc;
    201230}
    202231
     
    317346};
    318347
     348typedef struct {
     349        ipc_callid_t caller;
     350        ipc_callid_t data_caller;
     351        void *buffer;
     352} async_transaction_t;
     353
    319354void remote_usb_get_my_interface(ddf_fun_t *fun, void *iface,
    320355    ipc_callid_t callid, ipc_call_t *call)
     
    417452    ipc_callid_t callid, ipc_call_t *call)
    418453{
    419         usb_iface_t *usb_iface = (usb_iface_t *) iface;
     454        assert(fun);
     455        assert(iface);
     456        assert(call);
     457
     458        const usb_iface_t *usb_iface = iface;
    420459
    421460        if (!usb_iface->register_endpoint) {
     
    424463        }
    425464
    426         const usb_endpoint_t endpoint = DEV_IPC_GET_ARG1(*call);
    427         const pack8_t pack = { .arg = DEV_IPC_GET_ARG2(*call)};
    428         const size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
    429 
    430         const usb_transfer_type_t transfer_type = pack.arr[0];
    431         const usb_direction_t direction = pack.arr[1];
    432         unsigned packets = pack.arr[2];
    433         unsigned interval = pack.arr[3];
    434 
    435         const int ret = usb_iface->register_endpoint(fun, endpoint,
    436             transfer_type, direction, max_packet_size, packets, interval);
    437 
    438         async_answer_0(callid, ret);
     465        void *buffer = NULL;
     466        size_t size = 0;
     467        int rc = async_data_write_accept(&buffer, false,
     468                sizeof(usb_endpoint_desc_t), sizeof(usb_endpoint_desc_t), 0, &size);
     469
     470        if (rc != EOK) {
     471                free(buffer);
     472                async_answer_0(callid, rc);
     473                return;
     474        }
     475
     476        usb_endpoint_desc_t *endpoint_desc = (usb_endpoint_desc_t *) buffer;
     477        rc = usb_iface->register_endpoint(fun, endpoint_desc);
     478
     479        free(buffer);
     480        async_answer_0(callid, rc);
    439481}
    440482
     
    442484    ipc_callid_t callid, ipc_call_t *call)
    443485{
    444         usb_iface_t *usb_iface = (usb_iface_t *) iface;
     486        assert(fun);
     487        assert(iface);
     488        assert(call);
     489
     490        const usb_iface_t *usb_iface = iface;
    445491
    446492        if (!usb_iface->unregister_endpoint) {
     
    449495        }
    450496
    451         usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG1(*call);
    452         usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG2(*call);
    453 
    454         int rc = usb_iface->unregister_endpoint(fun, endpoint, direction);
    455 
     497        void *buffer = NULL;
     498        size_t size = 0;
     499        int rc = async_data_write_accept(&buffer, false,
     500                sizeof(usb_endpoint_desc_t), sizeof(usb_endpoint_desc_t), 0, &size);
     501
     502        if (rc != EOK) {
     503                free(buffer);
     504                async_answer_0(callid, rc);
     505                return;
     506        }
     507
     508        usb_endpoint_desc_t *endpoint_desc = (usb_endpoint_desc_t *) buffer;
     509        usb_iface->unregister_endpoint(fun, endpoint_desc);
     510
     511        free(buffer);
    456512        async_answer_0(callid, rc);
    457513}
    458 
    459 typedef struct {
    460         ipc_callid_t caller;
    461         ipc_callid_t data_caller;
    462         void *buffer;
    463 } async_transaction_t;
    464514
    465515static void async_transaction_destroy(async_transaction_t *trans)
  • uspace/lib/drv/include/usb_iface.h

    r367db39a re160bfe8  
    5757extern int usb_device_remove(async_exch_t *, unsigned port);
    5858
    59 extern int usb_register_endpoint(async_exch_t *, usb_endpoint_t,
    60     usb_transfer_type_t, usb_direction_t, size_t, unsigned, unsigned);
    61 extern int usb_unregister_endpoint(async_exch_t *, usb_endpoint_t,
    62     usb_direction_t);
     59extern int usb_register_endpoint(async_exch_t *, usb_endpoint_desc_t *);
     60extern int usb_unregister_endpoint(async_exch_t *, usb_endpoint_desc_t *);
    6361extern int usb_read(async_exch_t *, usb_endpoint_t, uint64_t, void *, size_t,
    6462    size_t *);
     
    8381        int (*device_remove)(ddf_fun_t *, unsigned);
    8482
    85         int (*register_endpoint)(ddf_fun_t *, usb_endpoint_t,
    86             usb_transfer_type_t, usb_direction_t, size_t, unsigned, unsigned);
    87         int (*unregister_endpoint)(ddf_fun_t *, usb_endpoint_t,
    88             usb_direction_t);
     83        int (*register_endpoint)(ddf_fun_t *, usb_endpoint_desc_t *);
     84        int (*unregister_endpoint)(ddf_fun_t *, usb_endpoint_desc_t *);
    8985
    9086        int (*read)(ddf_fun_t *, usb_endpoint_t, uint64_t, uint8_t *, size_t,
  • uspace/lib/pcm/src/format.c

    r367db39a re160bfe8  
    4141
    4242#include "format.h"
    43 
    44 #define uint8_t_le2host(x) (x)
    45 #define host2uint8_t_le(x) (x)
    46 #define uint8_t_be2host(x) (x)
    47 #define host2uint8_t_be(x) (x)
    4843
    4944#define int8_t_le2host(x) (x)
  • uspace/lib/usb/include/usb/descriptor.h

    r367db39a re160bfe8  
    4949        USB_DESCTYPE_OTHER_SPEED_CONFIGURATION = 7,
    5050        USB_DESCTYPE_INTERFACE_POWER = 8,
     51        /* USB 3.0 types */
     52        USB_DESCTYPE_OTG = 9,
     53        USB_DESCTYPE_DEBUG = 0xa,
     54        USB_DESCTYPE_IFACE_ASSOC = 0xb,
     55        USB_DESCTYPE_BOS = 0xf,
     56        USB_DESCTYPE_DEVICE_CAP = 0x10,
    5157        /* Class specific */
    5258        USB_DESCTYPE_HID = 0x21,
     
    5460        USB_DESCTYPE_HID_PHYSICAL = 0x23,
    5561        USB_DESCTYPE_HUB = 0x29,
     62        USB_DESCTYPE_SSPEED_EP_COMPANION = 0x30
    5663        /* USB_DESCTYPE_ = */
    5764} usb_descriptor_type_t;
     
    217224} __attribute__ ((packed)) usb_standard_endpoint_descriptor_t;
    218225
     226/** Superspeed USB endpoint companion descriptor.
     227 * See USB 3 specification, section 9.6.7.
     228 */
     229typedef struct {
     230        /** Size of this descriptor in bytes */
     231        uint8_t length;
     232        /** Descriptor type (USB_DESCTYPE_SSPEED_EP_COMPANION). */
     233        uint8_t descriptor_type;
     234        /** The maximum number of packets the endpoint can send
     235         * or receive as part of a burst. Valid values are from 0 to 15.
     236         * The endpoint can only burst max_burst + 1 packets at a time.
     237         */
     238        uint8_t max_burst;
     239        /** Valid only for bulk and isochronous endpoints.
     240         * For bulk endpoints, this field contains the amount of streams
     241         * supported by the endpoint.
     242         * For isochronous endpoints, this field contains either maximum
     243         * number of packets supported within a service interval, or
     244         * whether an isochronous endpoint companion descriptor follows.
     245         */
     246        uint8_t attributes;
     247        /** The total number of bytes this endpoint will transfer
     248         * every service interval (SI).
     249         * This field is only valid for periodic endpoints.
     250         */
     251        uint16_t bytes_per_interval;
     252} __attribute__ ((packed)) usb_superspeed_endpoint_companion_descriptor_t;
     253
    219254/** Part of standard USB HID descriptor specifying one class descriptor.
    220255 *
  • uspace/lib/usb/include/usb/request.h

    r367db39a re160bfe8  
    109109int assert[(sizeof(usb_device_request_setup_packet_t) == 8) ? 1: -1];
    110110
    111 int usb_request_needs_toggle_reset(
     111/** How much toggles needs to be reset */
     112typedef enum {
     113        RESET_NONE,
     114        RESET_EP,
     115        RESET_ALL
     116} toggle_reset_mode_t;
     117
     118toggle_reset_mode_t usb_request_get_toggle_reset_mode(
    112119    const usb_device_request_setup_packet_t *request);
     120
     121#define GET_DEVICE_DESC(size) \
     122{ \
     123        .request_type = SETUP_REQUEST_TYPE_DEVICE_TO_HOST \
     124            | (USB_REQUEST_TYPE_STANDARD << 5) \
     125            | USB_REQUEST_RECIPIENT_DEVICE, \
     126        .request = USB_DEVREQ_GET_DESCRIPTOR, \
     127        .value = uint16_host2usb(USB_DESCTYPE_DEVICE << 8), \
     128        .index = uint16_host2usb(0), \
     129        .length = uint16_host2usb(size), \
     130};
     131
     132#define SET_ADDRESS(address) \
     133{ \
     134        .request_type = SETUP_REQUEST_TYPE_HOST_TO_DEVICE \
     135            | (USB_REQUEST_TYPE_STANDARD << 5) \
     136            | USB_REQUEST_RECIPIENT_DEVICE, \
     137        .request = USB_DEVREQ_SET_ADDRESS, \
     138        .value = uint16_host2usb(address), \
     139        .index = uint16_host2usb(0), \
     140        .length = uint16_host2usb(0), \
     141};
     142
     143#define CTRL_PIPE_MIN_PACKET_SIZE 8
    113144
    114145#endif
  • uspace/lib/usb/include/usb/usb.h

    r367db39a re160bfe8  
    8181        /** USB 2.0 high speed (480Mbits/s). */
    8282        USB_SPEED_HIGH,
     83        /** USB 3.0 super speed (5Gbits/s). */
     84        USB_SPEED_SUPER,
    8385        /** Psuedo-speed serving as a boundary. */
    8486        USB_SPEED_MAX
     
    113115typedef int16_t usb_address_t;
    114116
     117typedef struct {
     118        usb_address_t address;
     119        unsigned port;
     120} usb_tt_address_t;
     121
    115122/** Default USB address. */
    116123#define USB_ADDRESS_DEFAULT 0
     
    157164
    158165
    159 /** USB complete address type. 
     166/** USB complete address type.
    160167 * Pair address + endpoint is identification of transaction recipient.
    161168 */
     
    167174        uint32_t packed;
    168175} usb_target_t;
     176
     177/** Description of usb endpoint.
     178 */
     179typedef struct {
     180        /** Endpoint number. */
     181        usb_endpoint_t endpoint_no;
     182
     183        /** Endpoint transfer type. */
     184        usb_transfer_type_t transfer_type;
     185
     186        /** Endpoint direction. */
     187        usb_direction_t direction;
     188
     189        /** Maximum packet size for the endpoint. */
     190        size_t max_packet_size;
     191
     192        /** Number of packets per frame/uframe.
     193         * Only valid for HS INT and ISO transfers. All others should set to 1*/
     194        unsigned packets;
     195
     196        struct {
     197                unsigned polling_interval;
     198        } usb2;
     199} usb_endpoint_desc_t;
    169200
    170201/** Check USB target for allowed values (address and endpoint).
  • uspace/lib/usb/src/usb.c

    r367db39a re160bfe8  
    4444        [USB_SPEED_FULL] = "full",
    4545        [USB_SPEED_HIGH] = "high",
     46        [USB_SPEED_SUPER] = "super",
    4647};
    4748
     
    127128 *
    128129 */
    129 int usb_request_needs_toggle_reset(
     130toggle_reset_mode_t usb_request_get_toggle_reset_mode(
    130131    const usb_device_request_setup_packet_t *request)
    131132{
     
    138139                if ((request->request_type == 0x2) &&
    139140                    (request->value == USB_FEATURE_ENDPOINT_HALT))
    140                         return uint16_usb2host(request->index);
     141                        return RESET_EP;
    141142                break;
    142143        case USB_DEVREQ_SET_CONFIGURATION:
     
    148149                 * interface of an already setup device. */
    149150                if (!(request->request_type & SETUP_REQUEST_TYPE_DEVICE_TO_HOST))
    150                         return 0;
     151                        return RESET_ALL;
    151152                break;
    152153        default:
    153154                break;
    154155        }
    155         return -1;
     156
     157        return RESET_NONE;
    156158}
    157159
  • uspace/lib/usbdev/include/usb/dev/pipes.h

    r367db39a re160bfe8  
    5050 */
    5151typedef struct {
    52         /** Endpoint number. */
    53         usb_endpoint_t endpoint_no;
    54 
    55         /** Endpoint transfer type. */
    56         usb_transfer_type_t transfer_type;
    57 
    58         /** Endpoint direction. */
    59         usb_direction_t direction;
    60 
    61         /** Maximum packet size for the endpoint. */
    62         size_t max_packet_size;
    63 
    64         /** Number of packets per frame/uframe.
    65          * Only valid for HS INT and ISO transfers. All others should set to 1*/
    66         unsigned packets;
    67 
     52        /** Endpoint description */
     53        usb_endpoint_desc_t desc;
    6854        /** Whether to automatically reset halt on the endpoint.
    6955         * Valid only for control endpoint zero.
    7056         */
    7157        bool auto_reset_halt;
    72 
    7358        /** The connection used for sending the data. */
    7459        usb_dev_session_t *bus_session;
  • uspace/lib/usbdev/src/devdrv.c

    r367db39a re160bfe8  
    5656        /** Connection to device on USB bus */
    5757        usb_dev_session_t *bus_session;
    58        
     58
    5959        /** devman handle */
    6060        devman_handle_t handle;
    61        
     61
    6262        /** The default control pipe. */
    6363        usb_pipe_t ctrl_pipe;
    64        
     64
    6565        /** Other endpoint pipes.
    6666         *
     
    6969         */
    7070        usb_endpoint_mapping_t *pipes;
    71        
     71
    7272        /** Number of other endpoint pipes. */
    7373        size_t pipes_count;
    74        
     74
    7575        /** Current interface.
    7676         *
     
    7979         */
    8080        int interface_no;
    81        
     81
    8282        /** Alternative interfaces. */
    8383        usb_alternate_interfaces_t alternate_interfaces;
    84        
     84
    8585        /** Some useful descriptors for USB device. */
    8686        usb_device_descriptors_t descriptors;
    87        
     87
    8888        /** Generic DDF device backing this one. DO NOT TOUCH! */
    8989        ddf_dev_t *ddf_dev;
    90        
     90
    9191        /** Custom driver data.
    9292         *
     
    146146                return rc;
    147147        }
    148        
     148
    149149        /* Change current alternative */
    150150        usb_dev->alternate_interfaces.current = alternate_setting;
     
    296296        assert(usb_dev);
    297297        assert(usb_dev->pipes || usb_dev->pipes_count == 0);
    298        
     298
    299299        /* Destroy the pipes. */
    300300        for (size_t i = 0; i < usb_dev->pipes_count; ++i) {
     
    304304                        usb_pipe_unregister(&usb_dev->pipes[i].pipe);
    305305        }
    306        
     306
    307307        free(usb_dev->pipes);
    308308        usb_dev->pipes = NULL;
     
    332332        assert(usb_dev);
    333333        for (unsigned i = 0; i < usb_dev->pipes_count; ++i) {
    334                 if (usb_dev->pipes[i].pipe.endpoint_no == ep)
     334                if (usb_dev->pipes[i].pipe.desc.endpoint_no == ep)
    335335                        return &usb_dev->pipes[i];
    336336        }
     
    462462        assert(handle);
    463463        assert(iface_no);
    464        
     464
    465465        async_exch_t *exch = async_exchange_begin(sess);
    466466        if (!exch)
    467467                return EPARTY;
    468        
     468
    469469        int ret = usb_get_my_device_handle(exch, handle);
    470470        if (ret == EOK) {
     
    475475                }
    476476        }
    477        
     477
    478478        async_exchange_end(exch);
    479479        return ret;
     
    502502                return ENOMEM;
    503503        }
    504        
     504
    505505        return usb_device_init(usb_dev, ddf_dev, desc, err, h, iface_no);
    506506}
  • uspace/lib/usbdev/src/devpoll.c

    r367db39a re160bfe8  
    9696                    (int) mapping->interface->interface_subclass,
    9797                    (int) mapping->interface->interface_protocol,
    98                     data->request_size, pipe->max_packet_size);
     98                    data->request_size, pipe->desc.max_packet_size);
    9999        }
    100100
     
    128128                        usb_request_clear_endpoint_halt(
    129129                            usb_device_get_default_pipe(data->dev),
    130                             pipe->endpoint_no);
     130                            pipe->desc.endpoint_no);
    131131                }
    132132
     
    156156
    157157                /* Take a rest before next request. */
    158                
     158
    159159                // FIXME TODO: This is broken, the time is in ms not us.
    160160                // but first we need to fix drivers to actually stop using this,
     
    216216        if (request_size == 0)
    217217                return EINVAL;
    218        
    219         if (!epm || (epm->pipe.transfer_type != USB_TRANSFER_INTERRUPT) ||
    220             (epm->pipe.direction != USB_DIRECTION_IN))
     218
     219        if (!epm || (epm->pipe.desc.transfer_type != USB_TRANSFER_INTERRUPT) ||
     220            (epm->pipe.desc.direction != USB_DIRECTION_IN))
    221221                return EINVAL;
    222        
     222
    223223
    224224        polling_data_t *polling_data = malloc(sizeof(polling_data_t));
  • uspace/lib/usbdev/src/pipes.c

    r367db39a re160bfe8  
    5151        assert(pipe != NULL);
    5252
    53         if (!pipe->auto_reset_halt || (pipe->endpoint_no != 0)) {
     53        if (!pipe->auto_reset_halt || (pipe->desc.endpoint_no != 0)) {
    5454                return;
    5555        }
     
    8888        }
    8989
    90         if ((pipe->direction != USB_DIRECTION_BOTH)
    91             || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
     90        if ((pipe->desc.direction != USB_DIRECTION_BOTH)
     91            || (pipe->desc.transfer_type != USB_TRANSFER_CONTROL)) {
    9292                return EBADF;
    9393        }
     
    9898        async_exch_t *exch = async_exchange_begin(pipe->bus_session);
    9999        size_t act_size = 0;
    100         const int rc = usb_read(exch, pipe->endpoint_no, setup_packet, buffer,
     100        const int rc = usb_read(exch, pipe->desc.endpoint_no, setup_packet, buffer,
    101101            buffer_size, &act_size);
    102102        async_exchange_end(exch);
     
    142142        }
    143143
    144         if ((pipe->direction != USB_DIRECTION_BOTH)
    145             || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
     144        if ((pipe->desc.direction != USB_DIRECTION_BOTH)
     145            || (pipe->desc.transfer_type != USB_TRANSFER_CONTROL)) {
    146146                return EBADF;
    147147        }
     
    152152        async_exch_t *exch = async_exchange_begin(pipe->bus_session);
    153153        const int rc = usb_write(exch,
    154             pipe->endpoint_no, setup_packet, buffer, buffer_size);
     154            pipe->desc.endpoint_no, setup_packet, buffer, buffer_size);
    155155        async_exchange_end(exch);
    156156
     
    183183        }
    184184
    185         if (pipe->direction != USB_DIRECTION_IN) {
    186                 return EBADF;
    187         }
    188 
    189         if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
     185        if (pipe->desc.direction != USB_DIRECTION_IN) {
     186                return EBADF;
     187        }
     188
     189        if (pipe->desc.transfer_type == USB_TRANSFER_CONTROL) {
    190190                return EBADF;
    191191        }
    192192
    193193        /* Isochronous transfer are not supported (yet) */
    194         if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
    195             pipe->transfer_type != USB_TRANSFER_BULK)
     194        if (pipe->desc.transfer_type != USB_TRANSFER_INTERRUPT &&
     195            pipe->desc.transfer_type != USB_TRANSFER_BULK)
    196196            return ENOTSUP;
    197197
     
    199199        size_t act_size = 0;
    200200        const int rc =
    201             usb_read(exch, pipe->endpoint_no, 0, buffer, size, &act_size);
     201            usb_read(exch, pipe->desc.endpoint_no, 0, buffer, size, &act_size);
    202202        async_exchange_end(exch);
    203203
     
    224224        }
    225225
    226         if (pipe->direction != USB_DIRECTION_OUT) {
    227                 return EBADF;
    228         }
    229 
    230         if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
     226        if (pipe->desc.direction != USB_DIRECTION_OUT) {
     227                return EBADF;
     228        }
     229
     230        if (pipe->desc.transfer_type == USB_TRANSFER_CONTROL) {
    231231                return EBADF;
    232232        }
    233233
    234234        /* Isochronous transfer are not supported (yet) */
    235         if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
    236             pipe->transfer_type != USB_TRANSFER_BULK)
     235        if (pipe->desc.transfer_type != USB_TRANSFER_INTERRUPT &&
     236            pipe->desc.transfer_type != USB_TRANSFER_BULK)
    237237            return ENOTSUP;
    238238
    239239        async_exch_t *exch = async_exchange_begin(pipe->bus_session);
    240         const int rc = usb_write(exch, pipe->endpoint_no, 0, buffer, size);
     240        const int rc = usb_write(exch, pipe->desc.endpoint_no, 0, buffer, size);
    241241        async_exchange_end(exch);
    242242        return rc;
     
    258258        assert(pipe);
    259259
    260         pipe->endpoint_no = endpoint_no;
    261         pipe->transfer_type = transfer_type;
    262         pipe->packets = packets;
    263         pipe->max_packet_size = max_packet_size;
    264         pipe->direction = direction;
     260        pipe->desc.endpoint_no = endpoint_no;
     261        pipe->desc.transfer_type = transfer_type;
     262        pipe->desc.packets = packets;
     263        pipe->desc.max_packet_size = max_packet_size;
     264        pipe->desc.direction = direction;
    265265        pipe->auto_reset_halt = false;
    266266        pipe->bus_session = bus_session;
     
    297297        assert(pipe);
    298298        assert(pipe->bus_session);
     299
     300        pipe->desc.usb2.polling_interval = interval;
    299301        async_exch_t *exch = async_exchange_begin(pipe->bus_session);
    300302        if (!exch)
    301303                return ENOMEM;
    302         const int ret = usb_register_endpoint(exch, pipe->endpoint_no,
    303             pipe->transfer_type, pipe->direction, pipe->max_packet_size,
    304             pipe->packets, interval);
     304
     305        const int ret = usb_register_endpoint(exch, &pipe->desc);
     306
    305307        async_exchange_end(exch);
    306308        return ret;
     
    319321        if (!exch)
    320322                return ENOMEM;
    321         const int ret = usb_unregister_endpoint(exch, pipe->endpoint_no,
    322             pipe->direction);
     323
     324        const int ret = usb_unregister_endpoint(exch, &pipe->desc);
     325
    323326        async_exchange_end(exch);
    324327        return ret;
  • uspace/lib/usbdev/src/pipesinit.c

    r367db39a re160bfe8  
    288288        if (config_descriptor == NULL)
    289289                return EBADMEM;
    290        
     290
    291291        if (config_descriptor_size <
    292292            sizeof(usb_standard_configuration_descriptor_t)) {
     
    343343        static_assert(DEV_DESCR_MAX_PACKET_SIZE_OFFSET < CTRL_PIPE_MIN_PACKET_SIZE);
    344344
    345         if ((pipe->direction != USB_DIRECTION_BOTH) ||
    346             (pipe->transfer_type != USB_TRANSFER_CONTROL) ||
    347             (pipe->endpoint_no != 0)) {
     345        if ((pipe->desc.direction != USB_DIRECTION_BOTH) ||
     346            (pipe->desc.transfer_type != USB_TRANSFER_CONTROL) ||
     347            (pipe->desc.endpoint_no != 0)) {
    348348                return EINVAL;
    349349        }
     
    369369        }
    370370
    371         pipe->max_packet_size
     371        pipe->desc.max_packet_size
    372372            = dev_descr_start[DEV_DESCR_MAX_PACKET_SIZE_OFFSET];
    373373
  • uspace/lib/usbdev/src/request.c

    r367db39a re160bfe8  
    844844        }
    845845        return usb_request_clear_endpoint_halt(ctrl_pipe,
    846             target_pipe->endpoint_no);
     846            target_pipe->desc.endpoint_no);
    847847}
    848848
     
    858858{
    859859        uint16_t status_tmp;
    860         uint16_t pipe_index = (uint16_t) pipe->endpoint_no;
     860        uint16_t pipe_index = (uint16_t) pipe->desc.endpoint_no;
    861861        int rc = usb_request_get_status(ctrl_pipe,
    862862            USB_REQUEST_RECIPIENT_ENDPOINT, uint16_host2usb(pipe_index),
  • uspace/lib/usbhost/Makefile

    r367db39a re160bfe8  
    3939        src/endpoint.c \
    4040        src/hcd.c \
    41         src/usb_bus.c \
     41        src/bus.c \
     42        src/usb2_bus.c \
     43        src/bandwidth.c \
    4244        src/usb_transfer_batch.c
    4345
  • uspace/lib/usbhost/include/usb/host/ddf_helpers.h

    r367db39a re160bfe8  
    3838
    3939#include <usb/host/hcd.h>
    40 #include <usb/host/usb_bus.h>
     40#include <usb/host/bus.h>
    4141#include <usb/usb.h>
    4242
     
    4545#include <device/hw_res_parsed.h>
    4646
    47 typedef int (*driver_init_t)(hcd_t *, const hw_res_list_parsed_t *, bool);
     47typedef int (*driver_init_t)(hcd_t *, const hw_res_list_parsed_t *, ddf_dev_t *);
     48typedef int (*irq_code_gen_t)(irq_code_t *, hcd_t *, const hw_res_list_parsed_t *);
     49typedef int (*claim_t)(hcd_t *, ddf_dev_t *);
     50typedef int (*driver_start_t)(hcd_t *, bool irq);
     51typedef int (*setup_root_hub_t)(hcd_t *, ddf_dev_t *);
     52
     53typedef void (*driver_stop_t)(hcd_t *);
    4854typedef void (*driver_fini_t)(hcd_t *);
    49 typedef int (*claim_t)(ddf_dev_t *);
    50 typedef int (*irq_code_gen_t)(irq_code_t *, const hw_res_list_parsed_t *);
    5155
     56/**
     57 * All callbacks are optional.
     58 */
    5259typedef struct {
    5360        hcd_ops_t ops;
    54         claim_t claim;
    55         usb_speed_t hc_speed;
    56         driver_init_t init;
    57         driver_fini_t fini;
    58         interrupt_handler_t *irq_handler;
    59         irq_code_gen_t irq_code_gen;
    6061        const char *name;
     62
     63        interrupt_handler_t *irq_handler;  /**< Handler of IRQ. Do have generic implementation. */
     64
     65        /* Initialization sequence: */
     66        driver_init_t init;                /**< Initialize internal structures, memory */
     67        claim_t claim;                     /**< Claim device from BIOS */
     68        irq_code_gen_t irq_code_gen;       /**< Generate IRQ handling code */
     69        driver_start_t start;              /**< Start the HC */
     70        setup_root_hub_t setup_root_hub;   /**< Setup the root hub */
     71
     72        /* Destruction sequence: */
     73        driver_stop_t stop;                /**< Stop the HC (counterpart of start) */
     74        driver_fini_t fini;                /**< Destroy internal structures (counterpart of init) */
    6175} ddf_hc_driver_t;
    6276
    6377int hcd_ddf_add_hc(ddf_dev_t *device, const ddf_hc_driver_t *driver);
    6478
    65 int hcd_ddf_setup_hc(ddf_dev_t *device, usb_speed_t max_speed,
    66     size_t bw, bw_count_func_t bw_count);
     79int hcd_ddf_setup_hc(ddf_dev_t *device);
    6780void hcd_ddf_clean_hc(ddf_dev_t *device);
    68 int hcd_ddf_setup_root_hub(ddf_dev_t *device);
     81
     82int hcd_setup_virtual_root_hub(hcd_t *, ddf_dev_t *);
     83
     84device_t *hcd_ddf_device_create(ddf_dev_t *, size_t);
     85void hcd_ddf_device_destroy(device_t *);
     86int hcd_ddf_device_explore(hcd_t *, device_t *);
    6987
    7088hcd_t *dev_to_hcd(ddf_dev_t *dev);
     
    7593    const hw_res_list_parsed_t *hw_res,
    7694    interrupt_handler_t handler,
    77     int (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *));
     95    irq_code_gen_t gen_irq_code);
    7896void ddf_hcd_gen_irq_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev);
    7997
  • uspace/lib/usbhost/include/usb/host/endpoint.h

    r367db39a re160bfe8  
    3232/** @file
    3333 *
     34 * Endpoint structure is tightly coupled to the bus. The bus controls the
     35 * life-cycle of endpoint. In order to keep endpoints lightweight, operations
     36 * on endpoints are part of the bus structure.
     37 *
    3438 */
    3539#ifndef LIBUSBHOST_HOST_ENDPOINT_H
     
    4246#include <atomic.h>
    4347
     48typedef struct bus bus_t;
     49typedef struct device device_t;
     50typedef struct usb_transfer_batch usb_transfer_batch_t;
     51
    4452/** Host controller side endpoint structure. */
    4553typedef struct endpoint {
     54        /** Managing bus */
     55        bus_t *bus;
    4656        /** Reference count. */
    47         atomic_t refcnt;       
     57        atomic_t refcnt;
    4858        /** Part of linked list. */
    4959        link_t link;
     60        /** USB device */
     61        device_t *device;
    5062        /** USB address. */
    51         usb_address_t address;
    52         /** USB endpoint number. */
    53         usb_endpoint_t endpoint;
     63        usb_target_t target;
    5464        /** Communication direction. */
    5565        usb_direction_t direction;
     
    6272        /** Additional opportunities per uframe */
    6373        unsigned packets;
    64         /** Necessary bandwidth. */
     74        /** Reserved bandwidth. */
    6575        size_t bandwidth;
    6676        /** Value of the toggle bit. */
    6777        unsigned toggle:1;
    6878        /** True if there is a batch using this scheduled for this endpoint. */
    69         volatile bool active;
     79        bool active;
    7080        /** Protects resources and active status changes. */
    7181        fibril_mutex_t guard;
    7282        /** Signals change of active status. */
    7383        fibril_condvar_t avail;
    74         /** High speed TT data */
    75         struct {
    76                 usb_address_t address;
    77                 unsigned port;
    78         } tt;
    79         /** Optional device specific data. */
    80         struct {
    81                 /** Device specific data. */
    82                 void *data;
    83                 /** Callback to get the value of toggle bit. */
    84                 int (*toggle_get)(void *);
    85                 /** Callback to set the value of toggle bit. */
    86                 void (*toggle_set)(void *, int);
    87         } hc_data;
     84
     85        /* This structure is meant to be extended by overriding. */
    8886} endpoint_t;
    8987
    90 extern endpoint_t *endpoint_create(usb_address_t, usb_endpoint_t,
    91     usb_direction_t, usb_transfer_type_t, usb_speed_t, size_t, unsigned int,
    92     size_t, usb_address_t, unsigned int);
    93 extern void endpoint_destroy(endpoint_t *);
     88extern void endpoint_init(endpoint_t *, bus_t *);
    9489
    9590extern void endpoint_add_ref(endpoint_t *);
    9691extern void endpoint_del_ref(endpoint_t *);
    97 
    98 extern void endpoint_set_hc_data(endpoint_t *, void *, int (*)(void *),
    99     void (*)(void *, int));
    100 extern void endpoint_clear_hc_data(endpoint_t *);
    10192
    10293extern void endpoint_use(endpoint_t *);
     
    10495
    10596extern int endpoint_toggle_get(endpoint_t *);
    106 extern void endpoint_toggle_set(endpoint_t *, int);
     97extern void endpoint_toggle_set(endpoint_t *, unsigned);
    10798
    10899/** list_get_instance wrapper.
  • uspace/lib/usbhost/include/usb/host/hcd.h

    r367db39a re160bfe8  
    3838
    3939#include <usb/host/endpoint.h>
    40 #include <usb/host/usb_bus.h>
     40#include <usb/host/bus.h>
    4141#include <usb/host/usb_transfer_batch.h>
    4242#include <usb/usb.h>
     
    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 {
    5857        /** Transfer scheduling, implement in device driver. */
    5958        schedule_hook_t schedule;
    60         /** Hook called upon registering new endpoint. */
    61         ep_add_hook_t ep_add_hook;
    62         /** Hook called upon removing of an endpoint. */
    63         ep_remove_hook_t ep_remove_hook;
    6459        /** Hook to be called on device interrupt, passes ARG1 */
    6560        interrupt_hook_t irq_hook;
    6661        /** Periodic polling hook */
    6762        status_hook_t status_hook;
     63        /** Hook to setup device address */
     64        address_device_hook_t address_device;
    6865} hcd_ops_t;
    6966
     
    7168struct hcd {
    7269        /** Endpoint manager. */
    73         usb_bus_t bus;
     70        bus_t *bus;
    7471
    7572        /** Interrupt replacement fibril */
     
    7875        /** Driver implementation */
    7976        hcd_ops_t ops;
     77
    8078        /** Device specific driver data. */
    8179        void * driver_data;
    8280};
    8381
    84 extern void hcd_init(hcd_t *, usb_speed_t, size_t, bw_count_func_t);
     82extern void hcd_init(hcd_t *);
    8583
    8684static inline void hcd_set_implementation(hcd_t *hcd, void *data,
    87     const hcd_ops_t *ops)
     85    const hcd_ops_t *ops, bus_t *bus)
    8886{
    8987        assert(hcd);
     
    9189                hcd->driver_data = data;
    9290                hcd->ops = *ops;
     91                hcd->bus = bus;
    9392        } else {
    9493                memset(&hcd->ops, 0, sizeof(hcd->ops));
     
    104103extern usb_address_t hcd_request_address(hcd_t *, usb_speed_t);
    105104
    106 extern int hcd_release_address(hcd_t *, usb_address_t);
    107 
    108 extern int hcd_reserve_default_address(hcd_t *, usb_speed_t);
    109 
    110 static inline int hcd_release_default_address(hcd_t *hcd)
    111 {
    112         return hcd_release_address(hcd, USB_ADDRESS_DEFAULT);
    113 }
    114 
    115105extern int hcd_add_ep(hcd_t *, usb_target_t, usb_direction_t,
    116     usb_transfer_type_t, size_t, unsigned int, size_t, usb_address_t,
    117     unsigned int);
     106    usb_transfer_type_t, size_t, unsigned int, size_t, usb_tt_address_t);
    118107
    119108extern int hcd_remove_ep(hcd_t *, usb_target_t, usb_direction_t);
  • uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h

    r367db39a re160bfe8  
    3737#define LIBUSBHOST_HOST_USB_TRANSFER_BATCH_H
    3838
    39 #include <usb/host/endpoint.h>
    4039#include <usb/usb.h>
     40#include <usb/request.h>
    4141
    42 #include <assert.h>
    4342#include <stddef.h>
    4443#include <stdint.h>
     
    4746#define USB_SETUP_PACKET_SIZE 8
    4847
     48typedef struct endpoint endpoint_t;
     49typedef struct bus bus_t;
     50typedef struct usb_transfer_batch usb_transfer_batch_t;
     51
     52/** Callback to be called on transfer. */
     53typedef int (*usb_transfer_batch_callback_t)(usb_transfer_batch_t *);
     54
    4955/** Structure stores additional data needed for communication with EP */
    5056typedef struct usb_transfer_batch {
    5157        /** Endpoint used for communication */
    5258        endpoint_t *ep;
    53         /** Function called on completion (IN version) */
    54         usbhc_iface_transfer_in_callback_t callback_in;
    55         /** Function called on completion (OUT version) */
    56         usbhc_iface_transfer_out_callback_t callback_out;
    57         /** Argument to pass to the completion function */
    58         void *arg;
     59        /** Size reported to be sent */
     60        size_t expected_size;
     61
     62        /** Direction of the transfer */
     63        usb_direction_t dir;
     64
     65        /** Function called on completion */
     66        usb_transfer_batch_callback_t on_complete;
     67        /** Arbitrary data for the handler */
     68        void *on_complete_data;
     69
     70        /** Place to store SETUP data needed by control transfers */
     71        union {
     72                char buffer [USB_SETUP_PACKET_SIZE];
     73                usb_device_request_setup_packet_t packet;
     74                uint64_t packed;
     75        } setup;
     76
     77        /** Resetting the Toggle */
     78        toggle_reset_mode_t toggle_reset_mode;
     79
    5980        /** Place for data to send/receive */
    6081        char *buffer;
    6182        /** Size of memory pointed to by buffer member */
    6283        size_t buffer_size;
    63         /** Place to store SETUP data needed by control transfers */
    64         char setup_buffer[USB_SETUP_PACKET_SIZE];
    65         /** Used portion of setup_buffer member
    66          *
    67          * SETUP buffer must be 8 bytes for control transfers and is left
    68          * unused for all other transfers. Thus, this field is either 0 or 8.
    69          */
    70         size_t setup_size;
    7184
    72         /** Actually used portion of the buffer
    73          * This member is never accessed by functions provided in this header,
    74          * with the exception of usb_transfer_batch_finish. For external use.
    75          */
     85        /** Actually used portion of the buffer */
    7686        size_t transfered_size;
    77         /** Indicates success/failure of the communication
    78          * This member is never accessed by functions provided in this header,
    79          * with the exception of usb_transfer_batch_finish. For external use.
    80          */
     87        /** Indicates success/failure of the communication */
    8188        int error;
    8289} usb_transfer_batch_t;
     
    8996 */
    9097#define USB_TRANSFER_BATCH_ARGS(batch) \
    91         (batch).ep->address, (batch).ep->endpoint, \
     98        (batch).ep->target.address, (batch).ep->target.endpoint, \
    9299        usb_str_speed((batch).ep->speed), \
    93100        usb_str_transfer_type_short((batch).ep->transfer_type), \
     
    95102        (batch).buffer_size, (batch).ep->max_packet_size
    96103
     104void usb_transfer_batch_init(usb_transfer_batch_t *, endpoint_t *);
     105void usb_transfer_batch_finish(usb_transfer_batch_t *);
    97106
    98 usb_transfer_batch_t * usb_transfer_batch_create(
    99     endpoint_t *ep,
    100     char *buffer,
    101     size_t buffer_size,
    102     uint64_t setup_buffer,
    103     usbhc_iface_transfer_in_callback_t func_in,
    104     usbhc_iface_transfer_out_callback_t func_out,
    105     void *arg
    106 );
    107 void usb_transfer_batch_destroy(const usb_transfer_batch_t *instance);
     107usb_transfer_batch_t *usb_transfer_batch_create(endpoint_t *);
     108void usb_transfer_batch_destroy(usb_transfer_batch_t *);
    108109
    109 void usb_transfer_batch_finish_error(const usb_transfer_batch_t *instance,
    110     const void* data, size_t size, int error);
    111 
    112 /** Finish batch using stored error value and transferred size.
    113  *
    114  * @param[in] instance Batch structure to use.
    115  * @param[in] data Data to copy to the output buffer.
     110/** Provided to ease the transition. Wraps old-style handlers into a new one.
    116111 */
    117 static inline void usb_transfer_batch_finish(
    118     const usb_transfer_batch_t *instance, const void* data)
    119 {
    120         assert(instance);
    121         usb_transfer_batch_finish_error(
    122             instance, data, instance->transfered_size, instance->error);
    123 }
    124 
    125 /** Determine batch direction based on the callbacks present
    126  * @param[in] instance Batch structure to use, non-null.
    127  * @return USB_DIRECTION_IN, or USB_DIRECTION_OUT.
    128  */
    129 static inline usb_direction_t usb_transfer_batch_direction(
    130     const usb_transfer_batch_t *instance)
    131 {
    132         assert(instance);
    133         if (instance->callback_in) {
    134                 assert(instance->callback_out == NULL);
    135                 assert(instance->ep == NULL
    136                     || instance->ep->transfer_type == USB_TRANSFER_CONTROL
    137                     || instance->ep->direction == USB_DIRECTION_IN);
    138                 return USB_DIRECTION_IN;
    139         }
    140         if (instance->callback_out) {
    141                 assert(instance->callback_in == NULL);
    142                 assert(instance->ep == NULL
    143                     || instance->ep->transfer_type == USB_TRANSFER_CONTROL
    144                     || instance->ep->direction == USB_DIRECTION_OUT);
    145                 return USB_DIRECTION_OUT;
    146         }
    147         assert(false);
    148 }
     112extern void usb_transfer_batch_set_old_handlers(usb_transfer_batch_t *,
     113        usbhc_iface_transfer_in_callback_t,
     114        usbhc_iface_transfer_out_callback_t, void *);
    149115
    150116#endif
  • uspace/lib/usbhost/src/ddf_helpers.c

    r367db39a re160bfe8  
    3535
    3636#include <usb/classes/classes.h>
     37#include <usb/host/bus.h>
    3738#include <usb/debug.h>
    3839#include <usb/descriptor.h>
     
    4950#include <fibril_synch.h>
    5051#include <macros.h>
    51 #include <stdio.h>
    5252#include <stdlib.h>
    5353#include <str_error.h>
     
    5656#include "ddf_helpers.h"
    5757
    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 
    7158typedef struct hc_dev {
    7259        ddf_fun_t *ctl_fun;
    7360        hcd_t hcd;
    74         usb_dev_t *root_hub;
    7561} hc_dev_t;
    7662
     
    9177
    9278
    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);
     79static int hcd_ddf_new_device(hcd_t *hcd, ddf_dev_t *hc, device_t *hub_dev, unsigned port);
     80static int hcd_ddf_remove_device(ddf_dev_t *device, device_t *hub, unsigned port);
    9581
    9682
     
    9985/** Register endpoint interface function.
    10086 * @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.
     87 * @param endpoint_desc Endpoint description.
    10788 * @return Error code.
    10889 */
    10990static 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)
     91        ddf_fun_t *fun, usb_endpoint_desc_t *endpoint_desc)
    11392{
    11493        assert(fun);
    11594        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    116         usb_dev_t *dev = ddf_fun_data_get(fun);
     95        device_t *dev = ddf_fun_data_get(fun);
    11796        assert(hcd);
     97        assert(hcd->bus);
    11898        assert(dev);
    119         const size_t size = max_packet_size;
    120         const usb_target_t target =
    121             {{.address = dev->address, .endpoint = endpoint}};
     99
     100        const size_t size = endpoint_desc->max_packet_size;
    122101
    123102        usb_log_debug("Register endpoint %d:%d %s-%s %zuB %ums.\n",
    124             dev->address, endpoint, usb_str_transfer_type(transfer_type),
    125             usb_str_direction(direction), max_packet_size, interval);
    126 
    127         return hcd_add_ep(hcd, target, direction, transfer_type,
    128             max_packet_size, packets, size, dev->tt_address, dev->port);
    129 }
    130 
    131 /** Unregister endpoint interface function.
    132  * @param fun DDF function.
    133  * @param address USB address of the endpoint.
    134  * @param endpoint USB endpoint number.
    135  * @param direction Communication direction of the enpdoint to unregister.
    136  * @return Error code.
    137  */
     103                dev->address, endpoint_desc->endpoint_no,
     104                usb_str_transfer_type(endpoint_desc->transfer_type),
     105                usb_str_direction(endpoint_desc->direction),
     106                endpoint_desc->max_packet_size, endpoint_desc->usb2.polling_interval);
     107
     108        return bus_add_ep(hcd->bus, dev, endpoint_desc->endpoint_no,
     109                endpoint_desc->direction, endpoint_desc->transfer_type,
     110                endpoint_desc->max_packet_size, endpoint_desc->packets,
     111                size);
     112}
     113
     114 /** Unregister endpoint interface function.
     115  * @param fun DDF function.
     116  * @param endpoint_desc Endpoint description.
     117  * @return Error code.
     118  */
    138119static int unregister_endpoint(
    139     ddf_fun_t *fun, usb_endpoint_t endpoint, usb_direction_t direction)
     120        ddf_fun_t *fun, usb_endpoint_desc_t *endpoint_desc)
    140121{
    141122        assert(fun);
    142123        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    143         usb_dev_t *dev = ddf_fun_data_get(fun);
     124        device_t *dev = ddf_fun_data_get(fun);
    144125        assert(hcd);
     126        assert(hcd->bus);
    145127        assert(dev);
    146         const usb_target_t target =
    147             {{.address = dev->address, .endpoint = endpoint}};
     128
     129        const usb_target_t target = {{
     130                .address = dev->address,
     131                .endpoint = endpoint_desc->endpoint_no
     132        }};
     133
    148134        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);
     135                dev->address, endpoint_desc->endpoint_no,
     136                usb_str_direction(endpoint_desc->direction));
     137        return bus_remove_ep(hcd->bus, target, endpoint_desc->direction);
    151138}
    152139
     
    155142        assert(fun);
    156143        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    157         usb_dev_t *dev = ddf_fun_data_get(fun);
     144        device_t *dev = ddf_fun_data_get(fun);
    158145        assert(hcd);
     146        assert(hcd->bus);
    159147        assert(dev);
    160148
    161149        usb_log_debug("Device %d requested default address at %s speed\n",
    162150            dev->address, usb_str_speed(speed));
    163         return hcd_reserve_default_address(hcd, speed);
     151        return bus_reserve_default_address(hcd->bus, speed);
    164152}
    165153
     
    168156        assert(fun);
    169157        hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    170         usb_dev_t *dev = ddf_fun_data_get(fun);
     158        device_t *dev = ddf_fun_data_get(fun);
    171159        assert(hcd);
     160        assert(hcd->bus);
    172161        assert(dev);
    173162
    174163        usb_log_debug("Device %d released default address\n", dev->address);
    175         return hcd_release_default_address(hcd);
     164        return bus_release_default_address(hcd->bus);
    176165}
    177166
    178167static int device_enumerate(ddf_fun_t *fun, unsigned port)
     168{
     169        assert(fun);
     170        ddf_dev_t *hc = ddf_fun_get_dev(fun);
     171        assert(hc);
     172        hcd_t *hcd = dev_to_hcd(hc);
     173        assert(hcd);
     174        device_t *hub = ddf_fun_data_get(fun);
     175        assert(hub);
     176
     177        usb_log_debug("Hub %d reported a new USB device on port: %u\n",
     178            hub->address, port);
     179        return hcd_ddf_new_device(hcd, hc, hub, port);
     180}
     181
     182static int device_remove(ddf_fun_t *fun, unsigned port)
    179183{
    180184        assert(fun);
    181185        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);
     186        device_t *dev = ddf_fun_data_get(fun);
    195187        assert(ddf_dev);
    196188        assert(dev);
     
    229221{
    230222        assert(fun);
    231         usb_dev_t *usb_dev = ddf_fun_data_get(fun);
    232         assert(usb_dev);
     223        device_t *dev = ddf_fun_data_get(fun);
     224        assert(dev);
    233225        const usb_target_t target = {{
    234             .address =  usb_dev->address,
     226            .address  = dev->address,
    235227            .endpoint = endpoint,
    236228        }};
     
    255247{
    256248        assert(fun);
    257         usb_dev_t *usb_dev = ddf_fun_data_get(fun);
    258         assert(usb_dev);
     249        device_t *dev = ddf_fun_data_get(fun);
     250        assert(dev);
    259251        const usb_target_t target = {{
    260             .address =  usb_dev->address,
     252            .address  = dev->address,
    261253            .endpoint = endpoint,
    262254        }};
     
    290282
    291283/* 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 }
    370284
    371285#define ADD_MATCHID_OR_RETURN(list, sc, str, ...) \
     
    394308        assert(l);
    395309        assert(d);
    396        
     310
    397311        if (d->vendor_id != 0) {
    398312                /* First, with release number. */
     
    401315                    d->vendor_id, d->product_id, (d->device_version >> 8),
    402316                    (d->device_version & 0xff));
    403        
     317
    404318                /* Next, without release number. */
    405319                ADD_MATCHID_OR_RETURN(l, 90, "usb&vendor=%#04x&product=%#04x",
     
    415329
    416330        return EOK;
    417 
    418 }
    419 
    420 static int hcd_ddf_remove_device(ddf_dev_t *device, usb_dev_t *hub,
     331}
     332
     333static int hcd_ddf_remove_device(ddf_dev_t *device, device_t *hub,
    421334    unsigned port)
    422335{
     
    425338        hcd_t *hcd = dev_to_hcd(device);
    426339        assert(hcd);
     340        assert(hcd->bus);
    427341
    428342        hc_dev_t *hc_dev = dev_to_hc_dev(device);
     
    431345        fibril_mutex_lock(&hub->guard);
    432346
    433         usb_dev_t *victim = NULL;
    434 
    435         list_foreach(hub->devices, link, usb_dev_t, it) {
     347        device_t *victim = NULL;
     348
     349        list_foreach(hub->devices, link, device_t, it) {
    436350                if (it->port == port) {
    437351                        victim = it;
     
    440354        }
    441355        if (victim) {
     356                assert(victim->fun);
    442357                assert(victim->port == port);
     358                assert(victim->hub == hub);
    443359                list_remove(&victim->link);
    444360                fibril_mutex_unlock(&hub->guard);
     
    446362                if (ret == EOK) {
    447363                        usb_address_t address = victim->address;
     364                        bus_remove_device(hcd->bus, hcd, victim);
    448365                        ddf_fun_destroy(victim->fun);
    449                         hcd_release_address(hcd, address);
     366                        bus_release_address(hcd->bus, address);
    450367                } else {
    451368                        usb_log_warning("Failed to unbind device `%s': %s\n",
     
    458375}
    459376
    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,
     377device_t *hcd_ddf_device_create(ddf_dev_t *hc, size_t device_size)
     378{
     379        /* Create DDF function for the new device */
     380        ddf_fun_t *fun = ddf_fun_create(hc, fun_inner, NULL);
     381        if (!fun)
     382                return NULL;
     383
     384        ddf_fun_set_ops(fun, &usb_ops);
     385
     386        /* Create USB device node for the new device */
     387        device_t *dev = ddf_fun_data_alloc(fun, device_size);
     388        if (!dev) {
     389                ddf_fun_destroy(fun);
     390                return NULL;
     391        }
     392
     393        device_init(dev);
     394        dev->fun = fun;
     395        return dev;
     396}
     397
     398void hcd_ddf_device_destroy(device_t *dev)
     399{
     400        assert(dev);
     401        assert(dev->fun);
     402        ddf_fun_destroy(dev->fun);
     403}
     404
     405int hcd_ddf_device_explore(hcd_t *hcd, device_t *device)
     406{
     407        int err;
     408        match_id_list_t mids;
     409        usb_standard_device_descriptor_t desc = { 0 };
     410
     411        init_match_ids(&mids);
     412
     413        usb_target_t control_ep = {{
     414                .address = device->address,
     415                .endpoint = 0
    481416        }};
    482 
    483         const usb_address_t address = hcd_request_address(hcd, speed);
    484         if (address < 0) {
    485                 usb_log_error("Failed to reserve new address: %s.",
    486                     str_error(address));
    487                 return address;
    488         }
    489 
    490         usb_log_debug("Reserved new address: %d\n", address);
    491 
    492         const usb_target_t target = {{
    493                 .address = address,
    494                 .endpoint = 0,
    495         }};
    496 
    497         const usb_address_t tt_address = hub ? hub->tt_address : -1;
    498 
    499         /* Add default pipe on default address */
    500         usb_log_debug("Device(%d): Adding default target(0:0)\n", address);
    501         ret = hcd_add_ep(hcd,
    502             default_target, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL,
    503             CTRL_PIPE_MIN_PACKET_SIZE, CTRL_PIPE_MIN_PACKET_SIZE, 1,
    504             tt_address, port);
    505         if (ret != EOK) {
    506                 usb_log_error("Device(%d): Failed to add default target: %s.",
    507                     address, str_error(ret));
    508                 hcd_release_address(hcd, address);
    509                 return ret;
    510         }
    511 
    512         /* Get max packet size for default pipe */
    513         usb_standard_device_descriptor_t desc = { 0 };
    514         const usb_device_request_setup_packet_t get_device_desc_8 =
    515             GET_DEVICE_DESC(CTRL_PIPE_MIN_PACKET_SIZE);
    516 
    517         // TODO CALLBACKS
    518         usb_log_debug("Device(%d): Requesting first 8B of device descriptor.",
    519             address);
    520         ssize_t got = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_IN,
    521             &desc, CTRL_PIPE_MIN_PACKET_SIZE, *(uint64_t *)&get_device_desc_8,
    522             "read first 8 bytes of dev descriptor");
    523 
    524         if (got != CTRL_PIPE_MIN_PACKET_SIZE) {
    525                 ret = got < 0 ? got : EOVERFLOW;
    526                 usb_log_error("Device(%d): Failed to get 8B of dev descr: %s.",
    527                     address, str_error(ret));
    528                 hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH);
    529                 hcd_release_address(hcd, address);
    530                 return ret;
    531         }
    532 
    533         /* Register EP on the new address */
    534         usb_log_debug("Device(%d): Registering control EP.", address);
    535         ret = hcd_add_ep(hcd, target, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL,
    536             ED_MPS_PACKET_SIZE_GET(uint16_usb2host(desc.max_packet_size)),
    537             ED_MPS_TRANS_OPPORTUNITIES_GET(uint16_usb2host(desc.max_packet_size)),
    538             ED_MPS_PACKET_SIZE_GET(uint16_usb2host(desc.max_packet_size)),
    539             tt_address, port);
    540         if (ret != EOK) {
    541                 usb_log_error("Device(%d): Failed to register EP0: %s",
    542                     address, str_error(ret));
    543                 hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH);
    544                 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
    545                 hcd_release_address(hcd, address);
    546                 return ret;
    547         }
    548 
    549         /* Set new address */
    550         const usb_device_request_setup_packet_t set_address =
    551             SET_ADDRESS(target.address);
    552 
    553         usb_log_debug("Device(%d): Setting USB address.", address);
    554         got = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_OUT,
    555             NULL, 0, *(uint64_t *)&set_address, "set address");
    556 
    557         usb_log_debug("Device(%d): Removing default (0:0) EP.", address);
    558         hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH);
    559 
    560         if (got != 0) {
    561                 usb_log_error("Device(%d): Failed to set new address: %s.",
    562                     address, str_error(got));
    563                 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
    564                 hcd_release_address(hcd, address);
    565                 return got;
    566         }
    567417
    568418        /* Get std device descriptor */
     
    571421
    572422        usb_log_debug("Device(%d): Requesting full device descriptor.",
    573             address);
    574         got = hcd_send_batch_sync(hcd, target, USB_DIRECTION_IN,
     423            device->address);
     424        ssize_t got = hcd_send_batch_sync(hcd, control_ep, USB_DIRECTION_IN,
    575425            &desc, sizeof(desc), *(uint64_t *)&get_device_desc,
    576426            "read device descriptor");
    577         if (ret != EOK) {
     427        if (got < 0) {
     428                err = got < 0 ? got : EOVERFLOW;
    578429                usb_log_error("Device(%d): Failed to set get dev descriptor: %s",
    579                     address, str_error(ret));
    580                 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
    581                 hcd_release_address(hcd, target.address);
    582                 return ret;
     430                    device->address, str_error(err));
     431                goto out;
    583432        }
    584433
    585434        /* Create match ids from the device descriptor */
    586         match_id_list_t mids;
    587         init_match_ids(&mids);
    588 
    589         usb_log_debug("Device(%d): Creating match IDs.", address);
    590         ret = create_match_ids(&mids, &desc);
    591         if (ret != EOK) {
    592                 usb_log_error("Device(%d): Failed to create match ids: %s",
    593                     address, str_error(ret));
    594                 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
    595                 hcd_release_address(hcd, target.address);
    596                 return ret;
    597         }
    598 
    599         /* Register device */
    600         usb_log_debug("Device(%d): Registering DDF device.", address);
    601         ret = hcd_ddf_add_device(device, hub, port, address, speed, NULL, &mids);
     435        usb_log_debug("Device(%d): Creating match IDs.", device->address);
     436        if ((err = create_match_ids(&mids, &desc))) {
     437                usb_log_error("Device(%d): Failed to create match ids: %s", device->address, str_error(err));
     438                goto out;
     439        }
     440
     441        list_foreach(mids.ids, link, const match_id_t, mid) {
     442                ddf_fun_add_match_id(device->fun, mid->id, mid->score);
     443        }
     444
     445out:
    602446        clean_match_ids(&mids);
    603         if (ret != EOK) {
    604                 usb_log_error("Device(%d): Failed to register: %s.",
    605                     address, str_error(ret));
    606                 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
    607                 hcd_release_address(hcd, target.address);
    608         }
    609 
    610         return ret;
     447        return err;
     448}
     449
     450static int hcd_ddf_new_device(hcd_t *hcd, ddf_dev_t *hc, device_t *hub, unsigned port)
     451{
     452        int err;
     453        assert(hcd);
     454        assert(hcd->bus);
     455        assert(hub);
     456        assert(hc);
     457
     458        device_t *dev = hcd_ddf_device_create(hc, hcd->bus->device_size);
     459        if (!dev) {
     460                usb_log_error("Failed to create USB device function.");
     461                return ENOMEM;
     462        }
     463
     464        dev->hub = hub;
     465        dev->port = port;
     466
     467        if ((err = bus_enumerate_device(hcd->bus, hcd, dev))) {
     468                usb_log_error("Failed to initialize USB dev memory structures.");
     469                return err;
     470        }
     471
     472        /* If the driver didn't name the dev when enumerating,
     473         * do it in some generic way.
     474         */
     475        if (!ddf_fun_get_name(dev->fun)) {
     476                device_set_default_name(dev);
     477        }
     478
     479        if ((err = ddf_fun_bind(dev->fun))) {
     480                usb_log_error("Device(%d): Failed to register: %s.", dev->address, str_error(err));
     481                goto err_usb_dev;
     482        }
     483
     484        fibril_mutex_lock(&hub->guard);
     485        list_append(&dev->link, &hub->devices);
     486        fibril_mutex_unlock(&hub->guard);
     487
     488        return EOK;
     489
     490err_usb_dev:
     491        hcd_ddf_device_destroy(dev);
     492        return err;
    611493}
    612494
     
    616498 * @return Error code
    617499 */
    618 int hcd_ddf_setup_root_hub(ddf_dev_t *device)
    619 {
    620         assert(device);
    621         hcd_t *hcd = dev_to_hcd(device);
     500int hcd_setup_virtual_root_hub(hcd_t *hcd, ddf_dev_t *hc)
     501{
     502        int err;
     503
     504        assert(hc);
    622505        assert(hcd);
    623 
    624         hcd_reserve_default_address(hcd, hcd->bus.max_speed);
    625         const int ret = hcd_ddf_new_device(device, NULL, 0);
    626         hcd_release_default_address(hcd);
    627         return ret;
     506        assert(hcd->bus);
     507
     508        if ((err = bus_reserve_default_address(hcd->bus, USB_SPEED_MAX))) {
     509                usb_log_error("Failed to reserve default address for roothub setup: %s", str_error(err));
     510                return err;
     511        }
     512
     513        device_t *dev = hcd_ddf_device_create(hc, USB_SPEED_MAX);
     514        if (!dev) {
     515                usb_log_error("Failed to create function for the root hub.");
     516                goto err_default_address;
     517        }
     518
     519        ddf_fun_set_name(dev->fun, "roothub");
     520
     521        dev->tt = (usb_tt_address_t) {
     522                .address = -1,
     523                .port = 0,
     524        };
     525
     526        /* Assign an address to the device */
     527        if ((err = bus_enumerate_device(hcd->bus, hcd, dev))) {
     528                usb_log_error("Failed to enumerate roothub device: %s", str_error(err));
     529                goto err_usb_dev;
     530        }
     531
     532        if ((err = ddf_fun_bind(dev->fun))) {
     533                usb_log_error("Failed to register roothub: %s.", str_error(err));
     534                goto err_usb_dev;
     535        }
     536
     537        bus_release_default_address(hcd->bus);
     538        return EOK;
     539
     540err_usb_dev:
     541        hcd_ddf_device_destroy(dev);
     542err_default_address:
     543        bus_release_default_address(hcd->bus);
     544        return err;
    628545}
    629546
     
    638555 * This function does all the ddf work for hc driver.
    639556 */
    640 int hcd_ddf_setup_hc(ddf_dev_t *device, usb_speed_t max_speed,
    641     size_t bw, bw_count_func_t bw_count)
     557int hcd_ddf_setup_hc(ddf_dev_t *device)
    642558{
    643559        assert(device);
     
    648564                return ENOMEM;
    649565        }
    650         instance->root_hub = NULL;
    651         hcd_init(&instance->hcd, max_speed, bw, bw_count);
     566        hcd_init(&instance->hcd);
    652567
    653568        int ret = ENOMEM;
     
    748663    const hw_res_list_parsed_t *hw_res,
    749664    interrupt_handler_t handler,
    750     int (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *hw_res))
    751 {
    752 
     665    irq_code_gen_t gen_irq_code)
     666{
    753667        assert(device);
     668
     669        hcd_t *hcd = dev_to_hcd(device);
     670
    754671        if (!handler || !gen_irq_code)
    755672                return ENOTSUP;
     
    757674        irq_code_t irq_code = {0};
    758675
    759         const int irq = gen_irq_code(&irq_code, hw_res);
     676        const int irq = gen_irq_code(&irq_code, hcd, hw_res);
    760677        if (irq < 0) {
    761678                usb_log_error("Failed to generate IRQ code: %s.\n",
     
    777694        int ret = hcd_ddf_enable_interrupt(device, irq);
    778695        if (ret != EOK) {
    779                 usb_log_error("Failed to register interrupt handler: %s.\n",
     696                usb_log_error("Failed to enable interrupts: %s.\n",
    780697                    str_error(ret));
    781698                unregister_interrupt_handler(device, irq_cap);
     
    844761{
    845762        assert(driver);
    846         static const struct { size_t bw; bw_count_func_t bw_count; }bw[] = {
    847             [USB_SPEED_FULL] = { .bw = BANDWIDTH_AVAILABLE_USB11,
    848                                  .bw_count = bandwidth_count_usb11 },
    849             [USB_SPEED_HIGH] = { .bw = BANDWIDTH_AVAILABLE_USB11,
    850                                  .bw_count = bandwidth_count_usb11 },
    851         };
    852763
    853764        int ret = EOK;
    854         const usb_speed_t speed = driver->hc_speed;
    855         if (speed >= ARRAY_SIZE(bw) || bw[speed].bw == 0) {
    856                 usb_log_error("Driver `%s' reported unsupported speed: %s",
    857                     driver->name, usb_str_speed(speed));
    858                 return ENOTSUP;
    859         }
    860765
    861766        hw_res_list_parsed_t hw_res;
     
    868773        }
    869774
    870         ret = hcd_ddf_setup_hc(device, speed, bw[speed].bw, bw[speed].bw_count);
     775        ret = hcd_ddf_setup_hc(device);
    871776        if (ret != EOK) {
    872777                usb_log_error("Failed to setup generic HCD.\n");
    873                 hw_res_list_parsed_clean(&hw_res);
    874                 return ret;
    875         }
    876 
     778                goto err_hw_res;
     779        }
     780
     781        hcd_t *hcd = dev_to_hcd(device);
     782
     783        if (driver->init)
     784                ret = driver->init(hcd, &hw_res, device);
     785        if (ret != EOK) {
     786                usb_log_error("Failed to init HCD.\n");
     787                goto err_hcd;
     788        }
     789
     790        /* Setup interrupts  */
    877791        interrupt_handler_t *irq_handler =
    878792            driver->irq_handler ? driver->irq_handler : ddf_hcd_gen_irq_handler;
     
    884798        }
    885799
     800        /* Claim the device from BIOS */
    886801        if (driver->claim)
    887                 ret = driver->claim(device);
     802                ret = driver->claim(hcd, device);
    888803        if (ret != EOK) {
    889                 usb_log_error("Failed to claim `%s' for driver `%s'",
    890                     ddf_dev_get_name(device), driver->name);
    891                 return ret;
    892         }
    893 
    894 
    895         /* Init hw driver */
    896         hcd_t *hcd = dev_to_hcd(device);
    897         ret = driver->init(hcd, &hw_res, irqs_enabled);
    898         hw_res_list_parsed_clean(&hw_res);
     804                usb_log_error("Failed to claim `%s' for driver `%s': %s",
     805                    ddf_dev_get_name(device), driver->name, str_error(ret));
     806                goto err_irq;
     807        }
     808
     809        /* Start hw driver */
     810        if (driver->start)
     811                ret = driver->start(hcd, irqs_enabled);
    899812        if (ret != EOK) {
    900                 usb_log_error("Failed to init HCD: %s.\n", str_error(ret));
    901                 goto irq_unregister;
     813                usb_log_error("Failed to start HCD: %s.\n", str_error(ret));
     814                goto err_irq;
    902815        }
    903816
     
    908821                        usb_log_error("Failed to create polling fibril\n");
    909822                        ret = ENOMEM;
    910                         goto irq_unregister;
     823                        goto err_started;
    911824                }
    912825                fibril_add_ready(hcd->polling_fibril);
     
    919832         * needs to be ready at this time.
    920833         */
    921         ret = hcd_ddf_setup_root_hub(device);
     834        if (driver->setup_root_hub)
     835                ret = driver->setup_root_hub(hcd, device);
    922836        if (ret != EOK) {
    923837                usb_log_error("Failed to setup HC root hub: %s.\n",
    924838                    str_error(ret));
    925                 driver->fini(dev_to_hcd(device));
    926 irq_unregister:
    927                 /* Unregistering non-existent should be ok */
    928                 unregister_interrupt_handler(device, irq_cap);
    929                 hcd_ddf_clean_hc(device);
    930                 return ret;
     839                goto err_polling;
    931840        }
    932841
     
    934843            driver->name, ddf_dev_get_name(device));
    935844        return EOK;
    936 }
     845
     846err_polling:
     847        // TODO: Stop the polling fibril (refactor the interrupt_polling func)
     848        //
     849err_started:
     850        if (driver->stop)
     851                driver->stop(hcd);
     852err_irq:
     853        unregister_interrupt_handler(device, irq_cap);
     854        if (driver->fini)
     855                driver->fini(hcd);
     856err_hcd:
     857        hcd_ddf_clean_hc(device);
     858err_hw_res:
     859        hw_res_list_parsed_clean(&hw_res);
     860        return ret;
     861}
     862
    937863/**
    938864 * @}
  • uspace/lib/usbhost/src/endpoint.c

    r367db39a re160bfe8  
    11/*
    22 * Copyright (c) 2011 Jan Vesely
     3 * Copyright (c) 2017 Ondrej Hlavaty <aearsis@eideo.cz>
    34 * All rights reserved.
    45 *
     
    3536
    3637#include <usb/host/endpoint.h>
     38#include <usb/host/bus.h>
    3739
    3840#include <assert.h>
     41#include <atomic.h>
     42#include <mem.h>
    3943#include <stdlib.h>
    40 #include <atomic.h>
    4144
    42 /** Allocate ad initialize endpoint_t structure.
    43  * @param address USB address.
    44  * @param endpoint USB endpoint number.
    45  * @param direction Communication direction.
    46  * @param type USB transfer type.
    47  * @param speed Communication speed.
    48  * @param max_packet_size Maximum size of data packets.
    49  * @param bw Required bandwidth.
    50  * @return Pointer to initialized endpoint_t structure, NULL on failure.
     45/** Initialize provided endpoint structure.
    5146 */
    52 endpoint_t * endpoint_create(usb_address_t address, usb_endpoint_t endpoint,
    53     usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed,
    54     size_t max_packet_size, unsigned packets, size_t bw,
    55     usb_address_t tt_address, unsigned tt_p)
     47void endpoint_init(endpoint_t *ep, bus_t *bus)
    5648{
    57         endpoint_t *instance = malloc(sizeof(endpoint_t));
    58         if (instance) {
    59                 atomic_set(&instance->refcnt, 0);
    60                 instance->address = address;
    61                 instance->endpoint = endpoint;
    62                 instance->direction = direction;
    63                 instance->transfer_type = type;
    64                 instance->speed = speed;
    65                 instance->max_packet_size = max_packet_size;
    66                 instance->packets = packets;
    67                 instance->bandwidth = bw;
    68                 instance->toggle = 0;
    69                 instance->active = false;
    70                 instance->tt.address = tt_address;
    71                 instance->tt.port = tt_p;
    72                 instance->hc_data.data = NULL;
    73                 instance->hc_data.toggle_get = NULL;
    74                 instance->hc_data.toggle_set = NULL;
    75                 link_initialize(&instance->link);
    76                 fibril_mutex_initialize(&instance->guard);
    77                 fibril_condvar_initialize(&instance->avail);
    78         }
    79         return instance;
     49        memset(ep, 0, sizeof(endpoint_t));
     50
     51        ep->bus = bus;
     52        atomic_set(&ep->refcnt, 0);
     53        link_initialize(&ep->link);
     54        fibril_mutex_initialize(&ep->guard);
     55        fibril_condvar_initialize(&ep->avail);
    8056}
    8157
    82 /** Properly dispose of endpoint_t structure.
    83  * @param instance endpoint_t structure.
    84  */
    85 void endpoint_destroy(endpoint_t *instance)
     58void endpoint_add_ref(endpoint_t *ep)
    8659{
    87         assert(instance);
    88         assert(!instance->active);
    89         assert(instance->hc_data.data == NULL);
    90         free(instance);
     60        atomic_inc(&ep->refcnt);
    9161}
    9262
    93 void endpoint_add_ref(endpoint_t *instance)
     63void endpoint_del_ref(endpoint_t *ep)
    9464{
    95         atomic_inc(&instance->refcnt);
    96 }
     65        if (atomic_predec(&ep->refcnt) == 0) {
     66                if (ep->bus->ops.destroy_endpoint) {
     67                        ep->bus->ops.destroy_endpoint(ep);
     68                }
     69                else {
     70                        assert(!ep->active);
    9771
    98 void endpoint_del_ref(endpoint_t *instance)
    99 {
    100         if (atomic_predec(&instance->refcnt) == 0)
    101                 endpoint_destroy(instance);
    102 }
    103 
    104 /** Set device specific data and hooks.
    105  * @param instance endpoint_t structure.
    106  * @param data device specific data.
    107  * @param toggle_get Hook to call when retrieving value of toggle bit.
    108  * @param toggle_set Hook to call when setting the value of toggle bit.
    109  */
    110 void endpoint_set_hc_data(endpoint_t *instance,
    111     void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int))
    112 {
    113         assert(instance);
    114         fibril_mutex_lock(&instance->guard);
    115         instance->hc_data.data = data;
    116         instance->hc_data.toggle_get = toggle_get;
    117         instance->hc_data.toggle_set = toggle_set;
    118         fibril_mutex_unlock(&instance->guard);
    119 }
    120 
    121 /** Clear device specific data and hooks.
    122  * @param instance endpoint_t structure.
    123  * @note This function does not free memory pointed to by data pointer.
    124  */
    125 void endpoint_clear_hc_data(endpoint_t *instance)
    126 {
    127         assert(instance);
    128         endpoint_set_hc_data(instance, NULL, NULL, NULL);
     72                        /* Assume mostly the eps will be allocated by malloc. */
     73                        free(ep);
     74                }
     75        }
    12976}
    13077
    13178/** Mark the endpoint as active and block access for further fibrils.
    132  * @param instance endpoint_t structure.
     79 * @param ep endpoint_t structure.
    13380 */
    134 void endpoint_use(endpoint_t *instance)
     81void endpoint_use(endpoint_t *ep)
    13582{
    136         assert(instance);
     83        assert(ep);
    13784        /* Add reference for active endpoint. */
    138         endpoint_add_ref(instance);
    139         fibril_mutex_lock(&instance->guard);
    140         while (instance->active)
    141                 fibril_condvar_wait(&instance->avail, &instance->guard);
    142         instance->active = true;
    143         fibril_mutex_unlock(&instance->guard);
     85        endpoint_add_ref(ep);
     86        fibril_mutex_lock(&ep->guard);
     87        while (ep->active)
     88                fibril_condvar_wait(&ep->avail, &ep->guard);
     89        ep->active = true;
     90        fibril_mutex_unlock(&ep->guard);
    14491}
    14592
    14693/** Mark the endpoint as inactive and allow access for further fibrils.
    147  * @param instance endpoint_t structure.
     94 * @param ep endpoint_t structure.
    14895 */
    149 void endpoint_release(endpoint_t *instance)
     96void endpoint_release(endpoint_t *ep)
    15097{
    151         assert(instance);
    152         fibril_mutex_lock(&instance->guard);
    153         instance->active = false;
    154         fibril_mutex_unlock(&instance->guard);
    155         fibril_condvar_signal(&instance->avail);
     98        assert(ep);
     99        fibril_mutex_lock(&ep->guard);
     100        ep->active = false;
     101        fibril_mutex_unlock(&ep->guard);
     102        fibril_condvar_signal(&ep->avail);
    156103        /* Drop reference for active endpoint. */
    157         endpoint_del_ref(instance);
     104        endpoint_del_ref(ep);
    158105}
    159106
    160 /** Get the value of toggle bit.
    161  * @param instance endpoint_t structure.
    162  * @note Will use provided hook.
     107/** Get the value of toggle bit. Either uses the toggle_get op, or just returns
     108 * the value of the toggle.
     109 * @param ep endpoint_t structure.
    163110 */
    164 int endpoint_toggle_get(endpoint_t *instance)
     111int endpoint_toggle_get(endpoint_t *ep)
    165112{
    166         assert(instance);
    167         fibril_mutex_lock(&instance->guard);
    168         if (instance->hc_data.toggle_get)
    169                 instance->toggle =
    170                     instance->hc_data.toggle_get(instance->hc_data.data);
    171         const int ret = instance->toggle;
    172         fibril_mutex_unlock(&instance->guard);
     113        assert(ep);
     114        fibril_mutex_lock(&ep->guard);
     115        const int ret = ep->bus->ops.endpoint_get_toggle
     116            ? ep->bus->ops.endpoint_get_toggle(ep)
     117            : ep->toggle;
     118        fibril_mutex_unlock(&ep->guard);
    173119        return ret;
    174120}
    175121
    176 /** Set the value of toggle bit.
    177  * @param instance endpoint_t structure.
    178  * @note Will use provided hook.
     122/** Set the value of toggle bit. Either uses the toggle_set op, or just sets
     123 * the toggle inside.
     124 * @param ep endpoint_t structure.
    179125 */
    180 void endpoint_toggle_set(endpoint_t *instance, int toggle)
     126void endpoint_toggle_set(endpoint_t *ep, unsigned toggle)
    181127{
    182         assert(instance);
     128        assert(ep);
    183129        assert(toggle == 0 || toggle == 1);
    184         fibril_mutex_lock(&instance->guard);
    185         instance->toggle = toggle;
    186         if (instance->hc_data.toggle_set)
    187                 instance->hc_data.toggle_set(instance->hc_data.data, toggle);
    188         fibril_mutex_unlock(&instance->guard);
     130        fibril_mutex_lock(&ep->guard);
     131        if (ep->bus->ops.endpoint_set_toggle) {
     132                ep->bus->ops.endpoint_set_toggle(ep, toggle);
     133        }
     134        else {
     135                ep->toggle = toggle;
     136        }
     137        fibril_mutex_unlock(&ep->guard);
    189138}
     139
    190140
    191141/**
  • uspace/lib/usbhost/src/hcd.c

    r367db39a re160bfe8  
    4141#include <errno.h>
    4242#include <usb_iface.h>
     43#include <str_error.h>
    4344
    4445#include "hcd.h"
    45 
    46 /** Calls ep_add_hook upon endpoint registration.
    47  * @param ep Endpoint to be registered.
    48  * @param arg hcd_t in disguise.
    49  * @return Error code.
    50  */
    51 static int register_helper(endpoint_t *ep, void *arg)
    52 {
    53         hcd_t *hcd = arg;
    54         assert(ep);
    55         assert(hcd);
    56         if (hcd->ops.ep_add_hook)
    57                 return hcd->ops.ep_add_hook(hcd, ep);
    58         return EOK;
    59 }
    60 
    61 /** Calls ep_remove_hook upon endpoint removal.
    62  * @param ep Endpoint to be unregistered.
    63  * @param arg hcd_t in disguise.
    64  */
    65 static void unregister_helper(endpoint_t *ep, void *arg)
    66 {
    67         hcd_t *hcd = arg;
    68         assert(ep);
    69         assert(hcd);
    70         if (hcd->ops.ep_remove_hook)
    71                 hcd->ops.ep_remove_hook(hcd, ep);
    72 }
    73 
    74 /** Calls ep_remove_hook upon endpoint removal. Prints warning.
    75  *  * @param ep Endpoint to be unregistered.
    76  *   * @param arg hcd_t in disguise.
    77  *    */
    78 static void unregister_helper_warn(endpoint_t *ep, void *arg)
    79 {
    80         assert(ep);
    81         usb_log_warning("Endpoint %d:%d %s was left behind, removing.\n",
    82             ep->address, ep->endpoint, usb_str_direction(ep->direction));
    83         unregister_helper(ep, arg);
    84 }
    8546
    8647
     
    9354 * @param bw_count Bandwidth compute function, passed to endpoint manager.
    9455 */
    95 void hcd_init(hcd_t *hcd, usb_speed_t max_speed, size_t bandwidth,
    96     bw_count_func_t bw_count)
    97 {
    98         assert(hcd);
    99         usb_bus_init(&hcd->bus, bandwidth, bw_count, max_speed);
    100 
    101         hcd_set_implementation(hcd, NULL, NULL);
     56void hcd_init(hcd_t *hcd) {
     57        assert(hcd);
     58
     59        hcd_set_implementation(hcd, NULL, NULL, NULL);
    10260}
    10361
     
    10664        assert(hcd);
    10765        usb_address_t address = 0;
    108         const int ret = usb_bus_request_address(
    109             &hcd->bus, &address, false, speed);
     66        const int ret = bus_request_address(hcd->bus, &address, false, speed);
    11067        if (ret != EOK)
    11168                return ret;
     
    11370}
    11471
    115 int hcd_release_address(hcd_t *hcd, usb_address_t address)
    116 {
    117         assert(hcd);
    118         return usb_bus_remove_address(&hcd->bus, address,
    119             unregister_helper_warn, hcd);
    120 }
    121 
    122 int hcd_reserve_default_address(hcd_t *hcd, usb_speed_t speed)
    123 {
    124         assert(hcd);
    125         usb_address_t address = 0;
    126         return usb_bus_request_address(&hcd->bus, &address, true, speed);
    127 }
    128 
    129 int hcd_add_ep(hcd_t *hcd, usb_target_t target, usb_direction_t dir,
    130     usb_transfer_type_t type, size_t max_packet_size, unsigned packets,
    131     size_t size, usb_address_t tt_address, unsigned tt_port)
    132 {
    133         assert(hcd);
    134         return usb_bus_add_ep(&hcd->bus, target.address,
    135             target.endpoint, dir, type, max_packet_size, packets, size,
    136             register_helper, hcd, tt_address, tt_port);
    137 }
    138 
    139 int hcd_remove_ep(hcd_t *hcd, usb_target_t target, usb_direction_t dir)
    140 {
    141         assert(hcd);
    142         return usb_bus_remove_ep(&hcd->bus, target.address,
    143             target.endpoint, dir, unregister_helper, hcd);
    144 }
    145 
    146 
    147 typedef struct {
    148         void *original_data;
    149         usbhc_iface_transfer_out_callback_t original_callback;
    150         usb_target_t target;
    151         hcd_t *hcd;
    152 } toggle_t;
    153 
    154 static void toggle_reset_callback(int retval, void *arg)
    155 {
    156         assert(arg);
    157         toggle_t *toggle = arg;
    158         if (retval == EOK) {
    159                 usb_log_debug2("Reseting toggle on %d:%d.\n",
    160                     toggle->target.address, toggle->target.endpoint);
    161                 usb_bus_reset_toggle(&toggle->hcd->bus,
    162                     toggle->target, toggle->target.endpoint == 0);
    163         }
    164 
    165         toggle->original_callback(retval, toggle->original_data);
    166 }
    167 
    16872/** Prepare generic usb_transfer_batch and schedule it.
    16973 * @param hcd Host controller driver.
    170  * @param fun DDF fun
    17174 * @param target address and endpoint number.
    17275 * @param setup_data Data to use in setup stage (Control communication type)
     
    17780 * @return Error code.
    17881 */
    179 int hcd_send_batch(
    180     hcd_t *hcd, usb_target_t target, usb_direction_t direction,
    181     void *data, size_t size, uint64_t setup_data,
    182     usbhc_iface_transfer_in_callback_t in,
    183     usbhc_iface_transfer_out_callback_t out, void *arg, const char* name)
    184 {
    185         assert(hcd);
    186 
    187         endpoint_t *ep = usb_bus_find_ep(&hcd->bus,
    188             target.address, target.endpoint, direction);
     82int hcd_send_batch(hcd_t *hcd, usb_target_t target, usb_direction_t direction,
     83        void *data, size_t size, uint64_t setup_data,
     84        usbhc_iface_transfer_in_callback_t in, usbhc_iface_transfer_out_callback_t out,
     85        void *arg, const char *name)
     86{
     87        assert(hcd);
     88
     89        endpoint_t *ep = bus_find_endpoint(hcd->bus, target, direction);
    18990        if (ep == NULL) {
    19091                usb_log_error("Endpoint(%d:%d) not registered for %s.\n",
     
    19697            name, target.address, target.endpoint, size, ep->max_packet_size);
    19798
    198         const size_t bw = bandwidth_count_usb11(
    199             ep->speed, ep->transfer_type, size, ep->max_packet_size);
     99        const size_t bw = bus_count_bw(ep, size);
    200100        /* Check if we have enough bandwidth reserved */
    201101        if (ep->bandwidth < bw) {
    202102                usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
    203103                    "but only %zu is reserved.\n",
    204                     ep->address, ep->endpoint, name, bw, ep->bandwidth);
     104                    ep->target.address, ep->target.endpoint, name, bw, ep->bandwidth);
    205105                return ENOSPC;
    206106        }
     
    210110        }
    211111
    212         /* Check for commands that reset toggle bit */
    213         if (ep->transfer_type == USB_TRANSFER_CONTROL) {
    214                 const int reset_toggle = usb_request_needs_toggle_reset(
    215                     (usb_device_request_setup_packet_t *) &setup_data);
    216                 if (reset_toggle >= 0) {
    217                         assert(out);
    218                         toggle_t *toggle = malloc(sizeof(toggle_t));
    219                         if (!toggle)
    220                                 return ENOMEM;
    221                         toggle->target.address = target.address;
    222                         toggle->target.endpoint = reset_toggle;
    223                         toggle->original_callback = out;
    224                         toggle->original_data = arg;
    225                         toggle->hcd = hcd;
    226 
    227                         arg = toggle;
    228                         out = toggle_reset_callback;
    229                 }
    230         }
    231 
    232         usb_transfer_batch_t *batch = usb_transfer_batch_create(
    233             ep, data, size, setup_data, in, out, arg);
     112        usb_transfer_batch_t *batch = usb_transfer_batch_create(ep);
    234113        if (!batch) {
    235114                usb_log_error("Failed to create transfer batch.\n");
     
    237116        }
    238117
     118        batch->buffer = data;
     119        batch->buffer_size = size;
     120        batch->setup.packed = setup_data;
     121        batch->dir = direction;
     122
     123        /* Check for commands that reset toggle bit */
     124        if (ep->transfer_type == USB_TRANSFER_CONTROL)
     125                batch->toggle_reset_mode
     126                        = usb_request_get_toggle_reset_mode(&batch->setup.packet);
     127
     128        usb_transfer_batch_set_old_handlers(batch, in, out, arg);
     129
    239130        const int ret = hcd->ops.schedule(hcd, batch);
    240         if (ret != EOK)
     131        if (ret != EOK) {
     132                usb_log_warning("Batch %p failed to schedule: %s", batch, str_error(ret));
    241133                usb_transfer_batch_destroy(batch);
     134        }
    242135
    243136        /* Drop our own reference to ep. */
     
    248141
    249142typedef struct {
    250         volatile unsigned done;
     143        fibril_mutex_t done_mtx;
     144        fibril_condvar_t done_cv;
     145        unsigned done;
    251146        int ret;
    252147        size_t size;
     
    258153        assert(d);
    259154        d->ret = ret;
     155        d->size = size;
     156        fibril_mutex_lock(&d->done_mtx);
    260157        d->done = 1;
    261         d->size = size;
     158        fibril_condvar_broadcast(&d->done_cv);
     159        fibril_mutex_unlock(&d->done_mtx);
    262160}
    263161
     
    267165        assert(data);
    268166        d->ret = ret;
     167        fibril_mutex_lock(&d->done_mtx);
    269168        d->done = 1;
     169        fibril_condvar_broadcast(&d->done_cv);
     170        fibril_mutex_unlock(&d->done_mtx);
    270171}
    271172
     
    277178        assert(hcd);
    278179        sync_data_t sd = { .done = 0, .ret = EBUSY, .size = size };
     180        fibril_mutex_initialize(&sd.done_mtx);
     181        fibril_condvar_initialize(&sd.done_cv);
    279182
    280183        const int ret = hcd_send_batch(hcd, target, dir, data, size, setup_data,
     
    284187                return ret;
    285188
    286         while (!sd.done) {
    287                 async_usleep(1000);
    288         }
     189        fibril_mutex_lock(&sd.done_mtx);
     190        while (!sd.done)
     191                fibril_condvar_wait(&sd.done_cv, &sd.done_mtx);
     192        fibril_mutex_unlock(&sd.done_mtx);
    289193
    290194        if (sd.ret == EOK)
  • uspace/lib/usbhost/src/usb_transfer_batch.c

    r367db39a re160bfe8  
    3434
    3535#include <usb/host/usb_transfer_batch.h>
     36#include <usb/host/endpoint.h>
     37#include <usb/host/bus.h>
    3638#include <usb/debug.h>
    3739
    3840#include <assert.h>
    3941#include <errno.h>
    40 #include <macros.h>
    41 #include <mem.h>
    42 #include <stdlib.h>
    43 #include <usbhc_iface.h>
     42#include <str_error.h>
    4443
    45 /** Allocate and initialize usb_transfer_batch structure.
    46  * @param ep endpoint used by the transfer batch.
    47  * @param buffer data to send/recieve.
    48  * @param buffer_size Size of data buffer.
    49  * @param setup_buffer Data to send in SETUP stage of control transfer.
    50  * @param func_in callback on IN transfer completion.
    51  * @param func_out callback on OUT transfer completion.
    52  * @param fun DDF function (passed to callback function).
    53  * @param arg Argument to pass to the callback function.
    54  * @param private_data driver specific per batch data.
    55  * @param private_data_dtor Function to properly destroy private_data.
    56  * @return Pointer to valid usb_transfer_batch_t structure, NULL on failure.
     44
     45/** Create a batch on given endpoint.
    5746 */
    58 usb_transfer_batch_t *usb_transfer_batch_create(endpoint_t *ep, char *buffer,
    59     size_t buffer_size,
    60     uint64_t setup_buffer,
    61     usbhc_iface_transfer_in_callback_t func_in,
    62     usbhc_iface_transfer_out_callback_t func_out,
    63     void *arg)
     47usb_transfer_batch_t *usb_transfer_batch_create(endpoint_t *ep)
    6448{
    65         if (func_in == NULL && func_out == NULL)
    66                 return NULL;
    67         if (func_in != NULL && func_out != NULL)
    68                 return NULL;
     49        assert(ep);
     50        assert(ep->bus);
    6951
    70         usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t));
    71         if (instance) {
    72                 instance->ep = ep;
    73                 instance->callback_in = func_in;
    74                 instance->callback_out = func_out;
    75                 instance->arg = arg;
    76                 instance->buffer = buffer;
    77                 instance->buffer_size = buffer_size;
    78                 instance->setup_size = 0;
    79                 instance->transfered_size = 0;
    80                 instance->error = EOK;
    81                 if (ep && ep->transfer_type == USB_TRANSFER_CONTROL) {
    82                         memcpy(instance->setup_buffer, &setup_buffer,
    83                             USB_SETUP_PACKET_SIZE);
    84                         instance->setup_size = USB_SETUP_PACKET_SIZE;
    85                 }
    86                 if (instance->ep)
    87                         endpoint_use(instance->ep);
    88         }
    89         return instance;
     52        usb_transfer_batch_t *batch;
     53        if (ep->bus->ops.create_batch)
     54                batch = ep->bus->ops.create_batch(ep->bus, ep);
     55        else
     56                batch = malloc(sizeof(usb_transfer_batch_t));
     57
     58        return batch;
    9059}
    9160
    92 /** Correctly dispose all used data structures.
    93  *
    94  * @param[in] instance Batch structure to use.
     61/** Initialize given batch structure.
    9562 */
    96 void usb_transfer_batch_destroy(const usb_transfer_batch_t *instance)
     63void usb_transfer_batch_init(usb_transfer_batch_t *batch, endpoint_t *ep)
    9764{
    98         if (!instance)
    99                 return;
    100         usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " disposing.\n",
    101             instance, USB_TRANSFER_BATCH_ARGS(*instance));
    102         if (instance->ep) {
    103                 endpoint_release(instance->ep);
    104         }
    105         free(instance);
     65        endpoint_use(ep);
     66
     67        memset(batch, 0, sizeof(*batch));
     68        batch->ep = ep;
    10669}
    10770
    108 /** Prepare data and call the right callback.
     71/** Call the handler of the batch.
    10972 *
    110  * @param[in] instance Batch structure to use.
    111  * @param[in] data Data to copy to the output buffer.
    112  * @param[in] size Size of @p data.
    113  * @param[in] error Error value to use.
     73 * @param[in] batch Batch structure to use.
    11474 */
    115 void usb_transfer_batch_finish_error(const usb_transfer_batch_t *instance,
    116     const void *data, size_t size, int error)
     75static int batch_complete(usb_transfer_batch_t *batch)
    11776{
    118         assert(instance);
    119         usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " finishing.\n",
    120             instance, USB_TRANSFER_BATCH_ARGS(*instance));
     77        assert(batch);
    12178
    122         /* NOTE: Only one of these pointers should be set. */
    123         if (instance->callback_out) {
    124                 instance->callback_out(error, instance->arg);
     79        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " completed.\n",
     80            batch, USB_TRANSFER_BATCH_ARGS(*batch));
     81
     82        if (batch->error == EOK && batch->toggle_reset_mode != RESET_NONE) {
     83                usb_log_debug2("Reseting %s due to transaction of %d:%d.\n",
     84                    batch->toggle_reset_mode == RESET_ALL ? "all EPs toggle" : "EP toggle",
     85                    batch->ep->target.address, batch->ep->target.endpoint);
     86                bus_reset_toggle(batch->ep->bus,
     87                    batch->ep->target, batch->toggle_reset_mode == RESET_ALL);
    12588        }
    12689
    127         if (instance->callback_in) {
    128                 /* We care about the data and there are some to copy */
    129                 const size_t safe_size = min(size, instance->buffer_size);
    130                 if (data) {
    131                         memcpy(instance->buffer, data, safe_size);
    132                 }
    133                 instance->callback_in(error, safe_size, instance->arg);
     90        return batch->on_complete
     91                ? batch->on_complete(batch)
     92                : EOK;
     93}
     94
     95/** Destroy the batch.
     96 *
     97 * @param[in] batch Batch structure to use.
     98 */
     99void usb_transfer_batch_destroy(usb_transfer_batch_t *batch)
     100{
     101        assert(batch);
     102        assert(batch->ep);
     103        assert(batch->ep->bus);
     104
     105        bus_t *bus = batch->ep->bus;
     106        if (bus->ops.destroy_batch) {
     107                usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " destroying.\n",
     108                    batch, USB_TRANSFER_BATCH_ARGS(*batch));
     109                bus->ops.destroy_batch(batch);
    134110        }
     111        else {
     112                usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " disposing.\n",
     113                    batch, USB_TRANSFER_BATCH_ARGS(*batch));
     114                free(batch);
     115        }
     116
     117        endpoint_release(batch->ep);
     118}
     119
     120/** Finish a transfer batch: call handler, destroy batch, release endpoint.
     121 *
     122 * Call only after the batch have been scheduled && completed!
     123 *
     124 * @param[in] batch Batch structure to use.
     125 */
     126void usb_transfer_batch_finish(usb_transfer_batch_t *batch)
     127{
     128        const int err = batch_complete(batch);
     129        if (err)
     130                usb_log_warning("batch %p failed to complete: %s", batch, str_error(err));
     131
     132        usb_transfer_batch_destroy(batch);
     133}
     134
     135
     136struct old_handler_wrapper_data {
     137        usbhc_iface_transfer_in_callback_t in_callback;
     138        usbhc_iface_transfer_out_callback_t out_callback;
     139        void *arg;
     140};
     141
     142static int old_handler_wrapper(usb_transfer_batch_t *batch)
     143{
     144        struct old_handler_wrapper_data *data = batch->on_complete_data;
     145
     146        assert(data);
     147
     148        if (data->out_callback)
     149                data->out_callback(batch->error, data->arg);
     150
     151        if (data->in_callback)
     152                data->in_callback(batch->error, batch->transfered_size, data->arg);
     153
     154        free(data);
     155        return EOK;
     156}
     157
     158void usb_transfer_batch_set_old_handlers(usb_transfer_batch_t *batch,
     159        usbhc_iface_transfer_in_callback_t in_callback,
     160        usbhc_iface_transfer_out_callback_t out_callback,
     161        void *arg)
     162{
     163        struct old_handler_wrapper_data *data = malloc(sizeof(*data));
     164
     165        assert((!in_callback) != (!out_callback));
     166
     167        data->in_callback = in_callback;
     168        data->out_callback = out_callback;
     169        data->arg = arg;
     170
     171        batch->on_complete = old_handler_wrapper;
     172        batch->on_complete_data = data;
    135173}
    136174/**
Note: See TracChangeset for help on using the changeset viewer.