Changes in / [6bb83c7:070f11e] in mainline


Ignore:
Files:
9 added
42 edited

Legend:

Unmodified
Added
Removed
  • .bzrignore

    r6bb83c7 r070f11e  
    8888./uspace/drv/usbhub/usbhub
    8989./uspace/drv/usbhid/usbhid
     90./uspace/drv/usbmid/usbmid
    9091./uspace/drv/vhc/vhc
    9192./uspace/srv/bd/ata_bd/ata_bd
  • boot/arch/amd64/Makefile.inc

    r6bb83c7 r070f11e  
    4747        usbhub \
    4848        usbhid \
     49        usbmid \
    4950        vhc
    5051
  • uspace/Makefile

    r6bb83c7 r070f11e  
    121121                drv/usbhid \
    122122                drv/usbhub \
     123                drv/usbmid \
    123124                drv/vhc
    124125endif
     
    136137                drv/usbhid \
    137138                drv/usbhub \
     139                drv/usbmid \
    138140                drv/vhc
    139141endif
  • uspace/doc/doxygroups.h

    r6bb83c7 r070f11e  
    220220
    221221        /**
     222         * @defgroup drvusbmid USB multi interface device driver
     223         * @ingroup usb
     224         * @brief USB multi interface device driver
     225         * @details
     226         * This driver serves as a mini hub (or bus) driver for devices
     227         * that have the class defined at interface level (those devices
     228         * usually have several interfaces).
     229         *
     230         * The term multi interface device driver (MID) was borrowed
     231         * Solaris operating system.
     232         */
     233
     234        /**
    222235         * @defgroup drvusbhub USB hub driver
    223236         * @ingroup usb
  • uspace/drv/pciintel/pci.c

    r6bb83c7 r070f11e  
    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>
    5155#include <ops/hw_res.h>
    5256#include <device/hw_res.h>
     
    7276static bool pciintel_enable_child_interrupt(device_t *dev)
    7377{
    74         /* TODO */
    75        
    76         return false;
     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;
    77110}
    78111
  • uspace/drv/uhci-hcd/batch.c

    r6bb83c7 r070f11e  
    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 */
    144143        instance->transfered_size = 0;
    145144        size_t i = 0;
     
    157156                    transfer_descriptor_actual_size(&instance->tds[i]);
    158157        }
     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
    193195        instance->next_step = batch_call_out_and_dispose;
    194196        batch_schedule(instance);
     
    221223        transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
    222224            0, 1, false, instance->target, USB_PID_OUT, NULL, NULL);
     225
     226        instance->tds[i].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
    223227
    224228        instance->next_step = batch_call_in_and_dispose;
     
    244248        }
    245249
     250        instance->tds[i - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
     251
    246252        instance->next_step = batch_call_in_and_dispose;
    247253        batch_schedule(instance);
     
    268274        }
    269275
     276        instance->tds[i - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
     277
    270278        instance->next_step = batch_call_out_and_dispose;
    271279        batch_schedule(instance);
  • uspace/drv/uhci-hcd/iface.c

    r6bb83c7 r070f11e  
    4242#include "uhci.h"
    4343
    44 static int get_address(device_t *dev, devman_handle_t handle,
    45     usb_address_t *address)
    46 {
    47         assert(dev);
    48         uhci_t *hc = dev_to_uhci(dev);
    49         assert(hc);
    50         *address = usb_address_keeping_find(&hc->address_manager, handle);
    51         if (*address <= 0)
    52           return *address;
    53         return EOK;
    54 }
    5544/*----------------------------------------------------------------------------*/
    56 static int reserve_default_address(device_t *dev, bool full_speed)
     45static int reserve_default_address(device_t *dev, usb_speed_t speed)
    5746{
    5847        assert(dev);
     
    7261}
    7362/*----------------------------------------------------------------------------*/
    74 static int request_address(device_t *dev, bool full_speed,
     63static int request_address(device_t *dev, usb_speed_t speed,
    7564    usb_address_t *address)
    7665{
     
    164153        return EOK;
    165154}
    166 /*----------------------------------------------------------------------------*/
    167 static 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;
    173155
    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 /*----------------------------------------------------------------------------*/
    183 static 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;
    189156
    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 /*----------------------------------------------------------------------------*/
    199 static 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 /*----------------------------------------------------------------------------*/
    214 static 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 /*----------------------------------------------------------------------------*/
    230 static 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 /*----------------------------------------------------------------------------*/
    246 static 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 }
    260157/*----------------------------------------------------------------------------*/
    261158usbhc_iface_t uhci_iface = {
    262         .tell_address = get_address,
    263 
    264159        .reserve_default_address = reserve_default_address,
    265160        .release_default_address = release_default_address,
     
    273168        .control_read = control_read,
    274169        .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
    283170};
    284171/**
  • uspace/drv/uhci-hcd/main.c

    r6bb83c7 r070f11e  
    3434#include <driver.h>
    3535#include <usb_iface.h>
     36#include <usb/ddfiface.h>
     37#include <device/hw_res.h>
    3638
    3739#include <errno.h>
     
    4648#define NAME "uhci-hcd"
    4749
    48 static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
     50static int uhci_add_device(device_t *device);
     51
     52static int usb_iface_get_address(device_t *dev, devman_handle_t handle,
     53    usb_address_t *address)
    4954{
    50         /* This shall be called only for the UHCI itself. */
    51         assert(dev->parent == NULL);
     55        assert(dev);
     56        uhci_t *hc = dev_to_uhci(dev);
     57        assert(hc);
    5258
    53         *handle = dev->handle;
     59        usb_address_t addr = usb_address_keeping_find(&hc->address_manager,
     60            handle);
     61        if (addr < 0) {
     62                return addr;
     63        }
     64
     65        if (address != NULL) {
     66                *address = addr;
     67        }
     68
    5469        return EOK;
    5570}
    5671
     72
    5773static usb_iface_t hc_usb_iface = {
    58         .get_hc_handle = usb_iface_get_hc_handle
     74        .get_hc_handle = usb_iface_get_hc_handle_hc_impl,
     75        .get_address = usb_iface_get_address
    5976};
    60 
     77/*----------------------------------------------------------------------------*/
    6178static device_ops_t uhci_ops = {
    6279        .interfaces[USB_DEV_IFACE] = &hc_usb_iface,
    6380        .interfaces[USBHC_DEV_IFACE] = &uhci_iface
    6481};
     82/*----------------------------------------------------------------------------*/
     83static driver_ops_t uhci_driver_ops = {
     84        .add_device = uhci_add_device,
     85};
     86/*----------------------------------------------------------------------------*/
     87static driver_t uhci_driver = {
     88        .name = NAME,
     89        .driver_ops = &uhci_driver_ops
     90};
     91/*----------------------------------------------------------------------------*/
     92static void irq_handler(device_t *device, ipc_callid_t iid, ipc_call_t *call)
     93{
     94        assert(device);
     95        uhci_t *hc = dev_to_uhci(device);
     96        uint16_t status = IPC_GET_ARG1(*call);
     97        assert(hc);
     98        uhci_interrupt(hc, status);
     99}
     100/*----------------------------------------------------------------------------*/
     101#define CHECK_RET_RETURN(ret, message...) \
     102if (ret != EOK) { \
     103        usb_log_error(message); \
     104        return ret; \
     105}
    65106
    66107static int uhci_add_device(device_t *device)
     
    75116        int irq;
    76117
    77         int rc = pci_get_my_registers(device,
    78             &io_reg_base, &io_reg_size, &irq);
     118        int ret =
     119            pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq);
    79120
    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 
     121        CHECK_RET_RETURN(ret,
     122            "Failed(%d) to get I/O addresses:.\n", ret, device->handle);
    86123        usb_log_info("I/O regs at 0x%X (size %zu), IRQ %d.\n",
    87124            io_reg_base, io_reg_size, irq);
    88125
     126        ret = pci_enable_interrupts(device);
     127        CHECK_RET_RETURN(ret, "Failed(%d) to get enable interrupts:\n", ret);
     128
    89129        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;
     130        ret = (uhci_hc != NULL) ? EOK : ENOMEM;
     131        CHECK_RET_RETURN(ret, "Failed to allocate memory for uhci hcd driver.\n");
     132
     133        ret = uhci_init(uhci_hc, (void*)io_reg_base, io_reg_size);
     134        if (ret != EOK) {
     135                usb_log_error("Failed to init uhci-hcd.\n");
     136                free(uhci_hc);
     137                return ret;
    93138        }
    94139
    95         int ret = uhci_init(uhci_hc, (void*)io_reg_base, io_reg_size);
     140        ret = register_interrupt_handler(device, irq, irq_handler,
     141            &uhci_hc->interrupt_code);
    96142        if (ret != EOK) {
    97                 usb_log_error("Failed to init uhci-hcd.\n");
     143                usb_log_error("Failed to register interrupt handler.\n");
     144                uhci_fini(uhci_hc);
     145                free(uhci_hc);
    98146                return ret;
    99147        }
     148
    100149        device_t *rh;
    101150        ret = setup_root_hub(&rh, device);
    102 
    103151        if (ret != EOK) {
    104152                usb_log_error("Failed to setup uhci root hub.\n");
    105                 /* TODO: destroy uhci here */
     153                uhci_fini(uhci_hc);
     154                free(uhci_hc);
    106155                return ret;
    107156        }
     
    110159        if (ret != EOK) {
    111160                usb_log_error("Failed to register root hub.\n");
    112                 /* TODO: destroy uhci here */
     161                uhci_fini(uhci_hc);
     162                free(uhci_hc);
     163                free(rh);
    113164                return ret;
    114165        }
    115166
    116167        device->driver_data = uhci_hc;
    117 
    118168        return EOK;
    119169}
    120 
    121 static driver_ops_t uhci_driver_ops = {
    122         .add_device = uhci_add_device,
    123 };
    124 
    125 static driver_t uhci_driver = {
    126         .name = NAME,
    127         .driver_ops = &uhci_driver_ops
    128 };
    129 
     170/*----------------------------------------------------------------------------*/
    130171int main(int argc, char *argv[])
    131172{
    132         /*
    133          * Do some global initializations.
    134          */
    135         sleep(5);
    136         usb_log_enable(USB_LOG_LEVEL_INFO, NAME);
     173        sleep(3);
     174        usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
    137175
    138176        return driver_main(&uhci_driver);
  • uspace/drv/uhci-hcd/pci.c

    r6bb83c7 r070f11e  
    121121        return rc;
    122122}
    123 
     123/*----------------------------------------------------------------------------*/
     124int 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}
    124131/**
    125132 * @}
  • uspace/drv/uhci-hcd/pci.h

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

    r6bb83c7 r070f11e  
    111111        /* I'm the first one here */
    112112        if (batch->link.prev == &instance->batch_list) {
    113                 usb_log_debug("Removing tracer %p was first, next element %x.\n",
     113                usb_log_debug("Removing batch %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 tracer %p was NOT first, next element %x.\n",
     117                usb_log_debug("Removing batch %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

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

    r6bb83c7 r070f11e  
    3939
    4040#include "uhci.h"
     41static 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};
    4156
    4257static int uhci_init_transfer_lists(uhci_t *instance);
    43 static int uhci_clean_finished(void *arg);
     58static int uhci_init_mem_structures(uhci_t *instance);
     59static void uhci_init_hw(uhci_t *instance);
     60
     61static int uhci_interrupt_emulator(void *arg);
    4462static int uhci_debug_checker(void *arg);
     63
    4564static bool allowed_usb_packet(
    4665        bool low_speed, usb_transfer_type_t, size_t size);
    4766
    48 int uhci_init(uhci_t *instance, void *regs, size_t reg_size)
    49 {
    50 #define CHECK_RET_RETURN(message...) \
     67#define CHECK_RET_RETURN(ret, message...) \
    5168        if (ret != EOK) { \
    5269                usb_log_error(message); \
     
    5471        } else (void) 0
    5572
    56         /* init address keeper(libusb) */
    57         usb_address_keeping_init(&instance->address_manager, USB11_ADDRESS_MAX);
    58         usb_log_debug("Initialized address manager.\n");
     73int uhci_init(uhci_t *instance, void *regs, size_t reg_size)
     74{
     75        assert(reg_size >= sizeof(regs_t));
    5976
    6077        /* allow access to hc control registers */
    6178        regs_t *io;
    62         assert(reg_size >= sizeof(regs_t));
    6379        int ret = pio_enable(regs, reg_size, (void**)&io);
    64         CHECK_RET_RETURN("Failed to gain access to registers at %p.\n", io);
     80        CHECK_RET_RETURN(ret, "Failed to gain access to registers at %p.\n", io);
    6581        instance->registers = io;
    6682        usb_log_debug("Device registers accessible.\n");
    6783
     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/*----------------------------------------------------------------------------*/
     98void 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/*----------------------------------------------------------------------------*/
     115int 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
    68131        /* init transfer lists */
    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");
     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 */
    75137        instance->frame_list = get_page();
    76138        ret = instance ? EOK : ENOMEM;
    77         CHECK_RET_RETURN("Failed to get frame list page.\n");
     139        CHECK_RET_RETURN(ret, "Failed to get frame list page.\n");
     140        usb_log_debug("Initialized frame list.\n");
    78141
    79142        /* initialize all frames to point to the first queue head */
     
    86149        }
    87150
    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);
     151        /* init address keeper(libusb) */
     152        usb_address_keeping_init(&instance->address_manager, USB11_ADDRESS_MAX);
     153        usb_log_debug("Initialized address manager.\n");
    108154
    109155        return EOK;
     
    114160        assert(instance);
    115161
    116         /* initialize */
     162        /* initialize TODO: check errors */
    117163        int ret;
    118164        ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL");
     
    146192        instance->transfers[1][USB_TRANSFER_CONTROL] =
    147193          &instance->transfers_control_slow;
    148         instance->transfers[0][USB_TRANSFER_CONTROL] =
    149           &instance->transfers_control_full;
     194        instance->transfers[0][USB_TRANSFER_BULK] =
     195          &instance->transfers_bulk_full;
    150196
    151197        return EOK;
     
    174220}
    175221/*----------------------------------------------------------------------------*/
    176 int uhci_clean_finished(void* arg)
    177 {
    178         usb_log_debug("Started cleaning fibril.\n");
     222void 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/*----------------------------------------------------------------------------*/
     234int uhci_interrupt_emulator(void* arg)
     235{
     236        usb_log_debug("Started interrupt emulator.\n");
    179237        uhci_t *instance = (uhci_t*)arg;
    180238        assert(instance);
    181239
    182240        while(1) {
    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);
     241                uint16_t status = pio_read_16(&instance->registers->usbsts);
     242                uhci_interrupt(instance, status);
    187243                async_usleep(UHCI_CLEANER_TIMEOUT);
    188244        }
     
    195251        assert(instance);
    196252        while (1) {
    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);
     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);
    200258
    201259                uintptr_t frame_list = pio_read_32(&instance->registers->flbaseadd);
    202                 if (frame_list != (uintptr_t)addr_to_phys(instance->frame_list)) {
     260                if (frame_list != addr_to_phys(instance->frame_list)) {
    203261                        usb_log_debug("Framelist address: %p vs. %p.\n",
    204262                                frame_list, addr_to_phys(instance->frame_list));
  • uspace/drv/uhci-hcd/uhci.h

    r6bb83c7 r070f11e  
    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
    6873        uint16_t frnum;
    6974        uint32_t flbaseadd;
     
    8186        link_pointer_t *frame_list;
    8287
    83         link_t batch_list;
    84         fibril_mutex_t batch_list_mutex;
    85 
    8688        transfer_list_t transfers_bulk_full;
    8789        transfer_list_t transfers_control_full;
     
    9092
    9193        transfer_list_t *transfers[2][4];
     94
     95        irq_code_t interrupt_code;
    9296
    9397        fid_t cleaner;
     
    98102int uhci_init(uhci_t *instance, void *regs, size_t reg_size);
    99103
    100 int uhci_fini(uhci_t *device);
    101 
    102 int 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 );
     104static inline void uhci_fini(uhci_t *instance) {};
    114105
    115106int uhci_schedule(uhci_t *instance, batch_t *batch);
    116107
     108void uhci_interrupt(uhci_t *instance, uint16_t status);
     109
    117110static inline uhci_t * dev_to_uhci(device_t *dev)
    118111        { return (uhci_t*)dev->driver_data; }
     112
    119113
    120114#endif
  • uspace/drv/uhci-rhd/main.c

    r6bb83c7 r070f11e  
    3434#include <driver.h>
    3535#include <usb_iface.h>
     36#include <usb/ddfiface.h>
    3637
    3738#include <errno.h>
     
    5657
    5758static usb_iface_t uhci_rh_usb_iface = {
    58         .get_hc_handle = usb_iface_get_hc_handle
     59        .get_hc_handle = usb_iface_get_hc_handle,
     60        .get_address = usb_iface_get_address_hub_impl
    5961};
    6062
  • uspace/drv/uhci-rhd/port.c

    r6bb83c7 r070f11e  
    131131        return EOK;
    132132}
    133 /*----------------------------------------------------------------------------*/
    134 static 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);
     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 */
     140static 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);
    170145
    171146        /*
    172          * the host then waits for at least 100 ms to allow completion of
     147         * The host then waits for at least 100 ms to allow completion of
    173148         * an insertion process and for power at the device to become stable.
    174149         */
    175150        async_usleep(100000);
    176151
    177         /* enable port */
     152        /* Enable the port. */
    178153        uhci_port_set_enabled(port, true);
    179154
     
    197172        }
    198173
    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);
     174        return EOK;
     175}
     176
     177/*----------------------------------------------------------------------------*/
     178static 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));
    221193                uhci_port_set_enabled(port, false);
    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 }
     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
    273203/*----------------------------------------------------------------------------*/
    274204static int uhci_port_remove_device(uhci_port_t *port)
  • uspace/drv/uhci-rhd/root_hub.c

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

    r6bb83c7 r070f11e  
    265265        for (i = 0; i < count; ++i) {
    266266                printf("%d ", key_codes[i]);
     267        }
     268        printf("\n");
     269
     270        for (i = 0; i < count; ++i) {
    267271                // TODO: Key press / release
    268272
    269273                // TODO: NOT WORKING
    270274                unsigned int key = usbkbd_parse_scancode(key_codes[i]);
     275
     276                if (key == 0) {
     277                        continue;
     278                }
    271279                kbd_push_ev(KEY_PRESS, key);
    272280        }
     
    348356                {
    349357                        .pipe = &kbd_dev->poll_pipe,
    350                         .description = &poll_endpoint_description
     358                        .description = &poll_endpoint_description,
     359                        .interface_no =
     360                            usb_device_get_assigned_interface(kbd_dev->device)
    351361                }
    352362        };
  • uspace/drv/usbhub/usbhub.c

    r6bb83c7 r070f11e  
    3939
    4040#include <usb_iface.h>
     41#include <usb/ddfiface.h>
    4142#include <usb/usbdrv.h>
    4243#include <usb/descriptor.h>
     
    5253#include "usb/pipes.h"
    5354
    54 static usb_iface_t hub_usb_iface = {
    55         .get_hc_handle = usb_drv_find_hc
    56 };
    57 
    5855static device_ops_t hub_device_ops = {
    59         .interfaces[USB_DEV_IFACE] = &hub_usb_iface
     56        .interfaces[USB_DEV_IFACE] = &usb_iface_hub_impl
    6057};
    6158
  • uspace/drv/vhc/conn.h

    r6bb83c7 r070f11e  
    3838#include <usb/usb.h>
    3939#include <usbhc_iface.h>
     40#include <usb_iface.h>
    4041#include "vhcd.h"
    4142#include "devices.h"
     
    4344void connection_handler_host(sysarg_t);
    4445
    45 usbhc_iface_t vhc_iface;
     46extern usbhc_iface_t vhc_iface;
     47extern usb_iface_t vhc_usb_iface;
    4648
    4749void address_init(void);
  • uspace/drv/vhc/connhost.c

    r6bb83c7 r070f11e  
    3737#include <usb/usb.h>
    3838#include <usb/addrkeep.h>
     39#include <usb/ddfiface.h>
    3940
    4041#include "vhcd.h"
     
    234235}
    235236
    236 static 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 
    256237static int enqueue_transfer_in(device_t *dev,
    257238    usb_target_t target, usb_transfer_type_t transfer_type,
     
    292273        return enqueue_transfer_in(dev, target, USB_TRANSFER_INTERRUPT,
    293274            data, size,
    294             callback, arg);
    295 }
    296 
    297 static 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 
    307 static 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 
    317 static 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,
    322275            callback, arg);
    323276}
     
    341294}
    342295
    343 static 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 
    353 static 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 
    363 static 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 
    371296static int control_read(device_t *dev, usb_target_t target,
    372297    size_t max_packet_size,
     
    389314static usb_address_keeping_t addresses;
    390315
    391 
    392 static int reserve_default_address(device_t *dev, bool ignored)
     316static int tell_address(device_t *dev, devman_handle_t handle,
     317    usb_address_t *address)
     318{
     319        usb_address_t addr = usb_address_keeping_find(&addresses, handle);
     320        if (addr < 0) {
     321                return addr;
     322        }
     323
     324        *address = addr;
     325        return EOK;
     326}
     327
     328static int reserve_default_address(device_t *dev, usb_speed_t ignored)
    393329{
    394330        usb_address_keeping_reserve_default(&addresses);
     
    402338}
    403339
    404 static int request_address(device_t *dev, bool ignored, usb_address_t *address)
     340static int request_address(device_t *dev, usb_speed_t ignored,
     341    usb_address_t *address)
    405342{
    406343        usb_address_t addr = usb_address_keeping_request(&addresses);
     
    425362}
    426363
    427 static int tell_address(device_t *dev, devman_handle_t handle,
    428     usb_address_t *address)
    429 {
    430         usb_address_t addr = usb_address_keeping_find(&addresses, handle);
    431         if (addr < 0) {
    432                 return addr;
    433         }
    434 
    435         *address = addr;
    436         return EOK;
    437 }
    438 
    439364void address_init(void)
    440365{
     
    443368
    444369usbhc_iface_t vhc_iface = {
    445         .tell_address = tell_address,
    446 
    447370        .reserve_default_address = reserve_default_address,
    448371        .release_default_address = release_default_address,
     
    454377        .interrupt_in = interrupt_in,
    455378
    456         .control_write_setup = control_write_setup,
    457         .control_write_data = control_write_data,
    458         .control_write_status = control_write_status,
    459 
    460379        .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 
    466380        .control_read = control_read
    467381};
     382
     383usb_iface_t vhc_usb_iface = {
     384        .get_hc_handle = usb_iface_get_hc_handle_hc_impl,
     385        .get_address = tell_address
     386};
     387
    468388
    469389/**
  • uspace/drv/vhc/hcd.c

    r6bb83c7 r070f11e  
    4545
    4646#include <usb/usb.h>
     47#include <usb/ddfiface.h>
    4748#include <usb_iface.h>
    4849#include "vhcd.h"
     
    5253#include "conn.h"
    5354
    54 static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
    55 {
    56         /* This shall be called only for VHC device. */
    57         assert(dev->parent == NULL);
    58 
    59         *handle = dev->handle;
    60         return EOK;
    61 }
    62 
    63 static usb_iface_t hc_usb_iface = {
    64         .get_hc_handle = usb_iface_get_hc_handle
    65 };
    66 
    6755static device_ops_t vhc_ops = {
    6856        .interfaces[USBHC_DEV_IFACE] = &vhc_iface,
    69         .interfaces[USB_DEV_IFACE] = &hc_usb_iface,
     57        .interfaces[USB_DEV_IFACE] = &vhc_usb_iface,
    7058        .close = on_client_close,
    7159        .default_handler = default_connection_handler
  • uspace/lib/c/generic/str_error.c

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

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

    r6bb83c7 r070f11e  
    4040
    4141
     42static void remote_usb_get_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
     43static void remote_usb_get_interface(device_t *, void *, ipc_callid_t, ipc_call_t *);
    4244static void remote_usb_get_hc_handle(device_t *, void *, ipc_callid_t, ipc_call_t *);
    4345//static void remote_usb(device_t *, void *, ipc_callid_t, ipc_call_t *);
     
    4547/** Remote USB interface operations. */
    4648static remote_iface_func_ptr_t remote_usb_iface_ops [] = {
     49        remote_usb_get_address,
     50        remote_usb_get_interface,
    4751        remote_usb_get_hc_handle
    4852};
     
    5660};
    5761
     62
     63void remote_usb_get_address(device_t *device, void *iface,
     64    ipc_callid_t callid, ipc_call_t *call)
     65{
     66        usb_iface_t *usb_iface = (usb_iface_t *) iface;
     67
     68        if (usb_iface->get_address == NULL) {
     69                async_answer_0(callid, ENOTSUP);
     70                return;
     71        }
     72
     73        devman_handle_t handle = DEV_IPC_GET_ARG1(*call);
     74
     75        usb_address_t address;
     76        int rc = usb_iface->get_address(device, handle, &address);
     77        if (rc != EOK) {
     78                async_answer_0(callid, rc);
     79        } else {
     80                async_answer_1(callid, EOK, address);
     81        }
     82}
     83
     84void remote_usb_get_interface(device_t *device, void *iface,
     85    ipc_callid_t callid, ipc_call_t *call)
     86{
     87        usb_iface_t *usb_iface = (usb_iface_t *) iface;
     88
     89        if (usb_iface->get_interface == NULL) {
     90                async_answer_0(callid, ENOTSUP);
     91                return;
     92        }
     93
     94        devman_handle_t handle = DEV_IPC_GET_ARG1(*call);
     95
     96        int iface_no;
     97        int rc = usb_iface->get_interface(device, handle, &iface_no);
     98        if (rc != EOK) {
     99                async_answer_0(callid, rc);
     100        } else {
     101                async_answer_1(callid, EOK, iface_no);
     102        }
     103}
    58104
    59105void remote_usb_get_hc_handle(device_t *device, void *iface,
  • uspace/lib/drv/generic/remote_usbhc.c

    r6bb83c7 r070f11e  
    4343#define HACK_MAX_PACKET_SIZE_INTERRUPT_IN 4
    4444
    45 static void remote_usbhc_get_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
    4645static void remote_usbhc_interrupt_out(device_t *, void *, ipc_callid_t, ipc_call_t *);
    4746static void remote_usbhc_interrupt_in(device_t *, void *, ipc_callid_t, ipc_call_t *);
    48 static void remote_usbhc_control_write_setup(device_t *, void *, ipc_callid_t, ipc_call_t *);
    49 static void remote_usbhc_control_write_data(device_t *, void *, ipc_callid_t, ipc_call_t *);
    50 static void remote_usbhc_control_write_status(device_t *, void *, ipc_callid_t, ipc_call_t *);
    51 static void remote_usbhc_control_read_setup(device_t *, void *, ipc_callid_t, ipc_call_t *);
    52 static void remote_usbhc_control_read_data(device_t *, void *, ipc_callid_t, ipc_call_t *);
    53 static void remote_usbhc_control_read_status(device_t *, void *, ipc_callid_t, ipc_call_t *);
     47static void remote_usbhc_bulk_out(device_t *, void *, ipc_callid_t, ipc_call_t *);
     48static void remote_usbhc_bulk_in(device_t *, void *, ipc_callid_t, ipc_call_t *);
    5449static void remote_usbhc_control_write(device_t *, void *, ipc_callid_t, ipc_call_t *);
    5550static void remote_usbhc_control_read(device_t *, void *, ipc_callid_t, ipc_call_t *);
     
    6358/** Remote USB host controller interface operations. */
    6459static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = {
    65         remote_usbhc_get_address,
    66 
    6760        remote_usbhc_reserve_default_address,
    6861        remote_usbhc_release_default_address,
     
    7568        remote_usbhc_interrupt_in,
    7669
    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,
     70        remote_usbhc_bulk_out,
     71        remote_usbhc_bulk_in,
    8472
    8573        remote_usbhc_control_write,
     
    135123}
    136124
    137 void remote_usbhc_get_address(device_t *device, void *iface,
    138     ipc_callid_t callid, ipc_call_t *call)
    139 {
    140         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    141 
    142         if (!usb_iface->tell_address) {
    143                 async_answer_0(callid, ENOTSUP);
    144                 return;
    145         }
    146 
    147         devman_handle_t handle = DEV_IPC_GET_ARG1(*call);
     125void remote_usbhc_reserve_default_address(device_t *device, void *iface,
     126    ipc_callid_t callid, ipc_call_t *call)
     127{
     128        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     129
     130        if (!usb_iface->reserve_default_address) {
     131                async_answer_0(callid, ENOTSUP);
     132                return;
     133        }
     134       
     135        usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
     136       
     137        int rc = usb_iface->reserve_default_address(device, speed);
     138
     139        async_answer_0(callid, rc);
     140}
     141
     142void remote_usbhc_release_default_address(device_t *device, void *iface,
     143    ipc_callid_t callid, ipc_call_t *call)
     144{
     145        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     146
     147        if (!usb_iface->release_default_address) {
     148                async_answer_0(callid, ENOTSUP);
     149                return;
     150        }
     151
     152        int rc = usb_iface->release_default_address(device);
     153
     154        async_answer_0(callid, rc);
     155}
     156
     157void remote_usbhc_request_address(device_t *device, void *iface,
     158    ipc_callid_t callid, ipc_call_t *call)
     159{
     160        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     161
     162        if (!usb_iface->request_address) {
     163                async_answer_0(callid, ENOTSUP);
     164                return;
     165        }
     166       
     167        usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
    148168
    149169        usb_address_t address;
    150         int rc = usb_iface->tell_address(device, handle, &address);
    151         if (rc != EOK) {
    152                 async_answer_0(callid, rc);
    153         } else {
    154                 async_answer_1(callid, EOK, address);
    155         }
    156 }
    157 
    158 void remote_usbhc_reserve_default_address(device_t *device, void *iface,
    159     ipc_callid_t callid, ipc_call_t *call)
    160 {
    161         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    162 
    163         if (!usb_iface->reserve_default_address) {
    164                 async_answer_0(callid, ENOTSUP);
    165                 return;
    166         }
    167        
    168         bool full_speed = DEV_IPC_GET_ARG1(*call);
    169        
    170         int rc = usb_iface->reserve_default_address(device, full_speed);
    171 
    172         async_answer_0(callid, rc);
    173 }
    174 
    175 void remote_usbhc_release_default_address(device_t *device, void *iface,
    176     ipc_callid_t callid, ipc_call_t *call)
    177 {
    178         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    179 
    180         if (!usb_iface->release_default_address) {
    181                 async_answer_0(callid, ENOTSUP);
    182                 return;
    183         }
    184 
    185         int rc = usb_iface->release_default_address(device);
    186 
    187         async_answer_0(callid, rc);
    188 }
    189 
    190 void remote_usbhc_request_address(device_t *device, void *iface,
    191     ipc_callid_t callid, ipc_call_t *call)
    192 {
    193         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    194 
    195         if (!usb_iface->request_address) {
    196                 async_answer_0(callid, ENOTSUP);
    197                 return;
    198         }
    199        
    200         bool full_speed = DEV_IPC_GET_ARG1(*call);
    201 
    202         usb_address_t address;
    203         int rc = usb_iface->request_address(device, full_speed, &address);
     170        int rc = usb_iface->request_address(device, speed, &address);
    204171        if (rc != EOK) {
    205172                async_answer_0(callid, rc);
     
    297264        }
    298265
    299         size_t expected_len = DEV_IPC_GET_ARG3(*call);
     266        size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
    300267        usb_target_t target = {
    301268                .address = DEV_IPC_GET_ARG1(*call),
     
    305272        size_t len = 0;
    306273        void *buffer = NULL;
    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                 }
     274
     275        int rc = async_data_write_accept(&buffer, false,
     276            1, USB_MAX_PAYLOAD_SIZE,
     277            0, &len);
     278
     279        if (rc != EOK) {
     280                async_answer_0(callid, rc);
     281                return;
    316282        }
    317283
     
    328294        trans->size = len;
    329295
    330         int rc = transfer_func(device, target, HACK_MAX_PACKET_SIZE,
     296        rc = transfer_func(device, target, max_packet_size,
    331297            buffer, len,
    332298            callback_out, trans);
     
    354320        }
    355321
    356         size_t len = DEV_IPC_GET_ARG3(*call);
     322        size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
    357323        usb_target_t target = {
    358324                .address = DEV_IPC_GET_ARG1(*call),
     
    360326        };
    361327
     328        size_t len;
    362329        ipc_callid_t data_callid;
    363330        if (!async_data_read_receive(&data_callid, &len)) {
     
    375342        trans->size = len;
    376343
    377         int rc = transfer_func(device, target, HACK_MAX_PACKET_SIZE_INTERRUPT_IN,
     344        int rc = transfer_func(device, target, max_packet_size,
    378345            trans->buffer, len,
    379346            callback_in, trans);
     
    385352}
    386353
    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  */
    396 static 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 
    455354void remote_usbhc_interrupt_out(device_t *device, void *iface,
    456355    ipc_callid_t callid, ipc_call_t *call)
     
    473372}
    474373
    475 void remote_usbhc_control_write_setup(device_t *device, void *iface,
     374void remote_usbhc_bulk_out(device_t *device, void *iface,
    476375    ipc_callid_t callid, ipc_call_t *call)
    477376{
     
    480379
    481380        return remote_usbhc_out_transfer(device, callid, call,
    482             usb_iface->control_write_setup);
    483 }
    484 
    485 void remote_usbhc_control_write_data(device_t *device, void *iface,
     381            usb_iface->bulk_out);
     382}
     383
     384void remote_usbhc_bulk_in(device_t *device, void *iface,
    486385    ipc_callid_t callid, ipc_call_t *call)
    487386{
     
    489388        assert(usb_iface != NULL);
    490389
    491         return remote_usbhc_out_transfer(device, callid, call,
    492             usb_iface->control_write_data);
    493 }
    494 
    495 void 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 
    505 void 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 
    515 void 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 
    521390        return remote_usbhc_in_transfer(device, callid, call,
    522             usb_iface->control_read_data);
    523 }
    524 
    525 void 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);
     391            usb_iface->bulk_in);
    533392}
    534393
     
    549408        };
    550409        size_t data_buffer_len = DEV_IPC_GET_ARG3(*call);
     410        size_t max_packet_size = DEV_IPC_GET_ARG4(*call);
    551411
    552412        int rc;
     
    584444        trans->size = data_buffer_len;
    585445
    586         rc = usb_iface->control_write(device, target, HACK_MAX_PACKET_SIZE,
     446        rc = usb_iface->control_write(device, target, max_packet_size,
    587447            setup_packet, setup_packet_len,
    588448            data_buffer, data_buffer_len,
     
    611471                .endpoint = DEV_IPC_GET_ARG2(*call)
    612472        };
     473        size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
    613474
    614475        int rc;
     
    648509        }
    649510
    650         rc = usb_iface->control_read(device, target, HACK_MAX_PACKET_SIZE,
     511        rc = usb_iface->control_read(device, target, max_packet_size,
    651512            setup_packet, setup_packet_len,
    652513            trans->buffer, trans->size,
  • uspace/lib/drv/include/usb_iface.h

    r6bb83c7 r070f11e  
    4141#include <usb/usb.h>
    4242typedef enum {
     43        /** Tell USB address assigned to device.
     44         * Parameters:
     45         * - devman handle id
     46         * Answer:
     47         * - EINVAL - unknown handle or handle not managed by this driver
     48         * - ENOTSUP - operation not supported (shall not happen)
     49         * - arbitrary error code if returned by remote implementation
     50         * - EOK - handle found, first parameter contains the USB address
     51         */
     52        IPC_M_USB_GET_ADDRESS,
     53
     54        /** Tell interface number given device can use.
     55         * Parameters
     56         * - devman handle id of the device
     57         * Answer:
     58         * - ENOTSUP - operation not supported (can also mean any interface)
     59         * - EOK - operation okay, first parameter contains interface number
     60         */
     61        IPC_M_USB_GET_INTERFACE,
     62
    4363        /** Tell devman handle of device host controller.
    4464         * Parameters:
     
    5575/** USB device communication interface. */
    5676typedef struct {
     77        int (*get_address)(device_t *, devman_handle_t, usb_address_t *);
     78        int (*get_interface)(device_t *, devman_handle_t, int *);
    5779        int (*get_hc_handle)(device_t *, devman_handle_t *);
    5880} usb_iface_t;
  • uspace/lib/drv/include/usbhc_iface.h

    r6bb83c7 r070f11e  
    5353 *   - argument #1 is target address
    5454 *   - argument #2 is target endpoint
    55  *   - argument #3 is buffer size
     55 *   - argument #3 is max packet size of the endpoint
    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 buffer size
     68 *   - argument #3 is max packet size of the endpoint
    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
     
    8585 */
    8686typedef enum {
    87         /** Tell USB address assigned to device.
    88          * Parameters:
    89          * - devman handle id
    90          * Answer:
    91          * - EINVAL - unknown handle or handle not managed by this driver
    92          * - ENOTSUP - operation not supported by HC (shall not happen)
    93          * - arbitrary error code if returned by remote implementation
    94          * - EOK - handle found, first parameter contains the USB address
    95          */
    96         IPC_M_USBHC_GET_ADDRESS,
    97 
    98 
    9987        /** Reserve usage of default address.
    10088         * This call informs the host controller that the caller will be
     
    153141        IPC_M_USBHC_INTERRUPT_IN,
    154142
    155 
    156         /** Start WRITE control transfer.
     143        /** Send bulk data to device.
    157144         * See explanation at usb_iface_funcs_t (OUT transaction).
    158145         */
    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.
     146        IPC_M_USBHC_BULK_OUT,
     147
     148        /** Get bulk data from device.
    179149         * See explanation at usb_iface_funcs_t (IN transaction).
    180150         */
    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,
     151        IPC_M_USBHC_BULK_IN,
    187152
    188153        /** Issue control WRITE transfer.
     
    194159        IPC_M_USBHC_CONTROL_WRITE,
    195160
    196         /** Issue control WRITE transfer.
     161        /** Issue control READ transfer.
    197162         * See explanation at usb_iface_funcs_t (IN transaction) for
    198163         * call parameters.
    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.
     164         * This call is immediately followed by IPC data write from the caller
     165         * (setup packet) and IPC data read (buffer that was read).
    202166         */
    203167        IPC_M_USBHC_CONTROL_READ,
     
    230194/** USB host controller communication interface. */
    231195typedef struct {
    232         int (*tell_address)(device_t *, devman_handle_t, usb_address_t *);
    233 
    234         int (*reserve_default_address)(device_t *, bool);
     196        int (*reserve_default_address)(device_t *, usb_speed_t);
    235197        int (*release_default_address)(device_t *);
    236         int (*request_address)(device_t *, bool, usb_address_t *);
     198        int (*request_address)(device_t *, usb_speed_t, usb_address_t *);
    237199        int (*bind_address)(device_t *, usb_address_t, devman_handle_t);
    238200        int (*release_address)(device_t *, usb_address_t);
     
    241203        usbhc_iface_transfer_in_t interrupt_in;
    242204
    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 *);
     205        usbhc_iface_transfer_out_t bulk_out;
     206        usbhc_iface_transfer_in_t bulk_in;
    252207
    253208        int (*control_write)(device_t *, usb_target_t,
  • uspace/lib/usb/Makefile

    r6bb83c7 r070f11e  
    3535        src/addrkeep.c \
    3636        src/class.c \
     37        src/ddfiface.c \
    3738        src/debug.c \
    3839        src/dp.c \
  • uspace/lib/usb/include/usb/dp.h

    r6bb83c7 r070f11e  
    4545} usb_dp_descriptor_nesting_t;
    4646
     47extern usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[];
     48
    4749typedef struct {
    4850        usb_dp_descriptor_nesting_t *nesting;
  • uspace/lib/usb/include/usb/hub.h

    r6bb83c7 r070f11e  
    3939#include <usb/usbdevice.h>
    4040
     41int 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 *);
    4143
    4244/** Info about device attached to host controller.
     
    5355} usb_hc_attached_device_t;
    5456
    55 int usb_hc_reserve_default_address(usb_hc_connection_t *, bool);
     57int usb_hc_reserve_default_address(usb_hc_connection_t *, usb_speed_t);
    5658int usb_hc_release_default_address(usb_hc_connection_t *);
    5759
    58 usb_address_t usb_hc_request_address(usb_hc_connection_t *, bool);
     60usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_speed_t);
    5961int usb_hc_register_device(usb_hc_connection_t *,
    6062    const usb_hc_attached_device_t *);
  • uspace/lib/usb/include/usb/pipes.h

    r6bb83c7 r070f11e  
    107107        /** Endpoint description. */
    108108        const usb_endpoint_description_t *description;
     109        /** Interface number the endpoint must belong to (-1 for any). */
     110        const int interface_no;
    109111        /** Found descriptor fitting the description. */
    110112        usb_standard_endpoint_descriptor_t *descriptor;
     
    121123int usb_device_connection_initialize(usb_device_connection_t *,
    122124    devman_handle_t, usb_address_t);
     125
     126int usb_device_get_assigned_interface(device_t *);
    123127
    124128int usb_endpoint_pipe_initialize(usb_endpoint_pipe_t *,
  • uspace/lib/usb/include/usb/recognise.h

    r6bb83c7 r070f11e  
    4141#include <ipc/devman.h>
    4242
     43int usb_device_create_match_ids_from_interface(
     44    const usb_standard_device_descriptor_t *,
     45    const usb_standard_interface_descriptor_t *, match_id_list_t *);
     46
    4347int usb_device_create_match_ids(usb_endpoint_pipe_t *, match_id_list_t *);
    4448
  • uspace/lib/usb/include/usb/usb.h

    r6bb83c7 r070f11e  
    6868        USB_DIRECTION_BOTH
    6969} usb_direction_t;
     70
     71/** USB speeds. */
     72typedef 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;
    7080
    7181/** USB request type target. */
  • uspace/lib/usb/include/usb/usbdrv.h

    r6bb83c7 r070f11e  
    103103int usb_drv_create_match_ids_from_device_descriptor(match_id_list_t *,
    104104    const usb_standard_device_descriptor_t *);
    105 int usb_drv_create_match_ids_from_configuration_descriptor(match_id_list_t *,
    106     const void *, size_t);
    107 
    108105
    109106#endif
  • uspace/lib/usb/src/dp.c

    r6bb83c7 r070f11e  
    4040#include <bool.h>
    4141#include <usb/dp.h>
     42#include <usb/descriptor.h>
     43
     44#define NESTING(parentname, childname) \
     45        { \
     46                .child = USB_DESCTYPE_##childname, \
     47                .parent = USB_DESCTYPE_##parentname, \
     48        }
     49#define LAST_NESTING { -1, -1 }
     50
     51/** Nesting of standard USB descriptors. */
     52usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[] = {
     53        NESTING(CONFIGURATION, INTERFACE),
     54        NESTING(INTERFACE, ENDPOINT),
     55        NESTING(INTERFACE, HUB),
     56        NESTING(INTERFACE, HID),
     57        NESTING(HID, HID_REPORT),
     58        LAST_NESTING
     59};
     60
     61#undef NESTING
     62#undef LAST_NESTING
    4263
    4364/** Tells whether pointer points inside descriptor data.
  • uspace/lib/usb/src/hub.c

    r6bb83c7 r070f11e  
    3434 */
    3535#include <usb/hub.h>
     36#include <usb/pipes.h>
     37#include <usb/request.h>
     38#include <usb/recognise.h>
    3639#include <usbhc_iface.h>
    3740#include <errno.h>
     
    5659 */
    5760int usb_hc_reserve_default_address(usb_hc_connection_t *connection,
    58     bool full_speed)
     61    usb_speed_t speed)
    5962{
    6063        CHECK_CONNECTION(connection);
     
    6265        return async_req_2_0(connection->hc_phone,
    6366            DEV_IFACE_ID(USBHC_DEV_IFACE),
    64             IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS, full_speed);
     67            IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS, speed);
    6568}
    6669
     
    8588 */
    8689usb_address_t usb_hc_request_address(usb_hc_connection_t *connection,
    87     bool full_speed)
     90    usb_speed_t speed)
    8891{
    8992        CHECK_CONNECTION(connection);
     
    9295        int rc = async_req_2_1(connection->hc_phone,
    9396            DEV_IFACE_ID(USBHC_DEV_IFACE),
    94             IPC_M_USBHC_REQUEST_ADDRESS, full_speed,
     97            IPC_M_USBHC_REQUEST_ADDRESS, speed,
    9598            &address);
    9699        if (rc != EOK) {
     
    138141
    139142
     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 */
     174int 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
     291leave_stop_session:
     292        usb_endpoint_pipe_end_session(&ctrl_pipe);
     293
     294leave_release_default_address:
     295        usb_hc_release_default_address(connection);
     296
     297leave_release_free_address:
     298        usb_hc_unregister_device(connection, dev_addr);
     299
     300        return rc;
     301}
     302
    140303/**
    141304 * @}
  • uspace/lib/usb/src/pipes.c

    r6bb83c7 r070f11e  
    3535#include <usb/usb.h>
    3636#include <usb/pipes.h>
     37#include <usbhc_iface.h>
     38#include <usb_iface.h>
    3739#include <errno.h>
    3840#include <assert.h>
    39 #include <usb/usbdrv.h>
     41
     42/** Tell USB address assigned to given device.
     43 *
     44 * @param phone Phone to parent device.
     45 * @param dev Device in question.
     46 * @return USB address or error code.
     47 */
     48static usb_address_t get_my_address(int phone, device_t *dev)
     49{
     50        sysarg_t address;
     51        int rc = async_req_2_1(phone, DEV_IFACE_ID(USB_DEV_IFACE),
     52            IPC_M_USB_GET_ADDRESS,
     53            dev->handle, &address);
     54
     55        if (rc != EOK) {
     56                return rc;
     57        }
     58
     59        return (usb_address_t) address;
     60}
     61
     62/** Tell USB interface assigned to given device.
     63 *
     64 * @param device Device in question.
     65 * @return Interface number (negative code means any).
     66 */
     67int usb_device_get_assigned_interface(device_t *device)
     68{
     69        int parent_phone = devman_parent_device_connect(device->handle,
     70            IPC_FLAG_BLOCKING);
     71        if (parent_phone < 0) {
     72                return -1;
     73        }
     74
     75        sysarg_t iface_no;
     76        int rc = async_req_2_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
     77            IPC_M_USB_GET_INTERFACE,
     78            device->handle, &iface_no);
     79
     80        async_hangup(parent_phone);
     81
     82        if (rc != EOK) {
     83                return -1;
     84        }
     85
     86        return (int) iface_no;
     87}
    4088
    4189/** Initialize connection to USB device.
     
    55103        usb_address_t my_address;
    56104
    57         rc = usb_drv_find_hc(device, &hc_handle);
     105        rc = usb_hc_find(device->handle, &hc_handle);
    58106        if (rc != EOK) {
    59107                return rc;
    60108        }
    61109
    62         int hc_phone = devman_device_connect(hc_handle, 0);
    63         if (hc_phone < 0) {
    64                 return hc_phone;
    65         }
    66 
    67         my_address = usb_drv_get_my_address(hc_phone, device);
     110        int parent_phone = devman_parent_device_connect(device->handle,
     111            IPC_FLAG_BLOCKING);
     112        if (parent_phone < 0) {
     113                return parent_phone;
     114        }
     115
     116        my_address = get_my_address(parent_phone, device);
    68117        if (my_address < 0) {
    69118                rc = my_address;
     
    75124
    76125leave:
    77         async_hangup(hc_phone);
     126        async_hangup(parent_phone);
    78127        return rc;
    79128}
  • uspace/lib/usb/src/pipesinit.c

    r6bb83c7 r070f11e  
    109109 * @param mapping_count Number of endpoint mappings in @p mapping.
    110110 * @param found_endpoint Description of found endpoint.
     111 * @param interface_number Number of currently processed interface.
    111112 * @return Endpoint mapping corresponding to @p found_endpoint.
    112113 * @retval NULL No corresponding endpoint found.
     
    114115static usb_endpoint_mapping_t *find_endpoint_mapping(
    115116    usb_endpoint_mapping_t *mapping, size_t mapping_count,
    116     usb_endpoint_description_t *found_endpoint)
     117    usb_endpoint_description_t *found_endpoint,
     118    int interface_number)
    117119{
    118120        while (mapping_count > 0) {
    119                 if (endpoint_fits_description(mapping->description,
    120                     found_endpoint)) {
     121                bool interface_number_fits = (mapping->interface_no < 0)
     122                    || (mapping->interface_no == interface_number);
     123
     124                bool endpoint_descriptions_fits = endpoint_fits_description(
     125                    mapping->description, found_endpoint);
     126
     127                if (interface_number_fits && endpoint_descriptions_fits) {
    121128                        return mapping;
    122129                }
     
    169176         */
    170177        usb_endpoint_mapping_t *ep_mapping = find_endpoint_mapping(mapping,
    171             mapping_count, &description);
     178            mapping_count, &description, interface->interface_number);
    172179        if (ep_mapping == NULL) {
    173180                return ENOENT;
  • uspace/lib/usb/src/pipesio.c

    r6bb83c7 r070f11e  
    7171                        ipc_method = IPC_M_USBHC_INTERRUPT_IN;
    7272                        break;
     73                case USB_TRANSFER_BULK:
     74                        ipc_method = IPC_M_USBHC_BULK_IN;
     75                        break;
    7376                default:
    7477                        return ENOTSUP;
     
    7881         * Make call identifying target USB device and type of transfer.
    7982         */
    80         aid_t opening_request = async_send_3(pipe->hc_phone,
     83        aid_t opening_request = async_send_4(pipe->hc_phone,
    8184            DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
    8285            pipe->wire->address, pipe->endpoint_no,
     86            pipe->max_packet_size,
    8387            NULL);
    8488        if (opening_request == 0) {
     
    194198                        ipc_method = IPC_M_USBHC_INTERRUPT_OUT;
    195199                        break;
     200                case USB_TRANSFER_BULK:
     201                        ipc_method = IPC_M_USBHC_BULK_OUT;
     202                        break;
    196203                default:
    197204                        return ENOTSUP;
     
    201208         * Make call identifying target USB device and type of transfer.
    202209         */
    203         aid_t opening_request = async_send_3(pipe->hc_phone,
     210        aid_t opening_request = async_send_4(pipe->hc_phone,
    204211            DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
    205212            pipe->wire->address, pipe->endpoint_no,
     213            pipe->max_packet_size,
    206214            NULL);
    207215        if (opening_request == 0) {
     
    283291         * Make call identifying target USB device and control transfer type.
    284292         */
    285         aid_t opening_request = async_send_3(pipe->hc_phone,
     293        aid_t opening_request = async_send_4(pipe->hc_phone,
    286294            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_READ,
    287295            pipe->wire->address, pipe->endpoint_no,
     296            pipe->max_packet_size,
    288297            NULL);
    289298        if (opening_request == 0) {
     
    402411         * Make call identifying target USB device and control transfer type.
    403412         */
    404         aid_t opening_request = async_send_4(pipe->hc_phone,
     413        aid_t opening_request = async_send_5(pipe->hc_phone,
    405414            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_WRITE,
    406415            pipe->wire->address, pipe->endpoint_no,
    407416            data_buffer_size,
     417            pipe->max_packet_size,
    408418            NULL);
    409419        if (opening_request == 0) {
  • uspace/lib/usb/src/recognise.c

    r6bb83c7 r070f11e  
    3434 */
    3535#include <sys/types.h>
    36 #include <usb_iface.h>
    3736#include <usb/usbdrv.h>
    3837#include <usb/pipes.h>
    3938#include <usb/recognise.h>
     39#include <usb/ddfiface.h>
    4040#include <usb/request.h>
    4141#include <usb/classes/classes.h>
     
    4646static FIBRIL_MUTEX_INITIALIZE(device_name_index_mutex);
    4747
    48 /** Callback for getting host controller handle.
    49  *
    50  * @param dev Device in question.
    51  * @param[out] handle Devman handle of the host controller.
    52  * @return Error code.
    53  */
    54 static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
    55 {
    56         assert(dev);
    57         assert(dev->parent != NULL);
    58 
    59         device_t *parent = dev->parent;
    60 
    61         if (parent->ops && parent->ops->interfaces[USB_DEV_IFACE]) {
    62                 usb_iface_t *usb_iface
    63                     = (usb_iface_t *) parent->ops->interfaces[USB_DEV_IFACE];
    64                 assert(usb_iface != NULL);
    65                 if (usb_iface->get_hc_handle) {
    66                         int rc = usb_iface->get_hc_handle(parent, handle);
    67                         return rc;
    68                 }
    69         }
    70 
    71         return ENOTSUP;
    72 }
    73 
    74 static usb_iface_t usb_iface = {
    75         .get_hc_handle = usb_iface_get_hc_handle
    76 };
    77 
    7848device_ops_t child_ops = {
    79         .interfaces[USB_DEV_IFACE] = &usb_iface
     49        .interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl
    8050};
    8151
     
    142112}
    143113
     114#define ADD_MATCHID_OR_RETURN(match_ids, score, format, ...) \
     115        do { \
     116                int __rc = usb_add_match_id((match_ids), (score), \
     117                    format, ##__VA_ARGS__); \
     118                if (__rc != EOK) { \
     119                        return __rc; \
     120                } \
     121        } while (0)
     122
     123/** Create device match ids based on its interface.
     124 *
     125 * @param[in] descriptor Interface descriptor.
     126 * @param[out] matches Initialized list of match ids.
     127 * @return Error code (the two mentioned are not the only ones).
     128 * @retval EINVAL Invalid input parameters (expects non NULL pointers).
     129 * @retval ENOENT Interface does not specify class.
     130 */
     131int usb_device_create_match_ids_from_interface(
     132    const usb_standard_device_descriptor_t *desc_device,
     133    const usb_standard_interface_descriptor_t *desc_interface,
     134    match_id_list_t *matches)
     135{
     136        if (desc_interface == NULL) {
     137                return EINVAL;
     138        }
     139        if (matches == NULL) {
     140                return EINVAL;
     141        }
     142
     143        if (desc_interface->interface_class == USB_CLASS_USE_INTERFACE) {
     144                return ENOENT;
     145        }
     146
     147        const char *classname = usb_str_class(desc_interface->interface_class);
     148        assert(classname != NULL);
     149
     150#define IFACE_PROTOCOL_FMT "interface&class=%s&subclass=0x%02x&protocol=0x%02x"
     151#define IFACE_PROTOCOL_ARGS classname, desc_interface->interface_subclass, \
     152    desc_interface->interface_protocol
     153
     154#define IFACE_SUBCLASS_FMT "interface&class=%s&subclass=0x%02x"
     155#define IFACE_SUBCLASS_ARGS classname, desc_interface->interface_subclass
     156
     157#define IFACE_CLASS_FMT "interface&class=%s"
     158#define IFACE_CLASS_ARGS classname
     159
     160#define VENDOR_RELEASE_FMT "vendor=0x%04x&product=0x%04x&release=" BCD_FMT
     161#define VENDOR_RELEASE_ARGS desc_device->vendor_id, desc_device->product_id, \
     162    BCD_ARGS(desc_device->device_version)
     163
     164#define VENDOR_PRODUCT_FMT "vendor=0x%04x&product=0x%04x"
     165#define VENDOR_PRODUCT_ARGS desc_device->vendor_id, desc_device->product_id
     166
     167#define VENDOR_ONLY_FMT "vendor=0x%04x"
     168#define VENDOR_ONLY_ARGS desc_device->vendor_id
     169
     170        /*
     171         * If the vendor is specified, create match ids with vendor with
     172         * higher score.
     173         * Then the same ones without the vendor part.
     174         */
     175        if ((desc_device != NULL) && (desc_device->vendor_id != 0)) {
     176                /* First, interface matches with device release number. */
     177                ADD_MATCHID_OR_RETURN(matches, 250,
     178                    "usb&" VENDOR_RELEASE_FMT "&" IFACE_PROTOCOL_FMT,
     179                    VENDOR_RELEASE_ARGS, IFACE_PROTOCOL_ARGS);
     180                ADD_MATCHID_OR_RETURN(matches, 240,
     181                    "usb&" VENDOR_RELEASE_FMT "&" IFACE_SUBCLASS_FMT,
     182                    VENDOR_RELEASE_ARGS, IFACE_SUBCLASS_ARGS);
     183                ADD_MATCHID_OR_RETURN(matches, 230,
     184                    "usb&" VENDOR_RELEASE_FMT "&" IFACE_CLASS_FMT,
     185                    VENDOR_RELEASE_ARGS, IFACE_CLASS_ARGS);
     186
     187                /* Next, interface matches without release number. */
     188                ADD_MATCHID_OR_RETURN(matches, 220,
     189                    "usb&" VENDOR_PRODUCT_FMT "&" IFACE_PROTOCOL_FMT,
     190                    VENDOR_PRODUCT_ARGS, IFACE_PROTOCOL_ARGS);
     191                ADD_MATCHID_OR_RETURN(matches, 210,
     192                    "usb&" VENDOR_PRODUCT_FMT "&" IFACE_SUBCLASS_FMT,
     193                    VENDOR_PRODUCT_ARGS, IFACE_SUBCLASS_ARGS);
     194                ADD_MATCHID_OR_RETURN(matches, 200,
     195                    "usb&" VENDOR_PRODUCT_FMT "&" IFACE_CLASS_FMT,
     196                    VENDOR_PRODUCT_ARGS, IFACE_CLASS_ARGS);
     197
     198                /* Finally, interface matches with only vendor. */
     199                ADD_MATCHID_OR_RETURN(matches, 190,
     200                    "usb&" VENDOR_ONLY_FMT "&" IFACE_PROTOCOL_FMT,
     201                    VENDOR_ONLY_ARGS, IFACE_PROTOCOL_ARGS);
     202                ADD_MATCHID_OR_RETURN(matches, 180,
     203                    "usb&" VENDOR_ONLY_FMT "&" IFACE_SUBCLASS_FMT,
     204                    VENDOR_ONLY_ARGS, IFACE_SUBCLASS_ARGS);
     205                ADD_MATCHID_OR_RETURN(matches, 170,
     206                    "usb&" VENDOR_ONLY_FMT "&" IFACE_CLASS_FMT,
     207                    VENDOR_ONLY_ARGS, IFACE_CLASS_ARGS);
     208        }
     209
     210        /* Now, the same but without any vendor specification. */
     211        ADD_MATCHID_OR_RETURN(matches, 160,
     212            "usb&" IFACE_PROTOCOL_FMT,
     213            IFACE_PROTOCOL_ARGS);
     214        ADD_MATCHID_OR_RETURN(matches, 150,
     215            "usb&" IFACE_SUBCLASS_FMT,
     216            IFACE_SUBCLASS_ARGS);
     217        ADD_MATCHID_OR_RETURN(matches, 140,
     218            "usb&" IFACE_CLASS_FMT,
     219            IFACE_CLASS_ARGS);
     220
     221#undef IFACE_PROTOCOL_FMT
     222#undef IFACE_PROTOCOL_ARGS
     223#undef IFACE_SUBCLASS_FMT
     224#undef IFACE_SUBCLASS_ARGS
     225#undef IFACE_CLASS_FMT
     226#undef IFACE_CLASS_ARGS
     227#undef VENDOR_RELEASE_FMT
     228#undef VENDOR_RELEASE_ARGS
     229#undef VENDOR_PRODUCT_FMT
     230#undef VENDOR_PRODUCT_ARGS
     231#undef VENDOR_ONLY_FMT
     232#undef VENDOR_ONLY_ARGS
     233
     234        return EOK;
     235}
     236
    144237/** Create DDF match ids from USB device descriptor.
    145238 *
     
    152245    const usb_standard_device_descriptor_t *device_descriptor)
    153246{
    154         int rc;
    155        
    156247        /*
    157248         * Unless the vendor id is 0, the pair idVendor-idProduct
     
    160251        if (device_descriptor->vendor_id != 0) {
    161252                /* First, with release number. */
    162                 rc = usb_add_match_id(matches, 100,
     253                ADD_MATCHID_OR_RETURN(matches, 100,
    163254                    "usb&vendor=0x%04x&product=0x%04x&release=" BCD_FMT,
    164255                    (int) device_descriptor->vendor_id,
    165256                    (int) device_descriptor->product_id,
    166257                    BCD_ARGS(device_descriptor->device_version));
    167                 if (rc != EOK) {
    168                         return rc;
    169                 }
    170258               
    171259                /* Next, without release number. */
    172                 rc = usb_add_match_id(matches, 90,
     260                ADD_MATCHID_OR_RETURN(matches, 90,
    173261                    "usb&vendor=0x%04x&product=0x%04x",
    174262                    (int) device_descriptor->vendor_id,
    175263                    (int) device_descriptor->product_id);
    176                 if (rc != EOK) {
    177                         return rc;
    178                 }
    179264        }       
    180265
    181266        /*
    182267         * If the device class points to interface we skip adding
    183          * class directly.
     268         * class directly but we add a multi interface device.
    184269         */
    185270        if (device_descriptor->device_class != USB_CLASS_USE_INTERFACE) {
    186                 rc = usb_add_match_id(matches, 50, "usb&class=%s",
     271                ADD_MATCHID_OR_RETURN(matches, 50, "usb&class=%s",
    187272                    usb_str_class(device_descriptor->device_class));
    188                 if (rc != EOK) {
    189                         return rc;
    190                 }
     273        } else {
     274                ADD_MATCHID_OR_RETURN(matches, 50, "usb&mid");
    191275        }
    192276       
     
    194278}
    195279
    196 /** Create DDF match ids from USB configuration descriptor.
    197  * The configuration descriptor is expected to be in the complete form,
    198  * i.e. including interface, endpoint etc. descriptors.
    199  *
    200  * @param matches List of match ids to extend.
    201  * @param config_descriptor Configuration descriptor returned by given device.
    202  * @param total_size Size of the @p config_descriptor.
    203  * @return Error code.
    204  */
    205 int usb_drv_create_match_ids_from_configuration_descriptor(
    206     match_id_list_t *matches,
    207     const void *config_descriptor, size_t total_size)
    208 {
    209         /*
    210          * Iterate through config descriptor to find the interface
    211          * descriptors.
    212          */
    213         size_t position = sizeof(usb_standard_configuration_descriptor_t);
    214         while (position + 1 < total_size) {
    215                 uint8_t *current_descriptor
    216                     = ((uint8_t *) config_descriptor) + position;
    217                 uint8_t cur_descr_len = current_descriptor[0];
    218                 uint8_t cur_descr_type = current_descriptor[1];
    219 
    220                 if (cur_descr_len == 0) {
    221                         return ENOENT;
    222                 }
    223                
    224                 position += cur_descr_len;
    225                
    226                 if (cur_descr_type != USB_DESCTYPE_INTERFACE) {
    227                         continue;
    228                 }
    229                
    230                 /*
    231                  * Finally, we found an interface descriptor.
    232                  */
    233                 usb_standard_interface_descriptor_t *interface
    234                     = (usb_standard_interface_descriptor_t *)
    235                     current_descriptor;
    236                
    237                 int rc = usb_add_match_id(matches, 50,
    238                     "usb&interface&class=%s",
    239                     usb_str_class(interface->interface_class));
    240                 if (rc != EOK) {
    241                         return rc;
    242                 }
    243         }
    244        
    245         return EOK;
    246 }
    247 
    248 /** Add match ids based on configuration descriptor.
    249  *
    250  * @param pipe Control pipe to the device.
    251  * @param matches Match ids list to add matches to.
    252  * @param config_count Number of configurations the device has.
    253  * @return Error code.
    254  */
    255 static int usb_add_config_descriptor_match_ids(usb_endpoint_pipe_t *pipe,
    256     match_id_list_t *matches, int config_count)
    257 {
    258         int final_rc = EOK;
    259        
    260         int config_index;
    261         for (config_index = 0; config_index < config_count; config_index++) {
    262                 int rc;
    263                 usb_standard_configuration_descriptor_t config_descriptor;
    264                 rc = usb_request_get_bare_configuration_descriptor(pipe,
    265                     config_index, &config_descriptor);
    266                 if (rc != EOK) {
    267                         final_rc = rc;
    268                         continue;
    269                 }
    270 
    271                 size_t full_config_descriptor_size;
    272                 void *full_config_descriptor
    273                     = malloc(config_descriptor.total_length);
    274                 rc = usb_request_get_full_configuration_descriptor(pipe,
    275                     config_index,
    276                     full_config_descriptor, config_descriptor.total_length,
    277                     &full_config_descriptor_size);
    278                 if (rc != EOK) {
    279                         final_rc = rc;
    280                         continue;
    281                 }
    282                 if (full_config_descriptor_size
    283                     != config_descriptor.total_length) {
    284                         final_rc = ERANGE;
    285                         continue;
    286                 }
    287                
    288                 rc = usb_drv_create_match_ids_from_configuration_descriptor(
    289                     matches,
    290                     full_config_descriptor, full_config_descriptor_size);
    291                 if (rc != EOK) {
    292                         final_rc = rc;
    293                         continue;
    294                 }
    295                
    296         }
    297        
    298         return final_rc;
    299 }
    300280
    301281/** Create match ids describing attached device.
     
    330310
    331311        /*
    332          * Go through all configurations and add matches
    333          * based on interface class.
    334          */
    335         rc = usb_add_config_descriptor_match_ids(ctrl_pipe, matches,
    336             device_descriptor.configuration_count);
    337         if (rc != EOK) {
    338                 return rc;
    339         }
    340 
    341         /*
    342312         * As a fallback, provide the simplest match id possible.
    343313         */
    344         rc = usb_add_match_id(matches, 1, "usb&fallback");
    345         if (rc != EOK) {
    346                 return rc;
    347         }
     314        ADD_MATCHID_OR_RETURN(matches, 1, "usb&fallback");
    348315
    349316        return EOK;
  • uspace/lib/usb/src/usbdrv.c

    r6bb83c7 r070f11e  
    3434 */
    3535#include <usb/usbdrv.h>
    36 #include <usbhc_iface.h>
    37 #include <usb_iface.h>
    3836#include <errno.h>
    39 #include <str_error.h>
    40 
    41 /** Information about pending transaction on HC. */
    42 typedef 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;
     37
    6038
    6139/** Find handle of host controller the device is physically attached to.
     
    6745int usb_drv_find_hc(device_t *dev, devman_handle_t *handle)
    6846{
    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;
     47        return ENOTSUP;
    9548}
    9649
     
    10558    unsigned int flags)
    10659{
    107         return devman_device_connect(hc_handle, flags);
     60        return ENOTSUP;
    10861}
    10962
     
    11669int usb_drv_hc_connect_auto(device_t *dev, unsigned int flags)
    11770{
    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);
     71        return ENOTSUP;
    13072}
    13173
     
    13880usb_address_t usb_drv_get_my_address(int phone, device_t *dev)
    13981{
    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;
     82        return ENOTSUP;
    15083}
    15184
     
    15790int usb_drv_reserve_default_address(int phone)
    15891{
    159         return async_req_1_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
    160             IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS);
     92        return ENOTSUP;
    16193}
    16294
     
    168100int usb_drv_release_default_address(int phone)
    169101{
    170         return async_req_1_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
    171             IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS);
     102        return ENOTSUP;
    172103}
    173104
     
    179110usb_address_t usb_drv_request_address(int phone)
    180111{
    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         }
     112        return ENOTSUP;
    189113}
    190114
     
    199123    devman_handle_t handle)
    200124{
    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;
     125        return ENOTSUP;
    206126}
    207127
     
    214134int usb_drv_release_address(int phone, usb_address_t address)
    215135{
    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  */
    232 static 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  */
    298 static 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 
     136        return ENOTSUP;
     137}
    344138
    345139/** Blocks caller until given USB transaction is finished.
     
    355149int usb_drv_async_wait_for(usb_handle_t handle)
    356150{
    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 
    391 leave:
    392         free(transfer);
    393 
    394         return rc;
     151        return ENOTSUP;
    395152}
    396153
     
    400157    usb_handle_t *handle)
    401158{
    402         return async_send_buffer(phone,
    403             IPC_M_USBHC_INTERRUPT_OUT,
    404             target,
    405             buffer, size,
    406             handle);
     159        return ENOTSUP;
    407160}
    408161
     
    412165    usb_handle_t *handle)
    413166{
    414         return async_recv_buffer(phone,
    415             IPC_M_USBHC_INTERRUPT_IN,
    416             target,
    417             buffer, size, actual_size,
    418             handle);
     167        return ENOTSUP;
    419168}
    420169
     
    424173    usb_handle_t *handle)
    425174{
    426         return async_send_buffer(phone,
    427             IPC_M_USBHC_CONTROL_WRITE_SETUP,
    428             target,
    429             buffer, size,
    430             handle);
     175        return ENOTSUP;
    431176}
    432177
     
    436181    usb_handle_t *handle)
    437182{
    438         return async_send_buffer(phone,
    439             IPC_M_USBHC_CONTROL_WRITE_DATA,
    440             target,
    441             buffer, size,
    442             handle);
     183        return ENOTSUP;
    443184}
    444185
     
    447188    usb_handle_t *handle)
    448189{
    449         return async_recv_buffer(phone,
    450             IPC_M_USBHC_CONTROL_WRITE_STATUS,
    451             target,
    452             NULL, 0, NULL,
    453             handle);
     190        return ENOTSUP;
    454191}
    455192
     
    460197    usb_handle_t *handle)
    461198{
    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;
     199        return ENOTSUP;
    507200}
    508201
     
    512205    usb_handle_t *handle)
    513206{
    514         return async_send_buffer(phone,
    515             IPC_M_USBHC_CONTROL_READ_SETUP,
    516             target,
    517             buffer, size,
    518             handle);
     207        return ENOTSUP;
    519208}
    520209
     
    524213    usb_handle_t *handle)
    525214{
    526         return async_recv_buffer(phone,
    527             IPC_M_USBHC_CONTROL_READ_DATA,
    528             target,
    529             buffer, size, actual_size,
    530             handle);
     215        return ENOTSUP;
    531216}
    532217
     
    535220    usb_handle_t *handle)
    536221{
    537         return async_send_buffer(phone,
    538             IPC_M_USBHC_CONTROL_READ_STATUS,
    539             target,
    540             NULL, 0,
    541             handle);
     222        return ENOTSUP;
    542223}
    543224
     
    548229    usb_handle_t *handle)
    549230{
    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;
     231        return ENOTSUP;
    590232}
    591233
Note: See TracChangeset for help on using the changeset viewer.