Changes in / [62066b4:6bb83c7] in mainline


Ignore:
Location:
uspace
Files:
24 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/pciintel/pci.c

    r62066b4 r6bb83c7  
    4949#include <ipc/devman.h>
    5050#include <ipc/dev_iface.h>
    51 #include <ipc/irc.h>
    52 #include <ipc/ns.h>
    53 #include <ipc/services.h>
    54 #include <sysinfo.h>
    5551#include <ops/hw_res.h>
    5652#include <device/hw_res.h>
     
    7672static bool pciintel_enable_child_interrupt(device_t *dev)
    7773{
    78         /* This is an old ugly way, copied from ne2000 driver */
    79         assert(dev);
    80         pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
    81 
    82   sysarg_t apic;
    83   sysarg_t i8259;
    84         int irc_phone = -1;
    85         int irc_service = 0;
    86 
    87   if ((sysinfo_get_value("apic", &apic) == EOK) && (apic)) {
    88     irc_service = SERVICE_APIC;
    89         } else if ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259)) {
    90     irc_service = SERVICE_I8259;
    91         }
    92 
    93   if (irc_service) {
    94     while (irc_phone < 0)
    95       irc_phone = service_connect_blocking(irc_service, 0, 0);
    96   } else {
    97                 return false;
    98         }
    99 
    100         size_t i;
    101   for (i = 0; i < dev_data->hw_resources.count; i++) {
    102                 if (dev_data->hw_resources.resources[i].type == INTERRUPT) {
    103                         int irq = dev_data->hw_resources.resources[i].res.interrupt.irq;
    104                         async_msg_1(irc_phone, IRC_ENABLE_INTERRUPT, irq);
    105                 }
    106         }
    107 
    108         async_hangup(irc_phone);
    109         return true;
     74        /* TODO */
     75       
     76        return false;
    11077}
    11178
  • uspace/drv/uhci-hcd/batch.c

    r62066b4 r6bb83c7  
    141141        usb_log_debug("Checking(%p) %d packet for completion.\n",
    142142            instance, instance->packets);
     143        /* This is just an ugly trick to support the old API */
    143144        instance->transfered_size = 0;
    144145        size_t i = 0;
     
    156157                    transfer_descriptor_actual_size(&instance->tds[i]);
    157158        }
    158         /* This is just an ugly trick to support the old API */
    159159        instance->transfered_size -= instance->setup_size;
    160160        return true;
     
    191191            0, 1, false, instance->target, USB_PID_IN, NULL, NULL);
    192192
    193         instance->tds[i].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
    194 
    195193        instance->next_step = batch_call_out_and_dispose;
    196194        batch_schedule(instance);
     
    223221        transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
    224222            0, 1, false, instance->target, USB_PID_OUT, NULL, NULL);
    225 
    226         instance->tds[i].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
    227223
    228224        instance->next_step = batch_call_in_and_dispose;
     
    248244        }
    249245
    250         instance->tds[i - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
    251 
    252246        instance->next_step = batch_call_in_and_dispose;
    253247        batch_schedule(instance);
     
    274268        }
    275269
    276         instance->tds[i - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
    277 
    278270        instance->next_step = batch_call_out_and_dispose;
    279271        batch_schedule(instance);
  • uspace/drv/uhci-hcd/iface.c

    r62066b4 r6bb83c7  
    5454}
    5555/*----------------------------------------------------------------------------*/
    56 static int reserve_default_address(device_t *dev, usb_speed_t speed)
     56static int reserve_default_address(device_t *dev, bool full_speed)
    5757{
    5858        assert(dev);
     
    7272}
    7373/*----------------------------------------------------------------------------*/
    74 static int request_address(device_t *dev, usb_speed_t speed,
     74static int request_address(device_t *dev, bool full_speed,
    7575    usb_address_t *address)
    7676{
     
    164164        return EOK;
    165165}
    166 
    167 
     166/*----------------------------------------------------------------------------*/
     167static int control_write_setup(device_t *dev, usb_target_t target,
     168    size_t max_packet_size,
     169    void *data, size_t size,
     170    usbhc_iface_transfer_out_callback_t callback, void *arg)
     171{
     172        dev_speed_t speed = FULL_SPEED;
     173
     174        usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
     175        batch_t *batch = batch_get(dev, target, USB_TRANSFER_CONTROL,
     176            max_packet_size, speed, NULL, 0, data, size, NULL, callback, arg);
     177        if (!batch)
     178                return ENOMEM;
     179        batch_control_setup_old(batch);
     180        return EOK;
     181}
     182/*----------------------------------------------------------------------------*/
     183static int control_write_data(device_t *dev, usb_target_t target,
     184    size_t max_packet_size,
     185    void *data, size_t size,
     186    usbhc_iface_transfer_out_callback_t callback, void *arg)
     187{
     188        dev_speed_t speed = FULL_SPEED;
     189
     190        usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
     191        batch_t *batch = batch_get(dev, target, USB_TRANSFER_CONTROL,
     192            max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg);
     193        if (!batch)
     194                return ENOMEM;
     195        batch_control_write_data_old(batch);
     196        return EOK;
     197}
     198/*----------------------------------------------------------------------------*/
     199static int control_write_status(device_t *dev, usb_target_t target,
     200    usbhc_iface_transfer_in_callback_t callback, void *arg)
     201{
     202        size_t max_packet_size = 8;
     203        dev_speed_t speed = FULL_SPEED;
     204
     205        usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
     206        batch_t *batch = batch_get(dev, target, USB_TRANSFER_CONTROL,
     207            max_packet_size, speed, NULL, 0, NULL, 0, callback, NULL, arg);
     208        if (!batch)
     209                return ENOMEM;
     210        batch_control_write_status_old(batch);
     211        return EOK;
     212}
     213/*----------------------------------------------------------------------------*/
     214static int control_read_setup(device_t *dev, usb_target_t target,
     215    size_t max_packet_size,
     216    void *data, size_t size,
     217    usbhc_iface_transfer_out_callback_t callback, void *arg)
     218{
     219        dev_speed_t speed = FULL_SPEED;
     220
     221        usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
     222        batch_t *batch = batch_get(dev, target, USB_TRANSFER_CONTROL,
     223            max_packet_size, speed, NULL, 0, data, size, NULL, callback, arg);
     224        if (!batch)
     225                return ENOMEM;
     226        batch_control_setup_old(batch);
     227        return EOK;
     228}
     229/*----------------------------------------------------------------------------*/
     230static int control_read_data(device_t *dev, usb_target_t target,
     231    size_t max_packet_size,
     232    void *data, size_t size,
     233    usbhc_iface_transfer_in_callback_t callback, void *arg)
     234{
     235        dev_speed_t speed = FULL_SPEED;
     236
     237        usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
     238        batch_t *batch = batch_get(dev, target, USB_TRANSFER_CONTROL,
     239            max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg);
     240        if (!batch)
     241                return ENOMEM;
     242        batch_control_read_data_old(batch);
     243        return EOK;
     244}
     245/*----------------------------------------------------------------------------*/
     246static int control_read_status(device_t *dev, usb_target_t target,
     247    usbhc_iface_transfer_out_callback_t callback, void *arg)
     248{
     249        size_t max_packet_size = 8;
     250        dev_speed_t speed = FULL_SPEED;
     251
     252        usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
     253        batch_t *batch = batch_get(dev, target, USB_TRANSFER_CONTROL,
     254            max_packet_size, speed, NULL, 0, NULL, 0, NULL, callback, arg);
     255        if (!batch)
     256                return ENOMEM;
     257        batch_control_read_status_old(batch);
     258        return EOK;
     259}
    168260/*----------------------------------------------------------------------------*/
    169261usbhc_iface_t uhci_iface = {
     
    181273        .control_read = control_read,
    182274        .control_write = control_write,
     275
     276        .control_write_setup = control_write_setup,
     277        .control_write_data = control_write_data,
     278        .control_write_status = control_write_status,
     279
     280        .control_read_setup = control_read_setup,
     281        .control_read_data = control_read_data,
     282        .control_read_status = control_read_status
    183283};
    184284/**
  • uspace/drv/uhci-hcd/main.c

    r62066b4 r6bb83c7  
    3434#include <driver.h>
    3535#include <usb_iface.h>
    36 #include <device/hw_res.h>
    3736
    3837#include <errno.h>
     
    4746#define NAME "uhci-hcd"
    4847
    49 static int uhci_add_device(device_t *device);
    50 static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle);
    51 /*----------------------------------------------------------------------------*/
    5248static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
    5349{
     
    5854        return EOK;
    5955}
    60 /*----------------------------------------------------------------------------*/
     56
    6157static usb_iface_t hc_usb_iface = {
    6258        .get_hc_handle = usb_iface_get_hc_handle
    6359};
    64 /*----------------------------------------------------------------------------*/
     60
    6561static device_ops_t uhci_ops = {
    6662        .interfaces[USB_DEV_IFACE] = &hc_usb_iface,
    6763        .interfaces[USBHC_DEV_IFACE] = &uhci_iface
    6864};
    69 /*----------------------------------------------------------------------------*/
    70 static driver_ops_t uhci_driver_ops = {
    71         .add_device = uhci_add_device,
    72 };
    73 /*----------------------------------------------------------------------------*/
    74 static driver_t uhci_driver = {
    75         .name = NAME,
    76         .driver_ops = &uhci_driver_ops
    77 };
    78 /*----------------------------------------------------------------------------*/
    79 static void irq_handler(device_t *device, ipc_callid_t iid, ipc_call_t *call)
    80 {
    81         assert(device);
    82         uhci_t *hc = dev_to_uhci(device);
    83         uint16_t status = IPC_GET_ARG1(*call);
    84         assert(hc);
    85         uhci_interrupt(hc, status);
    86 }
    87 /*----------------------------------------------------------------------------*/
    88 #define CHECK_RET_RETURN(ret, message...) \
    89 if (ret != EOK) { \
    90         usb_log_error(message); \
    91         return ret; \
    92 }
    9365
    9466static int uhci_add_device(device_t *device)
     
    10375        int irq;
    10476
    105         int ret =
    106             pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq);
     77        int rc = pci_get_my_registers(device,
     78            &io_reg_base, &io_reg_size, &irq);
    10779
    108         CHECK_RET_RETURN(ret,
    109             "Failed(%d) to get I/O addresses:.\n", ret, device->handle);
     80        if (rc != EOK) {
     81                usb_log_error("Failed(%d) to get I/O registers addresses for device:.\n",
     82                    rc, device->handle);
     83                return rc;
     84        }
     85
    11086        usb_log_info("I/O regs at 0x%X (size %zu), IRQ %d.\n",
    11187            io_reg_base, io_reg_size, irq);
    11288
    113         ret = pci_enable_interrupts(device);
    114         CHECK_RET_RETURN(ret, "Failed(%d) to get enable interrupts:\n", ret);
     89        uhci_t *uhci_hc = malloc(sizeof(uhci_t));
     90        if (!uhci_hc) {
     91                usb_log_error("Failed to allocaete memory for uhci hcd driver.\n");
     92                return ENOMEM;
     93        }
    11594
    116         uhci_t *uhci_hc = malloc(sizeof(uhci_t));
    117         ret = (uhci_hc != NULL) ? EOK : ENOMEM;
    118         CHECK_RET_RETURN(ret, "Failed to allocate memory for uhci hcd driver.\n");
    119 
    120         ret = uhci_init(uhci_hc, (void*)io_reg_base, io_reg_size);
     95        int ret = uhci_init(uhci_hc, (void*)io_reg_base, io_reg_size);
    12196        if (ret != EOK) {
    12297                usb_log_error("Failed to init uhci-hcd.\n");
    123                 free(uhci_hc);
    12498                return ret;
    12599        }
    126 
    127         ret = register_interrupt_handler(device, irq, irq_handler,
    128             &uhci_hc->interrupt_code);
    129         if (ret != EOK) {
    130                 usb_log_error("Failed to register interrupt handler.\n");
    131                 uhci_fini(uhci_hc);
    132                 free(uhci_hc);
    133                 return ret;
    134         }
    135 
    136100        device_t *rh;
    137101        ret = setup_root_hub(&rh, device);
     102
    138103        if (ret != EOK) {
    139104                usb_log_error("Failed to setup uhci root hub.\n");
    140                 uhci_fini(uhci_hc);
    141                 free(uhci_hc);
     105                /* TODO: destroy uhci here */
    142106                return ret;
    143107        }
     
    146110        if (ret != EOK) {
    147111                usb_log_error("Failed to register root hub.\n");
    148                 uhci_fini(uhci_hc);
    149                 free(uhci_hc);
    150                 free(rh);
     112                /* TODO: destroy uhci here */
    151113                return ret;
    152114        }
    153115
    154116        device->driver_data = uhci_hc;
     117
    155118        return EOK;
    156119}
    157 /*----------------------------------------------------------------------------*/
     120
     121static driver_ops_t uhci_driver_ops = {
     122        .add_device = uhci_add_device,
     123};
     124
     125static driver_t uhci_driver = {
     126        .name = NAME,
     127        .driver_ops = &uhci_driver_ops
     128};
     129
    158130int main(int argc, char *argv[])
    159131{
    160         sleep(3);
    161         usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
     132        /*
     133         * Do some global initializations.
     134         */
     135        sleep(5);
     136        usb_log_enable(USB_LOG_LEVEL_INFO, NAME);
    162137
    163138        return driver_main(&uhci_driver);
  • uspace/drv/uhci-hcd/pci.c

    r62066b4 r6bb83c7  
    121121        return rc;
    122122}
    123 /*----------------------------------------------------------------------------*/
    124 int pci_enable_interrupts(device_t *device)
    125 {
    126         int parent_phone = devman_parent_device_connect(device->handle,
    127             IPC_FLAG_BLOCKING);
    128         bool enabled = hw_res_enable_interrupt(parent_phone);
    129         return enabled ? EOK : EIO;
    130 }
     123
    131124/**
    132125 * @}
  • uspace/drv/uhci-hcd/pci.h

    r62066b4 r6bb83c7  
    3939
    4040int pci_get_my_registers(device_t *, uintptr_t *, size_t *, int *);
    41 int pci_enable_interrupts(device_t *device);
    4241
    4342#endif
  • uspace/drv/uhci-hcd/transfer_list.c

    r62066b4 r6bb83c7  
    111111        /* I'm the first one here */
    112112        if (batch->link.prev == &instance->batch_list) {
    113                 usb_log_debug("Removing batch %p was first, next element %x.\n",
     113                usb_log_debug("Removing tracer %p was first, next element %x.\n",
    114114                        batch, batch->qh->next_queue);
    115115                instance->queue_head->element = batch->qh->next_queue;
    116116        } else {
    117                 usb_log_debug("Removing batch %p was NOT first, next element %x.\n",
     117                usb_log_debug("Removing tracer %p was NOT first, next element %x.\n",
    118118                        batch, batch->qh->next_queue);
    119119                batch_t *prev = list_get_instance(batch->link.prev, batch_t, link);
  • uspace/drv/uhci-hcd/uhci-hcd.ma

    r62066b4 r6bb83c7  
    1110 pci/ven=8086&dev=7020
    2 10 pci/ven=8086&dev=7112
     2
  • uspace/drv/uhci-hcd/uhci.c

    r62066b4 r6bb83c7  
    3939
    4040#include "uhci.h"
    41 static irq_cmd_t uhci_cmds[] = {
    42         {
    43                 .cmd = CMD_PIO_READ_16,
    44                 .addr = (void*)0xc022,
    45                 .dstarg = 1
    46         },
    47         {
    48                 .cmd = CMD_PIO_WRITE_16,
    49                 .addr = (void*)0xc022,
    50                 .value = 0x1f
    51         },
    52         {
    53                 .cmd = CMD_ACCEPT
    54         }
    55 };
    5641
    5742static int uhci_init_transfer_lists(uhci_t *instance);
    58 static int uhci_init_mem_structures(uhci_t *instance);
    59 static void uhci_init_hw(uhci_t *instance);
    60 
    61 static int uhci_interrupt_emulator(void *arg);
     43static int uhci_clean_finished(void *arg);
    6244static int uhci_debug_checker(void *arg);
    63 
    6445static bool allowed_usb_packet(
    6546        bool low_speed, usb_transfer_type_t, size_t size);
    6647
    67 #define CHECK_RET_RETURN(ret, message...) \
     48int uhci_init(uhci_t *instance, void *regs, size_t reg_size)
     49{
     50#define CHECK_RET_RETURN(message...) \
    6851        if (ret != EOK) { \
    6952                usb_log_error(message); \
     
    7154        } else (void) 0
    7255
    73 int uhci_init(uhci_t *instance, void *regs, size_t reg_size)
    74 {
    75         assert(reg_size >= sizeof(regs_t));
     56        /* init address keeper(libusb) */
     57        usb_address_keeping_init(&instance->address_manager, USB11_ADDRESS_MAX);
     58        usb_log_debug("Initialized address manager.\n");
    7659
    7760        /* allow access to hc control registers */
    7861        regs_t *io;
     62        assert(reg_size >= sizeof(regs_t));
    7963        int ret = pio_enable(regs, reg_size, (void**)&io);
    80         CHECK_RET_RETURN(ret, "Failed to gain access to registers at %p.\n", io);
     64        CHECK_RET_RETURN("Failed to gain access to registers at %p.\n", io);
    8165        instance->registers = io;
    8266        usb_log_debug("Device registers accessible.\n");
    8367
    84         ret = uhci_init_mem_structures(instance);
    85         CHECK_RET_RETURN(ret, "Failed to initialize memory structures.\n");
    86 
    87         uhci_init_hw(instance);
    88 
    89         instance->cleaner = fibril_create(uhci_interrupt_emulator, instance);
    90 //      fibril_add_ready(instance->cleaner);
    91 
    92         instance->debug_checker = fibril_create(uhci_debug_checker, instance);
    93         fibril_add_ready(instance->debug_checker);
    94 
    95         return EOK;
    96 }
    97 /*----------------------------------------------------------------------------*/
    98 void uhci_init_hw(uhci_t *instance)
    99 {
    100 
    101         /* set framelist pointer */
    102         const uint32_t pa = addr_to_phys(instance->frame_list);
    103         pio_write_32(&instance->registers->flbaseadd, pa);
    104 
    105         /* enable all interrupts, but resume interrupt */
    106         pio_write_16(&instance->registers->usbintr,
    107                   UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);
    108 
    109         /* Start the hc with large(64B) packet FSBR */
    110         pio_write_16(&instance->registers->usbcmd,
    111             UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE);
    112         usb_log_debug("Started UHCI HC.\n");
    113 }
    114 /*----------------------------------------------------------------------------*/
    115 int uhci_init_mem_structures(uhci_t *instance)
    116 {
    117         assert(instance);
    118 
    119         /* init interrupt code */
    120         irq_cmd_t *interrupt_commands = malloc(sizeof(uhci_cmds));
    121         if (interrupt_commands == NULL) {
    122                 return ENOMEM;
    123         }
    124         memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds));
    125         interrupt_commands[0].addr = (void*)&instance->registers->usbsts;
    126         interrupt_commands[1].addr = (void*)&instance->registers->usbsts;
    127         instance->interrupt_code.cmds = interrupt_commands;
    128         instance->interrupt_code.cmdcount =
    129             sizeof(uhci_cmds) / sizeof(irq_cmd_t);
    130 
    13168        /* init transfer lists */
    132         int ret = uhci_init_transfer_lists(instance);
    133         CHECK_RET_RETURN(ret, "Failed to initialize transfer lists.\n");
    134         usb_log_debug("Initialized transfer lists.\n");
    135 
    136         /* frame list initialization */
     69        ret = uhci_init_transfer_lists(instance);
     70        CHECK_RET_RETURN("Failed to initialize transfer lists.\n");
     71        usb_log_debug("Transfer lists initialized.\n");
     72
     73
     74        usb_log_debug("Initializing frame list.\n");
    13775        instance->frame_list = get_page();
    13876        ret = instance ? EOK : ENOMEM;
    139         CHECK_RET_RETURN(ret, "Failed to get frame list page.\n");
    140         usb_log_debug("Initialized frame list.\n");
     77        CHECK_RET_RETURN("Failed to get frame list page.\n");
    14178
    14279        /* initialize all frames to point to the first queue head */
     
    14986        }
    15087
    151         /* init address keeper(libusb) */
    152         usb_address_keeping_init(&instance->address_manager, USB11_ADDRESS_MAX);
    153         usb_log_debug("Initialized address manager.\n");
     88        const uintptr_t pa = (uintptr_t)addr_to_phys(instance->frame_list);
     89        pio_write_32(&instance->registers->flbaseadd, (uint32_t)pa);
     90
     91        list_initialize(&instance->batch_list);
     92        fibril_mutex_initialize(&instance->batch_list_mutex);
     93
     94        instance->cleaner = fibril_create(uhci_clean_finished, instance);
     95        fibril_add_ready(instance->cleaner);
     96
     97        instance->debug_checker = fibril_create(uhci_debug_checker, instance);
     98        fibril_add_ready(instance->debug_checker);
     99
     100        /* Start the hc with large(64B) packet FSBR */
     101        pio_write_16(&instance->registers->usbcmd,
     102            UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET);
     103        usb_log_debug("Started UHCI HC.\n");
     104
     105        uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
     106        cmd |= UHCI_CMD_DEBUG;
     107        pio_write_16(&instance->registers->usbcmd, cmd);
    154108
    155109        return EOK;
     
    160114        assert(instance);
    161115
    162         /* initialize TODO: check errors */
     116        /* initialize */
    163117        int ret;
    164118        ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL");
     
    192146        instance->transfers[1][USB_TRANSFER_CONTROL] =
    193147          &instance->transfers_control_slow;
    194         instance->transfers[0][USB_TRANSFER_BULK] =
    195           &instance->transfers_bulk_full;
     148        instance->transfers[0][USB_TRANSFER_CONTROL] =
     149          &instance->transfers_control_full;
    196150
    197151        return EOK;
     
    220174}
    221175/*----------------------------------------------------------------------------*/
    222 void uhci_interrupt(uhci_t *instance, uint16_t status)
    223 {
    224         assert(instance);
    225         if ((status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) == 0)
    226                 return;
    227         usb_log_debug("UHCI interrupt: %X.\n", status);
    228         transfer_list_check(&instance->transfers_interrupt);
    229         transfer_list_check(&instance->transfers_control_slow);
    230         transfer_list_check(&instance->transfers_control_full);
    231         transfer_list_check(&instance->transfers_bulk_full);
    232 }
    233 /*----------------------------------------------------------------------------*/
    234 int uhci_interrupt_emulator(void* arg)
    235 {
    236         usb_log_debug("Started interrupt emulator.\n");
     176int uhci_clean_finished(void* arg)
     177{
     178        usb_log_debug("Started cleaning fibril.\n");
    237179        uhci_t *instance = (uhci_t*)arg;
    238180        assert(instance);
    239181
    240182        while(1) {
    241                 uint16_t status = pio_read_16(&instance->registers->usbsts);
    242                 uhci_interrupt(instance, status);
     183                transfer_list_check(&instance->transfers_interrupt);
     184                transfer_list_check(&instance->transfers_control_slow);
     185                transfer_list_check(&instance->transfers_control_full);
     186                transfer_list_check(&instance->transfers_bulk_full);
    243187                async_usleep(UHCI_CLEANER_TIMEOUT);
    244188        }
     
    251195        assert(instance);
    252196        while (1) {
    253                 const uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
    254                 const uint16_t sts = pio_read_16(&instance->registers->usbsts);
    255                 const uint16_t intr = pio_read_16(&instance->registers->usbintr);
    256                 usb_log_debug("Command: %X Status: %X Interrupts: %x\n",
    257                     cmd, sts, intr);
     197                uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
     198                uint16_t sts = pio_read_16(&instance->registers->usbsts);
     199                usb_log_debug("Command register: %X Status register: %X\n", cmd, sts);
    258200
    259201                uintptr_t frame_list = pio_read_32(&instance->registers->flbaseadd);
    260                 if (frame_list != addr_to_phys(instance->frame_list)) {
     202                if (frame_list != (uintptr_t)addr_to_phys(instance->frame_list)) {
    261203                        usb_log_debug("Framelist address: %p vs. %p.\n",
    262204                                frame_list, addr_to_phys(instance->frame_list));
  • uspace/drv/uhci-hcd/uhci.h

    r62066b4 r6bb83c7  
    6666
    6767        uint16_t usbintr;
    68 #define UHCI_INTR_SHORT_PACKET (1 << 3)
    69 #define UHCI_INTR_COMPLETE (1 << 2)
    70 #define UHCI_INTR_RESUME (1 << 1)
    71 #define UHCI_INTR_CRC (1 << 0)
    72 
    7368        uint16_t frnum;
    7469        uint32_t flbaseadd;
     
    8681        link_pointer_t *frame_list;
    8782
     83        link_t batch_list;
     84        fibril_mutex_t batch_list_mutex;
     85
    8886        transfer_list_t transfers_bulk_full;
    8987        transfer_list_t transfers_control_full;
     
    9290
    9391        transfer_list_t *transfers[2][4];
    94 
    95         irq_code_t interrupt_code;
    9692
    9793        fid_t cleaner;
     
    10298int uhci_init(uhci_t *instance, void *regs, size_t reg_size);
    10399
    104 static inline void uhci_fini(uhci_t *instance) {};
     100int uhci_fini(uhci_t *device);
     101
     102int uhci_transfer(
     103  uhci_t *instance,
     104  device_t *dev,
     105  usb_target_t target,
     106  usb_transfer_type_t transfer_type,
     107        bool toggle,
     108  usb_packet_id pid,
     109        bool low_speed,
     110  void *buffer, size_t size,
     111  usbhc_iface_transfer_out_callback_t callback_out,
     112  usbhc_iface_transfer_in_callback_t callback_in,
     113  void *arg );
    105114
    106115int uhci_schedule(uhci_t *instance, batch_t *batch);
    107116
    108 void uhci_interrupt(uhci_t *instance, uint16_t status);
    109 
    110117static inline uhci_t * dev_to_uhci(device_t *dev)
    111118        { return (uhci_t*)dev->driver_data; }
    112 
    113119
    114120#endif
  • uspace/drv/uhci-rhd/port.c

    r62066b4 r6bb83c7  
    131131        return EOK;
    132132}
    133 
    134 /** Callback for enabling port during adding a new device.
    135  *
    136  * @param portno Port number (unused).
    137  * @param arg Pointer to uhci_port_t of port with the new device.
    138  * @return Error code.
    139  */
    140 static int new_device_enable_port(int portno, void *arg)
    141 {
    142         uhci_port_t *port = (uhci_port_t *) arg;
    143 
    144         usb_log_debug("new_device_enable_port(%d)\n", port->number);
     133/*----------------------------------------------------------------------------*/
     134static int uhci_port_new_device(uhci_port_t *port)
     135{
     136        assert(port);
     137        assert(usb_hc_connection_is_opened(&port->hc_connection));
     138
     139        usb_log_info("Adding new device on port %d.\n", port->number);
     140
     141        /* get address of the future device */
     142        const usb_address_t usb_address = usb_hc_request_address(
     143            &port->hc_connection, true);
     144
     145        if (usb_address <= 0) {
     146                usb_log_error("Recieved invalid address(%d).\n", usb_address);
     147                return usb_address;
     148        }
     149        usb_log_debug("Sucessfully obtained address %d for port %d.\n",
     150            usb_address, port->number);
     151
     152        /* get default address */
     153        int ret = usb_hc_reserve_default_address(&port->hc_connection, true);
     154        if (ret != EOK) {
     155                usb_log_error("Failed to reserve default address on port %d.\n",
     156                    port->number);
     157                int ret2 = usb_hc_unregister_device(&port->hc_connection,
     158                    usb_address);
     159                if (ret2 != EOK) {
     160                        usb_log_fatal("Failed to return requested address on port %d.\n",
     161                           port->number);
     162                        return ret2;
     163                }
     164                usb_log_debug("Successfully returned reserved address on port %d.\n",
     165                        port->number);
     166                return ret;
     167        }
     168        usb_log_debug("Sucessfully obtained default address for port %d.\n",
     169            port->number);
    145170
    146171        /*
    147          * The host then waits for at least 100 ms to allow completion of
     172         * the host then waits for at least 100 ms to allow completion of
    148173         * an insertion process and for power at the device to become stable.
    149174         */
    150175        async_usleep(100000);
    151176
    152         /* Enable the port. */
     177        /* enable port */
    153178        uhci_port_set_enabled(port, true);
    154179
     
    172197        }
    173198
    174         return EOK;
    175 }
    176 
    177 /*----------------------------------------------------------------------------*/
    178 static int uhci_port_new_device(uhci_port_t *port)
    179 {
    180         assert(port);
    181         assert(usb_hc_connection_is_opened(&port->hc_connection));
    182 
    183         usb_log_info("Detected new device on port %u.\n", port->number);
    184 
    185         usb_address_t dev_addr;
    186         int rc = usb_hc_new_device_wrapper(port->rh, &port->hc_connection,
    187             USB_SPEED_FULL,
    188             new_device_enable_port, port->number, port,
    189             &dev_addr, &port->attached_device);
    190         if (rc != EOK) {
    191                 usb_log_error("Failed adding new device on port %u: %s.\n",
    192                     port->number, str_error(rc));
     199        /*
     200         * Initialize connection to the device.
     201         */
     202        /* FIXME: check for errors. */
     203        usb_device_connection_t new_dev_connection;
     204        usb_endpoint_pipe_t new_dev_ctrl_pipe;
     205        usb_device_connection_initialize_on_default_address(
     206            &new_dev_connection, &port->hc_connection);
     207        usb_endpoint_pipe_initialize_default_control(&new_dev_ctrl_pipe,
     208            &new_dev_connection);
     209
     210        /*
     211         * Assign new address to the device. This function updates
     212         * the backing connection to still point to the same device.
     213         */
     214        /* FIXME: check for errors. */
     215        usb_endpoint_pipe_start_session(&new_dev_ctrl_pipe);
     216        ret = usb_request_set_address(&new_dev_ctrl_pipe, usb_address);
     217        usb_endpoint_pipe_end_session(&new_dev_ctrl_pipe);
     218
     219        if (ret != EOK) { /* address assigning went wrong */
     220                usb_log_error("Failed(%d) to assign address to the device.\n", ret);
    193221                uhci_port_set_enabled(port, false);
    194                 return rc;
    195         }
    196 
    197         usb_log_info("New device on port %u has address %d (handle %zu).\n",
    198             port->number, dev_addr, port->attached_device);
    199 
    200         return EOK;
    201 }
    202 
     222                int release = usb_hc_release_default_address(&port->hc_connection);
     223                if (release != EOK) {
     224                        usb_log_error("Failed to release default address on port %d.\n",
     225                            port->number);
     226                        return release;
     227                }
     228                usb_log_debug("Sucessfully released default address on port %d.\n",
     229                    port->number);
     230                return ret;
     231        }
     232        usb_log_debug("Sucessfully assigned address %d for port %d.\n",
     233            usb_address, port->number);
     234
     235        /* release default address */
     236        ret = usb_hc_release_default_address(&port->hc_connection);
     237        if (ret != EOK) {
     238                usb_log_error("Failed to release default address on port %d.\n",
     239                    port->number);
     240                return ret;
     241        }
     242        usb_log_debug("Sucessfully released default address on port %d.\n",
     243            port->number);
     244
     245        /* communicate and possibly report to devman */
     246        assert(port->attached_device == 0);
     247
     248        ret = usb_device_register_child_in_devman(new_dev_connection.address,
     249            new_dev_connection.hc_handle, port->rh, &port->attached_device);
     250
     251        if (ret != EOK) { /* something went wrong */
     252                usb_log_error("Failed(%d) in usb_drv_register_child.\n", ret);
     253                uhci_port_set_enabled(port, false);
     254                return ENOMEM;
     255        }
     256        usb_log_info("Sucessfully added device on port(%d) address(%d) handle %d.\n",
     257                port->number, usb_address, port->attached_device);
     258
     259        /*
     260         * Register the device in the host controller.
     261         */
     262        usb_hc_attached_device_t new_device = {
     263                .address = new_dev_connection.address,
     264                .handle = port->attached_device
     265        };
     266
     267        ret = usb_hc_register_device(&port->hc_connection, &new_device);
     268        // TODO: proper error check here
     269        assert(ret == EOK);
     270
     271        return EOK;
     272}
    203273/*----------------------------------------------------------------------------*/
    204274static int uhci_port_remove_device(uhci_port_t *port)
  • uspace/drv/uhci-rhd/root_hub.c

    r62066b4 r6bb83c7  
    4747        assert(rh);
    4848        int ret;
    49         ret = usb_hc_find(rh->handle, &instance->hc_handle);
     49        ret = usb_drv_find_hc(rh, &instance->hc_handle);
    5050        usb_log_info("rh found(%d) hc handle: %d.\n", ret, instance->hc_handle);
    5151        if (ret != EOK) {
  • uspace/drv/usbhub/usbhub.c

    r62066b4 r6bb83c7  
    5252#include "usb/pipes.h"
    5353
    54 static int iface_get_hc_handle(device_t *device, devman_handle_t *handle)
    55 {
    56         return usb_hc_find(device->handle, handle);
    57 }
    58 
    5954static usb_iface_t hub_usb_iface = {
    60         .get_hc_handle = iface_get_hc_handle
     55        .get_hc_handle = usb_drv_find_hc
    6156};
    6257
     
    268263        //get default address
    269264        //opResult = usb_drv_reserve_default_address(hc);
    270         opResult = usb_hc_reserve_default_address(&hub->connection, USB_SPEED_LOW);
     265        opResult = usb_hc_reserve_default_address(&hub->connection, false);
    271266        if (opResult != EOK) {
    272267                dprintf(USB_LOG_LEVEL_WARNING, "cannot assign default address, it is probably used");
     
    325320        usb_address_t new_device_address = usb_hc_request_address(
    326321                        &hub->connection,
    327                         USB_SPEED_LOW/// \TODO fullspeed??
     322                        false/// \TODO fullspeed??
    328323                        );
    329324        if (new_device_address < 0) {
  • uspace/drv/vhc/connhost.c

    r62066b4 r6bb83c7  
    234234}
    235235
     236static int enqueue_transfer_setup(device_t *dev,
     237    usb_target_t target, usb_transfer_type_t transfer_type,
     238    void *buffer, size_t size,
     239    usbhc_iface_transfer_out_callback_t callback, void *arg)
     240{
     241        usb_log_debug2("Transfer SETUP [%d.%d (%s); %zu].\n",
     242            target.address, target.endpoint,
     243            usb_str_transfer_type(transfer_type),
     244            size);
     245
     246        transfer_info_t *transfer
     247            = create_transfer_info(dev, USB_DIRECTION_OUT, arg);
     248        transfer->out_callback = callback;
     249
     250        hc_add_transaction_to_device(true, target, transfer_type, buffer, size,
     251            universal_callback, transfer);
     252
     253        return EOK;
     254}
     255
    236256static int enqueue_transfer_in(device_t *dev,
    237257    usb_target_t target, usb_transfer_type_t transfer_type,
     
    275295}
    276296
     297static int control_write_setup(device_t *dev, usb_target_t target,
     298    size_t max_packet_size,
     299    void *data, size_t size,
     300    usbhc_iface_transfer_out_callback_t callback, void *arg)
     301{
     302        return enqueue_transfer_setup(dev, target, USB_TRANSFER_CONTROL,
     303            data, size,
     304            callback, arg);
     305}
     306
     307static int control_write_data(device_t *dev, usb_target_t target,
     308    size_t max_packet_size,
     309    void *data, size_t size,
     310    usbhc_iface_transfer_out_callback_t callback, void *arg)
     311{
     312        return enqueue_transfer_out(dev, target, USB_TRANSFER_CONTROL,
     313            data, size,
     314            callback, arg);
     315}
     316
     317static int control_write_status(device_t *dev, usb_target_t target,
     318    usbhc_iface_transfer_in_callback_t callback, void *arg)
     319{
     320        return enqueue_transfer_in(dev, target, USB_TRANSFER_CONTROL,
     321            NULL, 0,
     322            callback, arg);
     323}
     324
    277325static int control_write(device_t *dev, usb_target_t target,
    278326    size_t max_packet_size,
     
    293341}
    294342
     343static int control_read_setup(device_t *dev, usb_target_t target,
     344    size_t max_packet_size,
     345    void *data, size_t size,
     346    usbhc_iface_transfer_out_callback_t callback, void *arg)
     347{
     348        return enqueue_transfer_setup(dev, target, USB_TRANSFER_CONTROL,
     349            data, size,
     350            callback, arg);
     351}
     352
     353static int control_read_data(device_t *dev, usb_target_t target,
     354    size_t max_packet_size,
     355    void *data, size_t size,
     356    usbhc_iface_transfer_in_callback_t callback, void *arg)
     357{
     358        return enqueue_transfer_in(dev, target, USB_TRANSFER_CONTROL,
     359            data, size,
     360            callback, arg);
     361}
     362
     363static int control_read_status(device_t *dev, usb_target_t target,
     364    usbhc_iface_transfer_out_callback_t callback, void *arg)
     365{
     366        return enqueue_transfer_out(dev, target, USB_TRANSFER_CONTROL,
     367            NULL, 0,
     368            callback, arg);
     369}
     370
    295371static int control_read(device_t *dev, usb_target_t target,
    296372    size_t max_packet_size,
     
    314390
    315391
    316 static int reserve_default_address(device_t *dev, usb_speed_t ignored)
     392static int reserve_default_address(device_t *dev, bool ignored)
    317393{
    318394        usb_address_keeping_reserve_default(&addresses);
     
    326402}
    327403
    328 static int request_address(device_t *dev, usb_speed_t ignored,
    329     usb_address_t *address)
     404static int request_address(device_t *dev, bool ignored, usb_address_t *address)
    330405{
    331406        usb_address_t addr = usb_address_keeping_request(&addresses);
     
    379454        .interrupt_in = interrupt_in,
    380455
     456        .control_write_setup = control_write_setup,
     457        .control_write_data = control_write_data,
     458        .control_write_status = control_write_status,
     459
    381460        .control_write = control_write,
     461
     462        .control_read_setup = control_read_setup,
     463        .control_read_data = control_read_data,
     464        .control_read_status = control_read_status,
     465
    382466        .control_read = control_read
    383467};
  • uspace/lib/c/generic/str_error.c

    r62066b4 r6bb83c7  
    7373                case EBADCHECKSUM:
    7474                        return "Bad checksum";
    75                 case ESTALL:
    76                         return "Operation stalled";
    7775                case EAGAIN:
    7876                        return "Resource temporarily unavailable";
  • uspace/lib/c/include/errno.h

    r62066b4 r6bb83c7  
    5959#define EBADCHECKSUM  (-300)
    6060
    61 /** USB: stalled operation. */
    62 #define ESTALL (-301)
    63 
    6461/** An API function is called while another blocking function is in progress. */
    6562#define EINPROGRESS  (-10036)
  • uspace/lib/drv/generic/remote_usbhc.c

    r62066b4 r6bb83c7  
    4646static void remote_usbhc_interrupt_out(device_t *, void *, ipc_callid_t, ipc_call_t *);
    4747static void remote_usbhc_interrupt_in(device_t *, void *, ipc_callid_t, ipc_call_t *);
     48static void remote_usbhc_control_write_setup(device_t *, void *, ipc_callid_t, ipc_call_t *);
     49static void remote_usbhc_control_write_data(device_t *, void *, ipc_callid_t, ipc_call_t *);
     50static void remote_usbhc_control_write_status(device_t *, void *, ipc_callid_t, ipc_call_t *);
     51static void remote_usbhc_control_read_setup(device_t *, void *, ipc_callid_t, ipc_call_t *);
     52static void remote_usbhc_control_read_data(device_t *, void *, ipc_callid_t, ipc_call_t *);
     53static void remote_usbhc_control_read_status(device_t *, void *, ipc_callid_t, ipc_call_t *);
    4854static void remote_usbhc_control_write(device_t *, void *, ipc_callid_t, ipc_call_t *);
    4955static void remote_usbhc_control_read(device_t *, void *, ipc_callid_t, ipc_call_t *);
     
    6975        remote_usbhc_interrupt_in,
    7076
     77        remote_usbhc_control_write_setup,
     78        remote_usbhc_control_write_data,
     79        remote_usbhc_control_write_status,
     80
     81        remote_usbhc_control_read_setup,
     82        remote_usbhc_control_read_data,
     83        remote_usbhc_control_read_status,
     84
    7185        remote_usbhc_control_write,
    7286        remote_usbhc_control_read
     
    152166        }
    153167       
    154         usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
     168        bool full_speed = DEV_IPC_GET_ARG1(*call);
    155169       
    156         int rc = usb_iface->reserve_default_address(device, speed);
     170        int rc = usb_iface->reserve_default_address(device, full_speed);
    157171
    158172        async_answer_0(callid, rc);
     
    184198        }
    185199       
    186         usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
     200        bool full_speed = DEV_IPC_GET_ARG1(*call);
    187201
    188202        usb_address_t address;
    189         int rc = usb_iface->request_address(device, speed, &address);
     203        int rc = usb_iface->request_address(device, full_speed, &address);
    190204        if (rc != EOK) {
    191205                async_answer_0(callid, rc);
     
    283297        }
    284298
    285         size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
     299        size_t expected_len = DEV_IPC_GET_ARG3(*call);
    286300        usb_target_t target = {
    287301                .address = DEV_IPC_GET_ARG1(*call),
     
    291305        size_t len = 0;
    292306        void *buffer = NULL;
    293 
    294         int rc = async_data_write_accept(&buffer, false,
    295             1, USB_MAX_PAYLOAD_SIZE,
    296             0, &len);
    297 
    298         if (rc != EOK) {
    299                 async_answer_0(callid, rc);
    300                 return;
     307        if (expected_len > 0) {
     308                int rc = async_data_write_accept(&buffer, false,
     309                    1, USB_MAX_PAYLOAD_SIZE,
     310                    0, &len);
     311
     312                if (rc != EOK) {
     313                        async_answer_0(callid, rc);
     314                        return;
     315                }
    301316        }
    302317
     
    313328        trans->size = len;
    314329
    315         rc = transfer_func(device, target, max_packet_size,
     330        int rc = transfer_func(device, target, HACK_MAX_PACKET_SIZE,
    316331            buffer, len,
    317332            callback_out, trans);
     
    339354        }
    340355
    341         size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
     356        size_t len = DEV_IPC_GET_ARG3(*call);
    342357        usb_target_t target = {
    343358                .address = DEV_IPC_GET_ARG1(*call),
     
    345360        };
    346361
    347         size_t len;
    348362        ipc_callid_t data_callid;
    349363        if (!async_data_read_receive(&data_callid, &len)) {
     
    361375        trans->size = len;
    362376
    363         int rc = transfer_func(device, target, max_packet_size,
     377        int rc = transfer_func(device, target, HACK_MAX_PACKET_SIZE_INTERRUPT_IN,
    364378            trans->buffer, len,
    365379            callback_in, trans);
     
    371385}
    372386
     387/** Process status part of control transfer.
     388 *
     389 * @param device Target device.
     390 * @param callid Initiating caller.
     391 * @param call Initiating call.
     392 * @param direction Transfer direction (read ~ in, write ~ out).
     393 * @param transfer_in_func Transfer function for control read (might be NULL).
     394 * @param transfer_out_func Transfer function for control write (might be NULL).
     395 */
     396static void remote_usbhc_status_transfer(device_t *device,
     397    ipc_callid_t callid, ipc_call_t *call,
     398    usb_direction_t direction,
     399    int (*transfer_in_func)(device_t *, usb_target_t,
     400        usbhc_iface_transfer_in_callback_t, void *),
     401    int (*transfer_out_func)(device_t *, usb_target_t,
     402        usbhc_iface_transfer_out_callback_t, void *))
     403{
     404        switch (direction) {
     405                case USB_DIRECTION_IN:
     406                        if (!transfer_in_func) {
     407                                async_answer_0(callid, ENOTSUP);
     408                                return;
     409                        }
     410                        break;
     411                case USB_DIRECTION_OUT:
     412                        if (!transfer_out_func) {
     413                                async_answer_0(callid, ENOTSUP);
     414                                return;
     415                        }
     416                        break;
     417                default:
     418                        assert(false && "unreachable code");
     419                        break;
     420        }
     421
     422        usb_target_t target = {
     423                .address = DEV_IPC_GET_ARG1(*call),
     424                .endpoint = DEV_IPC_GET_ARG2(*call)
     425        };
     426
     427        async_transaction_t *trans = async_transaction_create(callid);
     428        if (trans == NULL) {
     429                async_answer_0(callid, ENOMEM);
     430                return;
     431        }
     432
     433        int rc;
     434        switch (direction) {
     435                case USB_DIRECTION_IN:
     436                        rc = transfer_in_func(device, target,
     437                            callback_in, trans);
     438                        break;
     439                case USB_DIRECTION_OUT:
     440                        rc = transfer_out_func(device, target,
     441                            callback_out, trans);
     442                        break;
     443                default:
     444                        assert(false && "unreachable code");
     445                        break;
     446        }
     447
     448        if (rc != EOK) {
     449                async_answer_0(callid, rc);
     450                async_transaction_destroy(trans);
     451        }
     452}
     453
     454
    373455void remote_usbhc_interrupt_out(device_t *device, void *iface,
    374456    ipc_callid_t callid, ipc_call_t *call)
     
    389471        return remote_usbhc_in_transfer(device, callid, call,
    390472            usb_iface->interrupt_in);
     473}
     474
     475void remote_usbhc_control_write_setup(device_t *device, void *iface,
     476    ipc_callid_t callid, ipc_call_t *call)
     477{
     478        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     479        assert(usb_iface != NULL);
     480
     481        return remote_usbhc_out_transfer(device, callid, call,
     482            usb_iface->control_write_setup);
     483}
     484
     485void remote_usbhc_control_write_data(device_t *device, void *iface,
     486    ipc_callid_t callid, ipc_call_t *call)
     487{
     488        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     489        assert(usb_iface != NULL);
     490
     491        return remote_usbhc_out_transfer(device, callid, call,
     492            usb_iface->control_write_data);
     493}
     494
     495void remote_usbhc_control_write_status(device_t *device, void *iface,
     496    ipc_callid_t callid, ipc_call_t *call)
     497{
     498        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     499        assert(usb_iface != NULL);
     500
     501        return remote_usbhc_status_transfer(device, callid, call,
     502            USB_DIRECTION_IN, usb_iface->control_write_status, NULL);
     503}
     504
     505void remote_usbhc_control_read_setup(device_t *device, void *iface,
     506    ipc_callid_t callid, ipc_call_t *call)
     507{
     508        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     509        assert(usb_iface != NULL);
     510
     511        return remote_usbhc_out_transfer(device, callid, call,
     512            usb_iface->control_read_setup);
     513}
     514
     515void remote_usbhc_control_read_data(device_t *device, void *iface,
     516            ipc_callid_t callid, ipc_call_t *call)
     517{
     518        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     519        assert(usb_iface != NULL);
     520
     521        return remote_usbhc_in_transfer(device, callid, call,
     522            usb_iface->control_read_data);
     523}
     524
     525void remote_usbhc_control_read_status(device_t *device, void *iface,
     526            ipc_callid_t callid, ipc_call_t *call)
     527{
     528        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     529        assert(usb_iface != NULL);
     530
     531        return remote_usbhc_status_transfer(device, callid, call,
     532            USB_DIRECTION_OUT, NULL, usb_iface->control_read_status);
    391533}
    392534
     
    407549        };
    408550        size_t data_buffer_len = DEV_IPC_GET_ARG3(*call);
    409         size_t max_packet_size = DEV_IPC_GET_ARG4(*call);
    410551
    411552        int rc;
     
    443584        trans->size = data_buffer_len;
    444585
    445         rc = usb_iface->control_write(device, target, max_packet_size,
     586        rc = usb_iface->control_write(device, target, HACK_MAX_PACKET_SIZE,
    446587            setup_packet, setup_packet_len,
    447588            data_buffer, data_buffer_len,
     
    470611                .endpoint = DEV_IPC_GET_ARG2(*call)
    471612        };
    472         size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
    473613
    474614        int rc;
     
    508648        }
    509649
    510         rc = usb_iface->control_read(device, target, max_packet_size,
     650        rc = usb_iface->control_read(device, target, HACK_MAX_PACKET_SIZE,
    511651            setup_packet, setup_packet_len,
    512652            trans->buffer, trans->size,
  • uspace/lib/drv/include/usbhc_iface.h

    r62066b4 r6bb83c7  
    5353 *   - argument #1 is target address
    5454 *   - argument #2 is target endpoint
    55  *   - argument #3 is max packet size of the endpoint
     55 *   - argument #3 is buffer size
    5656 * - this call is immediately followed by IPC data write (from caller)
    5757 * - the initial call (and the whole transaction) is answer after the
     
    6666 *   - argument #1 is target address
    6767 *   - argument #2 is target endpoint
    68  *   - argument #3 is max packet size of the endpoint
     68 *   - argument #3 is buffer size
    6969 * - this call is immediately followed by IPC data read (async version)
    7070 * - the call is not answered until the device returns some data (or until
     
    153153        IPC_M_USBHC_INTERRUPT_IN,
    154154
     155
     156        /** Start WRITE control transfer.
     157         * See explanation at usb_iface_funcs_t (OUT transaction).
     158         */
     159        IPC_M_USBHC_CONTROL_WRITE_SETUP,
     160
     161        /** Send control-transfer data to device.
     162         * See explanation at usb_iface_funcs_t (OUT transaction).
     163         */
     164        IPC_M_USBHC_CONTROL_WRITE_DATA,
     165
     166        /** Terminate WRITE control transfer.
     167         * See explanation at usb_iface_funcs_t (NO-DATA transaction).
     168         */
     169        IPC_M_USBHC_CONTROL_WRITE_STATUS,
     170
     171
     172
     173        /** Start READ control transfer.
     174         * See explanation at usb_iface_funcs_t (OUT transaction).
     175         */
     176        IPC_M_USBHC_CONTROL_READ_SETUP,
     177
     178        /** Get control-transfer data from device.
     179         * See explanation at usb_iface_funcs_t (IN transaction).
     180         */
     181        IPC_M_USBHC_CONTROL_READ_DATA,
     182
     183        /** Terminate READ control transfer.
     184         * See explanation at usb_iface_funcs_t (NO-DATA transaction).
     185         */
     186        IPC_M_USBHC_CONTROL_READ_STATUS,
     187
    155188        /** Issue control WRITE transfer.
    156189         * See explanation at usb_iface_funcs_t (OUT transaction) for
     
    161194        IPC_M_USBHC_CONTROL_WRITE,
    162195
    163         /** Issue control READ transfer.
     196        /** Issue control WRITE transfer.
    164197         * See explanation at usb_iface_funcs_t (IN transaction) for
    165198         * call parameters.
    166          * This call is immediately followed by IPC data write from the caller
    167          * (setup packet) and IPC data read (buffer that was read).
     199         * This call is immediately followed by IPC data read from the caller
     200         * (setup packet).
     201         * Actual data are retrieved through IPC_M_USBHC_GET_BUFFER.
    168202         */
    169203        IPC_M_USBHC_CONTROL_READ,
     
    198232        int (*tell_address)(device_t *, devman_handle_t, usb_address_t *);
    199233
    200         int (*reserve_default_address)(device_t *, usb_speed_t);
     234        int (*reserve_default_address)(device_t *, bool);
    201235        int (*release_default_address)(device_t *);
    202         int (*request_address)(device_t *, usb_speed_t, usb_address_t *);
     236        int (*request_address)(device_t *, bool, usb_address_t *);
    203237        int (*bind_address)(device_t *, usb_address_t, devman_handle_t);
    204238        int (*release_address)(device_t *, usb_address_t);
     
    206240        usbhc_iface_transfer_out_t interrupt_out;
    207241        usbhc_iface_transfer_in_t interrupt_in;
     242
     243        usbhc_iface_transfer_setup_t control_write_setup;
     244        usbhc_iface_transfer_out_t control_write_data;
     245        int (*control_write_status)(device_t *, usb_target_t,
     246            usbhc_iface_transfer_in_callback_t, void *);
     247
     248        usbhc_iface_transfer_setup_t control_read_setup;
     249        usbhc_iface_transfer_in_t control_read_data;
     250        int (*control_read_status)(device_t *, usb_target_t,
     251            usbhc_iface_transfer_out_callback_t, void *);
    208252
    209253        int (*control_write)(device_t *, usb_target_t,
  • uspace/lib/usb/include/usb/hub.h

    r62066b4 r6bb83c7  
    3939#include <usb/usbdevice.h>
    4040
    41 int usb_hc_new_device_wrapper(device_t *, usb_hc_connection_t *, usb_speed_t,
    42     int (*)(int, void *), int, void *, usb_address_t *, devman_handle_t *);
    4341
    4442/** Info about device attached to host controller.
     
    5553} usb_hc_attached_device_t;
    5654
    57 int usb_hc_reserve_default_address(usb_hc_connection_t *, usb_speed_t);
     55int usb_hc_reserve_default_address(usb_hc_connection_t *, bool);
    5856int usb_hc_release_default_address(usb_hc_connection_t *);
    5957
    60 usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_speed_t);
     58usb_address_t usb_hc_request_address(usb_hc_connection_t *, bool);
    6159int usb_hc_register_device(usb_hc_connection_t *,
    6260    const usb_hc_attached_device_t *);
  • uspace/lib/usb/include/usb/usb.h

    r62066b4 r6bb83c7  
    6868        USB_DIRECTION_BOTH
    6969} usb_direction_t;
    70 
    71 /** USB speeds. */
    72 typedef enum {
    73         /** USB 1.1 low speed (1.5Mbits/s). */
    74         USB_SPEED_LOW,
    75         /** USB 1.1 full speed (12Mbits/s). */
    76         USB_SPEED_FULL,
    77         /** USB 2.0 high speed (480Mbits/s). */
    78         USB_SPEED_HIGH
    79 } usb_speed_t;
    8070
    8171/** USB request type target. */
  • uspace/lib/usb/src/hub.c

    r62066b4 r6bb83c7  
    3434 */
    3535#include <usb/hub.h>
    36 #include <usb/pipes.h>
    37 #include <usb/request.h>
    38 #include <usb/recognise.h>
    3936#include <usbhc_iface.h>
    4037#include <errno.h>
     
    5956 */
    6057int usb_hc_reserve_default_address(usb_hc_connection_t *connection,
    61     usb_speed_t speed)
     58    bool full_speed)
    6259{
    6360        CHECK_CONNECTION(connection);
     
    6562        return async_req_2_0(connection->hc_phone,
    6663            DEV_IFACE_ID(USBHC_DEV_IFACE),
    67             IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS, speed);
     64            IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS, full_speed);
    6865}
    6966
     
    8885 */
    8986usb_address_t usb_hc_request_address(usb_hc_connection_t *connection,
    90     usb_speed_t speed)
     87    bool full_speed)
    9188{
    9289        CHECK_CONNECTION(connection);
     
    9592        int rc = async_req_2_1(connection->hc_phone,
    9693            DEV_IFACE_ID(USBHC_DEV_IFACE),
    97             IPC_M_USBHC_REQUEST_ADDRESS, speed,
     94            IPC_M_USBHC_REQUEST_ADDRESS, full_speed,
    9895            &address);
    9996        if (rc != EOK) {
     
    141138
    142139
    143 /** Wrapper for registering attached device to the hub.
    144  *
    145  * The @p enable_port function is expected to enable singalling on given
    146  * port.
    147  * The two arguments to it can have arbitrary meaning
    148  * (the @p port_no is only a suggestion)
    149  * and are not touched at all by this function
    150  * (they are passed as is to the @p enable_port function).
    151  *
    152  * If the @p enable_port fails (i.e. does not return EOK), the device
    153  * addition is cancelled.
    154  * The return value is then returned (it is good idea to use different
    155  * error codes than those listed as return codes by this function itself).
    156  *
    157  * @param parent Parent device (i.e. the hub device).
    158  * @param connection Opened connection to host controller.
    159  * @param dev_speed New device speed.
    160  * @param enable_port Function for enabling signalling through the port the
    161  *      device is attached to.
    162  * @param port_no Port number (passed through to @p enable_port).
    163  * @param arg Any data argument to @p enable_port.
    164  * @param[out] assigned_address USB address of the device.
    165  * @param[out] assigned_handle Devman handle of the new device.
    166  * @return Error code.
    167  * @retval ENOENT Connection to HC not opened.
    168  * @retval EADDRNOTAVAIL Failed retrieving free address from host controller.
    169  * @retval EBUSY Failed reserving default USB address.
    170  * @retval ENOTCONN Problem connecting to the host controller via USB pipe.
    171  * @retval ESTALL Problem communication with device (either SET_ADDRESS
    172  *      request or requests for descriptors when creating match ids).
    173  */
    174 int usb_hc_new_device_wrapper(device_t *parent, usb_hc_connection_t *connection,
    175     usb_speed_t dev_speed,
    176     int (*enable_port)(int port_no, void *arg), int port_no, void *arg,
    177     usb_address_t *assigned_address, devman_handle_t *assigned_handle)
    178 {
    179         CHECK_CONNECTION(connection);
    180 
    181         /*
    182          * Request new address.
    183          */
    184         usb_address_t dev_addr = usb_hc_request_address(connection, dev_speed);
    185         if (dev_addr < 0) {
    186                 return EADDRNOTAVAIL;
    187         }
    188 
    189         int rc;
    190 
    191         /*
    192          * Reserve the default address.
    193          */
    194         rc = usb_hc_reserve_default_address(connection, dev_speed);
    195         if (rc != EOK) {
    196                 rc = EBUSY;
    197                 goto leave_release_free_address;
    198         }
    199 
    200         /*
    201          * Enable the port (i.e. allow signalling through this port).
    202          */
    203         rc = enable_port(port_no, arg);
    204         if (rc != EOK) {
    205                 goto leave_release_default_address;
    206         }
    207 
    208         /*
    209          * Change the address from default to the free one.
    210          * We need to create a new control pipe for that.
    211          */
    212         usb_device_connection_t dev_conn;
    213         rc = usb_device_connection_initialize_on_default_address(&dev_conn,
    214             connection);
    215         if (rc != EOK) {
    216                 rc = ENOTCONN;
    217                 goto leave_release_default_address;
    218         }
    219 
    220         usb_endpoint_pipe_t ctrl_pipe;
    221         rc = usb_endpoint_pipe_initialize_default_control(&ctrl_pipe,
    222             &dev_conn);
    223         if (rc != EOK) {
    224                 rc = ENOTCONN;
    225                 goto leave_release_default_address;
    226         }
    227 
    228         rc = usb_endpoint_pipe_start_session(&ctrl_pipe);
    229         if (rc != EOK) {
    230                 rc = ENOTCONN;
    231                 goto leave_release_default_address;
    232         }
    233 
    234         rc = usb_request_set_address(&ctrl_pipe, dev_addr);
    235         if (rc != EOK) {
    236                 rc = ESTALL;
    237                 goto leave_stop_session;
    238         }
    239 
    240         usb_endpoint_pipe_end_session(&ctrl_pipe);
    241 
    242         /*
    243          * Once the address is changed, we can return the default address.
    244          */
    245         usb_hc_release_default_address(connection);
    246 
    247         /*
    248          * It is time to register the device with devman.
    249          */
    250         /* FIXME: create device_register that will get opened ctrl pipe. */
    251         devman_handle_t child_handle;
    252         rc = usb_device_register_child_in_devman(dev_addr, dev_conn.hc_handle,
    253             parent, &child_handle);
    254         if (rc != EOK) {
    255                 rc = ESTALL;
    256                 goto leave_release_free_address;
    257         }
    258 
    259         /*
    260          * And now inform the host controller about the handle.
    261          */
    262         usb_hc_attached_device_t new_device = {
    263                 .address = dev_addr,
    264                 .handle = child_handle
    265         };
    266         rc = usb_hc_register_device(connection, &new_device);
    267         if (rc != EOK) {
    268                 rc = EDESTADDRREQ;
    269                 goto leave_release_free_address;
    270         }
    271 
    272         /*
    273          * And we are done.
    274          */
    275         if (assigned_address != NULL) {
    276                 *assigned_address = dev_addr;
    277         }
    278         if (assigned_handle != NULL) {
    279                 *assigned_handle = child_handle;
    280         }
    281 
    282         return EOK;
    283 
    284 
    285 
    286         /*
    287          * Error handling (like nested exceptions) starts here.
    288          * Completely ignoring errors here.
    289          */
    290 
    291 leave_stop_session:
    292         usb_endpoint_pipe_end_session(&ctrl_pipe);
    293 
    294 leave_release_default_address:
    295         usb_hc_release_default_address(connection);
    296 
    297 leave_release_free_address:
    298         usb_hc_unregister_device(connection, dev_addr);
    299 
    300         return rc;
    301 }
    302 
    303 
    304140/**
    305141 * @}
  • uspace/lib/usb/src/pipes.c

    r62066b4 r6bb83c7  
    3535#include <usb/usb.h>
    3636#include <usb/pipes.h>
    37 #include <usbhc_iface.h>
    3837#include <errno.h>
    3938#include <assert.h>
    40 
    41 /** Tell USB address assigned to given device.
    42  *
    43  * @param phone Phone to my HC.
    44  * @param dev Device in question.
    45  * @return USB address or error code.
    46  */
    47 static usb_address_t get_my_address(int phone, device_t *dev)
    48 {
    49         sysarg_t address;
    50         int rc = async_req_2_1(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
    51             IPC_M_USBHC_GET_ADDRESS,
    52             dev->handle, &address);
    53 
    54         if (rc != EOK) {
    55                 return rc;
    56         }
    57 
    58         return (usb_address_t) address;
    59 }
     39#include <usb/usbdrv.h>
    6040
    6141/** Initialize connection to USB device.
     
    7555        usb_address_t my_address;
    7656
    77         rc = usb_hc_find(device->handle, &hc_handle);
     57        rc = usb_drv_find_hc(device, &hc_handle);
    7858        if (rc != EOK) {
    7959                return rc;
     
    8565        }
    8666
    87         my_address = get_my_address(hc_phone, device);
     67        my_address = usb_drv_get_my_address(hc_phone, device);
    8868        if (my_address < 0) {
    8969                rc = my_address;
  • uspace/lib/usb/src/pipesio.c

    r62066b4 r6bb83c7  
    7878         * Make call identifying target USB device and type of transfer.
    7979         */
    80         aid_t opening_request = async_send_4(pipe->hc_phone,
     80        aid_t opening_request = async_send_3(pipe->hc_phone,
    8181            DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
    8282            pipe->wire->address, pipe->endpoint_no,
    83             pipe->max_packet_size,
    8483            NULL);
    8584        if (opening_request == 0) {
     
    202201         * Make call identifying target USB device and type of transfer.
    203202         */
    204         aid_t opening_request = async_send_4(pipe->hc_phone,
     203        aid_t opening_request = async_send_3(pipe->hc_phone,
    205204            DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
    206205            pipe->wire->address, pipe->endpoint_no,
    207             pipe->max_packet_size,
    208206            NULL);
    209207        if (opening_request == 0) {
     
    285283         * Make call identifying target USB device and control transfer type.
    286284         */
    287         aid_t opening_request = async_send_4(pipe->hc_phone,
     285        aid_t opening_request = async_send_3(pipe->hc_phone,
    288286            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_READ,
    289287            pipe->wire->address, pipe->endpoint_no,
    290             pipe->max_packet_size,
    291288            NULL);
    292289        if (opening_request == 0) {
     
    405402         * Make call identifying target USB device and control transfer type.
    406403         */
    407         aid_t opening_request = async_send_5(pipe->hc_phone,
     404        aid_t opening_request = async_send_4(pipe->hc_phone,
    408405            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_WRITE,
    409406            pipe->wire->address, pipe->endpoint_no,
    410407            data_buffer_size,
    411             pipe->max_packet_size,
    412408            NULL);
    413409        if (opening_request == 0) {
  • uspace/lib/usb/src/usbdrv.c

    r62066b4 r6bb83c7  
    3434 */
    3535#include <usb/usbdrv.h>
     36#include <usbhc_iface.h>
     37#include <usb_iface.h>
    3638#include <errno.h>
    37 
     39#include <str_error.h>
     40
     41/** Information about pending transaction on HC. */
     42typedef struct {
     43        /** Phone to host controller driver. */
     44        int phone;
     45        /** Data buffer. */
     46        void *buffer;
     47        /** Buffer size. */
     48        size_t size;
     49        /** Storage for actual number of bytes transferred. */
     50        size_t *size_transferred;
     51        /** Initial call reply data. */
     52        ipc_call_t reply;
     53        /** Initial call identifier. */
     54        aid_t request;
     55        /** Reply data for data read call. */
     56        ipc_call_t read_reply;
     57        /** Data read call identifier. */
     58        aid_t read_request;
     59} transfer_info_t;
    3860
    3961/** Find handle of host controller the device is physically attached to.
     
    4567int usb_drv_find_hc(device_t *dev, devman_handle_t *handle)
    4668{
    47         return ENOTSUP;
     69        if (dev == NULL) {
     70                return EBADMEM;
     71        }
     72        if (handle == NULL) {
     73                return EBADMEM;
     74        }
     75
     76        int parent_phone = devman_parent_device_connect(dev->handle,
     77            IPC_FLAG_BLOCKING);
     78        if (parent_phone < 0) {
     79                return parent_phone;
     80        }
     81
     82        devman_handle_t h;
     83        int rc = async_req_1_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
     84            IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h);
     85
     86        async_hangup(parent_phone);
     87
     88        if (rc != EOK) {
     89                return rc;
     90        }
     91
     92        *handle = h;
     93
     94        return EOK;
    4895}
    4996
     
    58105    unsigned int flags)
    59106{
    60         return ENOTSUP;
     107        return devman_device_connect(hc_handle, flags);
    61108}
    62109
     
    69116int usb_drv_hc_connect_auto(device_t *dev, unsigned int flags)
    70117{
    71         return ENOTSUP;
     118        int rc;
     119        devman_handle_t hc_handle;
     120
     121        /*
     122         * Call parent hub to obtain device handle of respective HC.
     123         */
     124        rc = usb_drv_find_hc(dev, &hc_handle);
     125        if (rc != EOK) {
     126                return rc;
     127        }
     128       
     129        return usb_drv_hc_connect(dev, hc_handle, flags);
    72130}
    73131
     
    80138usb_address_t usb_drv_get_my_address(int phone, device_t *dev)
    81139{
    82         return ENOTSUP;
     140        sysarg_t address;
     141        int rc = async_req_2_1(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
     142            IPC_M_USBHC_GET_ADDRESS,
     143            dev->handle, &address);
     144
     145        if (rc != EOK) {
     146                return rc;
     147        }
     148
     149        return (usb_address_t) address;
    83150}
    84151
     
    90157int usb_drv_reserve_default_address(int phone)
    91158{
    92         return ENOTSUP;
     159        return async_req_1_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
     160            IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS);
    93161}
    94162
     
    100168int usb_drv_release_default_address(int phone)
    101169{
    102         return ENOTSUP;
     170        return async_req_1_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
     171            IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS);
    103172}
    104173
     
    110179usb_address_t usb_drv_request_address(int phone)
    111180{
    112         return ENOTSUP;
     181        sysarg_t address;
     182        int rc = async_req_1_1(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
     183            IPC_M_USBHC_REQUEST_ADDRESS, &address);
     184        if (rc != EOK) {
     185                return rc;
     186        } else {
     187                return (usb_address_t) address;
     188        }
    113189}
    114190
     
    123199    devman_handle_t handle)
    124200{
    125         return ENOTSUP;
     201        int rc = async_req_3_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
     202            IPC_M_USBHC_BIND_ADDRESS,
     203            address, handle);
     204
     205        return rc;
    126206}
    127207
     
    134214int usb_drv_release_address(int phone, usb_address_t address)
    135215{
    136         return ENOTSUP;
    137 }
     216        return async_req_2_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
     217            IPC_M_USBHC_RELEASE_ADDRESS, address);
     218}
     219
     220/** Send data to HCD.
     221 *
     222 * @param phone Phone to HC.
     223 * @param method Method used for calling.
     224 * @param target Targeted device.
     225 * @param buffer Data buffer (NULL to skip data transfer phase).
     226 * @param size Buffer size (must be zero when @p buffer is NULL).
     227 * @param handle Storage for transaction handle (cannot be NULL).
     228 * @return Error status.
     229 * @retval EINVAL Invalid parameter.
     230 * @retval ENOMEM Not enough memory to complete the operation.
     231 */
     232static int async_send_buffer(int phone, int method,
     233    usb_target_t target,
     234    void *buffer, size_t size,
     235    usb_handle_t *handle)
     236{
     237        if (phone < 0) {
     238                return EINVAL;
     239        }
     240
     241        if ((buffer == NULL) && (size > 0)) {
     242                return EINVAL;
     243        }
     244
     245        if (handle == NULL) {
     246                return EINVAL;
     247        }
     248
     249        transfer_info_t *transfer
     250            = (transfer_info_t *) malloc(sizeof(transfer_info_t));
     251        if (transfer == NULL) {
     252                return ENOMEM;
     253        }
     254
     255        transfer->read_request = 0;
     256        transfer->size_transferred = NULL;
     257        transfer->buffer = NULL;
     258        transfer->size = 0;
     259        transfer->phone = phone;
     260
     261        int rc;
     262
     263        transfer->request = async_send_4(phone,
     264            DEV_IFACE_ID(USBHC_DEV_IFACE),
     265            method,
     266            target.address, target.endpoint,
     267            size,
     268            &transfer->reply);
     269
     270        if (size > 0) {
     271                rc = async_data_write_start(phone, buffer, size);
     272                if (rc != EOK) {
     273                        async_wait_for(transfer->request, NULL);
     274                        return rc;
     275                }
     276        }
     277
     278        *handle = (usb_handle_t) transfer;
     279
     280        return EOK;
     281}
     282
     283/** Prepare data retrieval.
     284 *
     285 * @param phone Opened phone to HCD.
     286 * @param method Method used for calling.
     287 * @param target Targeted device.
     288 * @param buffer Buffer where to store retrieved data
     289 *      (NULL to skip data transfer phase).
     290 * @param size Buffer size (must be zero when @p buffer is NULL).
     291 * @param actual_size Storage where actual number of bytes transferred will
     292 *      be stored.
     293 * @param handle Storage for transaction handle (cannot be NULL).
     294 * @return Error status.
     295 * @retval EINVAL Invalid parameter.
     296 * @retval ENOMEM Not enough memory to complete the operation.
     297 */
     298static int async_recv_buffer(int phone, int method,
     299    usb_target_t target,
     300    void *buffer, size_t size, size_t *actual_size,
     301    usb_handle_t *handle)
     302{
     303        if (phone < 0) {
     304                return EINVAL;
     305        }
     306
     307        if ((buffer == NULL) && (size > 0)) {
     308                return EINVAL;
     309        }
     310
     311        if (handle == NULL) {
     312                return EINVAL;
     313        }
     314
     315        transfer_info_t *transfer
     316            = (transfer_info_t *) malloc(sizeof(transfer_info_t));
     317        if (transfer == NULL) {
     318                return ENOMEM;
     319        }
     320
     321        transfer->read_request = 0;
     322        transfer->size_transferred = actual_size;
     323        transfer->buffer = buffer;
     324        transfer->size = size;
     325        transfer->phone = phone;
     326
     327        transfer->request = async_send_4(phone,
     328            DEV_IFACE_ID(USBHC_DEV_IFACE),
     329            method,
     330            target.address, target.endpoint,
     331            size,
     332            &transfer->reply);
     333
     334        if (buffer != NULL) {
     335                transfer->read_request = async_data_read(phone, buffer, size,
     336                    &transfer->read_reply);
     337        }
     338
     339        *handle = (usb_handle_t) transfer;
     340
     341        return EOK;
     342}
     343
    138344
    139345/** Blocks caller until given USB transaction is finished.
     
    149355int usb_drv_async_wait_for(usb_handle_t handle)
    150356{
    151         return ENOTSUP;
     357        if (handle == 0) {
     358                return EBADMEM;
     359        }
     360
     361        int rc = EOK;
     362
     363        transfer_info_t *transfer = (transfer_info_t *) handle;
     364
     365        sysarg_t answer_rc;
     366
     367        /*
     368         * If the buffer is not NULL, we must accept some data.
     369         */
     370        if ((transfer->buffer != NULL) && (transfer->size > 0)) {
     371                async_wait_for(transfer->read_request, &answer_rc);
     372
     373                if (answer_rc != EOK) {
     374                        rc = (int) answer_rc;
     375                        goto leave;
     376                }
     377
     378                if (transfer->size_transferred != NULL) {
     379                        *(transfer->size_transferred)
     380                            = IPC_GET_ARG2(transfer->read_reply);
     381                }
     382        }
     383
     384        async_wait_for(transfer->request, &answer_rc);
     385
     386        if (answer_rc != EOK) {
     387                rc = (int) answer_rc;
     388                goto leave;
     389        }
     390
     391leave:
     392        free(transfer);
     393
     394        return rc;
    152395}
    153396
     
    157400    usb_handle_t *handle)
    158401{
    159         return ENOTSUP;
     402        return async_send_buffer(phone,
     403            IPC_M_USBHC_INTERRUPT_OUT,
     404            target,
     405            buffer, size,
     406            handle);
    160407}
    161408
     
    165412    usb_handle_t *handle)
    166413{
    167         return ENOTSUP;
     414        return async_recv_buffer(phone,
     415            IPC_M_USBHC_INTERRUPT_IN,
     416            target,
     417            buffer, size, actual_size,
     418            handle);
    168419}
    169420
     
    173424    usb_handle_t *handle)
    174425{
    175         return ENOTSUP;
     426        return async_send_buffer(phone,
     427            IPC_M_USBHC_CONTROL_WRITE_SETUP,
     428            target,
     429            buffer, size,
     430            handle);
    176431}
    177432
     
    181436    usb_handle_t *handle)
    182437{
    183         return ENOTSUP;
     438        return async_send_buffer(phone,
     439            IPC_M_USBHC_CONTROL_WRITE_DATA,
     440            target,
     441            buffer, size,
     442            handle);
    184443}
    185444
     
    188447    usb_handle_t *handle)
    189448{
    190         return ENOTSUP;
     449        return async_recv_buffer(phone,
     450            IPC_M_USBHC_CONTROL_WRITE_STATUS,
     451            target,
     452            NULL, 0, NULL,
     453            handle);
    191454}
    192455
     
    197460    usb_handle_t *handle)
    198461{
    199         return ENOTSUP;
     462        // FIXME - check input parameters instead of asserting them
     463        assert(phone > 0);
     464        assert(setup_packet != NULL);
     465        assert(setup_packet_size > 0);
     466        assert(((buffer != NULL) && (buffer_size > 0))
     467            || ((buffer == NULL) && (buffer_size == 0)));
     468        assert(handle != NULL);
     469
     470        transfer_info_t *transfer
     471            = (transfer_info_t *) malloc(sizeof(transfer_info_t));
     472        if (transfer == NULL) {
     473                return ENOMEM;
     474        }
     475
     476        transfer->read_request = 0;
     477        transfer->size_transferred = NULL;
     478        transfer->buffer = NULL;
     479        transfer->size = 0;
     480        transfer->phone = phone;
     481
     482        int rc;
     483
     484        transfer->request = async_send_3(phone,
     485            DEV_IFACE_ID(USBHC_DEV_IFACE),
     486            IPC_M_USBHC_CONTROL_WRITE,
     487            target.address, target.endpoint,
     488            &transfer->reply);
     489
     490        rc = async_data_write_start(phone, setup_packet, setup_packet_size);
     491        if (rc != EOK) {
     492                async_wait_for(transfer->request, NULL);
     493                return rc;
     494        }
     495
     496        if (buffer_size > 0) {
     497                rc = async_data_write_start(phone, buffer, buffer_size);
     498                if (rc != EOK) {
     499                        async_wait_for(transfer->request, NULL);
     500                        return rc;
     501                }
     502        }
     503
     504        *handle = (usb_handle_t) transfer;
     505
     506        return EOK;
    200507}
    201508
     
    205512    usb_handle_t *handle)
    206513{
    207         return ENOTSUP;
     514        return async_send_buffer(phone,
     515            IPC_M_USBHC_CONTROL_READ_SETUP,
     516            target,
     517            buffer, size,
     518            handle);
    208519}
    209520
     
    213524    usb_handle_t *handle)
    214525{
    215         return ENOTSUP;
     526        return async_recv_buffer(phone,
     527            IPC_M_USBHC_CONTROL_READ_DATA,
     528            target,
     529            buffer, size, actual_size,
     530            handle);
    216531}
    217532
     
    220535    usb_handle_t *handle)
    221536{
    222         return ENOTSUP;
     537        return async_send_buffer(phone,
     538            IPC_M_USBHC_CONTROL_READ_STATUS,
     539            target,
     540            NULL, 0,
     541            handle);
    223542}
    224543
     
    229548    usb_handle_t *handle)
    230549{
    231         return ENOTSUP;
     550        // FIXME - check input parameters instead of asserting them
     551        assert(phone > 0);
     552        assert(setup_packet != NULL);
     553        assert(setup_packet_size > 0);
     554        assert(buffer != NULL);
     555        assert(buffer_size > 0);
     556        assert(handle != NULL);
     557
     558        transfer_info_t *transfer
     559            = (transfer_info_t *) malloc(sizeof(transfer_info_t));
     560        if (transfer == NULL) {
     561                return ENOMEM;
     562        }
     563
     564        transfer->size_transferred = actual_size;
     565        transfer->buffer = buffer;
     566        transfer->size = buffer_size;
     567        transfer->phone = phone;
     568
     569        int rc;
     570
     571        transfer->request = async_send_4(phone,
     572            DEV_IFACE_ID(USBHC_DEV_IFACE),
     573            IPC_M_USBHC_CONTROL_READ,
     574            target.address, target.endpoint,
     575            buffer_size,
     576            &transfer->reply);
     577
     578        rc = async_data_write_start(phone, setup_packet, setup_packet_size);
     579        if (rc != EOK) {
     580                async_wait_for(transfer->request, NULL);
     581                return rc;
     582        }
     583
     584        transfer->read_request = async_data_read(phone, buffer, buffer_size,
     585            &transfer->read_reply);
     586
     587        *handle = (usb_handle_t) transfer;
     588
     589        return EOK;
    232590}
    233591
Note: See TracChangeset for help on using the changeset viewer.