Changeset 6843a9c in mainline for uspace/drv/bus


Ignore:
Timestamp:
2012-06-29T13:02:14Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
722912e
Parents:
ba72f2b (diff), 0bbd13e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes

Trivial conflicts.

Location:
uspace/drv/bus
Files:
2 added
2 deleted
66 edited
6 moved

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/isa/Makefile

    rba72f2b r6843a9c  
    3434
    3535SOURCES = \
    36         dma_controller.c \
     36        i8237.c \
    3737        isa.c
    3838
  • uspace/drv/bus/isa/i8237.h

    rba72f2b r6843a9c  
    11/*
    2  * Copyright (c) 2011 Vojtech Horky
     2 * Copyright (c) 2011 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2727 */
    2828
    29 /** @addtogroup drvusbehci
     29/** @addtogroup isa
    3030 * @{
    3131 */
     32
    3233/** @file
    33  * Common EHCI definitions.
     34 * @brief DMA memory management
    3435 */
    35 #ifndef DRV_EHCI_EHCI_H
    36 #define DRV_EHCI_EHCI_H
    3736
    38 #include <usbhc_iface.h>
     37#ifndef DRV_BUS_ISA_I8237_H
     38#define DRV_BUS_ISA_I8237_H
    3939
    40 #define NAME "ehci"
    41 
    42 extern usbhc_iface_t ehci_hc_iface;
     40extern int dma_setup_channel(unsigned int, uint32_t, uint16_t, uint8_t);
    4341
    4442#endif
     43
    4544/**
    4645 * @}
    4746 */
    48 
  • uspace/drv/bus/isa/isa.c

    rba72f2b r6843a9c  
    5252#include <dirent.h>
    5353#include <fcntl.h>
     54#include <ipc/irc.h>
     55#include <ipc/services.h>
     56#include <sysinfo.h>
     57#include <ns.h>
    5458#include <sys/stat.h>
    5559#include <ipc/irc.h>
     
    6266#include <ops/hw_res.h>
    6367
    64 #include <devman.h>
    65 #include <ipc/devman.h>
    6668#include <device/hw_res.h>
    6769
    68 #include "dma_controller.h"
     70#include "i8237.h"
    6971
    7072#define NAME "isa"
     
    146148
    147149static int isa_dma_channel_fun_setup(ddf_fun_t *fnode,
    148     unsigned channel, uint32_t pa, uint16_t size, uint8_t mode)
     150    unsigned int channel, uint32_t pa, uint16_t size, uint8_t mode)
    149151{
    150152        assert(fnode);
     
    152154        const hw_resource_list_t *res = &isa_fun->hw_resources;
    153155        assert(res);
    154         const int ch = channel;
     156       
     157        const unsigned int ch = channel;
    155158        for (size_t i = 0; i < res->count; ++i) {
    156                 if ((res->resources[i].type == DMA_CHANNEL_16 &&
    157                     res->resources[i].res.dma_channel.dma16 == ch) ||
    158                     (res->resources[i].type == DMA_CHANNEL_8 &&
    159                     res->resources[i].res.dma_channel.dma8 == ch)) {
     159                if (((res->resources[i].type == DMA_CHANNEL_16) &&
     160                    (res->resources[i].res.dma_channel.dma16 == ch)) ||
     161                    ((res->resources[i].type == DMA_CHANNEL_8) &&
     162                    (res->resources[i].res.dma_channel.dma8 == ch))) {
    160163                        return dma_setup_channel(channel, pa, size, mode);
    161164                }
    162165        }
     166       
    163167        return EINVAL;
    164168}
     
    172176static ddf_dev_ops_t isa_fun_ops;
    173177
    174 static int isa_add_device(ddf_dev_t *dev);
     178static int isa_dev_add(ddf_dev_t *dev);
    175179static int isa_dev_remove(ddf_dev_t *dev);
    176180static int isa_fun_online(ddf_fun_t *fun);
     
    179183/** The isa device driver's standard operations */
    180184static driver_ops_t isa_ops = {
    181         .add_device = &isa_add_device,
     185        .dev_add = &isa_dev_add,
    182186        .dev_remove = &isa_dev_remove,
    183187        .fun_online = &isa_fun_online,
     
    198202
    199203        isa_fun_t *fun = ddf_fun_data_alloc(fnode, sizeof(isa_fun_t));
    200         if (fun == NULL)
     204        if (fun == NULL) {
     205                ddf_fun_destroy(fnode);
    201206                return NULL;
     207        }
    202208
    203209        fibril_mutex_initialize(&fun->mutex);
     
    344350        size_t count = fun->hw_resources.count;
    345351        hw_resource_t *resources = fun->hw_resources.resources;
    346 
     352       
    347353        if (count < ISA_MAX_HW_RES) {
    348                 if (dma > 0 && dma < 4) {
     354                if ((dma > 0) && (dma < 4)) {
    349355                        resources[count].type = DMA_CHANNEL_8;
    350356                        resources[count].res.dma_channel.dma8 = dma;
    351 
     357                       
    352358                        fun->hw_resources.count++;
    353359                        ddf_msg(LVL_NOTE, "Added dma 0x%x to function %s", dma,
    354360                            fun->fnode->name);
     361                       
    355362                        return;
    356363                }
    357364
    358                 if (dma > 4 && dma < 8) {
     365                if ((dma > 4) && (dma < 8)) {
    359366                        resources[count].type = DMA_CHANNEL_16;
    360367                        resources[count].res.dma_channel.dma16 = dma;
    361 
     368                       
    362369                        fun->hw_resources.count++;
    363370                        ddf_msg(LVL_NOTE, "Added dma 0x%x to function %s", dma,
    364371                            fun->fnode->name);
     372                       
    365373                        return;
    366374                }
    367 
     375               
    368376                ddf_msg(LVL_WARN, "Skipped dma 0x%x for function %s", dma,
    369377                    fun->fnode->name);
     
    396404
    397405        val = skip_spaces(val);
    398         irq = (int)strtol(val, &end, 0x10);
     406        irq = (int) strtol(val, &end, 10);
    399407
    400408        if (val != end)
     
    404412static void fun_parse_dma(isa_fun_t *fun, char *val)
    405413{
    406         int dma = 0;
     414        unsigned int dma = 0;
    407415        char *end = NULL;
    408 
     416       
    409417        val = skip_spaces(val);
    410         dma = (int)strtol(val, &end, 10);
    411 
     418        dma = (unsigned int) strtol(val, &end, 10);
     419       
    412420        if (val != end)
    413421                isa_fun_set_dma(fun, dma);
     
    589597}
    590598
    591 static int isa_add_device(ddf_dev_t *dev)
     599static int isa_dev_add(ddf_dev_t *dev)
    592600{
    593601        isa_bus_t *isa;
    594602
    595         ddf_msg(LVL_DEBUG, "isa_add_device, device handle = %d",
     603        ddf_msg(LVL_DEBUG, "isa_dev_add, device handle = %d",
    596604            (int) dev->handle);
    597605
  • uspace/drv/bus/isa/isa.dev

    rba72f2b r6843a9c  
    99        io_range 2f8 8
    1010
    11 keyboard:
    12         match 100 isa/keyboard
     11i8042:
     12        match 100 isa/i8042
    1313        irq 1
    14         io_range 060 10
     14        irq 12
     15        io_range 060 5
     16
     17ne2k:
     18        match 100 isa/ne2k
     19        irq 5
     20        io_range 300 20
    1521
    1622sb16:
  • uspace/drv/bus/isa/isa.ma

    rba72f2b r6843a9c  
    1 9       pci/ven=8086&dev=7000
     19 pci/class=06&subclass=01
  • uspace/drv/bus/pci/pciintel/pci.c

    rba72f2b r6843a9c  
    7878#define PCI_BUS_FROM_FUN(fun) ((fun)->busptr)
    7979
     80/** Max is 47, align to something nice. */
     81#define ID_MAX_STR_LEN 50
     82
    8083static hw_resource_list_t *pciintel_get_resources(ddf_fun_t *fnode)
    8184{
     
    8992static bool pciintel_enable_interrupt(ddf_fun_t *fnode)
    9093{
    91         /* This is an old ugly way, copied from ne2000 driver */
     94        /* This is an old ugly way */
    9295        assert(fnode);
    9396        pci_fun_t *dev_data = (pci_fun_t *) fnode->driver_data;
     
    202205};
    203206
    204 static int pci_add_device(ddf_dev_t *);
     207static int pci_dev_add(ddf_dev_t *);
    205208static int pci_fun_online(ddf_fun_t *);
    206209static int pci_fun_offline(ddf_fun_t *);
     
    208211/** PCI bus driver standard operations */
    209212static driver_ops_t pci_ops = {
    210         .add_device = &pci_add_device,
     213        .dev_add = &pci_dev_add,
    211214        .fun_online = &pci_fun_online,
    212215        .fun_offline = &pci_fun_offline,
     
    225228        fibril_mutex_lock(&bus->conf_mutex);
    226229       
    227         uint32_t conf_addr;
    228         conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
     230        const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
    229231        void *addr = bus->conf_data_port + (reg & 3);
    230232       
     
    311313void pci_fun_create_match_ids(pci_fun_t *fun)
    312314{
    313         char *match_id_str;
    314315        int rc;
    315        
    316         asprintf(&match_id_str, "pci/ven=%04x&dev=%04x",
     316        char match_id_str[ID_MAX_STR_LEN];
     317
     318        /* Vendor ID & Device ID, length(incl \0) 22 */
     319        rc = snprintf(match_id_str, ID_MAX_STR_LEN, "pci/ven=%04x&dev=%04x",
    317320            fun->vendor_id, fun->device_id);
    318 
    319         if (match_id_str == NULL) {
    320                 ddf_msg(LVL_ERROR, "Out of memory creating match ID.");
    321                 return;
     321        if (rc < 0) {
     322                ddf_msg(LVL_ERROR, "Failed creating match ID str: %s",
     323                    str_error(rc));
    322324        }
    323325
    324326        rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 90);
    325327        if (rc != EOK) {
    326                 ddf_msg(LVL_ERROR, "Failed adding match ID: %s",
     328                ddf_msg(LVL_ERROR, "Failed adding match ID: %s", str_error(rc));
     329        }
     330
     331        /* Class, subclass, prog IF, revision, length(incl \0) 47 */
     332        rc = snprintf(match_id_str, ID_MAX_STR_LEN,
     333            "pci/class=%02x&subclass=%02x&progif=%02x&revision=%02x",
     334            fun->class_code, fun->subclass_code, fun->prog_if, fun->revision);
     335        if (rc < 0) {
     336                ddf_msg(LVL_ERROR, "Failed creating match ID str: %s",
    327337                    str_error(rc));
    328338        }
    329        
    330         free(match_id_str);
    331        
    332         /* TODO add more ids (with subsys ids, using class id etc.) */
     339
     340        rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 70);
     341        if (rc != EOK) {
     342                ddf_msg(LVL_ERROR, "Failed adding match ID: %s", str_error(rc));
     343        }
     344
     345        /* Class, subclass, prog IF, length(incl \0) 35 */
     346        rc = snprintf(match_id_str, ID_MAX_STR_LEN,
     347            "pci/class=%02x&subclass=%02x&progif=%02x",
     348            fun->class_code, fun->subclass_code, fun->prog_if);
     349        if (rc < 0) {
     350                ddf_msg(LVL_ERROR, "Failed creating match ID str: %s",
     351                    str_error(rc));
     352        }
     353
     354        rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 60);
     355        if (rc != EOK) {
     356                ddf_msg(LVL_ERROR, "Failed adding match ID: %s", str_error(rc));
     357        }
     358
     359        /* Class, subclass, length(incl \0) 25 */
     360        rc = snprintf(match_id_str, ID_MAX_STR_LEN,
     361            "pci/class=%02x&subclass=%02x",
     362            fun->class_code, fun->subclass_code);
     363        if (rc < 0) {
     364                ddf_msg(LVL_ERROR, "Failed creating match ID str: %s",
     365                    str_error(rc));
     366        }
     367
     368        rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 50);
     369        if (rc != EOK) {
     370                ddf_msg(LVL_ERROR, "Failed adding match ID: %s", str_error(rc));
     371        }
     372
     373        /* Class, length(incl \0) 13 */
     374        rc = snprintf(match_id_str, ID_MAX_STR_LEN, "pci/class=%02x",
     375            fun->class_code);
     376        if (rc < 0) {
     377                ddf_msg(LVL_ERROR, "Failed creating match ID str: %s",
     378                    str_error(rc));
     379        }
     380
     381        rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 40);
     382        if (rc != EOK) {
     383                ddf_msg(LVL_ERROR, "Failed adding match ID: %s", str_error(rc));
     384        }
     385
     386        /* TODO add subsys ids, but those exist only in header type 0 */
    333387}
    334388
     
    481535                for (fnum = 0; multi && fnum < 8; fnum++) {
    482536                        pci_fun_init(fun, bus_num, dnum, fnum);
    483                         fun->vendor_id = pci_conf_read_16(fun,
    484                             PCI_VENDOR_ID);
    485                         fun->device_id = pci_conf_read_16(fun,
    486                             PCI_DEVICE_ID);
    487537                        if (fun->vendor_id == 0xffff) {
    488538                                /*
     
    511561                       
    512562                        fnode = ddf_fun_create(bus->dnode, fun_inner, fun_name);
     563                        free(fun_name);
    513564                        if (fnode == NULL) {
    514565                                ddf_msg(LVL_ERROR, "Failed creating function.");
     
    516567                        }
    517568                       
    518                         free(fun_name);
    519569                        fun->fnode = fnode;
    520570                       
     
    560610}
    561611
    562 static int pci_add_device(ddf_dev_t *dnode)
     612static int pci_dev_add(ddf_dev_t *dnode)
    563613{
    564614        pci_bus_t *bus = NULL;
     
    567617        int rc;
    568618       
    569         ddf_msg(LVL_DEBUG, "pci_add_device");
     619        ddf_msg(LVL_DEBUG, "pci_dev_add");
    570620        dnode->parent_sess = NULL;
    571621       
    572622        bus = ddf_dev_data_alloc(dnode, sizeof(pci_bus_t));
    573623        if (bus == NULL) {
    574                 ddf_msg(LVL_ERROR, "pci_add_device allocation failed.");
     624                ddf_msg(LVL_ERROR, "pci_dev_add allocation failed.");
    575625                rc = ENOMEM;
    576626                goto fail;
     
    584634            dnode->handle, IPC_FLAG_BLOCKING);
    585635        if (!dnode->parent_sess) {
    586                 ddf_msg(LVL_ERROR, "pci_add_device failed to connect to the "
     636                ddf_msg(LVL_ERROR, "pci_dev_add failed to connect to the "
    587637                    "parent driver.");
    588638                rc = ENOENT;
     
    594644        rc = hw_res_get_resource_list(dnode->parent_sess, &hw_resources);
    595645        if (rc != EOK) {
    596                 ddf_msg(LVL_ERROR, "pci_add_device failed to get hw resources "
     646                ddf_msg(LVL_ERROR, "pci_dev_add failed to get hw resources "
    597647                    "for the device.");
    598648                goto fail;
     
    691741        fun->dev = dev;
    692742        fun->fn = fn;
     743        fun->vendor_id = pci_conf_read_16(fun, PCI_VENDOR_ID);
     744        fun->device_id = pci_conf_read_16(fun, PCI_DEVICE_ID);
     745        fun->class_code = pci_conf_read_8(fun, PCI_BASE_CLASS);
     746        fun->subclass_code = pci_conf_read_8(fun, PCI_SUB_CLASS);
     747        fun->prog_if = pci_conf_read_8(fun, PCI_PROG_IF);
     748        fun->revision = pci_conf_read_8(fun, PCI_REVISION_ID);
    693749}
    694750
     
    711767bool pci_alloc_resource_list(pci_fun_t *fun)
    712768{
    713         fun->hw_resources.resources =
    714             (hw_resource_t *) malloc(PCI_MAX_HW_RES * sizeof(hw_resource_t));
    715         return fun->hw_resources.resources != NULL;
     769        fun->hw_resources.resources = fun->resources;
     770        return true;
    716771}
    717772
    718773void pci_clean_resource_list(pci_fun_t *fun)
    719774{
    720         if (fun->hw_resources.resources != NULL) {
    721                 free(fun->hw_resources.resources);
    722                 fun->hw_resources.resources = NULL;
    723         }
     775        fun->hw_resources.resources = NULL;
    724776}
    725777
  • uspace/drv/bus/pci/pciintel/pci.h

    rba72f2b r6843a9c  
    6060        int vendor_id;
    6161        int device_id;
     62        uint8_t class_code;
     63        uint8_t subclass_code;
     64        uint8_t prog_if;
     65        uint8_t revision;
    6266        hw_resource_list_t hw_resources;
     67        hw_resource_t resources[PCI_MAX_HW_RES];
    6368} pci_fun_t;
    6469
  • uspace/drv/bus/usb/ehci/Makefile

    rba72f2b r6843a9c  
    4242
    4343SOURCES = \
    44         hc_iface.c \
    4544        main.c \
    46         pci.c
     45        res.c
    4746
    4847include $(USPACE_PREFIX)/Makefile.common
  • uspace/drv/bus/usb/ehci/ehci.ma

    rba72f2b r6843a9c  
    1 10 pci/ven=1002&dev=4345
    2 10 pci/ven=1002&dev=4386
    3 10 pci/ven=1002&dev=4396
    4 10 pci/ven=1002&dev=4373
    5 10 pci/ven=1022&dev=7463
    6 10 pci/ven=1022&dev=7808
    7 10 pci/ven=102f&dev=01b5
    8 10 pci/ven=10cf&dev=1415
    9 10 pci/ven=10de&dev=00e8
    10 10 pci/ven=10de&dev=055f
    11 10 pci/ven=10de&dev=056a
    12 10 pci/ven=10de&dev=077c
    13 10 pci/ven=10de&dev=077e
    14 10 pci/ven=10de&dev=0aa6
    15 10 pci/ven=10de&dev=0aa9
    16 10 pci/ven=10de&dev=0aaa
    17 10 pci/ven=10de&dev=0d9d
    18 10 pci/ven=1166&dev=0414
    19 10 pci/ven=1166&dev=0416
    20 10 pci/ven=1414&dev=5805
    21 10 pci/ven=1414&dev=5807
    22 10 pci/ven=15ad&dev=0770
    23 10 pci/ven=17a0&dev=8084
    24 10 pci/ven=8086&dev=24cd
    25 10 pci/ven=8086&dev=24dd
    26 10 pci/ven=8086&dev=265c
    27 10 pci/ven=8086&dev=268c
    28 10 pci/ven=8086&dev=27cc
    29 10 pci/ven=8086&dev=2836
    30 10 pci/ven=8086&dev=283a
    31 10 pci/ven=8086&dev=293a
    32 10 pci/ven=8086&dev=293c
    33 10 pci/ven=8086&dev=3a3a
    34 10 pci/ven=8086&dev=3a3c
    35 10 pci/ven=8086&dev=3a6a
    36 10 pci/ven=8086&dev=3a6c
    37 10 pci/ven=8086&dev=8117
    38 10 pci/ven=8086&dev=8807
    39 10 pci/ven=8086&dev=880f
     110 pci/class=0c&subclass=03&progif=20
  • uspace/drv/bus/usb/ehci/main.c

    rba72f2b r6843a9c  
    4242#include <usb/ddfiface.h>
    4343#include <usb/debug.h>
     44#include <usb/host/hcd.h>
    4445
    45 #include "pci.h"
    46 #include "ehci.h"
     46#include "res.h"
    4747
    48 static int ehci_add_device(ddf_dev_t *device);
     48#define NAME "ehci"
     49
     50static int ehci_dev_add(ddf_dev_t *device);
    4951/*----------------------------------------------------------------------------*/
    5052static driver_ops_t ehci_driver_ops = {
    51         .add_device = ehci_add_device,
     53        .dev_add = ehci_dev_add,
    5254};
    5355/*----------------------------------------------------------------------------*/
     
    5759};
    5860static ddf_dev_ops_t hc_ops = {
    59         .interfaces[USBHC_DEV_IFACE] = &ehci_hc_iface,
     61        .interfaces[USBHC_DEV_IFACE] = &hcd_iface,
    6062};
    6163
     
    6668 * @return Error code.
    6769 */
    68 static int ehci_add_device(ddf_dev_t *device)
     70static int ehci_dev_add(ddf_dev_t *device)
    6971{
    7072        assert(device);
     
    7981        int irq = 0;
    8082
    81         int ret = pci_get_my_registers(device, &reg_base, &reg_size, &irq);
     83        int ret = get_my_registers(device, &reg_base, &reg_size, &irq);
    8284        CHECK_RET_RETURN(ret,
    8385            "Failed to get memory addresses for %" PRIun ": %s.\n",
     
    8688            reg_base, reg_size, irq);
    8789
    88         ret = pci_disable_legacy(device, reg_base, reg_size, irq);
     90        ret = disable_legacy(device, reg_base, reg_size);
    8991        CHECK_RET_RETURN(ret,
    9092            "Failed to disable legacy USB: %s.\n", str_error(ret));
     
    9597                return ENOMEM;
    9698        }
     99        hcd_t *ehci_hc = ddf_fun_data_alloc(hc_fun, sizeof(hcd_t));
     100        if (ehci_hc == NULL) {
     101                usb_log_error("Failed to alloc generic HC driver.\n");
     102                return ENOMEM;
     103        }
     104        /* High Speed, no bandwidth */
     105        hcd_init(ehci_hc, USB_SPEED_HIGH, 0, NULL);
    97106        hc_fun->ops = &hc_ops;
    98107
  • uspace/drv/bus/usb/ehci/res.h

    rba72f2b r6843a9c  
    3838#include <ddf/driver.h>
    3939
    40 int pci_get_my_registers(const ddf_dev_t *, uintptr_t *, size_t *, int *);
    41 int pci_enable_interrupts(const ddf_dev_t *);
    42 int pci_disable_legacy(const ddf_dev_t *, uintptr_t, size_t, int);
     40int get_my_registers(const ddf_dev_t *, uintptr_t *, size_t *, int *);
     41int enable_interrupts(const ddf_dev_t *);
     42int disable_legacy(const ddf_dev_t *, uintptr_t, size_t);
    4343
    4444#endif
  • uspace/drv/bus/usb/ohci/Makefile

    rba72f2b r6843a9c  
    5050        ohci_batch.c \
    5151        ohci_endpoint.c \
    52         pci.c \
     52        res.c \
    5353        root_hub.c \
    5454        hw_struct/endpoint_descriptor.c \
  • uspace/drv/bus/usb/ohci/endpoint_list.c

    rba72f2b r6843a9c  
    7373 * Does not check whether this replaces an existing list.
    7474 */
    75 void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next)
     75void endpoint_list_set_next(
     76    const endpoint_list_t *instance, const endpoint_list_t *next)
    7677{
    7778        assert(instance);
  • uspace/drv/bus/usb/ohci/endpoint_list.h

    rba72f2b r6843a9c  
    6868
    6969int endpoint_list_init(endpoint_list_t *instance, const char *name);
    70 void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next);
     70void endpoint_list_set_next(
     71    const endpoint_list_t *instance, const endpoint_list_t *next);
    7172void endpoint_list_add_ep(endpoint_list_t *instance, ohci_endpoint_t *ep);
    7273void endpoint_list_remove_ep(endpoint_list_t *instance, ohci_endpoint_t *ep);
  • uspace/drv/bus/usb/ohci/hc.c

    rba72f2b r6843a9c  
    4747    (I_SO | I_WDH | I_UE | I_RHSC)
    4848
    49 static const irq_cmd_t ohci_irq_commands[] =
    50 {
    51         { .cmd = CMD_MEM_READ_32, .dstarg = 1, .addr = NULL /*filled later*/ },
     49static const irq_pio_range_t ohci_pio_ranges[] = {
     50        {
     51                .base = 0,      /* filled later */
     52                .size = sizeof(ohci_regs_t)
     53        }
     54};
     55
     56static const irq_cmd_t ohci_irq_commands[] = {
     57        { .cmd = CMD_PIO_READ_32, .dstarg = 1, .addr = NULL /* filled later */ },
    5258        { .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2, .value = OHCI_USED_INTERRUPTS },
    5359        { .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 },
    54         { .cmd = CMD_MEM_WRITE_A_32, .srcarg = 1, .addr = NULL /*filled later*/ },
     60        { .cmd = CMD_PIO_WRITE_A_32, .srcarg = 1, .addr = NULL /* filled later */ },
    5561        { .cmd = CMD_ACCEPT },
    5662};
     
    6369static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
    6470/*----------------------------------------------------------------------------*/
     71/** Get number of PIO ranges used in IRQ code.
     72 * @return Number of ranges.
     73 */
     74size_t hc_irq_pio_range_count(void)
     75{
     76        return sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t);
     77}
     78/*----------------------------------------------------------------------------*/
     79/*----------------------------------------------------------------------------*/
    6580/** Get number of commands used in IRQ code.
    6681 * @return Number of commands.
     
    7186}
    7287/*----------------------------------------------------------------------------*/
    73 /** Generate IRQ code commands.
    74  * @param[out] cmds Place to store the commands.
    75  * @param[in] cmd_size Size of the place (bytes).
     88/** Generate IRQ code.
     89 * @param[out] ranges PIO ranges buffer.
     90 * @param[in] ranges_size Size of the ranges buffer (bytes).
     91 * @param[out] cmds Commands buffer.
     92 * @param[in] cmds_size Size of the commands buffer (bytes).
    7693 * @param[in] regs Physical address of device's registers.
    7794 * @param[in] reg_size Size of the register area (bytes).
     
    7996 * @return Error code.
    8097 */
    81 int hc_get_irq_commands(
    82     irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size)
    83 {
    84         if (cmd_size < sizeof(ohci_irq_commands)
    85             || reg_size < sizeof(ohci_regs_t))
     98int
     99hc_get_irq_code(irq_pio_range_t ranges[], size_t ranges_size, irq_cmd_t cmds[],
     100    size_t cmds_size, uintptr_t regs, size_t reg_size)
     101{
     102        if ((ranges_size < sizeof(ohci_pio_ranges)) ||
     103            (cmds_size < sizeof(ohci_irq_commands)) ||
     104            (reg_size < sizeof(ohci_regs_t)))
    86105                return EOVERFLOW;
    87106
    88         /* Create register mapping to use in IRQ handler.
    89          * This mapping should be present in kernel only.
    90          * Remove it from here when kernel knows how to create mappings
    91          * and accepts physical addresses in IRQ code.
    92          * TODO: remove */
    93         ohci_regs_t *registers;
    94         const int ret = pio_enable((void*)regs, reg_size, (void**)&registers);
    95         if (ret != EOK)
    96                 return ret;
    97 
    98         /* Some bogus access to force create mapping. DO NOT remove,
    99          * unless whole virtual addresses in irq is replaced
    100          * NOTE: Compiler won't remove this as ohci_regs_t members
    101          * are declared volatile.
    102          *
    103          * Introducing CMD_MEM set of IRQ code commands broke
    104          * assumption that IRQ code does not cause page faults.
    105          * If this happens during idling (THREAD == NULL)
    106          * it causes kernel panic.
    107          */
    108         registers->revision;
     107        memcpy(ranges, ohci_pio_ranges, sizeof(ohci_pio_ranges));
     108        ranges[0].base = regs;
    109109
    110110        memcpy(cmds, ohci_irq_commands, sizeof(ohci_irq_commands));
    111 
    112         void *address = (void*)&registers->interrupt_status;
    113         cmds[0].addr = address;
    114         cmds[3].addr = address;
     111        ohci_regs_t *registers = (ohci_regs_t *) regs;
     112        cmds[0].addr = (void *) &registers->interrupt_status;
     113        cmds[3].addr = (void *) &registers->interrupt_status;
     114
    115115        return EOK;
    116116}
     
    127127        assert(hub_fun);
    128128
    129         const usb_address_t hub_address =
    130             usb_device_manager_get_free_address(
    131                 &instance->generic.dev_manager, USB_SPEED_FULL);
    132         if (hub_address <= 0) {
     129        /* Try to get address 1 for root hub. */
     130        instance->rh.address = 1;
     131        int ret = usb_device_manager_request_address(
     132            &instance->generic.dev_manager, &instance->rh.address, false,
     133            USB_SPEED_FULL);
     134        if (ret != EOK) {
    133135                usb_log_error("Failed to get OHCI root hub address: %s\n",
    134                     str_error(hub_address));
    135                 return hub_address;
    136         }
    137         instance->rh.address = hub_address;
    138         usb_device_manager_bind(
    139             &instance->generic.dev_manager, hub_address, hub_fun->handle);
     136                    str_error(ret));
     137                return ret;
     138        }
    140139
    141140#define CHECK_RET_UNREG_RETURN(ret, message...) \
    142141if (ret != EOK) { \
    143142        usb_log_error(message); \
    144         usb_endpoint_manager_unregister_ep( \
    145             &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH);\
    146         usb_device_manager_release( \
    147             &instance->generic.dev_manager, hub_address); \
     143        usb_endpoint_manager_remove_ep( \
     144            &instance->generic.ep_manager, instance->rh.address, 0, \
     145            USB_DIRECTION_BOTH, NULL, NULL); \
     146        usb_device_manager_release_address( \
     147            &instance->generic.dev_manager, instance->rh.address); \
    148148        return ret; \
    149149} else (void)0
    150         int ret = usb_endpoint_manager_add_ep(
    151             &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH,
    152             USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64, 0);
     150
     151        ret = usb_endpoint_manager_add_ep(
     152            &instance->generic.ep_manager, instance->rh.address, 0,
     153            USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64,
     154            0, NULL, NULL);
    153155        CHECK_RET_UNREG_RETURN(ret,
    154156            "Failed to register root hub control endpoint: %s.\n",
     
    162164        CHECK_RET_UNREG_RETURN(ret,
    163165            "Failed to bind root hub function: %s.\n", str_error(ret));
     166
     167        ret = usb_device_manager_bind_address(&instance->generic.dev_manager,
     168            instance->rh.address, hub_fun->handle);
     169        if (ret != EOK)
     170                usb_log_warning("Failed to bind root hub address: %s.\n",
     171                    str_error(ret));
    164172
    165173        return EOK;
     
    192200        list_initialize(&instance->pending_batches);
    193201
    194         ret = hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,
    195             bandwidth_count_usb11);
    196         CHECK_RET_RETURN(ret, "Failed to initialize generic driver: %s.\n",
    197             str_error(ret));
     202        hcd_init(&instance->generic, USB_SPEED_FULL,
     203            BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11);
    198204        instance->generic.private_data = instance;
    199205        instance->generic.schedule = hc_schedule;
    200206        instance->generic.ep_add_hook = ohci_endpoint_init;
     207        instance->generic.ep_remove_hook = ohci_endpoint_fini;
    201208
    202209        ret = hc_init_memory(instance);
     
    221228}
    222229/*----------------------------------------------------------------------------*/
    223 void hc_enqueue_endpoint(hc_t *instance, endpoint_t *ep)
    224 {
     230void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep)
     231{
     232        assert(instance);
     233        assert(ep);
     234
    225235        endpoint_list_t *list = &instance->lists[ep->transfer_type];
    226236        ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ep);
     237        assert(list);
     238        assert(ohci_ep);
     239
    227240        /* Enqueue ep */
    228241        switch (ep->transfer_type) {
     
    247260}
    248261/*----------------------------------------------------------------------------*/
    249 void hc_dequeue_endpoint(hc_t *instance, endpoint_t *ep)
    250 {
     262void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep)
     263{
     264        assert(instance);
     265        assert(ep);
     266
    251267        /* Dequeue ep */
    252268        endpoint_list_t *list = &instance->lists[ep->transfer_type];
    253269        ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ep);
     270
     271        assert(list);
     272        assert(ohci_ep);
    254273        switch (ep->transfer_type) {
    255274        case USB_TRANSFER_CONTROL:
  • uspace/drv/bus/usb/ohci/hc.h

    rba72f2b r6843a9c  
    7474} hc_t;
    7575
     76size_t hc_irq_pio_range_count(void);
    7677size_t hc_irq_cmd_count(void);
    77 int hc_get_irq_commands(
    78     irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size);
     78int hc_get_irq_code(irq_pio_range_t [], size_t, irq_cmd_t [], size_t, uintptr_t,
     79    size_t);
    7980int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun);
    8081int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts);
     
    8687static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ };
    8788
    88 void hc_enqueue_endpoint(hc_t *instance, endpoint_t *ep);
    89 void hc_dequeue_endpoint(hc_t *instance, endpoint_t *ep);
     89void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep);
     90void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep);
    9091
    9192void hc_interrupt(hc_t *instance, uint32_t status);
  • uspace/drv/bus/usb/ohci/hw_struct/hcca.h

    rba72f2b r6843a9c  
    4646        uint16_t pad1;
    4747        uint32_t done_head;
    48         uint32_t reserved[29];
    49 } __attribute__((packed, aligned)) hcca_t;
     48        uint32_t reserved[30];
     49} hcca_t;
    5050
    5151static inline void * hcca_get(void)
  • uspace/drv/bus/usb/ohci/main.c

    rba72f2b r6843a9c  
    4848 * @return Error code.
    4949 */
    50 static int ohci_add_device(ddf_dev_t *device)
     50static int ohci_dev_add(ddf_dev_t *device)
    5151{
    52         usb_log_debug("ohci_add_device() called\n");
     52        usb_log_debug("ohci_dev_add() called\n");
    5353        assert(device);
    5454
     
    6565/*----------------------------------------------------------------------------*/
    6666static driver_ops_t ohci_driver_ops = {
    67         .add_device = ohci_add_device,
     67        .dev_add = ohci_dev_add,
    6868};
    6969/*----------------------------------------------------------------------------*/
  • uspace/drv/bus/usb/ohci/ohci.c

    rba72f2b r6843a9c  
    4242
    4343#include "ohci.h"
    44 #include "pci.h"
     44#include "res.h"
    4545#include "hc.h"
    4646
     
    7676}
    7777/*----------------------------------------------------------------------------*/
    78 /** Get address of the device identified by handle.
    79  *
    80  * @param[in] dev DDF instance of the device to use.
    81  * @param[in] iid (Unused).
    82  * @param[in] call Pointer to the call that represents interrupt.
    83  */
    84 static int usb_iface_get_address(
    85     ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address)
     78/** Get USB address assigned to root hub.
     79 *
     80 * @param[in] fun Root hub function.
     81 * @param[out] address Store the address here.
     82 * @return Error code.
     83 */
     84static int rh_get_my_address(ddf_fun_t *fun, usb_address_t *address)
    8685{
    8786        assert(fun);
    88         usb_device_manager_t *manager =
    89             &dev_to_ohci(fun->dev)->hc.generic.dev_manager;
    90 
    91         const usb_address_t addr = usb_device_manager_find(manager, handle);
    92         if (addr < 0) {
    93                 return addr;
    94         }
    9587
    9688        if (address != NULL) {
    97                 *address = addr;
     89                *address = dev_to_ohci(fun->dev)->hc.rh.address;
    9890        }
    9991
     
    10799 * @return Error code.
    108100 */
    109 static int usb_iface_get_hc_handle(
     101static int rh_get_hc_handle(
    110102    ddf_fun_t *fun, devman_handle_t *handle)
    111103{
     
    121113/** Root hub USB interface */
    122114static usb_iface_t usb_iface = {
    123         .get_hc_handle = usb_iface_get_hc_handle,
    124         .get_address = usb_iface_get_address
     115        .get_hc_handle = rh_get_hc_handle,
     116        .get_my_address = rh_get_my_address,
    125117};
    126118/*----------------------------------------------------------------------------*/
     
    148140int device_setup_ohci(ddf_dev_t *device)
    149141{
    150         assert(device);
    151 
    152         ohci_t *instance = malloc(sizeof(ohci_t));
     142        if (device == NULL)
     143                return EBADMEM;
     144
     145        ohci_t *instance = ddf_dev_data_alloc(device,sizeof(ohci_t));
    153146        if (instance == NULL) {
    154147                usb_log_error("Failed to allocate OHCI driver.\n");
    155148                return ENOMEM;
    156149        }
    157         instance->rh_fun = NULL;
    158         instance->hc_fun = NULL;
    159150
    160151#define CHECK_RET_DEST_FREE_RETURN(ret, message...) \
    161152if (ret != EOK) { \
    162153        if (instance->hc_fun) { \
     154                instance->hc_fun->driver_data = NULL; \
    163155                ddf_fun_destroy(instance->hc_fun); \
    164156        } \
    165157        if (instance->rh_fun) { \
     158                instance->rh_fun->driver_data = NULL; \
    166159                ddf_fun_destroy(instance->rh_fun); \
    167160        } \
    168         free(instance); \
    169161        usb_log_error(message); \
    170162        return ret; \
     
    188180        int irq = 0;
    189181
    190         ret = pci_get_my_registers(device, &reg_base, &reg_size, &irq);
     182        ret = get_my_registers(device, &reg_base, &reg_size, &irq);
    191183        CHECK_RET_DEST_FREE_RETURN(ret,
    192184            "Failed to get register memory addresses for %" PRIun ": %s.\n",
     
    195187            (void *) reg_base, reg_size, irq);
    196188
    197         const size_t cmd_count = hc_irq_cmd_count();
    198         irq_cmd_t irq_cmds[cmd_count];
    199         irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds };
    200 
    201         ret =
    202             hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size);
    203         CHECK_RET_DEST_FREE_RETURN(ret,
    204             "Failed to generate IRQ commands: %s.\n", str_error(ret));
     189        const size_t ranges_count = hc_irq_pio_range_count();
     190        const size_t cmds_count = hc_irq_cmd_count();
     191        irq_pio_range_t irq_ranges[ranges_count];
     192        irq_cmd_t irq_cmds[cmds_count];
     193        irq_code_t irq_code = {
     194                .rangecount = ranges_count,
     195                .ranges = irq_ranges,
     196                .cmdcount = cmds_count,
     197                .cmds = irq_cmds
     198        };
     199
     200        ret = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds,
     201            sizeof(irq_cmds), reg_base, reg_size);
     202        CHECK_RET_DEST_FREE_RETURN(ret,
     203            "Failed to generate IRQ code: %s.\n", str_error(ret));
    205204
    206205
     
    212211        /* Try to enable interrupts */
    213212        bool interrupts = false;
    214         ret = pci_enable_interrupts(device);
     213        ret = enable_interrupts(device);
    215214        if (ret != EOK) {
    216215                usb_log_warning("Failed to enable interrupts: %s."
     
    227226            "Failed to init ohci_hcd: %s.\n", str_error(ret));
    228227
    229         device->driver_data = instance;
    230 
    231228#define CHECK_RET_FINI_RETURN(ret, message...) \
    232229if (ret != EOK) { \
  • uspace/drv/bus/usb/ohci/ohci.ma

    rba72f2b r6843a9c  
    1 10 pci/ven=106b&dev=0026
    2 10 pci/ven=106b&dev=003f
    3 10 pci/ven=10de&dev=0aa5
    4 
    5 10 pci/ven=1002&dev=4374
    6 10 pci/ven=1002&dev=4375
    7 
    8 10 pci/ven=1002&dev=4387
    9 10 pci/ven=1002&dev=4388
    10 10 pci/ven=1002&dev=4389
    11 10 pci/ven=1002&dev=438a
    12 10 pci/ven=1002&dev=438b
    13 10 pci/ven=1002&dev=4397
    14 10 pci/ven=1002&dev=4398
    15 10 pci/ven=1002&dev=4399
     110 pci/class=0c&subclass=03&progif=10
  • uspace/drv/bus/usb/ohci/ohci_batch.c

    rba72f2b r6843a9c  
    3434#include <errno.h>
    3535#include <str_error.h>
     36#include <macros.h>
    3637
    3738#include <usb/usb.h>
     
    5354                return;
    5455        if (ohci_batch->tds) {
     56                const ohci_endpoint_t *ohci_ep =
     57                    ohci_endpoint_get(ohci_batch->usb_batch->ep);
     58                assert(ohci_ep);
    5559                for (unsigned i = 0; i < ohci_batch->td_count; ++i) {
    56                         if (i != ohci_batch->leave_td)
     60                        if (ohci_batch->tds[i] != ohci_ep->td)
    5761                                free32(ohci_batch->tds[i]);
    5862                }
    5963                free(ohci_batch->tds);
    6064        }
    61         usb_transfer_batch_dispose(ohci_batch->usb_batch);
     65        usb_transfer_batch_destroy(ohci_batch->usb_batch);
    6266        free32(ohci_batch->device_buffer);
    6367        free(ohci_batch);
    6468}
    6569/*----------------------------------------------------------------------------*/
     70/** Finishes usb_transfer_batch and destroys the structure.
     71 *
     72 * @param[in] uhci_batch Instance to finish and destroy.
     73 */
    6674void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *ohci_batch)
    6775{
     
    6977        assert(ohci_batch->usb_batch);
    7078        usb_transfer_batch_finish(ohci_batch->usb_batch,
    71             ohci_batch->device_buffer + ohci_batch->usb_batch->setup_size,
    72             ohci_batch->usb_batch->buffer_size);
     79            ohci_batch->device_buffer + ohci_batch->usb_batch->setup_size);
    7380        ohci_transfer_batch_dispose(ohci_batch);
    7481}
    7582/*----------------------------------------------------------------------------*/
     83/** Allocate memory and initialize internal data structure.
     84 *
     85 * @param[in] usb_batch Pointer to generic USB batch structure.
     86 * @return Valid pointer if all structures were successfully created,
     87 * NULL otherwise.
     88 *
     89 * Determines the number of needed transfer descriptors (TDs).
     90 * Prepares a transport buffer (that is accessible by the hardware).
     91 * Initializes parameters needed for the transfer and callback.
     92 */
    7693ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *usb_batch)
    7794{
     
    105122        ohci_batch->ed = ohci_endpoint_get(usb_batch->ep)->ed;
    106123        ohci_batch->tds[0] = ohci_endpoint_get(usb_batch->ep)->td;
    107         ohci_batch->leave_td = 0;
    108124
    109125        for (unsigned i = 1; i <= ohci_batch->td_count; ++i) {
     
    152168 * completes with the last TD.
    153169 */
    154 bool ohci_transfer_batch_is_complete(ohci_transfer_batch_t *ohci_batch)
     170bool ohci_transfer_batch_is_complete(const ohci_transfer_batch_t *ohci_batch)
    155171{
    156172        assert(ohci_batch);
     
    174190
    175191        /* Assume we will leave the last(unused) TD behind */
    176         ohci_batch->leave_td = ohci_batch->td_count;
     192        unsigned leave_td = ohci_batch->td_count;
    177193
    178194        /* Check all TDs */
     
    212228                         * It will be the one TD we leave behind.
    213229                         */
    214                         ohci_batch->leave_td = i + 1;
     230                        leave_td = i + 1;
    215231
    216232                        /* Check TD assumption */
    217                         const uint32_t pa = addr_to_phys(
    218                             ohci_batch->tds[ohci_batch->leave_td]);
    219                         assert((ohci_batch->ed->td_head & ED_TDTAIL_PTR_MASK)
     233                        const uint32_t pa =
     234                            addr_to_phys(ohci_batch->tds[leave_td]);
     235                        assert((ohci_batch->ed->td_head & ED_TDHEAD_PTR_MASK)
    220236                            == pa);
    221237
    222238                        ed_set_tail_td(ohci_batch->ed,
    223                             ohci_batch->tds[ohci_batch->leave_td]);
     239                            ohci_batch->tds[leave_td]);
    224240
    225241                        /* Clear possible ED HALT */
     
    234250        ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ohci_batch->usb_batch->ep);
    235251        assert(ohci_ep);
    236         ohci_ep->td = ohci_batch->tds[ohci_batch->leave_td];
     252        ohci_ep->td = ohci_batch->tds[leave_td];
    237253
    238254        /* Make sure that we are leaving the right TD behind */
     
    248264 * @param[in] ohci_batch Batch structure to use
    249265 */
    250 void ohci_transfer_batch_commit(ohci_transfer_batch_t *ohci_batch)
     266void ohci_transfer_batch_commit(const ohci_transfer_batch_t *ohci_batch)
    251267{
    252268        assert(ohci_batch);
     
    295311        while (remain_size > 0) {
    296312                const size_t transfer_size =
    297                     remain_size > OHCI_TD_MAX_TRANSFER ?
    298                     OHCI_TD_MAX_TRANSFER : remain_size;
     313                    min(remain_size, OHCI_TD_MAX_TRANSFER);
    299314                toggle = 1 - toggle;
    300315
     
    378393}
    379394/*----------------------------------------------------------------------------*/
     395/** Transfer setup table. */
    380396static void (*const batch_setup[])(ohci_transfer_batch_t*, usb_direction_t) =
    381397{
  • uspace/drv/bus/usb/ohci/ohci_batch.h

    rba72f2b r6843a9c  
    5353        /** Number of TDs used by the transfer */
    5454        size_t td_count;
    55         /** Dummy TD to be left at the ED and used by the next transfer */
    56         size_t leave_td;
    5755        /** Data buffer, must be accessible by the OHCI hw. */
    5856        char *device_buffer;
     
    6260
    6361ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *batch);
    64 bool ohci_transfer_batch_is_complete(ohci_transfer_batch_t *batch);
    65 void ohci_transfer_batch_commit(ohci_transfer_batch_t *batch);
     62bool ohci_transfer_batch_is_complete(const ohci_transfer_batch_t *batch);
     63void ohci_transfer_batch_commit(const ohci_transfer_batch_t *batch);
    6664void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *batch);
    6765/*----------------------------------------------------------------------------*/
  • uspace/drv/bus/usb/ohci/ohci_endpoint.c

    rba72f2b r6843a9c  
    6262}
    6363/*----------------------------------------------------------------------------*/
    64 /** Disposes hcd endpoint structure
    65  *
    66  * @param[in] hcd_ep endpoint structure
    67  */
    68 static void ohci_endpoint_fini(endpoint_t *ep)
    69 {
    70         ohci_endpoint_t *instance = ep->hc_data.data;
    71         hc_dequeue_endpoint(instance->hcd->private_data, ep);
    72         if (instance) {
    73                 free32(instance->ed);
    74                 free32(instance->td);
    75                 free(instance);
    76         }
    77 }
    78 /*----------------------------------------------------------------------------*/
    7964/** Creates new hcd endpoint representation.
    8065 *
    8166 * @param[in] ep USBD endpoint structure
    82  * @return pointer to a new hcd endpoint structure, NULL on failure.
     67 * @return Error code.
    8368 */
    8469int ohci_endpoint_init(hcd_t *hcd, endpoint_t *ep)
     
    10489        ed_init(ohci_ep->ed, ep, ohci_ep->td);
    10590        endpoint_set_hc_data(
    106             ep, ohci_ep, ohci_endpoint_fini, ohci_ep_toggle_get, ohci_ep_toggle_set);
    107         ohci_ep->hcd = hcd;
     91            ep, ohci_ep, ohci_ep_toggle_get, ohci_ep_toggle_set);
    10892        hc_enqueue_endpoint(hcd->private_data, ep);
    10993        return EOK;
     94}
     95/*----------------------------------------------------------------------------*/
     96/** Disposes hcd endpoint structure
     97 *
     98 * @param[in] hcd driver using this instance.
     99 * @param[in] ep endpoint structure.
     100 */
     101void ohci_endpoint_fini(hcd_t *hcd, endpoint_t *ep)
     102{
     103        assert(hcd);
     104        assert(ep);
     105        ohci_endpoint_t *instance = ohci_endpoint_get(ep);
     106        hc_dequeue_endpoint(hcd->private_data, ep);
     107        if (instance) {
     108                free32(instance->ed);
     109                free32(instance->td);
     110                free(instance);
     111        }
     112        endpoint_clear_hc_data(ep);
    110113}
    111114/**
  • uspace/drv/bus/usb/ohci/ohci_endpoint.h

    rba72f2b r6843a9c  
    5151        /** Linked list used by driver software */
    5252        link_t link;
    53         /** Device using this ep */
    54         hcd_t *hcd;
    5553} ohci_endpoint_t;
    5654
    5755int ohci_endpoint_init(hcd_t *hcd, endpoint_t *ep);
     56void ohci_endpoint_fini(hcd_t *hcd, endpoint_t *ep);
    5857
    5958/** Get and convert assigned ohci_endpoint_t structure
     
    6160 * @return Pointer to assigned hcd endpoint structure
    6261 */
    63 static inline ohci_endpoint_t * ohci_endpoint_get(endpoint_t *ep)
     62static inline ohci_endpoint_t * ohci_endpoint_get(const endpoint_t *ep)
    6463{
    6564        assert(ep);
  • uspace/drv/bus/usb/ohci/ohci_regs.h

    rba72f2b r6843a9c  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbohcihc
     28/** @addtogroup drvusbohci
    2929 * @{
    3030 */
  • uspace/drv/bus/usb/ohci/res.c

    rba72f2b r6843a9c  
    3838#include <errno.h>
    3939#include <assert.h>
    40 #include <as.h>
    4140#include <devman.h>
    42 #include <ddi.h>
    43 #include <libarch/ddi.h>
    44 #include <device/hw_res.h>
     41#include <device/hw_res_parsed.h>
    4542
    4643#include <usb/debug.h>
    47 #include <pci_dev_iface.h>
    4844
    49 #include "pci.h"
     45#include "res.h"
    5046
    5147/** Get address of registers and IRQ for given device.
     
    5753 * @return Error code.
    5854 */
    59 int pci_get_my_registers(ddf_dev_t *dev,
     55int get_my_registers(const ddf_dev_t *dev,
    6056    uintptr_t *mem_reg_address, size_t *mem_reg_size, int *irq_no)
    6157{
    6258        assert(dev);
    63         assert(mem_reg_address);
    64         assert(mem_reg_size);
    65         assert(irq_no);
    6659
    6760        async_sess_t *parent_sess =
     
    7164                return ENOMEM;
    7265
    73         hw_resource_list_t hw_resources;
    74         int rc = hw_res_get_resource_list(parent_sess, &hw_resources);
     66        hw_res_list_parsed_t hw_res;
     67        hw_res_list_parsed_init(&hw_res);
     68        const int ret =  hw_res_get_list_parsed(parent_sess, &hw_res, 0);
    7569        async_hangup(parent_sess);
    76         if (rc != EOK) {
    77                 return rc;
     70        if (ret != EOK) {
     71                return ret;
    7872        }
    7973
    80         uintptr_t mem_address = 0;
    81         size_t mem_size = 0;
    82         bool mem_found = false;
     74        /* We want one irq and one mem range. */
     75        if (hw_res.irqs.count != 1 || hw_res.mem_ranges.count != 1) {
     76                hw_res_list_parsed_clean(&hw_res);
     77                return EINVAL;
     78        }
    8379
    84         int irq = 0;
    85         bool irq_found = false;
     80        if (mem_reg_address)
     81                *mem_reg_address = hw_res.mem_ranges.ranges[0].address;
     82        if (mem_reg_size)
     83                *mem_reg_size = hw_res.mem_ranges.ranges[0].size;
     84        if (irq_no)
     85                *irq_no = hw_res.irqs.irqs[0];
    8686
    87         for (size_t i = 0; i < hw_resources.count; i++) {
    88                 hw_resource_t *res = &hw_resources.resources[i];
    89                 switch (res->type) {
    90                 case INTERRUPT:
    91                         irq = res->res.interrupt.irq;
    92                         irq_found = true;
    93                         usb_log_debug2("Found interrupt: %d.\n", irq);
    94                         break;
    95                 case MEM_RANGE:
    96                         if (res->res.mem_range.address != 0
    97                             && res->res.mem_range.size != 0 ) {
    98                                 mem_address = res->res.mem_range.address;
    99                                 mem_size = res->res.mem_range.size;
    100                                 usb_log_debug2("Found mem: %p %zu.\n",
    101                                     (void *) mem_address, mem_size);
    102                                 mem_found = true;
    103                         }
    104                 default:
    105                         break;
    106                 }
    107         }
    108         free(hw_resources.resources);
    109 
    110         if (mem_found && irq_found) {
    111                 *mem_reg_address = mem_address;
    112                 *mem_reg_size = mem_size;
    113                 *irq_no = irq;
    114                 return EOK;
    115         }
    116         return ENOENT;
     87        hw_res_list_parsed_clean(&hw_res);
     88        return EOK;
    11789}
    11890
     
    12294 * @return Error code.
    12395 */
    124 int pci_enable_interrupts(ddf_dev_t *device)
     96int enable_interrupts(const ddf_dev_t *device)
    12597{
    12698        async_sess_t *parent_sess =
     
    130102                return ENOMEM;
    131103       
    132         bool enabled = hw_res_enable_interrupt(parent_sess);
     104        const bool enabled = hw_res_enable_interrupt(parent_sess);
    133105        async_hangup(parent_sess);
    134106       
  • uspace/drv/bus/usb/ohci/res.h

    rba72f2b r6843a9c  
    3232 * PCI related functions needed by OHCI driver.
    3333 */
    34 #ifndef DRV_OHCI_PCI_H
    35 #define DRV_OHCI_PCI_H
     34#ifndef DRV_OHCI_RES_H
     35#define DRV_OHCI_RES_H
    3636
    3737#include <ddf/driver.h>
    3838
    39 int pci_get_my_registers(ddf_dev_t *, uintptr_t *, size_t *, int *);
    40 int pci_enable_interrupts(ddf_dev_t *);
    41 int pci_disable_legacy(ddf_dev_t *);
     39int get_my_registers(const ddf_dev_t *, uintptr_t *, size_t *, int *);
     40int enable_interrupts(const ddf_dev_t *);
    4241
    4342#endif
  • uspace/drv/bus/usb/ohci/root_hub.c

    rba72f2b r6843a9c  
    100100        .attributes = USB_TRANSFER_INTERRUPT,
    101101        .descriptor_type = USB_DESCTYPE_ENDPOINT,
    102         .endpoint_address = 1 + (1 << 7),
     102        .endpoint_address = 1 | (1 << 7),
    103103        .length = sizeof(usb_standard_endpoint_descriptor_t),
    104104        .max_packet_size = 2,
     
    109109static void rh_init_descriptors(rh_t *instance);
    110110static uint16_t create_interrupt_mask(const rh_t *instance);
    111 static int get_status(const rh_t *instance, usb_transfer_batch_t *request);
    112 static int get_descriptor(const rh_t *instance, usb_transfer_batch_t *request);
    113 static int set_feature(const rh_t *instance, usb_transfer_batch_t *request);
    114 static int clear_feature(const rh_t *instance, usb_transfer_batch_t *request);
     111static void get_status(const rh_t *instance, usb_transfer_batch_t *request);
     112static void get_descriptor(const rh_t *instance, usb_transfer_batch_t *request);
     113static void set_feature(const rh_t *instance, usb_transfer_batch_t *request);
     114static void clear_feature(const rh_t *instance, usb_transfer_batch_t *request);
    115115static int set_feature_port(
    116116    const rh_t *instance, uint16_t feature, uint16_t port);
    117117static int clear_feature_port(
    118118    const rh_t *instance, uint16_t feature, uint16_t port);
    119 static int control_request(rh_t *instance, usb_transfer_batch_t *request);
     119static void control_request(rh_t *instance, usb_transfer_batch_t *request);
    120120static inline void interrupt_request(
    121121    usb_transfer_batch_t *request, uint16_t mask, size_t size)
    122122{
    123123        assert(request);
    124 
    125         request->transfered_size = size;
    126124        usb_transfer_batch_finish_error(request, &mask, size, EOK);
    127 }
    128 
    129 #define TRANSFER_OK(bytes) \
     125        usb_transfer_batch_destroy(request);
     126}
     127
     128#define TRANSFER_END_DATA(request, data, bytes) \
    130129do { \
    131         request->transfered_size = bytes; \
    132         return EOK; \
     130        usb_transfer_batch_finish_error(request, data, bytes, EOK); \
     131        usb_transfer_batch_destroy(request); \
     132        return; \
     133} while (0)
     134
     135#define TRANSFER_END(request, error) \
     136do { \
     137        usb_transfer_batch_finish_error(request, NULL, 0, error); \
     138        usb_transfer_batch_destroy(request); \
     139        return; \
    133140} while (0)
    134141
     
    212219        case USB_TRANSFER_CONTROL:
    213220                usb_log_debug("Root hub got CONTROL packet\n");
    214                 const int ret = control_request(instance, request);
    215                 usb_transfer_batch_finish_error(request, NULL, 0, ret);
     221                control_request(instance, request);
    216222                break;
     223
    217224        case USB_TRANSFER_INTERRUPT:
    218225                usb_log_debug("Root hub got INTERRUPT packet\n");
    219226                fibril_mutex_lock(&instance->guard);
    220227                assert(instance->unfinished_interrupt_transfer == NULL);
    221                 const uint16_t mask = create_interrupt_mask(instance);
     228                uint16_t mask = create_interrupt_mask(instance);
    222229                if (mask == 0) {
    223                         usb_log_debug("No changes..\n");
     230                        usb_log_debug("No changes...\n");
    224231                        instance->unfinished_interrupt_transfer = request;
    225                         fibril_mutex_unlock(&instance->guard);
    226                         return;
     232                } else {
     233                        usb_log_debug("Processing changes...\n");
     234                        interrupt_request(
     235                            request, mask, instance->interrupt_mask_size);
    227236                }
    228                 usb_log_debug("Processing changes...\n");
    229                 interrupt_request(request, mask, instance->interrupt_mask_size);
    230237                fibril_mutex_unlock(&instance->guard);
    231238                break;
     
    233240        default:
    234241                usb_log_error("Root hub got unsupported request.\n");
    235                 usb_transfer_batch_finish_error(request, NULL, 0, EINVAL);
    236         }
    237         usb_transfer_batch_dispose(request);
     242                TRANSFER_END(request, ENOTSUP);
     243        }
    238244}
    239245/*----------------------------------------------------------------------------*/
     
    251257        if (instance->unfinished_interrupt_transfer) {
    252258                usb_log_debug("Finalizing interrupt transfer\n");
    253                 const uint16_t mask = create_interrupt_mask(instance);
     259                uint16_t mask = create_interrupt_mask(instance);
    254260                interrupt_request(instance->unfinished_interrupt_transfer,
    255261                    mask, instance->interrupt_mask_size);
    256                 usb_transfer_batch_dispose(
    257                     instance->unfinished_interrupt_transfer);
    258262                instance->unfinished_interrupt_transfer = NULL;
    259263        }
     
    274278
    275279        /* 7 bytes + 2 port bit fields (port count + global bit) */
    276         const size_t size = 7 + (instance->interrupt_mask_size * 2);
     280        size_t size = 7 + (instance->interrupt_mask_size * 2);
    277281        assert(size <= HUB_DESCRIPTOR_MAX_SIZE);
    278282        instance->hub_descriptor_size = size;
    279283
    280         const uint32_t hub_desc = instance->registers->rh_desc_a;
    281         const uint32_t port_desc = instance->registers->rh_desc_b;
     284        uint32_t hub_desc = instance->registers->rh_desc_a;
     285        uint32_t port_desc = instance->registers->rh_desc_b;
    282286
    283287        /* bDescLength */
     
    384388 * @return error code
    385389 */
    386 int get_status(const rh_t *instance, usb_transfer_batch_t *request)
     390void get_status(const rh_t *instance, usb_transfer_batch_t *request)
    387391{
    388392        assert(instance);
    389393        assert(request);
    390394
    391         const usb_device_request_setup_packet_t *request_packet =
     395
     396        usb_device_request_setup_packet_t *request_packet =
    392397            (usb_device_request_setup_packet_t*)request->setup_buffer;
    393398
    394         if (request->buffer_size < 4) {
    395                 usb_log_error("Buffer too small for get status request.\n");
    396                 return EOVERFLOW;
    397         }
    398 
     399        switch (request_packet->request_type)
     400        {
     401        case USB_HUB_REQ_TYPE_GET_HUB_STATUS:
    399402        /* Hub status: just filter relevant info from rh_status reg */
    400         if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS) {
    401                 const uint32_t data = instance->registers->rh_status &
    402                     (RHS_LPS_FLAG | RHS_LPSC_FLAG | RHS_OCI_FLAG | RHS_OCIC_FLAG);
    403                 memcpy(request->buffer, &data, sizeof(data));
    404                 TRANSFER_OK(sizeof(data));
    405         }
     403                if (request->buffer_size < 4) {
     404                        usb_log_error("Buffer(%zu) too small for hub get "
     405                            "status request.\n", request->buffer_size);
     406                        TRANSFER_END(request, EOVERFLOW);
     407                } else {
     408                        uint32_t data = instance->registers->rh_status &
     409                            (RHS_LPS_FLAG | RHS_LPSC_FLAG
     410                                | RHS_OCI_FLAG | RHS_OCIC_FLAG);
     411                        TRANSFER_END_DATA(request, &data, sizeof(data));
     412                }
    406413
    407414        /* Copy appropriate rh_port_status register, OHCI designers were
    408415         * kind enough to make those bit values match USB specification */
    409         if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS) {
    410                 const unsigned port = request_packet->index;
    411                 if (port < 1 || port > instance->port_count)
    412                         return EINVAL;
    413 
    414                 const uint32_t data =
    415                     instance->registers->rh_port_status[port - 1];
    416                 memcpy(request->buffer, &data, sizeof(data));
    417                 TRANSFER_OK(sizeof(data));
    418         }
    419 
    420         return ENOTSUP;
     416        case USB_HUB_REQ_TYPE_GET_PORT_STATUS:
     417                if (request->buffer_size < 4) {
     418                        usb_log_error("Buffer(%zu) too small for hub get "
     419                            "status request.\n", request->buffer_size);
     420                        TRANSFER_END(request, EOVERFLOW);
     421                } else {
     422                        unsigned port = request_packet->index;
     423                        if (port < 1 || port > instance->port_count)
     424                                TRANSFER_END(request, EINVAL);
     425
     426                        uint32_t data =
     427                            instance->registers->rh_port_status[port - 1];
     428                        TRANSFER_END_DATA(request, &data, sizeof(data));
     429                }
     430        case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE):
     431                if (request->buffer_size < 2) {
     432                        usb_log_error("Buffer(%zu) too small for hub generic "
     433                            "get status request.\n", request->buffer_size);
     434                        TRANSFER_END(request, EOVERFLOW);
     435                } else {
     436                        uint16_t data =
     437                            uint16_host2usb(USB_DEVICE_STATUS_SELF_POWERED);
     438                        TRANSFER_END_DATA(request, &data, sizeof(data));
     439                }
     440
     441        case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE):
     442                /* Hubs are allowed to have only one interface */
     443                if (request_packet->index != 0)
     444                        TRANSFER_END(request, EINVAL);
     445                /* Fall through, as the answer will be the same: 0x0000 */
     446        case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_ENDPOINT):
     447                /* Endpoint 0 (default control) and 1 (interrupt) */
     448                if (request_packet->index >= 2)
     449                        TRANSFER_END(request, EINVAL);
     450
     451                if (request->buffer_size < 2) {
     452                        usb_log_error("Buffer(%zu) too small for hub generic "
     453                            "get status request.\n", request->buffer_size);
     454                        TRANSFER_END(request, EOVERFLOW);
     455                } else {
     456                        /* Endpoints are OK. (We don't halt) */
     457                        uint16_t data = 0;
     458                        TRANSFER_END_DATA(request, &data, sizeof(data));
     459                }
     460
     461        default:
     462                usb_log_error("Unsupported GET_STATUS request.\n");
     463                TRANSFER_END(request, ENOTSUP);
     464        }
     465
    421466}
    422467/*----------------------------------------------------------------------------*/
     
    430475 * @return Error code
    431476 */
    432 int get_descriptor(const rh_t *instance, usb_transfer_batch_t *request)
     477void get_descriptor(const rh_t *instance, usb_transfer_batch_t *request)
    433478{
    434479        assert(instance);
    435480        assert(request);
    436481
    437         const usb_device_request_setup_packet_t *setup_request =
     482        usb_device_request_setup_packet_t *setup_request =
    438483            (usb_device_request_setup_packet_t *) request->setup_buffer;
    439         size_t size;
    440         const void *descriptor = NULL;
    441         const uint16_t setup_request_value = setup_request->value_high;
    442         //(setup_request->value_low << 8);
     484        uint16_t setup_request_value = setup_request->value_high;
    443485        switch (setup_request_value)
    444486        {
    445487        case USB_DESCTYPE_HUB:
    446488                usb_log_debug2("USB_DESCTYPE_HUB\n");
    447                 /* Hub descriptor was generated locally */
    448                 descriptor = instance->descriptors.hub;
    449                 size = instance->hub_descriptor_size;
    450                 break;
     489                /* Hub descriptor was generated locally.
     490                 * Class specific request. */
     491                TRANSFER_END_DATA(request, instance->descriptors.hub,
     492                    instance->hub_descriptor_size);
    451493
    452494        case USB_DESCTYPE_DEVICE:
    453495                usb_log_debug2("USB_DESCTYPE_DEVICE\n");
    454                 /* Device descriptor is shared (No one should ask for it)*/
    455                 descriptor = &ohci_rh_device_descriptor;
    456                 size = sizeof(ohci_rh_device_descriptor);
    457                 break;
     496                /* Device descriptor is shared
     497                 * (No one should ask for it, as the device is already setup)
     498                 * Standard USB device request. */
     499                TRANSFER_END_DATA(request, &ohci_rh_device_descriptor,
     500                    sizeof(ohci_rh_device_descriptor));
    458501
    459502        case USB_DESCTYPE_CONFIGURATION:
    460503                usb_log_debug2("USB_DESCTYPE_CONFIGURATION\n");
    461504                /* Start with configuration and add others depending on
    462                  * request size */
    463                 descriptor = &instance->descriptors;
    464                 size = instance->descriptors.configuration.total_length;
    465                 break;
     505                 * request size. Standard USB request. */
     506                TRANSFER_END_DATA(request, &instance->descriptors,
     507                    instance->descriptors.configuration.total_length);
    466508
    467509        case USB_DESCTYPE_INTERFACE:
    468510                usb_log_debug2("USB_DESCTYPE_INTERFACE\n");
    469511                /* Use local interface descriptor. There is one and it
    470                  * might be modified */
    471                 descriptor = &instance->descriptors.interface;
    472                 size = sizeof(instance->descriptors.interface);
    473                 break;
     512                 * might be modified. Hub driver should not ask or this
     513                 * descriptor as it is not part of standard requests set. */
     514                TRANSFER_END_DATA(request, &instance->descriptors.interface,
     515                    sizeof(instance->descriptors.interface));
    474516
    475517        case USB_DESCTYPE_ENDPOINT:
    476518                /* Use local endpoint descriptor. There is one
    477                  * it might have max_packet_size field modified*/
     519                 * it might have max_packet_size field modified. Hub driver
     520                 * should not ask for this descriptor as it is not part
     521                 * of standard requests set. */
    478522                usb_log_debug2("USB_DESCTYPE_ENDPOINT\n");
    479                 descriptor = &instance->descriptors.endpoint;
    480                 size = sizeof(instance->descriptors.endpoint);
    481                 break;
     523                TRANSFER_END_DATA(request, &instance->descriptors.endpoint,
     524                    sizeof(instance->descriptors.endpoint));
    482525
    483526        default:
     
    489532                    setup_request_value, setup_request->index,
    490533                    setup_request->length);
    491                 return EINVAL;
    492         }
    493         if (request->buffer_size < size) {
    494                 size = request->buffer_size;
    495         }
    496 
    497         memcpy(request->buffer, descriptor, size);
    498         TRANSFER_OK(size);
     534                TRANSFER_END(request, EINVAL);
     535        }
     536
     537        TRANSFER_END(request, ENOTSUP);
    499538}
    500539/*----------------------------------------------------------------------------*/
     
    604643 * @return error code
    605644 */
    606 int set_feature(const rh_t *instance, usb_transfer_batch_t *request)
     645void set_feature(const rh_t *instance, usb_transfer_batch_t *request)
    607646{
    608647        assert(instance);
    609648        assert(request);
    610649
    611         const usb_device_request_setup_packet_t *setup_request =
     650        usb_device_request_setup_packet_t *setup_request =
    612651            (usb_device_request_setup_packet_t *) request->setup_buffer;
    613652        switch (setup_request->request_type)
     
    615654        case USB_HUB_REQ_TYPE_SET_PORT_FEATURE:
    616655                usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
    617                 return set_feature_port(instance,
     656                int ret = set_feature_port(instance,
    618657                    setup_request->value, setup_request->index);
     658                TRANSFER_END(request, ret);
    619659
    620660        case USB_HUB_REQ_TYPE_SET_HUB_FEATURE:
     
    623663                 * features. It makes no sense to SET either. */
    624664                usb_log_error("Invalid HUB set feature request.\n");
    625                 return ENOTSUP;
     665                TRANSFER_END(request, ENOTSUP);
     666        //TODO: Consider standard USB requests: REMOTE WAKEUP, ENDPOINT STALL
    626667        default:
    627668                usb_log_error("Invalid set feature request type: %d\n",
    628669                    setup_request->request_type);
    629                 return EINVAL;
     670                TRANSFER_END(request, ENOTSUP);
    630671        }
    631672}
     
    640681 * @return error code
    641682 */
    642 int clear_feature(const rh_t *instance, usb_transfer_batch_t *request)
     683void clear_feature(const rh_t *instance, usb_transfer_batch_t *request)
    643684{
    644685        assert(instance);
    645686        assert(request);
    646687
    647         const usb_device_request_setup_packet_t *setup_request =
     688        usb_device_request_setup_packet_t *setup_request =
    648689            (usb_device_request_setup_packet_t *) request->setup_buffer;
    649 
    650         request->transfered_size = 0;
    651690
    652691        switch (setup_request->request_type)
     
    654693        case USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE:
    655694                usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE\n");
    656                 return clear_feature_port(instance,
     695                int ret = clear_feature_port(instance,
    657696                    setup_request->value, setup_request->index);
     697                TRANSFER_END(request, ret);
    658698
    659699        case USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE:
     
    668708                if (setup_request->value == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) {
    669709                        instance->registers->rh_status = RHS_OCIC_FLAG;
    670                         TRANSFER_OK(0);
     710                        TRANSFER_END(request, EOK);
    671711                }
     712        //TODO: Consider standard USB requests: REMOTE WAKEUP, ENDPOINT STALL
    672713        default:
    673714                usb_log_error("Invalid clear feature request type: %d\n",
    674715                    setup_request->request_type);
    675                 return EINVAL;
     716                TRANSFER_END(request, ENOTSUP);
    676717        }
    677718}
     
    695736 * @return error code
    696737 */
    697 int control_request(rh_t *instance, usb_transfer_batch_t *request)
     738void control_request(rh_t *instance, usb_transfer_batch_t *request)
    698739{
    699740        assert(instance);
     
    702743        if (!request->setup_buffer) {
    703744                usb_log_error("Root hub received empty transaction!");
    704                 return EINVAL;
     745                TRANSFER_END(request, EBADMEM);
    705746        }
    706747
    707748        if (sizeof(usb_device_request_setup_packet_t) > request->setup_size) {
    708749                usb_log_error("Setup packet too small\n");
    709                 return EOVERFLOW;
     750                TRANSFER_END(request, EOVERFLOW);
    710751        }
    711752
    712753        usb_log_debug2("CTRL packet: %s.\n",
    713754            usb_debug_str_buffer((uint8_t *) request->setup_buffer, 8, 8));
    714         const usb_device_request_setup_packet_t *setup_request =
     755        usb_device_request_setup_packet_t *setup_request =
    715756            (usb_device_request_setup_packet_t *) request->setup_buffer;
    716757        switch (setup_request->request)
     
    718759        case USB_DEVREQ_GET_STATUS:
    719760                usb_log_debug("USB_DEVREQ_GET_STATUS\n");
    720                 return get_status(instance, request);
     761                get_status(instance, request);
     762                break;
    721763
    722764        case USB_DEVREQ_GET_DESCRIPTOR:
    723765                usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n");
    724                 return get_descriptor(instance, request);
     766                get_descriptor(instance, request);
     767                break;
    725768
    726769        case USB_DEVREQ_GET_CONFIGURATION:
    727770                usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n");
    728                 if (request->buffer_size != 1)
    729                         return EINVAL;
    730                 request->buffer[0] = 1;
    731                 TRANSFER_OK(1);
     771                if (request->buffer_size == 0)
     772                        TRANSFER_END(request, EOVERFLOW);
     773                uint8_t config = 1;
     774                TRANSFER_END_DATA(request, &config, sizeof(config));
    732775
    733776        case USB_DEVREQ_CLEAR_FEATURE:
    734                 usb_log_debug2("Processing request without "
    735                     "additional data\n");
    736                 return clear_feature(instance, request);
     777                usb_log_debug2("USB_DEVREQ_CLEAR_FEATURE\n");
     778                clear_feature(instance, request);
     779                break;
    737780
    738781        case USB_DEVREQ_SET_FEATURE:
    739                 usb_log_debug2("Processing request without "
    740                     "additional data\n");
    741                 return set_feature(instance, request);
     782                usb_log_debug2("USB_DEVREQ_SET_FEATURE\n");
     783                set_feature(instance, request);
     784                break;
    742785
    743786        case USB_DEVREQ_SET_ADDRESS:
    744                 usb_log_debug("USB_DEVREQ_SET_ADDRESS\n");
     787                usb_log_debug("USB_DEVREQ_SET_ADDRESS: %u\n",
     788                    setup_request->value);
     789                if (uint16_usb2host(setup_request->value) > 127)
     790                        TRANSFER_END(request, EINVAL);
     791
    745792                instance->address = setup_request->value;
    746                 TRANSFER_OK(0);
     793                TRANSFER_END(request, EOK);
    747794
    748795        case USB_DEVREQ_SET_CONFIGURATION:
    749                 usb_log_debug("USB_DEVREQ_SET_CONFIGURATION\n");
    750                 /* We don't need to do anything */
    751                 TRANSFER_OK(0);
    752 
    753         case USB_DEVREQ_SET_DESCRIPTOR: /* Not supported by OHCI RH */
     796                usb_log_debug("USB_DEVREQ_SET_CONFIGURATION: %u\n",
     797                    setup_request->value);
     798                /* We have only one configuration, it's number is 1 */
     799                if (uint16_usb2host(setup_request->value) != 1)
     800                        TRANSFER_END(request, EINVAL);
     801                TRANSFER_END(request, EOK);
     802
     803        /* Both class specific and std is optional for hubs */
     804        case USB_DEVREQ_SET_DESCRIPTOR:
     805        /* Hubs have only one interface GET/SET is not supported */
     806        case USB_DEVREQ_GET_INTERFACE:
     807        case USB_DEVREQ_SET_INTERFACE:
    754808        default:
     809                /* Hub class GET_STATE(2) falls in here too. */
    755810                usb_log_error("Received unsupported request: %d.\n",
    756811                    setup_request->request);
    757                 return ENOTSUP;
    758         }
    759 }
    760 
     812                TRANSFER_END(request, ENOTSUP);
     813        }
     814}
    761815/**
    762816 * @}
  • uspace/drv/bus/usb/ohci/utils/malloc32.h

    rba72f2b r6843a9c  
    3737#include <assert.h>
    3838#include <malloc.h>
     39#include <unistd.h>
    3940#include <errno.h>
    4041#include <mem.h>
     
    5657        uintptr_t result;
    5758        int ret = as_get_physical_mapping(addr, &result);
    58 
     59       
    5960        if (ret != EOK)
    6061                return 0;
    61         return (result | ((uintptr_t)addr & 0xfff));
     62       
     63        return result;
    6264}
    6365/*----------------------------------------------------------------------------*/
  • uspace/drv/bus/usb/uhci/Makefile

    rba72f2b r6843a9c  
    4444        hc.c \
    4545        main.c \
    46         pci.c \
     46        res.c \
    4747        root_hub.c \
    4848        transfer_list.c \
  • uspace/drv/bus/usb/uhci/hc.c

    rba72f2b r6843a9c  
    4848    (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)
    4949
    50 
    51 static const irq_cmd_t uhci_irq_commands[] =
    52 {
     50static const irq_pio_range_t uhci_irq_pio_ranges[] = {
     51        {
     52                .base = 0,      /* filled later */
     53                .size = sizeof(uhci_regs_t)
     54        }
     55};
     56
     57static const irq_cmd_t uhci_irq_commands[] = {
    5358        { .cmd = CMD_PIO_READ_16, .dstarg = 1, .addr = NULL/*filled later*/},
    5459        { .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2,
     
    6873
    6974/*----------------------------------------------------------------------------*/
     75/** Get number of PIO ranges used in IRQ code.
     76 * @return Number of ranges.
     77 */
     78size_t hc_irq_pio_range_count(void)
     79{
     80        return sizeof(uhci_irq_pio_ranges) / sizeof(irq_pio_range_t);
     81}
     82/*----------------------------------------------------------------------------*/
    7083/** Get number of commands used in IRQ code.
    7184 * @return Number of commands.
     
    7689}
    7790/*----------------------------------------------------------------------------*/
    78 /** Generate IRQ code commands.
    79  * @param[out] cmds Place to store the commands.
    80  * @param[in] cmd_size Size of the place (bytes).
     91/** Generate IRQ code.
     92 * @param[out] ranges PIO ranges buffer.
     93 * @param[in] ranges_size Size of the ranges buffer (bytes).
     94 * @param[out] cmds Commands buffer.
     95 * @param[in] cmds_size Size of the commands buffer (bytes).
    8196 * @param[in] regs Physical address of device's registers.
    8297 * @param[in] reg_size Size of the register area (bytes).
     
    8499 * @return Error code.
    85100 */
    86 int hc_get_irq_commands(
    87     irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size)
    88 {
    89         if (cmd_size < sizeof(uhci_irq_commands)
    90             || reg_size < sizeof(uhci_regs_t))
     101int
     102hc_get_irq_code(irq_pio_range_t ranges[], size_t ranges_size, irq_cmd_t cmds[],
     103    size_t cmds_size, uintptr_t regs, size_t reg_size)
     104{
     105        if ((ranges_size < sizeof(uhci_irq_pio_ranges)) ||
     106            (cmds_size < sizeof(uhci_irq_commands)) ||
     107            (reg_size < sizeof(uhci_regs_t)))
    91108                return EOVERFLOW;
    92109
    93         uhci_regs_t *registers = (uhci_regs_t*)regs;
     110        memcpy(ranges, uhci_irq_pio_ranges, sizeof(uhci_irq_pio_ranges));
     111        ranges[0].base = regs;
    94112
    95113        memcpy(cmds, uhci_irq_commands, sizeof(uhci_irq_commands));
    96 
    97         cmds[0].addr = (void*)&registers->usbsts;
    98         cmds[3].addr = (void*)&registers->usbsts;
     114        uhci_regs_t *registers = (uhci_regs_t *) regs;
     115        cmds[0].addr = &registers->usbsts;
     116        cmds[3].addr = &registers->usbsts;
     117
    99118        return EOK;
    100119}
     
    130149                        uhci_transfer_batch_t *batch =
    131150                            uhci_transfer_batch_from_link(item);
    132                         uhci_transfer_batch_call_dispose(batch);
     151                        uhci_transfer_batch_finish_dispose(batch);
    133152                }
    134153        }
     
    192211            "Device registers at %p (%zuB) accessible.\n", io, reg_size);
    193212
    194         ret = hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,
    195             bandwidth_count_usb11);
    196         CHECK_RET_RETURN(ret, "Failed to initialize HCD generic driver: %s.\n",
     213        ret = hc_init_mem_structures(instance);
     214        CHECK_RET_RETURN(ret,
     215            "Failed to initialize UHCI memory structures: %s.\n",
    197216            str_error(ret));
     217
     218#undef CHECK_RET_RETURN
     219
     220        hcd_init(&instance->generic, USB_SPEED_FULL,
     221            BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11);
    198222
    199223        instance->generic.private_data = instance;
    200224        instance->generic.schedule = hc_schedule;
    201225        instance->generic.ep_add_hook = NULL;
    202 
    203 #undef CHECK_RET_DEST_FUN_RETURN
    204 
    205         ret = hc_init_mem_structures(instance);
    206         if (ret != EOK) {
    207                 usb_log_error(
    208                     "Failed to initialize UHCI memory structures: %s.\n",
    209                     str_error(ret));
    210                 hcd_destroy(&instance->generic);
    211                 return ret;
    212         }
    213226
    214227        hc_init_hw(instance);
  • uspace/drv/bus/usb/uhci/hc.h

    rba72f2b r6843a9c  
    121121} hc_t;
    122122
     123size_t hc_irq_pio_range_count(void);
    123124size_t hc_irq_cmd_count(void);
    124 int hc_get_irq_commands(
    125     irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size);
     125int hc_get_irq_code(irq_pio_range_t [], size_t, irq_cmd_t [], size_t, uintptr_t,
     126    size_t);
    126127void hc_interrupt(hc_t *instance, uint16_t status);
    127128int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interupts);
  • uspace/drv/bus/usb/uhci/main.c

    rba72f2b r6843a9c  
    4343#define NAME "uhci"
    4444
    45 static int uhci_add_device(ddf_dev_t *device);
     45static int uhci_dev_add(ddf_dev_t *device);
    4646/*----------------------------------------------------------------------------*/
    4747static driver_ops_t uhci_driver_ops = {
    48         .add_device = uhci_add_device,
     48        .dev_add = uhci_dev_add,
    4949};
    5050/*----------------------------------------------------------------------------*/
     
    5959 * @return Error code.
    6060 */
    61 int uhci_add_device(ddf_dev_t *device)
     61int uhci_dev_add(ddf_dev_t *device)
    6262{
    63         usb_log_debug2("uhci_add_device() called\n");
     63        usb_log_debug2("uhci_dev_add() called\n");
    6464        assert(device);
    6565
  • uspace/drv/bus/usb/uhci/res.c

    rba72f2b r6843a9c  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 
    2928/**
    3029 * @addtogroup drvusbuhcihc
     
    3938#include <assert.h>
    4039#include <devman.h>
    41 #include <device/hw_res.h>
     40#include <device/hw_res_parsed.h>
     41#include <device/pci.h>
    4242
    43 #include <usb/debug.h>
    44 #include <pci_dev_iface.h>
    45 
    46 #include "pci.h"
     43#include "res.h"
    4744
    4845/** Get I/O address of registers and IRQ for given device.
     
    5451 * @return Error code.
    5552 */
    56 int pci_get_my_registers(const ddf_dev_t *dev,
     53int get_my_registers(const ddf_dev_t *dev,
    5754    uintptr_t *io_reg_address, size_t *io_reg_size, int *irq_no)
    5855{
    5956        assert(dev);
    60         assert(io_reg_address);
    61         assert(io_reg_size);
    62         assert(irq_no);
    6357
    6458        async_sess_t *parent_sess =
     
    6862                return ENOMEM;
    6963
    70         hw_resource_list_t hw_resources;
    71         const int rc = hw_res_get_resource_list(parent_sess, &hw_resources);
     64        hw_res_list_parsed_t hw_res;
     65        hw_res_list_parsed_init(&hw_res);
     66        const int ret =  hw_res_get_list_parsed(parent_sess, &hw_res, 0);
    7267        async_hangup(parent_sess);
    73         if (rc != EOK) {
    74                 return rc;
     68        if (ret != EOK) {
     69                return ret;
    7570        }
    7671
    77         uintptr_t io_address = 0;
    78         size_t io_size = 0;
    79         bool io_found = false;
     72        /* We want one irq and one io range. */
     73        if (hw_res.irqs.count != 1 || hw_res.io_ranges.count != 1) {
     74                hw_res_list_parsed_clean(&hw_res);
     75                return EINVAL;
     76        }
    8077
    81         int irq = 0;
    82         bool irq_found = false;
     78        if (io_reg_address)
     79                *io_reg_address = hw_res.io_ranges.ranges[0].address;
     80        if (io_reg_size)
     81                *io_reg_size = hw_res.io_ranges.ranges[0].size;
     82        if (irq_no)
     83                *irq_no = hw_res.irqs.irqs[0];
    8384
    84         for (size_t i = 0; i < hw_resources.count; i++) {
    85                 const hw_resource_t *res = &hw_resources.resources[i];
    86                 switch (res->type) {
    87                 case INTERRUPT:
    88                         irq = res->res.interrupt.irq;
    89                         irq_found = true;
    90                         usb_log_debug2("Found interrupt: %d.\n", irq);
    91                         break;
    92                 case IO_RANGE:
    93                         io_address = res->res.io_range.address;
    94                         io_size = res->res.io_range.size;
    95                         usb_log_debug2("Found io: %" PRIx64" %zu.\n",
    96                             res->res.io_range.address, res->res.io_range.size);
    97                         io_found = true;
    98                         break;
    99                 default:
    100                         break;
    101                 }
    102         }
    103         free(hw_resources.resources);
    104 
    105         if (!io_found || !irq_found)
    106                 return ENOENT;
    107 
    108         *io_reg_address = io_address;
    109         *io_reg_size = io_size;
    110         *irq_no = irq;
    111 
     85        hw_res_list_parsed_clean(&hw_res);
    11286        return EOK;
    11387}
    114 /*----------------------------------------------------------------------------*/
     88
    11589/** Call the PCI driver with a request to enable interrupts
    11690 *
     
    11892 * @return Error code.
    11993 */
    120 int pci_enable_interrupts(const ddf_dev_t *device)
     94int enable_interrupts(const ddf_dev_t *device)
    12195{
    12296        async_sess_t *parent_sess =
     
    131105        return enabled ? EOK : EIO;
    132106}
    133 /*----------------------------------------------------------------------------*/
     107
    134108/** Call the PCI driver with a request to clear legacy support register
    135109 *
     
    137111 * @return Error code.
    138112 */
    139 int pci_disable_legacy(const ddf_dev_t *device)
     113int disable_legacy(const ddf_dev_t *device)
    140114{
    141115        assert(device);
    142116
    143         async_sess_t *parent_sess =
    144             devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle,
    145             IPC_FLAG_BLOCKING);
     117        async_sess_t *parent_sess = devman_parent_device_connect(
     118            EXCHANGE_SERIALIZE, device->handle, IPC_FLAG_BLOCKING);
    146119        if (!parent_sess)
    147120                return ENOMEM;
    148121
    149         /* See UHCI design guide for these values p.45,
    150          * write all WC bits in USB legacy register */
    151         const sysarg_t address = 0xc0;
    152         const sysarg_t value = 0xaf00;
     122        /* See UHCI design guide page 45 for these values.
     123         * Write all WC bits in USB legacy register */
     124        const int rc = pci_config_space_write_16(parent_sess, 0xc0, 0xaf00);
    153125
    154         async_exch_t *exch = async_exchange_begin(parent_sess);
    155 
    156         const int rc = async_req_3_0(exch, DEV_IFACE_ID(PCI_DEV_IFACE),
    157             IPC_M_CONFIG_SPACE_WRITE_16, address, value);
    158 
    159         async_exchange_end(exch);
    160126        async_hangup(parent_sess);
    161 
    162127        return rc;
    163128}
  • uspace/drv/bus/usb/uhci/res.h

    rba72f2b r6843a9c  
    3838#include <ddf/driver.h>
    3939
    40 int pci_get_my_registers(const ddf_dev_t *, uintptr_t *, size_t *, int *);
    41 int pci_enable_interrupts(const ddf_dev_t *);
    42 int pci_disable_legacy(const ddf_dev_t *);
     40int get_my_registers(const ddf_dev_t *, uintptr_t *, size_t *, int *);
     41int enable_interrupts(const ddf_dev_t *);
     42int disable_legacy(const ddf_dev_t *);
    4343
    4444#endif
  • uspace/drv/bus/usb/uhci/transfer_list.c

    rba72f2b r6843a9c  
    110110        assert(instance);
    111111        assert(uhci_batch);
    112         usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name,
    113             uhci_batch->usb_batch);
     112        usb_log_debug2("Batch %p adding to queue %s.\n",
     113            uhci_batch->usb_batch, instance->name);
    114114
    115115        fibril_mutex_lock(&instance->guard);
     
    139139        list_append(&uhci_batch->link, &instance->batch_list);
    140140
    141         usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " scheduled in queue %s.\n",
    142             uhci_batch, USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch),
    143             instance->name);
     141        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT
     142            " scheduled in queue %s.\n", uhci_batch->usb_batch,
     143            USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch), instance->name);
    144144        fibril_mutex_unlock(&instance->guard);
    145145}
     
    184184                    uhci_transfer_batch_from_link(current);
    185185                transfer_list_remove_batch(instance, batch);
    186                 batch->usb_batch->error = EINTR;
    187                 uhci_transfer_batch_call_dispose(batch);
     186                uhci_transfer_batch_abort(batch);
    188187        }
    189188        fibril_mutex_unlock(&instance->guard);
     
    206205        assert(fibril_mutex_is_locked(&instance->guard));
    207206
    208         usb_log_debug2("Queue %s: removing batch(%p).\n",
    209             instance->name, uhci_batch->usb_batch);
     207        usb_log_debug2("Batch %p removing from queue %s.\n",
     208            uhci_batch->usb_batch, instance->name);
    210209
    211210        /* Assume I'm the first */
     
    229228        list_remove(&uhci_batch->link);
    230229        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " removed (%s) "
    231             "from %s, next: %x.\n",
    232             uhci_batch, USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch),
     230            "from %s, next: %x.\n", uhci_batch->usb_batch,
     231            USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch),
    233232            qpos, instance->name, uhci_batch->qh->next);
    234233}
  • uspace/drv/bus/usb/uhci/uhci.c

    rba72f2b r6843a9c  
    4141
    4242#include "uhci.h"
    43 #include "pci.h"
    44 
     43
     44#include "res.h"
    4545#include "hc.h"
    4646#include "root_hub.h"
     
    4949 * and USB root hub */
    5050typedef struct uhci {
    51         /** Pointer to DDF represenation of UHCI host controller */
     51        /** Pointer to DDF representation of UHCI host controller */
    5252        ddf_fun_t *hc_fun;
    53         /** Pointer to DDF represenation of UHCI root hub */
     53        /** Pointer to DDF representation of UHCI root hub */
    5454        ddf_fun_t *rh_fun;
    5555
    56         /** Internal driver's represenation of UHCI host controller */
     56        /** Internal driver's representation of UHCI host controller */
    5757        hc_t hc;
    58         /** Internal driver's represenation of UHCI root hub */
     58        /** Internal driver's representation of UHCI root hub */
    5959        rh_t rh;
    6060} uhci_t;
     
    8989};
    9090/*----------------------------------------------------------------------------*/
    91 /** Get address of the device identified by handle.
    92  *
    93  * @param[in] fun DDF instance of the function to use.
    94  * @param[in] handle DDF handle of the driver seeking its USB address.
    95  * @param[out] address Found address.
    96  */
    97 static int usb_iface_get_address(
    98     ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address)
    99 {
    100         assert(fun);
    101         usb_device_manager_t *manager =
    102             &dev_to_uhci(fun->dev)->hc.generic.dev_manager;
    103         const usb_address_t addr = usb_device_manager_find(manager, handle);
    104 
    105         if (addr < 0) {
    106                 return addr;
    107         }
    108 
    109         if (address != NULL) {
    110                 *address = addr;
    111         }
    112 
    113         return EOK;
    114 }
    115 /*----------------------------------------------------------------------------*/
    11691/** Gets handle of the respective hc.
    11792 *
     
    134109static usb_iface_t usb_iface = {
    135110        .get_hc_handle = usb_iface_get_hc_handle,
    136         .get_address = usb_iface_get_address
    137111};
    138112/*----------------------------------------------------------------------------*/
     
    174148int device_setup_uhci(ddf_dev_t *device)
    175149{
    176         assert(device);
    177         uhci_t *instance = malloc(sizeof(uhci_t));
     150        if (!device)
     151                return EBADMEM;
     152
     153        uhci_t *instance = ddf_dev_data_alloc(device, sizeof(uhci_t));
    178154        if (instance == NULL) {
    179155                usb_log_error("Failed to allocate OHCI driver.\n");
     
    184160if (ret != EOK) { \
    185161        if (instance->hc_fun) \
    186                 instance->hc_fun->ops = NULL; \
    187162                instance->hc_fun->driver_data = NULL; \
    188163                ddf_fun_destroy(instance->hc_fun); \
    189164        if (instance->rh_fun) {\
    190                 instance->rh_fun->ops = NULL; \
    191165                instance->rh_fun->driver_data = NULL; \
    192166                ddf_fun_destroy(instance->rh_fun); \
    193167        } \
    194         device->driver_data = NULL; \
    195168        usb_log_error(message); \
    196169        return ret; \
     
    214187        int irq = 0;
    215188
    216         ret = pci_get_my_registers(device, &reg_base, &reg_size, &irq);
     189        ret = get_my_registers(device, &reg_base, &reg_size, &irq);
    217190        CHECK_RET_DEST_FREE_RETURN(ret,
    218191            "Failed to get I/O addresses for %" PRIun ": %s.\n",
     
    221194            (void *) reg_base, reg_size, irq);
    222195
    223         ret = pci_disable_legacy(device);
     196        ret = disable_legacy(device);
    224197        CHECK_RET_DEST_FREE_RETURN(ret,
    225198            "Failed to disable legacy USB: %s.\n", str_error(ret));
    226199
    227         const size_t cmd_count = hc_irq_cmd_count();
    228         irq_cmd_t irq_cmds[cmd_count];
    229         ret =
    230             hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size);
     200        const size_t ranges_count = hc_irq_pio_range_count();
     201        const size_t cmds_count = hc_irq_cmd_count();
     202        irq_pio_range_t irq_ranges[ranges_count];
     203        irq_cmd_t irq_cmds[cmds_count];
     204        ret = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds,
     205            sizeof(irq_cmds), reg_base, reg_size);
    231206        CHECK_RET_DEST_FREE_RETURN(ret,
    232207            "Failed to generate IRQ commands: %s.\n", str_error(ret));
    233208
    234         irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds };
     209        irq_code_t irq_code = {
     210                .rangecount = ranges_count,
     211                .ranges = irq_ranges,
     212                .cmdcount = cmds_count,
     213                .cmds = irq_cmds
     214        };
    235215
    236216        /* Register handler to avoid interrupt lockup */
     
    240220
    241221        bool interrupts = false;
    242         ret = pci_enable_interrupts(device);
     222        ret = enable_interrupts(device);
    243223        if (ret != EOK) {
    244224                usb_log_warning("Failed to enable interrupts: %s."
     
    253233            "Failed to init uhci_hcd: %s.\n", str_error(ret));
    254234
    255         device->driver_data = instance;
    256 
    257235#define CHECK_RET_FINI_RETURN(ret, message...) \
    258236if (ret != EOK) { \
  • uspace/drv/bus/usb/uhci/uhci.ma

    rba72f2b r6843a9c  
    1 10 pci/ven=8086&dev=7020
    2 10 pci/ven=8086&dev=7112
    3 
    4 10 pci/ven=8086&dev=27c8
    5 10 pci/ven=8086&dev=27c9
    6 10 pci/ven=8086&dev=27ca
    7 10 pci/ven=8086&dev=27cb
    8 
    9 10 pci/ven=8086&dev=2830
    10 10 pci/ven=8086&dev=2831
    11 10 pci/ven=8086&dev=2832
    12 10 pci/ven=8086&dev=2834
    13 10 pci/ven=8086&dev=2835
    14 
    15 10 pci/ven=8086&dev=2934
    16 10 pci/ven=8086&dev=2935
    17 10 pci/ven=8086&dev=2936
    18 10 pci/ven=8086&dev=2937
    19 10 pci/ven=8086&dev=2938
    20 10 pci/ven=8086&dev=2939
    21 
    22 10 pci/ven=8086&dev=24c2
    23 10 pci/ven=8086&dev=24c4
    24 10 pci/ven=8086&dev=24c7
    25 
    26 10 pci/ven=8086&dev=2688
    27 10 pci/ven=8086&dev=2689
    28 10 pci/ven=8086&dev=268a
    29 10 pci/ven=8086&dev=268b
     110 pci/class=0c&subclass=03&progif=00
  • uspace/drv/bus/usb/uhci/uhci_batch.c

    rba72f2b r6843a9c  
    3434#include <errno.h>
    3535#include <str_error.h>
     36#include <macros.h>
    3637
    3738#include <usb/usb.h>
     
    4546#define DEFAULT_ERROR_COUNT 3
    4647
     48/** Safely destructs uhci_transfer_batch_t structure.
     49 *
     50 * @param[in] uhci_batch Instance to destroy.
     51 */
    4752static void uhci_transfer_batch_dispose(uhci_transfer_batch_t *uhci_batch)
    4853{
    4954        if (uhci_batch) {
    50                 usb_transfer_batch_dispose(uhci_batch->usb_batch);
     55                usb_transfer_batch_destroy(uhci_batch->usb_batch);
    5156                free32(uhci_batch->device_buffer);
    5257                free(uhci_batch);
     
    5459}
    5560/*----------------------------------------------------------------------------*/
    56 /** Safely destructs uhci_transfer_batch_t structure
    57  *
    58  * @param[in] uhci_batch Instance to destroy.
    59  */
    60 void uhci_transfer_batch_call_dispose(uhci_transfer_batch_t *uhci_batch)
     61/** Finishes usb_transfer_batch and destroys the structure.
     62 *
     63 * @param[in] uhci_batch Instance to finish and destroy.
     64 */
     65void uhci_transfer_batch_finish_dispose(uhci_transfer_batch_t *uhci_batch)
    6166{
    6267        assert(uhci_batch);
    6368        assert(uhci_batch->usb_batch);
    6469        usb_transfer_batch_finish(uhci_batch->usb_batch,
    65             uhci_transfer_batch_data_buffer(uhci_batch),
    66             uhci_batch->usb_batch->buffer_size);
     70            uhci_transfer_batch_data_buffer(uhci_batch));
    6771        uhci_transfer_batch_dispose(uhci_batch);
    6872}
    6973/*----------------------------------------------------------------------------*/
     74/** Transfer batch setup table. */
    7075static void (*const batch_setup[])(uhci_transfer_batch_t*, usb_direction_t);
    7176/*----------------------------------------------------------------------------*/
    7277/** Allocate memory and initialize internal data structure.
    7378 *
    74  * @param[in] fun DDF function to pass to callback.
    75  * @param[in] ep Communication target
    76  * @param[in] buffer Data source/destination.
    77  * @param[in] buffer_size Size of the buffer.
    78  * @param[in] setup_buffer Setup data source (if not NULL)
    79  * @param[in] setup_size Size of setup_buffer (should be always 8)
    80  * @param[in] func_in function to call on inbound transfer completion
    81  * @param[in] func_out function to call on outbound transfer completion
    82  * @param[in] arg additional parameter to func_in or func_out
     79 * @param[in] usb_batch Pointer to generic USB batch structure.
    8380 * @return Valid pointer if all structures were successfully created,
    8481 * NULL otherwise.
     
    156153 * is reached.
    157154 */
    158 bool uhci_transfer_batch_is_complete(uhci_transfer_batch_t *uhci_batch)
     155bool uhci_transfer_batch_is_complete(const uhci_transfer_batch_t *uhci_batch)
    159156{
    160157        assert(uhci_batch);
     
    177174                        assert(uhci_batch->usb_batch->ep != NULL);
    178175
    179                         usb_log_debug("Batch(%p) found error TD(%zu):%"
     176                        usb_log_debug("Batch %p found error TD(%zu->%p):%"
    180177                            PRIx32 ".\n", uhci_batch->usb_batch, i,
    181                             uhci_batch->tds[i].status);
     178                            &uhci_batch->tds[i], uhci_batch->tds[i].status);
    182179                        td_print_status(&uhci_batch->tds[i]);
    183180
     
    200197}
    201198/*----------------------------------------------------------------------------*/
     199/** Direction to pid conversion table */
    202200static const usb_packet_id direction_pids[] = {
    203201        [USB_DIRECTION_IN] = USB_PID_IN,
     
    237235
    238236        while (remain_size > 0) {
    239                 const size_t packet_size =
    240                     (remain_size < mps) ? remain_size : mps;
     237                const size_t packet_size = min(remain_size, mps);
    241238
    242239                const td_t *next_td = (td + 1 < uhci_batch->td_count)
     
    309306
    310307        while (remain_size > 0) {
    311                 const size_t packet_size =
    312                     (remain_size < mps) ? remain_size : mps;
     308                const size_t packet_size = min(remain_size, mps);
    313309
    314310                td_init(
  • uspace/drv/bus/usb/uhci/uhci_batch.h

    rba72f2b r6843a9c  
    6161
    6262uhci_transfer_batch_t * uhci_transfer_batch_get(usb_transfer_batch_t *batch);
    63 void uhci_transfer_batch_call_dispose(uhci_transfer_batch_t *uhci_batch);
    64 bool uhci_transfer_batch_is_complete(uhci_transfer_batch_t *uhci_batch);
     63void uhci_transfer_batch_finish_dispose(uhci_transfer_batch_t *uhci_batch);
     64bool uhci_transfer_batch_is_complete(const uhci_transfer_batch_t *uhci_batch);
    6565
     66/** Get offset to setup buffer accessible to the HC hw.
     67 * @param uhci_batch UHCI batch structure.
     68 * @return Pointer to the setup buffer.
     69 */
    6670static inline void * uhci_transfer_batch_setup_buffer(
    6771    const uhci_transfer_batch_t *uhci_batch)
     
    7377}
    7478/*----------------------------------------------------------------------------*/
     79/** Get offset to data buffer accessible to the HC hw.
     80 * @param uhci_batch UHCI batch structure.
     81 * @return Pointer to the data buffer.
     82 */
    7583static inline void * uhci_transfer_batch_data_buffer(
    7684    const uhci_transfer_batch_t *uhci_batch)
     
    8290}
    8391/*----------------------------------------------------------------------------*/
     92/** Aborts the batch.
     93 * Sets error to EINTR and size off transferd data to 0, before finishing the
     94 * batch.
     95 * @param uhci_batch Batch to abort.
     96 */
     97static inline void uhci_transfer_batch_abort(uhci_transfer_batch_t *uhci_batch)
     98{
     99        assert(uhci_batch);
     100        assert(uhci_batch->usb_batch);
     101        uhci_batch->usb_batch->error = EINTR;
     102        uhci_batch->usb_batch->transfered_size = 0;
     103        uhci_transfer_batch_finish_dispose(uhci_batch);
     104}
     105/*----------------------------------------------------------------------------*/
     106/** Linked list conversion wrapper.
     107 * @param l Linked list link.
     108 * @return Pointer to the uhci batch structure.
     109 */
    84110static inline uhci_transfer_batch_t *uhci_transfer_batch_from_link(link_t *l)
    85111{
  • uspace/drv/bus/usb/uhci/utils/malloc32.h

    rba72f2b r6843a9c  
    3636
    3737#include <assert.h>
     38#include <unistd.h>
    3839#include <errno.h>
    3940#include <malloc.h>
     
    5455        if (addr == NULL)
    5556                return 0;
    56 
     57       
    5758        uintptr_t result;
    5859        const int ret = as_get_physical_mapping(addr, &result);
    5960        if (ret != EOK)
    6061                return 0;
    61         return (result | ((uintptr_t)addr & 0xfff));
     62       
     63        return result;
    6264}
    6365/*----------------------------------------------------------------------------*/
     
    9799static inline void * get_page(void)
    98100{
    99         void *free_address = as_get_mappable_page(UHCI_REQUIRED_PAGE_SIZE);
    100         if (free_address == 0)
     101        void *address = as_area_create(AS_AREA_ANY, UHCI_REQUIRED_PAGE_SIZE,
     102            AS_AREA_READ | AS_AREA_WRITE);
     103        if (address == AS_MAP_FAILED)
    101104                return NULL;
    102         void *address = as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE,
    103                   AS_AREA_READ | AS_AREA_WRITE);
    104         if (address != free_address)
    105                 return NULL;
     105       
    106106        return address;
    107107}
  • uspace/drv/bus/usb/uhcirh/main.c

    rba72f2b r6843a9c  
    3636#include <ddf/driver.h>
    3737#include <devman.h>
    38 #include <device/hw_res.h>
     38#include <device/hw_res_parsed.h>
    3939#include <errno.h>
    4040#include <str_error.h>
     
    5151    uintptr_t *io_reg_address, size_t *io_reg_size);
    5252
    53 static int uhci_rh_add_device(ddf_dev_t *device);
     53static int uhci_rh_dev_add(ddf_dev_t *device);
    5454
    5555static driver_ops_t uhci_rh_driver_ops = {
    56         .add_device = uhci_rh_add_device,
     56        .dev_add = uhci_rh_dev_add,
    5757};
    5858
     
    8282 * @return Error code.
    8383 */
    84 static int uhci_rh_add_device(ddf_dev_t *device)
     84static int uhci_rh_dev_add(ddf_dev_t *device)
    8585{
    8686        if (!device)
    8787                return EINVAL;
    8888
    89         usb_log_debug2("uhci_rh_add_device(handle=%" PRIun ")\n",
     89        usb_log_debug2("uhci_rh_dev_add(handle=%" PRIun ")\n",
    9090            device->handle);
    9191
     
    136136{
    137137        assert(dev);
    138        
     138
    139139        async_sess_t *parent_sess =
    140140            devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
     
    142142        if (!parent_sess)
    143143                return ENOMEM;
    144        
    145         hw_resource_list_t hw_resources;
    146         const int ret = hw_res_get_resource_list(parent_sess, &hw_resources);
     144
     145        hw_res_list_parsed_t hw_res;
     146        hw_res_list_parsed_init(&hw_res);
     147        const int ret =  hw_res_get_list_parsed(parent_sess, &hw_res, 0);
     148        async_hangup(parent_sess);
    147149        if (ret != EOK) {
    148                 async_hangup(parent_sess);
    149150                return ret;
    150151        }
    151        
    152         uintptr_t io_address = 0;
    153         size_t io_size = 0;
    154         bool io_found = false;
    155        
    156         size_t i = 0;
    157         for (; i < hw_resources.count; i++) {
    158                 hw_resource_t *res = &hw_resources.resources[i];
    159                 if (res->type == IO_RANGE) {
    160                         io_address = res->res.io_range.address;
    161                         io_size = res->res.io_range.size;
    162                         io_found = true;
    163                 }
    164        
     152
     153        if (hw_res.io_ranges.count != 1) {
     154                hw_res_list_parsed_clean(&hw_res);
     155                return EINVAL;
    165156        }
    166         async_hangup(parent_sess);
    167        
    168         if (!io_found)
    169                 return ENOENT;
    170        
     157
    171158        if (io_reg_address != NULL)
    172                 *io_reg_address = io_address;
    173        
     159                *io_reg_address = hw_res.io_ranges.ranges[0].address;
     160
    174161        if (io_reg_size != NULL)
    175                 *io_reg_size = io_size;
    176        
     162                *io_reg_size = hw_res.io_ranges.ranges[0].size;
     163
     164        hw_res_list_parsed_clean(&hw_res);
    177165        return EOK;
    178166}
  • uspace/drv/bus/usb/uhcirh/port.c

    rba72f2b r6843a9c  
    3737#include <str_error.h>
    3838#include <async.h>
    39 #include <devman.h>
    4039
    4140#include <usb/usb.h>    /* usb_address_t */
     
    260259{
    261260        assert(port);
    262         assert(usb_hc_connection_is_opened(&port->hc_connection));
    263261
    264262        usb_log_debug("%s: Detected new device.\n", port->id_string);
     
    314312
    315313        /* Driver stopped, free used address */
    316         ret = usb_hc_unregister_device(&port->hc_connection,
    317             port->attached_device.address);
     314        ret = usb_hub_unregister_device(&port->hc_connection,
     315            &port->attached_device);
    318316        if (ret != EOK) {
    319317                usb_log_error("%s: Failed to unregister address of removed "
  • uspace/drv/bus/usb/usbflbk/main.c

    rba72f2b r6843a9c  
    9393        return EOK;
    9494}
     95
    9596/** USB fallback driver ops. */
    96 static usb_driver_ops_t usbfallback_driver_ops = {
     97static const usb_driver_ops_t usbfallback_driver_ops = {
    9798        .device_add = usbfallback_device_add,
     99        .device_rem = usbfallback_device_gone,
    98100        .device_gone = usbfallback_device_gone,
    99101};
    100102
    101103/** USB fallback driver. */
    102 static usb_driver_t usbfallback_driver = {
     104static const usb_driver_t usbfallback_driver = {
    103105        .name = NAME,
    104106        .ops = &usbfallback_driver_ops,
  • uspace/drv/bus/usb/usbhid/generic/hiddev.c

    rba72f2b r6843a9c  
    6161
    6262/*----------------------------------------------------------------------------*/
    63 
    6463static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun);
    65 
    66 static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer,
     64static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer,
    6765    size_t size, size_t *act_size, int *event_nr, unsigned int flags);
    68 
    6966static int usb_generic_hid_client_connected(ddf_fun_t *fun);
    70 
    7167static size_t usb_generic_get_report_descriptor_length(ddf_fun_t *fun);
    72 
    73 static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc,
     68static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc,
    7469    size_t size, size_t *actual_size);
    75 
    76 /*----------------------------------------------------------------------------*/
    77 
     70/*----------------------------------------------------------------------------*/
    7871static usbhid_iface_t usb_generic_iface = {
    7972        .get_event = usb_generic_hid_get_event,
     
    8275        .get_report_descriptor = usb_generic_get_report_descriptor
    8376};
    84 
     77/*----------------------------------------------------------------------------*/
    8578static ddf_dev_ops_t usb_generic_hid_ops = {
    8679        .interfaces[USBHID_DEV_IFACE] = &usb_generic_iface,
    8780        .open = usb_generic_hid_client_connected
    8881};
    89 
    90 /*----------------------------------------------------------------------------*/
    91 
     82/*----------------------------------------------------------------------------*/
    9283static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun)
    9384{
     
    9990        }
    10091
    101         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
     92        const usb_hid_dev_t *hid_dev = fun->driver_data;
    10293
    10394        usb_log_debug2("hid_dev: %p, Max input report size (%zu).\n",
     
    10697        return hid_dev->max_input_report_size;
    10798}
    108 
    109 /*----------------------------------------------------------------------------*/
    110 
    111 static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer,
     99/*----------------------------------------------------------------------------*/
     100static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer,
    112101    size_t size, size_t *act_size, int *event_nr, unsigned int flags)
    113102{
     
    120109        }
    121110
    122         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
     111        const usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
    123112
    124113        if (hid_dev->input_report_size > size) {
    125                 usb_log_debug("input_report_size > size (%zu, %zu)\n", 
     114                usb_log_debug("input_report_size > size (%zu, %zu)\n",
    126115                    hid_dev->input_report_size, size);
    127116                return EINVAL;  // TODO: other error code
     
    129118
    130119        /*! @todo This should probably be somehow atomic. */
    131         memcpy(buffer, hid_dev->input_report, 
     120        memcpy(buffer, hid_dev->input_report,
    132121            hid_dev->input_report_size);
    133122        *act_size = hid_dev->input_report_size;
     
    138127        return EOK;
    139128}
    140 
    141 /*----------------------------------------------------------------------------*/
    142 
     129/*----------------------------------------------------------------------------*/
    143130static size_t usb_generic_get_report_descriptor_length(ddf_fun_t *fun)
    144131{
     
    150137        }
    151138
    152         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
    153 
    154         usb_log_debug2("hid_dev->report_desc_size = %zu\n", 
     139        const usb_hid_dev_t *hid_dev = fun->driver_data;
     140
     141        usb_log_debug2("hid_dev->report_desc_size = %zu\n",
    155142            hid_dev->report_desc_size);
    156143
    157144        return hid_dev->report_desc_size;
    158145}
    159 
    160 /*----------------------------------------------------------------------------*/
    161 
    162 static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc,
     146/*----------------------------------------------------------------------------*/
     147static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc,
    163148    size_t size, size_t *actual_size)
    164149{
     
    170155        }
    171156
    172         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
     157        const usb_hid_dev_t *hid_dev = fun->driver_data;
    173158
    174159        if (hid_dev->report_desc_size > size) {
     
    181166        return EOK;
    182167}
    183 
    184 /*----------------------------------------------------------------------------*/
    185 
     168/*----------------------------------------------------------------------------*/
    186169static int usb_generic_hid_client_connected(ddf_fun_t *fun)
    187170{
     
    189172        return EOK;
    190173}
    191 
    192 /*----------------------------------------------------------------------------*/
    193 
     174/*----------------------------------------------------------------------------*/
    194175void usb_generic_hid_deinit(usb_hid_dev_t *hid_dev, void *data)
    195176{
    196177        ddf_fun_t *fun = data;
    197         const int ret = ddf_fun_unbind(fun);
    198         if (ret != EOK) {
     178        if (fun == NULL)
     179                return;
     180
     181        if (ddf_fun_unbind(fun) != EOK) {
    199182                usb_log_error("Failed to unbind generic hid fun.\n");
    200183                return;
     
    206189        ddf_fun_destroy(fun);
    207190}
    208 
    209 /*----------------------------------------------------------------------------*/
    210 
     191/*----------------------------------------------------------------------------*/
    211192int usb_generic_hid_init(usb_hid_dev_t *hid_dev, void **data)
    212193{
     
    216197
    217198        /* Create the exposed function. */
    218         /** @todo Generate numbers for the devices? */
    219199        usb_log_debug("Creating DDF function %s...\n", HID_GENERIC_FUN_NAME);
    220200        ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
     
    225205        }
    226206
     207        /* This is nasty, both device and this function have the same
     208         * driver data, thus destruction causes to double free */
     209        fun->driver_data = hid_dev;
    227210        fun->ops = &usb_generic_hid_ops;
    228211
     
    231214                usb_log_error("Could not bind DDF function: %s.\n",
    232215                    str_error(rc));
     216                fun->driver_data = NULL;
    233217                ddf_fun_destroy(fun);
    234218                return rc;
    235219        }
    236         /* This is nasty both device and this function have the same
    237          * driver data, thus destruction would lead to double free */
    238         fun->driver_data = hid_dev;
    239220
    240221        usb_log_debug("HID function created. Handle: %" PRIun "\n", fun->handle);
     
    243224        return EOK;
    244225}
    245 
    246 /*----------------------------------------------------------------------------*/
    247 
     226/*----------------------------------------------------------------------------*/
    248227bool usb_generic_hid_polling_callback(usb_hid_dev_t *hid_dev, void *data)
    249228{
    250229        return true;
    251230}
    252 
    253231/**
    254232 * @}
  • uspace/drv/bus/usb/usbhid/kbd/kbddev.c

    rba72f2b r6843a9c  
    4141#include <io/keycode.h>
    4242#include <io/console.h>
     43#include <abi/ipc/methods.h>
    4344#include <ipc/kbdev.h>
    4445#include <async.h>
     
    8687
    8788/*----------------------------------------------------------------------------*/
    88 
    8989/** Keyboard polling endpoint description for boot protocol class. */
    9090const usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description = {
     
    101101
    102102static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev);
    103 
    104 /*----------------------------------------------------------------------------*/
    105 
    106 enum {
    107         USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE = 63
     103/*----------------------------------------------------------------------------*/
     104static const uint8_t USB_KBD_BOOT_REPORT_DESCRIPTOR[] = {
     105        0x05, 0x01,  /* Usage Page (Generic Desktop), */
     106        0x09, 0x06,  /* Usage (Keyboard), */
     107        0xA1, 0x01,  /* Collection (Application), */
     108        0x75, 0x01,  /*   Report Size (1), */
     109        0x95, 0x08,  /*   Report Count (8), */
     110        0x05, 0x07,  /*   Usage Page (Key Codes); */
     111        0x19, 0xE0,  /*   Usage Minimum (224), */
     112        0x29, 0xE7,  /*   Usage Maximum (231), */
     113        0x15, 0x00,  /*   Logical Minimum (0), */
     114        0x25, 0x01,  /*   Logical Maximum (1), */
     115        0x81, 0x02,  /*   Input (Data, Variable, Absolute),  ; Modifier byte */
     116        0x95, 0x01,  /*   Report Count (1), */
     117        0x75, 0x08,  /*   Report Size (8), */
     118        0x81, 0x01,  /*   Input (Constant),                  ; Reserved byte */
     119        0x95, 0x05,  /*   Report Count (5), */
     120        0x75, 0x01,  /*   Report Size (1), */
     121        0x05, 0x08,  /*   Usage Page (Page# for LEDs), */
     122        0x19, 0x01,  /*   Usage Minimum (1), */
     123        0x29, 0x05,  /*   Usage Maxmimum (5), */
     124        0x91, 0x02,  /*   Output (Data, Variable, Absolute),  ; LED report */
     125        0x95, 0x01,  /*   Report Count (1), */
     126        0x75, 0x03,  /*   Report Size (3), */
     127        0x91, 0x01,  /*   Output (Constant),            ; LED report padding */
     128        0x95, 0x06,  /*   Report Count (6), */
     129        0x75, 0x08,  /*   Report Size (8), */
     130        0x15, 0x00,  /*   Logical Minimum (0), */
     131        0x25, 0xff,  /*   Logical Maximum (255), */
     132        0x05, 0x07,  /*   Usage Page (Key Codes), */
     133        0x19, 0x00,  /*   Usage Minimum (0), */
     134        0x29, 0xff,  /*   Usage Maximum (255), */
     135        0x81, 0x00,  /*   Input (Data, Array),   ; Key arrays (6 bytes) */
     136        0xC0         /* End Collection */
    108137};
    109 
    110 static const uint8_t USB_KBD_BOOT_REPORT_DESCRIPTOR[
    111     USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE] = {
    112         0x05, 0x01,  // Usage Page (Generic Desktop),
    113         0x09, 0x06,  // Usage (Keyboard),
    114         0xA1, 0x01,  // Collection (Application),
    115         0x75, 0x01,  //   Report Size (1),
    116         0x95, 0x08,  //   Report Count (8),       
    117         0x05, 0x07,  //   Usage Page (Key Codes);
    118         0x19, 0xE0,  //   Usage Minimum (224),
    119         0x29, 0xE7,  //   Usage Maximum (231),
    120         0x15, 0x00,  //   Logical Minimum (0),
    121         0x25, 0x01,  //   Logical Maximum (1),
    122         0x81, 0x02,  //   Input (Data, Variable, Absolute),   ; Modifier byte
    123         0x95, 0x01,  //   Report Count (1),
    124         0x75, 0x08,  //   Report Size (8),
    125         0x81, 0x01,  //   Input (Constant),                   ; Reserved byte
    126         0x95, 0x05,  //   Report Count (5),
    127         0x75, 0x01,  //   Report Size (1),
    128         0x05, 0x08,  //   Usage Page (Page# for LEDs),
    129         0x19, 0x01,  //   Usage Minimum (1),
    130         0x29, 0x05,  //   Usage Maxmimum (5),
    131         0x91, 0x02,  //   Output (Data, Variable, Absolute),  ; LED report
    132         0x95, 0x01,  //   Report Count (1),
    133         0x75, 0x03,  //   Report Size (3),
    134         0x91, 0x01,  //   Output (Constant),              ; LED report padding
    135         0x95, 0x06,  //   Report Count (6),
    136         0x75, 0x08,  //   Report Size (8),
    137         0x15, 0x00,  //   Logical Minimum (0),
    138         0x25, 0xff,  //   Logical Maximum (255),
    139         0x05, 0x07,  //   Usage Page (Key Codes),
    140         0x19, 0x00,  //   Usage Minimum (0),
    141         0x29, 0xff,  //   Usage Maximum (255),
    142         0x81, 0x00,  //   Input (Data, Array),            ; Key arrays (6 bytes)
    143         0xC0           // End Collection
    144 
    145 };
    146 
    147 /*----------------------------------------------------------------------------*/
    148 
     138/*----------------------------------------------------------------------------*/
    149139typedef enum usb_kbd_flags {
    150140        USB_KBD_STATUS_UNINITIALIZED = 0,
     
    152142        USB_KBD_STATUS_TO_DESTROY = -1
    153143} usb_kbd_flags;
    154 
    155144/*----------------------------------------------------------------------------*/
    156145/* IPC method handler                                                         */
    157146/*----------------------------------------------------------------------------*/
    158 
    159 static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
    160 
    161147/**
    162148 * Default handler for IPC methods not handled by DDF.
    163149 *
    164  * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it
    165  * assumes the caller is the console and thus it stores IPC session to it for
    166  * later use by the driver to notify about key events.
     150 * Currently recognizes only two methods (IPC_M_CONNECT_TO_ME and KBDEV_SET_IND)
     151 * IPC_M_CONNECT_TO_ME assumes the caller is the console and  stores IPC
     152 * session to it for later use by the driver to notify about key events.
     153 * KBDEV_SET_IND sets LED keyboard indicators.
    167154 *
    168155 * @param fun Device function handling the call.
     
    173160    ipc_callid_t icallid, ipc_call_t *icall)
    174161{
    175         sysarg_t method = IPC_GET_IMETHOD(*icall);
    176 
    177         usb_kbd_t *kbd_dev = (usb_kbd_t *) fun->driver_data;
    178         if (kbd_dev == NULL) {
    179                 usb_log_debug("default_connection_handler: "
    180                     "Missing parameter.\n");
     162        if (fun == NULL || fun->driver_data == NULL) {
     163                usb_log_error("%s: Missing parameter.\n", __FUNCTION__);
    181164                async_answer_0(icallid, EINVAL);
    182165                return;
    183166        }
    184167
    185         async_sess_t *sess =
    186             async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
    187         if (sess != NULL) {
     168        const sysarg_t method = IPC_GET_IMETHOD(*icall);
     169        usb_kbd_t *kbd_dev = fun->driver_data;
     170
     171        switch (method) {
     172        case KBDEV_SET_IND:
     173                kbd_dev->mods = IPC_GET_ARG1(*icall);
     174                usb_kbd_set_led(kbd_dev->hid_dev, kbd_dev);
     175                async_answer_0(icallid, EOK);
     176                break;
     177        /* This might be ugly but async_callback_receive_start makes no
     178         * difference for incorrect call and malloc failure. */
     179        case IPC_M_CONNECT_TO_ME: {
     180                async_sess_t *sess =
     181                    async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
     182                /* Probably ENOMEM error, try again. */
     183                if (sess == NULL) {
     184                        usb_log_warning(
     185                            "Failed to create start console session.\n");
     186                        async_answer_0(icallid, EAGAIN);
     187                        break;
     188                }
    188189                if (kbd_dev->console_sess == NULL) {
    189190                        kbd_dev->console_sess = sess;
    190                         usb_log_debug("default_connection_handler: OK\n");
     191                        usb_log_debug("%s: OK\n", __FUNCTION__);
    191192                        async_answer_0(icallid, EOK);
    192193                } else {
    193                         usb_log_debug("default_connection_handler: "
    194                             "console session already set\n");
     194                        usb_log_error("%s: console session already set\n",
     195                           __FUNCTION__);
    195196                        async_answer_0(icallid, ELIMIT);
    196197                }
    197         } else {
    198                 switch (method) {
    199                 case KBDEV_SET_IND:
    200                         kbd_dev->mods = IPC_GET_ARG1(*icall);
    201                         usb_kbd_set_led(kbd_dev->hid_dev, kbd_dev);
    202                         async_answer_0(icallid, EOK);
    203                         break;
    204                 default:
    205                         usb_log_debug("default_connection_handler: Wrong function.\n");
     198                break;
     199        }
     200        default:
     201                        usb_log_error("%s: Unknown method: %d.\n",
     202                            __FUNCTION__, (int) method);
    206203                        async_answer_0(icallid, EINVAL);
    207204                        break;
    208                 }
    209         }
    210 }
    211 
     205        }
     206
     207}
    212208/*----------------------------------------------------------------------------*/
    213209/* Key processing functions                                                   */
     
    226222 * @param kbd_dev Keyboard device structure.
    227223 */
    228 static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev) 
     224static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev)
    229225{
    230226        if (kbd_dev->output_size == 0) {
     
    274270        }
    275271
    276         usb_log_debug("Output report buffer: %s\n", 
    277             usb_debug_str_buffer(kbd_dev->output_buffer, kbd_dev->output_size, 
     272        usb_log_debug("Output report buffer: %s\n",
     273            usb_debug_str_buffer(kbd_dev->output_buffer, kbd_dev->output_size,
    278274                0));
    279275
    280         usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe,
    281             hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT, 
     276        rc = usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe,
     277            hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT,
    282278            kbd_dev->output_buffer, kbd_dev->output_size);
    283 }
    284 
     279        if (rc != EOK) {
     280                usb_log_warning("Failed to set kbd indicators.\n");
     281        }
     282}
    285283/*----------------------------------------------------------------------------*/
    286284/** Send key event.
     
    291289 * @param key Key code
    292290 */
    293 void usb_kbd_push_ev(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev, int type,
    294     unsigned int key)
     291void usb_kbd_push_ev(usb_kbd_t *kbd_dev, int type, unsigned key)
    295292{
    296293        usb_log_debug2("Sending kbdev event %d/%d to the console\n", type, key);
     
    302299
    303300        async_exch_t *exch = async_exchange_begin(kbd_dev->console_sess);
    304         async_msg_2(exch, KBDEV_EVENT, type, key);
    305         async_exchange_end(exch);
    306 }
    307 
    308 /*----------------------------------------------------------------------------*/
    309 
    310 static inline int usb_kbd_is_lock(unsigned int key_code)
     301        if (exch != NULL) {
     302                async_msg_2(exch, KBDEV_EVENT, type, key);
     303                async_exchange_end(exch);
     304        } else {
     305                usb_log_warning("Failed to send key to console.\n");
     306        }
     307}
     308/*----------------------------------------------------------------------------*/
     309static inline int usb_kbd_is_lock(unsigned int key_code)
    311310{
    312311        return (key_code == KC_NUM_LOCK
     
    314313            || key_code == KC_CAPS_LOCK);
    315314}
    316 
     315/*----------------------------------------------------------------------------*/
    317316static size_t find_in_array_int32(int32_t val, int32_t *arr, size_t arr_size)
    318317{
     
    325324        return (size_t) -1;
    326325}
    327 
    328326/*----------------------------------------------------------------------------*/
    329327/**
     
    342340 * @sa usb_kbd_push_ev(), usb_kbd_repeat_start(), usb_kbd_repeat_stop()
    343341 */
    344 static void usb_kbd_check_key_changes(usb_hid_dev_t *hid_dev, 
     342static void usb_kbd_check_key_changes(usb_hid_dev_t *hid_dev,
    345343    usb_kbd_t *kbd_dev)
    346344{
    347         unsigned int key;
    348         size_t i;
    349345
    350346        /*
     
    356352         * whole input report.
    357353         */
    358         i = find_in_array_int32(ERROR_ROLLOVER, kbd_dev->keys,
     354        size_t i = find_in_array_int32(ERROR_ROLLOVER, kbd_dev->keys,
    359355            kbd_dev->key_count);
    360356        if (i != (size_t) -1) {
    361                 usb_log_debug("Detected phantom state.\n");
     357                usb_log_error("Detected phantom state.\n");
    362358                return;
    363359        }
     
    367363         */
    368364        for (i = 0; i < kbd_dev->key_count; i++) {
    369                 int32_t old_key = kbd_dev->keys_old[i];
     365                const int32_t old_key = kbd_dev->keys_old[i];
    370366                /* Find the old key among currently pressed keys. */
    371                 size_t pos = find_in_array_int32(old_key, kbd_dev->keys,
     367                const size_t pos = find_in_array_int32(old_key, kbd_dev->keys,
    372368                    kbd_dev->key_count);
    373369                /* If the key was not found, we need to signal release. */
    374370                if (pos == (size_t) -1) {
    375                         key = usbhid_parse_scancode(old_key);
     371                        const unsigned key = usbhid_parse_scancode(old_key);
    376372                        if (!usb_kbd_is_lock(key)) {
    377373                                usb_kbd_repeat_stop(kbd_dev, key);
    378374                        }
    379                         usb_kbd_push_ev(hid_dev, kbd_dev, KEY_RELEASE, key);
     375                        usb_kbd_push_ev(kbd_dev, KEY_RELEASE, key);
    380376                        usb_log_debug2("Key released: %u "
    381377                            "(USB code %" PRIu32 ")\n", key, old_key);
     
    387383         */
    388384        for (i = 0; i < kbd_dev->key_count; ++i) {
    389                 int32_t new_key = kbd_dev->keys[i];
     385                const int32_t new_key = kbd_dev->keys[i];
    390386                /* Find the new key among already pressed keys. */
    391                 size_t pos = find_in_array_int32(new_key, kbd_dev->keys_old,
    392                     kbd_dev->key_count);
     387                const size_t pos = find_in_array_int32(new_key,
     388                    kbd_dev->keys_old, kbd_dev->key_count);
    393389                /* If the key was not found, we need to signal press. */
    394390                if (pos == (size_t) -1) {
    395                         key = usbhid_parse_scancode(kbd_dev->keys[i]);
     391                        unsigned key = usbhid_parse_scancode(kbd_dev->keys[i]);
    396392                        if (!usb_kbd_is_lock(key)) {
    397393                                usb_kbd_repeat_start(kbd_dev, key);
    398394                        }
    399                         usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS, key);
     395                        usb_kbd_push_ev(kbd_dev, KEY_PRESS, key);
    400396                        usb_log_debug2("Key pressed: %u "
    401397                            "(USB code %" PRIu32 ")\n", key, new_key);
     
    405401        memcpy(kbd_dev->keys_old, kbd_dev->keys, kbd_dev->key_count * 4);
    406402
     403        // TODO Get rid of this
    407404        char key_buffer[512];
    408405        ddf_dump_buffer(key_buffer, 512,
     
    410407        usb_log_debug2("Stored keys %s.\n", key_buffer);
    411408}
    412 
    413409/*----------------------------------------------------------------------------*/
    414410/* General kbd functions                                                      */
     
    436432
    437433        usb_hid_report_path_t *path = usb_hid_report_path();
    438         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
    439 
    440         usb_hid_report_path_set_report_id (path, hid_dev->report_id);
    441 
    442         // fill in the currently pressed keys
    443 
     434        if (path == NULL) {
     435                usb_log_error("Failed to create hid/kbd report path.\n");
     436                return;
     437        }
     438
     439        int ret =
     440           usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
     441        if (ret != EOK) {
     442                usb_log_error("Failed to append to hid/kbd report path.\n");
     443                return;
     444        }
     445
     446        usb_hid_report_path_set_report_id(path, hid_dev->report_id);
     447
     448        /* Fill in the currently pressed keys. */
    444449        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    445450            &hid_dev->report, NULL, path,
     
    449454
    450455        while (field != NULL) {
    451                 usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n", 
     456                usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n",
    452457                    field, field->value, field->usage);
    453                
     458
    454459                assert(i < kbd_dev->key_count);
    455460
    456                 // save the key usage
     461                /* Save the key usage. */
    457462                if (field->value != 0) {
    458463                        kbd_dev->keys[i] = field->usage;
     
    474479        usb_kbd_check_key_changes(hid_dev, kbd_dev);
    475480}
    476 
    477481/*----------------------------------------------------------------------------*/
    478482/* HID/KBD structure manipulation                                             */
    479483/*----------------------------------------------------------------------------*/
    480 
    481 static void usb_kbd_mark_unusable(usb_kbd_t *kbd_dev)
    482 {
    483         kbd_dev->initialized = USB_KBD_STATUS_TO_DESTROY;
    484 }
    485 
    486 /*----------------------------------------------------------------------------*/
    487 
    488 /**
    489  * Creates a new USB/HID keyboard structure.
    490  *
    491  * The structure returned by this function is not initialized. Use
    492  * usb_kbd_init() to initialize it prior to polling.
    493  *
    494  * @return New uninitialized structure for representing a USB/HID keyboard or
    495  *         NULL if not successful (memory error).
    496  */
    497 static usb_kbd_t *usb_kbd_new(void)
    498 {
    499         usb_kbd_t *kbd_dev =
    500             (usb_kbd_t *)calloc(1, sizeof(usb_kbd_t));
    501 
    502         if (kbd_dev == NULL) {
    503                 usb_log_error("No memory!\n");
    504                 return NULL;
    505         }
    506 
    507         kbd_dev->console_sess = NULL;
    508         kbd_dev->initialized = USB_KBD_STATUS_UNINITIALIZED;
    509 
    510         return kbd_dev;
    511 }
    512 
    513 /*----------------------------------------------------------------------------*/
    514 
    515484static int usb_kbd_create_function(usb_kbd_t *kbd_dev)
    516485{
     
    528497        }
    529498
    530         /*
    531          * Store the initialized HID device and HID ops
    532          * to the DDF function.
    533          */
     499        /* Store the initialized HID device and HID ops
     500         * to the DDF function. */
    534501        fun->ops = &kbd_dev->ops;
    535502        fun->driver_data = kbd_dev;
     
    539506                usb_log_error("Could not bind DDF function: %s.\n",
    540507                    str_error(rc));
    541                 fun->driver_data = NULL; /* We need this later */
     508                fun->driver_data = NULL; /* We did not allocate this. */
    542509                ddf_fun_destroy(fun);
    543510                return rc;
     
    547514            HID_KBD_FUN_NAME, fun->handle);
    548515
    549         usb_log_debug("Adding DDF function to category %s...\n", 
     516        usb_log_debug("Adding DDF function to category %s...\n",
    550517            HID_KBD_CLASS_NAME);
    551518        rc = ddf_fun_add_to_category(fun, HID_KBD_CATEGORY_NAME);
     
    554521                    "Could not add DDF function to category %s: %s.\n",
    555522                    HID_KBD_CLASS_NAME, str_error(rc));
    556                 fun->driver_data = NULL; /* We need this later */
    557                 ddf_fun_destroy(fun);
     523                if (ddf_fun_unbind(fun) == EOK) {
     524                        fun->driver_data = NULL; /* We did not allocate this. */
     525                        ddf_fun_destroy(fun);
     526                } else {
     527                        usb_log_error(
     528                            "Failed to unbind `%s', will not destroy.\n",
     529                            fun->name);
     530                }
    558531                return rc;
    559532        }
     
    562535        return EOK;
    563536}
    564 
    565537/*----------------------------------------------------------------------------*/
    566538/* API functions                                                              */
     
    591563
    592564        if (hid_dev == NULL) {
    593                 usb_log_error("Failed to init keyboard structure: no structure"
    594                     " given.\n");
     565                usb_log_error(
     566                    "Failed to init keyboard structure: no structure given.\n");
    595567                return EINVAL;
    596568        }
    597569
    598         usb_kbd_t *kbd_dev = usb_kbd_new();
     570        usb_kbd_t *kbd_dev = calloc(1, sizeof(usb_kbd_t));
    599571        if (kbd_dev == NULL) {
    600                 usb_log_error("Error while creating USB/HID KBD device "
    601                     "structure.\n");
    602                 return ENOMEM;  // TODO: some other code??
    603         }
     572                usb_log_error("Failed to allocate KBD device structure.\n");
     573                return ENOMEM;
     574        }
     575        /* Default values */
     576        fibril_mutex_initialize(&kbd_dev->repeat_mtx);
     577        kbd_dev->initialized = USB_KBD_STATUS_UNINITIALIZED;
     578        kbd_dev->ops.default_handler = default_connection_handler;
    604579
    605580        /* Store link to HID device */
    606581        kbd_dev->hid_dev = hid_dev;
    607582
    608         /*
    609          * TODO: make more general
    610          */
     583        /* Modifiers and locks */
     584        kbd_dev->mods = DEFAULT_ACTIVE_MODS;
     585
     586        /* Autorepeat */
     587        kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;
     588        kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
     589
     590
     591        // TODO: make more general
    611592        usb_hid_report_path_t *path = usb_hid_report_path();
    612         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
     593        if (path == NULL) {
     594                usb_log_error("Failed to create kbd report path.\n");
     595                usb_kbd_destroy(kbd_dev);
     596                return ENOMEM;
     597        }
     598
     599        int ret =
     600            usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
     601        if (ret != EOK) {
     602                usb_log_error("Failed to append item to kbd report path.\n");
     603                usb_hid_report_path_free(path);
     604                usb_kbd_destroy(kbd_dev);
     605                return ret;
     606        }
    613607
    614608        usb_hid_report_path_set_report_id(path, 0);
    615609
    616         kbd_dev->key_count = usb_hid_report_size(
    617             &hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT);
     610        kbd_dev->key_count =
     611            usb_hid_report_size(&hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT);
     612
    618613        usb_hid_report_path_free(path);
    619614
     
    621616
    622617        kbd_dev->keys = calloc(kbd_dev->key_count, sizeof(int32_t));
    623 
    624618        if (kbd_dev->keys == NULL) {
    625                 usb_log_error("No memory!\n");
    626                 free(kbd_dev);
     619                usb_log_error("Failed to allocate key buffer.\n");
     620                usb_kbd_destroy(kbd_dev);
    627621                return ENOMEM;
    628622        }
    629623
    630         kbd_dev->keys_old =
    631                 (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
    632 
     624        kbd_dev->keys_old = calloc(kbd_dev->key_count, sizeof(int32_t));
    633625        if (kbd_dev->keys_old == NULL) {
    634                 usb_log_error("No memory!\n");
    635                 free(kbd_dev->keys);
    636                 free(kbd_dev);
     626                usb_log_error("Failed to allocate old_key buffer.\n");
     627                usb_kbd_destroy(kbd_dev);
    637628                return ENOMEM;
    638629        }
    639630
    640         /*
    641          * Output report
    642          */
     631        /* Output report */
    643632        kbd_dev->output_size = 0;
    644633        kbd_dev->output_buffer = usb_hid_report_output(&hid_dev->report,
    645634            &kbd_dev->output_size, 0);
    646635        if (kbd_dev->output_buffer == NULL) {
    647                 usb_log_warning("Error creating output report buffer.\n");
    648                 free(kbd_dev->keys);
     636                usb_log_error("Error creating output report buffer.\n");
     637                usb_kbd_destroy(kbd_dev);
    649638                return ENOMEM;
    650639        }
     
    653642
    654643        kbd_dev->led_path = usb_hid_report_path();
    655         usb_hid_report_path_append_item(
     644        if (kbd_dev->led_path == NULL) {
     645                usb_log_error("Failed to create kbd led report path.\n");
     646                usb_kbd_destroy(kbd_dev);
     647                return ENOMEM;
     648        }
     649
     650        ret = usb_hid_report_path_append_item(
    656651            kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
     652        if (ret != EOK) {
     653                usb_log_error("Failed to append to kbd/led report path.\n");
     654                usb_kbd_destroy(kbd_dev);
     655                return ret;
     656        }
    657657
    658658        kbd_dev->led_output_size = usb_hid_report_size(
    659659            &hid_dev->report, 0, USB_HID_REPORT_TYPE_OUTPUT);
    660660
    661         usb_log_debug("Output report size (in items): %zu\n", 
     661        usb_log_debug("Output report size (in items): %zu\n",
    662662            kbd_dev->led_output_size);
    663663
    664         kbd_dev->led_data = (int32_t *)calloc(
    665             kbd_dev->led_output_size, sizeof(int32_t));
    666 
     664        kbd_dev->led_data = calloc(kbd_dev->led_output_size, sizeof(int32_t));
    667665        if (kbd_dev->led_data == NULL) {
    668                 usb_log_warning("Error creating buffer for LED output report."
    669                     "\n");
    670                 free(kbd_dev->keys);
    671                 usb_hid_report_output_free(kbd_dev->output_buffer);
    672                 free(kbd_dev);
     666                usb_log_error("Error creating buffer for LED output report.\n");
     667                usb_kbd_destroy(kbd_dev);
    673668                return ENOMEM;
    674669        }
    675670
    676         /*
    677          * Modifiers and locks
    678          */
    679         kbd_dev->modifiers = 0;
    680         kbd_dev->mods = DEFAULT_ACTIVE_MODS;
    681         kbd_dev->lock_keys = 0;
    682 
    683         /*
    684          * Autorepeat
    685          */
    686         kbd_dev->repeat.key_new = 0;
    687         kbd_dev->repeat.key_repeated = 0;
    688         kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;
    689         kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
    690 
    691         fibril_mutex_initialize(&kbd_dev->repeat_mtx);
    692 
    693         // save the KBD device structure into the HID device structure
     671        /* Set LEDs according to initial setup.
     672         * Set Idle rate */
     673        usb_kbd_set_led(hid_dev, kbd_dev);
     674
     675        usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
     676            hid_dev->usb_dev->interface_no, IDLE_RATE);
     677
     678        /* Save the KBD device structure into the HID device structure. */
    694679        *data = kbd_dev;
    695680
    696         // set handler for incoming calls
    697         kbd_dev->ops.default_handler = default_connection_handler;
    698 
    699         /*
    700          * Set LEDs according to initial setup.
    701          * Set Idle rate
    702          */
    703         usb_kbd_set_led(hid_dev, kbd_dev);
    704 
    705         usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
    706             hid_dev->usb_dev->interface_no, IDLE_RATE);
    707 
    708         /*
    709          * Create new fibril for auto-repeat
    710          */
     681        kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;
     682        usb_log_debug("HID/KBD device structure initialized.\n");
     683
     684        usb_log_debug("Creating KBD function...\n");
     685        ret = usb_kbd_create_function(kbd_dev);
     686        if (ret != EOK) {
     687                usb_kbd_destroy(kbd_dev);
     688                return ret;
     689        }
     690
     691        /* Create new fibril for auto-repeat. */
    711692        fid_t fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev);
    712693        if (fid == 0) {
    713694                usb_log_error("Failed to start fibril for KBD auto-repeat");
     695                usb_kbd_destroy(kbd_dev);
    714696                return ENOMEM;
    715697        }
    716698        fibril_add_ready(fid);
    717699
    718         kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;
    719         usb_log_debug("HID/KBD device structure initialized.\n");
    720 
    721         usb_log_debug("Creating KBD function...\n");
    722         int rc = usb_kbd_create_function(kbd_dev);
    723         if (rc != EOK) {
    724                 usb_kbd_destroy(kbd_dev);
    725                 return rc;
    726         }
    727 
    728700        return EOK;
    729701}
    730 
    731 /*----------------------------------------------------------------------------*/
    732 
     702/*----------------------------------------------------------------------------*/
    733703bool usb_kbd_polling_callback(usb_hid_dev_t *hid_dev, void *data)
    734704{
    735         if (hid_dev == NULL/* || buffer == NULL*/ || data == NULL) {
    736                 // do not continue polling (???)
     705        if (hid_dev == NULL || data == NULL) {
     706                /* This means something serious */
    737707                return false;
    738708        }
    739709
    740         usb_kbd_t *kbd_dev = (usb_kbd_t *)data;
    741         assert(kbd_dev != NULL);
    742 
     710        usb_kbd_t *kbd_dev = data;
    743711        // TODO: add return value from this function
    744712        usb_kbd_process_data(hid_dev, kbd_dev);
     
    746714        return true;
    747715}
    748 
    749 /*----------------------------------------------------------------------------*/
    750 
     716/*----------------------------------------------------------------------------*/
    751717int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev)
    752718{
    753719        return (kbd_dev->initialized == USB_KBD_STATUS_INITIALIZED);
    754720}
    755 
    756 /*----------------------------------------------------------------------------*/
    757 
     721/*----------------------------------------------------------------------------*/
    758722int usb_kbd_is_ready_to_destroy(const usb_kbd_t *kbd_dev)
    759723{
    760724        return (kbd_dev->initialized == USB_KBD_STATUS_TO_DESTROY);
    761725}
    762 
    763726/*----------------------------------------------------------------------------*/
    764727/**
     
    773736        }
    774737
    775         // hangup session to the console
    776         async_hangup(kbd_dev->console_sess);
     738        /* Hangup session to the console. */
     739        if (kbd_dev->console_sess)
     740                async_hangup(kbd_dev->console_sess);
    777741
    778742        //assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
     
    781745        while (fibril_mutex_is_locked(&kbd_dev->repeat_mtx)) {}
    782746
    783         // free all buffers
     747        /* Free all buffers. */
    784748        free(kbd_dev->keys);
    785749        free(kbd_dev->keys_old);
    786750        free(kbd_dev->led_data);
    787751
    788         if (kbd_dev->led_path != NULL) {
    789                 usb_hid_report_path_free(kbd_dev->led_path);
    790         }
    791         if (kbd_dev->output_buffer != NULL) {
    792                 usb_hid_report_output_free(kbd_dev->output_buffer);
    793         }
    794 
    795         if (ddf_fun_unbind(kbd_dev->fun) != EOK) {
    796                 usb_log_warning("Failed to unbind kbd function.\n");
    797         } else {
    798                 usb_log_debug2("%s unbound.\n", kbd_dev->fun->name);
    799                 kbd_dev->fun->driver_data = NULL;
    800                 ddf_fun_destroy(kbd_dev->fun);
    801         }
    802 }
    803 
    804 /*----------------------------------------------------------------------------*/
    805 
     752        usb_hid_report_path_free(kbd_dev->led_path);
     753        usb_hid_report_output_free(kbd_dev->output_buffer);
     754
     755        if (kbd_dev->fun) {
     756                if (ddf_fun_unbind(kbd_dev->fun) != EOK) {
     757                        usb_log_warning("Failed to unbind %s.\n",
     758                            kbd_dev->fun->name);
     759                } else {
     760                        usb_log_debug2("%s unbound.\n", kbd_dev->fun->name);
     761                        kbd_dev->fun->driver_data = NULL;
     762                        ddf_fun_destroy(kbd_dev->fun);
     763                }
     764        }
     765        free(kbd_dev);
     766}
     767/*----------------------------------------------------------------------------*/
    806768void usb_kbd_deinit(usb_hid_dev_t *hid_dev, void *data)
    807769{
    808         if (hid_dev == NULL) {
    809                 return;
    810         }
    811 
    812770        if (data != NULL) {
    813771                usb_kbd_t *kbd_dev = data;
    814772                if (usb_kbd_is_initialized(kbd_dev)) {
    815                         usb_kbd_mark_unusable(kbd_dev);
    816                         /* wait for autorepeat */
     773                        kbd_dev->initialized = USB_KBD_STATUS_TO_DESTROY;
     774                        /* Wait for autorepeat */
    817775                        async_usleep(CHECK_DELAY);
    818                         usb_kbd_destroy(kbd_dev);
    819                 }
    820         }
    821 }
    822 
    823 /*----------------------------------------------------------------------------*/
    824 
     776                }
     777                usb_kbd_destroy(kbd_dev);
     778        }
     779}
     780/*----------------------------------------------------------------------------*/
    825781int usb_kbd_set_boot_protocol(usb_hid_dev_t *hid_dev)
    826782{
     783        assert(hid_dev);
    827784        int rc = usb_hid_parse_report_descriptor(
    828785            &hid_dev->report, USB_KBD_BOOT_REPORT_DESCRIPTOR,
    829             USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE);
     786            sizeof(USB_KBD_BOOT_REPORT_DESCRIPTOR));
    830787
    831788        if (rc != EOK) {
     
    846803        return EOK;
    847804}
    848 
    849805/**
    850806 * @}
  • uspace/drv/bus/usb/usbhid/kbd/kbddev.h

    rba72f2b r6843a9c  
    135135void usb_kbd_destroy(usb_kbd_t *kbd_dev);
    136136
    137 void usb_kbd_push_ev(struct usb_hid_dev *hid_dev, usb_kbd_t *kbd_dev,
     137void usb_kbd_push_ev(usb_kbd_t *kbd_dev,
    138138    int type, unsigned int key);
    139139
  • uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.c

    rba72f2b r6843a9c  
    4545#include "kbddev.h"
    4646
    47 
    48 
    49 /*----------------------------------------------------------------------------*/
    5047/**
    5148 * Main loop handling the auto-repeat of keys.
     
    5855 * If the same key is still pressed, it uses the delay between repeats stored
    5956 * in the keyboard structure to wait until the key should be repeated.
    60  * 
     57 *
    6158 * If the currently repeated key is not pressed any more (
    62  * usb_kbd_repeat_stop() was called), it stops repeating it and starts 
     59 * usb_kbd_repeat_stop() was called), it stops repeating it and starts
    6360 * checking again.
    6461 *
    6562 * @note For accessing the keyboard device auto-repeat information a fibril
    6663 *       mutex (repeat_mtx) from the @a kbd structure is used.
    67  * 
     64 *
    6865 * @param kbd Keyboard device structure.
    6966 */
     
    7572
    7673        while (true) {
    77                 // check if the kbd structure is usable
     74                /* Check if the kbd structure is usable. */
    7875                if (!usb_kbd_is_initialized(kbd)) {
    7976                        usb_log_warning("kbd not ready, exiting autorepeat.\n");
    8077                        return;
    8178                }
    82                
     79
    8380                fibril_mutex_lock(&kbd->repeat_mtx);
    8481
    8582                if (kbd->repeat.key_new > 0) {
    8683                        if (kbd->repeat.key_new == kbd->repeat.key_repeated) {
    87                                 usb_log_debug2("Repeating key: %u.\n", 
     84                                usb_log_debug2("Repeating key: %u.\n",
    8885                                    kbd->repeat.key_repeated);
    89                                 // ugly hack with the NULL
    90                                 usb_kbd_push_ev(NULL, kbd, KEY_PRESS,
     86                                usb_kbd_push_ev(kbd, KEY_PRESS,
    9187                                    kbd->repeat.key_repeated);
    9288                                delay = kbd->repeat.delay_between;
     
    106102                }
    107103                fibril_mutex_unlock(&kbd->repeat_mtx);
    108                
    109104                async_usleep(delay);
    110105        }
    111106}
    112 
    113107/*----------------------------------------------------------------------------*/
    114108/**
     
    116110 *
    117111 * Starts the loop for checking changes in auto-repeat.
    118  * 
     112 *
    119113 * @param arg User-specified argument. Expects pointer to the keyboard device
    120114 *            structure representing the keyboard.
     
    132126        }
    133127
    134         usb_kbd_t *kbd = (usb_kbd_t *)arg;
     128        usb_kbd_t *kbd = arg;
    135129
    136130        usb_kbd_repeat_loop(kbd);
     
    138132        return EOK;
    139133}
    140 
    141134/*----------------------------------------------------------------------------*/
    142135/**
     
    156149        fibril_mutex_unlock(&kbd->repeat_mtx);
    157150}
    158 
    159151/*----------------------------------------------------------------------------*/
    160152/**
     
    162154 *
    163155 * @note Only one key is repeated at any time, but this function may be called
    164  *       even with key that is not currently repeated (in that case nothing 
     156 *       even with key that is not currently repeated (in that case nothing
    165157 *       happens).
    166158 *
     
    176168        fibril_mutex_unlock(&kbd->repeat_mtx);
    177169}
    178 
    179170/**
    180171 * @}
  • uspace/drv/bus/usb/usbhid/main.c

    rba72f2b r6843a9c  
    4646#include "usbhid.h"
    4747
    48 /*----------------------------------------------------------------------------*/
    49 
    5048#define NAME "usbhid"
    5149
    5250/**
    53  * Function for adding a new device of type USB/HID/keyboard.
     51 * Callback for passing a new device to the driver.
    5452 *
    55  * This functions initializes required structures from the device's descriptors
    56  * and starts new fibril for polling the keyboard for events and another one for
    57  * handling auto-repeat of keys.
     53 * @note Currently, only boot-protocol keyboards are supported by this driver.
    5854 *
    59  * During initialization, the keyboard is switched into boot protocol, the idle
    60  * rate is set to 0 (infinity), resulting in the keyboard only reporting event
    61  * when a key is pressed or released. Finally, the LED lights are turned on
    62  * according to the default setup of lock keys.
    63  *
    64  * @note By default, the keyboards is initialized with Num Lock turned on and
    65  *       other locks turned off.
    66  * @note Currently supports only boot-protocol keyboards.
    67  *
    68  * @param dev Device to add.
    69  *
    70  * @retval EOK if successful.
    71  * @retval ENOMEM if there
    72  * @return Other error code inherited from one of functions usb_kbd_init(),
    73  *         ddf_fun_bind() and ddf_fun_add_to_class().
     55 * @param dev Structure representing the new device.
     56 * @return Error code.
    7457 */
    75 static int usb_hid_try_add_device(usb_device_t *dev)
     58static int usb_hid_device_add(usb_device_t *dev)
    7659{
    77         assert(dev != NULL);
     60        usb_log_debug("%s\n", __FUNCTION__);
    7861
    79         /* Initialize device (get and process descriptors, get address, etc.) */
    80         usb_log_debug("Initializing USB/HID device...\n");
     62        if (dev == NULL) {
     63                usb_log_error("Wrong parameter given for add_device().\n");
     64                return EINVAL;
     65        }
    8166
     67        if (dev->interface_no < 0) {
     68                usb_log_error("Failed to add HID device: endpoints not found."
     69                    "\n");
     70                return ENOTSUP;
     71        }
    8272        usb_hid_dev_t *hid_dev =
    8373            usb_device_data_alloc(dev, sizeof(usb_hid_dev_t));
    8474        if (hid_dev == NULL) {
    85                 usb_log_error("Error while creating USB/HID device "
    86                     "structure.\n");
     75                usb_log_error("Failed to create USB/HID device structure.\n");
    8776                return ENOMEM;
    8877        }
    8978
    9079        int rc = usb_hid_init(hid_dev, dev);
    91 
    9280        if (rc != EOK) {
    9381                usb_log_error("Failed to initialize USB/HID device.\n");
     
    9886        usb_log_debug("USB/HID device structure initialized.\n");
    9987
    100         /*
    101          * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da
    102          *    do nej.
    103          * 2) do tych ops do .interfaces[DEV_IFACE_USBHID (asi)] priradi
    104          *    vyplnenu strukturu usbhid_iface_t.
    105          * 3) klientska aplikacia - musi si rucne vytvorit telefon
    106          *    (devman_device_connect() - cesta k zariadeniu (/hw/pci0/...) az
    107          *    k tej fcii.
    108          *    pouzit usb/classes/hid/iface.h - prvy int je telefon
    109          */
    110 
    11188        /* Start automated polling function.
    11289         * This will create a separate fibril that will query the device
    113          * for the data continuously
    114          */
     90         * for the data continuously. */
    11591       rc = usb_device_auto_poll(dev,
    11692           /* Index of the polling pipe. */
     
    11995           usb_hid_polling_callback,
    12096           /* How much data to request. */
    121            dev->pipes[hid_dev->poll_pipe_index].pipe->max_packet_size,
     97           dev->pipes[hid_dev->poll_pipe_index].pipe.max_packet_size,
    12298           /* Callback when the polling ends. */
    12399           usb_hid_polling_ended_callback,
     
    133109        hid_dev->running = true;
    134110
    135         /*
    136          * Hurrah, device is initialized.
    137          */
    138         return EOK;
    139 }
    140 
    141 /*----------------------------------------------------------------------------*/
    142 /**
    143  * Callback for passing a new device to the driver.
    144  *
    145  * @note Currently, only boot-protocol keyboards are supported by this driver.
    146  *
    147  * @param dev Structure representing the new device.
    148  *
    149  * @retval EOK if successful.
    150  * @retval EREFUSED if the device is not supported.
    151  */
    152 static int usb_hid_device_add(usb_device_t *dev)
    153 {
    154         usb_log_debug("usb_hid_device_add()\n");
    155 
    156         if (dev == NULL) {
    157                 usb_log_warning("Wrong parameter given for add_device().\n");
    158                 return EINVAL;
    159         }
    160 
    161         if (dev->interface_no < 0) {
    162                 usb_log_warning("Device is not a supported HID device.\n");
    163                 usb_log_error("Failed to add HID device: endpoints not found."
    164                     "\n");
    165                 return ENOTSUP;
    166         }
    167 
    168         int rc = usb_hid_try_add_device(dev);
    169 
    170         if (rc != EOK) {
    171                 usb_log_warning("Device is not a supported HID device.\n");
    172                 usb_log_error("Failed to add HID device: %s.\n",
    173                     str_error(rc));
    174                 return rc;
    175         }
    176 
    177111        usb_log_info("HID device `%s' ready to use.\n", dev->ddf_dev->name);
    178112
    179113        return EOK;
    180114}
    181 
    182115/*----------------------------------------------------------------------------*/
    183 
     116/**
     117 * Callback for a device about to be removed from the driver.
     118 *
     119 * @param dev Structure representing the device.
     120 * @return Error code.
     121 */
     122static int usb_hid_device_rem(usb_device_t *dev)
     123{
     124        // TODO: Stop device polling
     125        // TODO: Call deinit (stops autorepeat too)
     126        return ENOTSUP;
     127}
     128/*----------------------------------------------------------------------------*/
    184129/**
    185130 * Callback for removing a device from the driver.
    186131 *
    187132 * @param dev Structure representing the device.
    188  *
    189  * @retval EOK if successful.
    190  * @retval EREFUSED if the device is not supported.
     133 * @return Error code.
    191134 */
    192135static int usb_hid_device_gone(usb_device_t *dev)
    193136{
     137        assert(dev);
     138        assert(dev->driver_data);
    194139        usb_hid_dev_t *hid_dev = dev->driver_data;
    195         unsigned tries = 10;
    196         while (hid_dev->running) {
     140        unsigned tries = 100;
     141        /* Wait for fail. */
     142        while (hid_dev->running && tries--) {
    197143                async_usleep(100000);
    198                 if (!tries--) {
    199                         usb_log_error("Can't remove hub, still running.\n");
    200                         return EINPROGRESS;
    201                 }
     144        }
     145        if (hid_dev->running) {
     146                usb_log_error("Can't remove hid, still running.\n");
     147                return EBUSY;
    202148        }
    203149
    204         assert(!hid_dev->running);
    205150        usb_hid_deinit(hid_dev);
    206151        usb_log_debug2("%s destruction complete.\n", dev->ddf_dev->name);
    207152        return EOK;
    208153}
    209 
     154/*----------------------------------------------------------------------------*/
    210155/** USB generic driver callbacks */
    211 static usb_driver_ops_t usb_hid_driver_ops = {
     156static const usb_driver_ops_t usb_hid_driver_ops = {
    212157        .device_add = usb_hid_device_add,
     158        .device_rem = usb_hid_device_rem,
    213159        .device_gone = usb_hid_device_gone,
    214160};
    215 
    216 
     161/*----------------------------------------------------------------------------*/
    217162/** The driver itself. */
    218 static usb_driver_t usb_hid_driver = {
     163static const usb_driver_t usb_hid_driver = {
    219164        .name = NAME,
    220165        .ops = &usb_hid_driver_ops,
    221166        .endpoints = usb_hid_endpoints
    222167};
    223 
    224168/*----------------------------------------------------------------------------*/
    225 
    226169int main(int argc, char *argv[])
    227170{
     
    232175        return usb_driver_main(&usb_hid_driver);
    233176}
    234 
    235177/**
    236178 * @}
  • uspace/drv/bus/usb/usbhid/mouse/mousedev.c

    rba72f2b r6843a9c  
    5252#include "../usbhid.h"
    5353
    54 /** Number of simulated arrow-key presses for singel wheel step. */
    55 #define ARROWS_PER_SINGLE_WHEEL 3
    56 
    57 #define NAME  "mouse"
     54#define NAME "mouse"
    5855
    5956/*----------------------------------------------------------------------------*/
     
    6966
    7067const char *HID_MOUSE_FUN_NAME = "mouse";
    71 const char *HID_MOUSE_WHEEL_FUN_NAME = "mouse-wheel";
    7268const char *HID_MOUSE_CATEGORY = "mouse";
    73 const char *HID_MOUSE_WHEEL_CATEGORY = "keyboard";
    7469
    7570/** Default idle rate for mouses. */
     
    7772
    7873/*----------------------------------------------------------------------------*/
    79 
    80 enum {
    81         USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE = 63
    82 };
    83 
    84 static const uint8_t USB_MOUSE_BOOT_REPORT_DESCRIPTOR[
    85     USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE] = {
     74static const uint8_t USB_MOUSE_BOOT_REPORT_DESCRIPTOR[] = {
    8675        0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    8776        0x09, 0x02,                    // USAGE (Mouse)
     
    123112    ipc_callid_t icallid, ipc_call_t *icall)
    124113{
    125         usb_mouse_t *mouse_dev = (usb_mouse_t *) fun->driver_data;
     114        usb_mouse_t *mouse_dev = fun->driver_data;
    126115
    127116        if (mouse_dev == NULL) {
    128                 usb_log_debug("default_connection_handler: Missing "
    129                     "parameters.\n");
     117                usb_log_debug("%s: Missing parameters.\n", __FUNCTION__);
    130118                async_answer_0(icallid, EINVAL);
    131119                return;
    132120        }
    133121
    134         usb_log_debug("default_connection_handler: fun->name: %s\n",
    135                       fun->name);
    136         usb_log_debug("default_connection_handler: mouse_sess: %p, "
    137             "wheel_sess: %p\n", mouse_dev->mouse_sess, mouse_dev->wheel_sess);
    138 
    139         async_sess_t **sess_ptr =
    140             (str_cmp(fun->name, HID_MOUSE_FUN_NAME) == 0) ?
    141             &mouse_dev->mouse_sess : &mouse_dev->wheel_sess;
     122        usb_log_debug("%s: fun->name: %s\n", __FUNCTION__, fun->name);
     123        usb_log_debug("%s: mouse_sess: %p\n",
     124            __FUNCTION__, mouse_dev->mouse_sess);
    142125
    143126        async_sess_t *sess =
    144127            async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
    145128        if (sess != NULL) {
    146                 if (*sess_ptr == NULL) {
    147                         *sess_ptr = sess;
    148                         usb_log_debug("Console session to mouse set ok (%p).\n",
    149                             sess);
     129                if (mouse_dev->mouse_sess == NULL) {
     130                        mouse_dev->mouse_sess = sess;
     131                        usb_log_debug("Console session to %s set ok (%p).\n",
     132                            fun->name, sess);
    150133                        async_answer_0(icallid, EOK);
    151134                } else {
    152                         usb_log_debug("default_connection_handler: Console "
    153                             "session to mouse already set.\n");
     135                        usb_log_error("Console session to %s already set.\n",
     136                            fun->name);
    154137                        async_answer_0(icallid, ELIMIT);
     138                        async_hangup(sess);
    155139                }
    156140        } else {
    157                 usb_log_debug("default_connection_handler: Invalid function.\n");
     141                usb_log_debug("%s: Invalid function.\n", __FUNCTION__);
    158142                async_answer_0(icallid, EINVAL);
    159143        }
    160144}
    161 
    162 /*----------------------------------------------------------------------------*/
    163 
    164 static usb_mouse_t *usb_mouse_new(void)
    165 {
    166         usb_mouse_t *mouse = calloc(1, sizeof(usb_mouse_t));
    167         if (mouse == NULL) {
    168                 return NULL;
    169         }
    170         mouse->mouse_sess = NULL;
    171         mouse->wheel_sess = NULL;
    172 
    173         return mouse;
    174 }
    175 
    176 /*----------------------------------------------------------------------------*/
    177 
    178 static void usb_mouse_destroy(usb_mouse_t *mouse_dev)
    179 {
    180         assert(mouse_dev != NULL);
    181 
    182         // hangup session to the console
    183         if (mouse_dev->mouse_sess != NULL)
    184                 async_hangup(mouse_dev->mouse_sess);
    185 
    186         if (mouse_dev->wheel_sess != NULL)
    187                 async_hangup(mouse_dev->wheel_sess);
    188         int ret = ddf_fun_unbind(mouse_dev->mouse_fun);
    189         if (ret != EOK) {
    190                 usb_log_error("Failed to unbind mouse function.\n");
    191         } else {
    192                 ddf_fun_destroy(mouse_dev->mouse_fun);
    193                 /* Prevent double free */
    194                 mouse_dev->wheel_fun->driver_data = NULL;
    195         }
    196 
    197         ret = ddf_fun_unbind(mouse_dev->wheel_fun);
    198         if (ret != EOK) {
    199                 usb_log_error("Failed to unbind wheel function.\n");
    200         } else {
    201                 ddf_fun_destroy(mouse_dev->wheel_fun);
    202         }
    203 }
    204 
    205 /*----------------------------------------------------------------------------*/
    206 
    207 static void usb_mouse_send_wheel(const usb_mouse_t *mouse_dev, int wheel)
    208 {
    209         unsigned int key = (wheel > 0) ? KC_UP : KC_DOWN;
    210 
    211         if (mouse_dev->wheel_sess == NULL) {
    212                 usb_log_warning(
    213                     "Connection to console not ready, wheel roll discarded.\n");
    214                 return;
    215         }
    216 
    217         int count = ((wheel < 0) ? -wheel : wheel) * ARROWS_PER_SINGLE_WHEEL;
    218         int i;
    219 
    220         for (i = 0; i < count; i++) {
    221                 /* Send arrow press and release. */
    222                 usb_log_debug2("Sending key %d to the console\n", key);
    223                
    224                 async_exch_t *exch = async_exchange_begin(mouse_dev->wheel_sess);
    225                
    226                 async_msg_4(exch, KBDEV_EVENT, KEY_PRESS, key, 0, 0);
    227                 async_msg_4(exch, KBDEV_EVENT, KEY_RELEASE, key, 0, 0);
    228                
    229                 async_exchange_end(exch);
    230         }
    231 }
    232 
    233 /*----------------------------------------------------------------------------*/
    234 
     145/*----------------------------------------------------------------------------*/
    235146static int get_mouse_axis_move_value(uint8_t rid, usb_hid_report_t *report,
    236147    int32_t usage)
     
    267178        }
    268179
    269         int shift_x = get_mouse_axis_move_value(hid_dev->report_id,
     180        const int shift_x = get_mouse_axis_move_value(hid_dev->report_id,
    270181            &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_X);
    271         int shift_y = get_mouse_axis_move_value(hid_dev->report_id,
     182        const int shift_y = get_mouse_axis_move_value(hid_dev->report_id,
    272183            &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_Y);
    273         int wheel = get_mouse_axis_move_value(hid_dev->report_id,
     184        const int wheel = get_mouse_axis_move_value(hid_dev->report_id,
    274185            &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL);
    275186
    276         if ((shift_x != 0) || (shift_y != 0)) {
     187        if (shift_x || shift_y || wheel) {
    277188                async_exch_t *exch =
    278189                    async_exchange_begin(mouse_dev->mouse_sess);
    279                 async_req_2_0(exch, MOUSEEV_MOVE_EVENT, shift_x, shift_y);
    280                 async_exchange_end(exch);
    281         }
    282 
    283         if (wheel != 0)
    284                 usb_mouse_send_wheel(mouse_dev, wheel);
    285 
    286         /*
    287          * Buttons
    288          */
     190                if (exch != NULL) {
     191                        async_msg_3(exch, MOUSEEV_MOVE_EVENT,
     192                            shift_x, shift_y, wheel);
     193                        async_exchange_end(exch);
     194                }
     195        }
     196
     197        /* Buttons */
    289198        usb_hid_report_path_t *path = usb_hid_report_path();
    290         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_BUTTON, 0);
     199        if (path == NULL) {
     200                usb_log_warning("Failed to create USB HID report path.\n");
     201                return true;
     202        }
     203        int ret =
     204           usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_BUTTON, 0);
     205        if (ret != EOK) {
     206                usb_hid_report_path_free(path);
     207                usb_log_warning("Failed to add buttons to report path.\n");
     208                return true;
     209        }
    291210        usb_hid_report_path_set_report_id(path, hid_dev->report_id);
    292211
     
    298217                usb_log_debug2(NAME " VALUE(%X) USAGE(%X)\n", field->value,
    299218                    field->usage);
    300                
    301                 if (mouse_dev->buttons[field->usage - field->usage_minimum] == 0
    302                     && field->value != 0) {
     219                assert(field->usage > field->usage_minimum);
     220                const unsigned index = field->usage - field->usage_minimum;
     221                assert(index < mouse_dev->buttons_count);
     222
     223                if (mouse_dev->buttons[index] == 0 && field->value != 0) {
    303224                        async_exch_t *exch =
    304225                            async_exchange_begin(mouse_dev->mouse_sess);
    305                         async_req_2_0(exch, MOUSEEV_BUTTON_EVENT, field->usage, 1);
    306                         async_exchange_end(exch);
    307                        
    308                         mouse_dev->buttons[field->usage - field->usage_minimum]
    309                             = field->value;
    310                 } else if (mouse_dev->buttons[field->usage - field->usage_minimum] != 0
    311                     && field->value == 0) {
     226                        if (exch != NULL) {
     227                                async_req_2_0(exch, MOUSEEV_BUTTON_EVENT,
     228                                    field->usage, 1);
     229                                async_exchange_end(exch);
     230                                mouse_dev->buttons[index] = field->value;
     231                        }
     232
     233                } else if (mouse_dev->buttons[index] != 0 && field->value == 0) {
    312234                        async_exch_t *exch =
    313235                            async_exchange_begin(mouse_dev->mouse_sess);
    314                         async_req_2_0(exch, MOUSEEV_BUTTON_EVENT, field->usage, 0);
    315                         async_exchange_end(exch);
    316 
    317                         mouse_dev->buttons[field->usage - field->usage_minimum] =
    318                            field->value;
     236                        if (exch != NULL) {
     237                                async_req_2_0(exch, MOUSEEV_BUTTON_EVENT,
     238                                    field->usage, 0);
     239                                async_exchange_end(exch);
     240                                mouse_dev->buttons[index] = field->value;
     241                        }
    319242                }
    320243
     
    329252        return true;
    330253}
    331 
    332 /*----------------------------------------------------------------------------*/
    333 
     254/*----------------------------------------------------------------------------*/
     255#define FUN_UNBIND_DESTROY(fun) \
     256if (fun) { \
     257        if (ddf_fun_unbind((fun)) == EOK) { \
     258                (fun)->driver_data = NULL; \
     259                ddf_fun_destroy((fun)); \
     260        } else { \
     261                usb_log_error("Could not unbind function `%s', it " \
     262                    "will not be destroyed.\n", (fun)->name); \
     263        } \
     264} else (void)0
     265/*----------------------------------------------------------------------------*/
    334266static int usb_mouse_create_function(usb_hid_dev_t *hid_dev, usb_mouse_t *mouse)
    335267{
     
    339271        /* Create the exposed function. */
    340272        usb_log_debug("Creating DDF function %s...\n", HID_MOUSE_FUN_NAME);
    341         ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
     273        ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    342274            HID_MOUSE_FUN_NAME);
    343275        if (fun == NULL) {
    344                 usb_log_error("Could not create DDF function node.\n");
     276                usb_log_error("Could not create DDF function node `%s'.\n",
     277                    HID_MOUSE_FUN_NAME);
    345278                return ENOMEM;
    346279        }
     
    351284        int rc = ddf_fun_bind(fun);
    352285        if (rc != EOK) {
    353                 usb_log_error("Could not bind DDF function: %s.\n",
    354                     str_error(rc));
     286                usb_log_error("Could not bind DDF function `%s': %s.\n",
     287                    fun->name, str_error(rc));
     288                fun->driver_data = NULL;
     289                ddf_fun_destroy(fun);
    355290                return rc;
    356291        }
    357292
    358         usb_log_debug("Adding DDF function to category %s...\n",
    359             HID_MOUSE_CATEGORY);
     293        usb_log_debug("Adding DDF function `%s' to category %s...\n",
     294            fun->name, HID_MOUSE_CATEGORY);
    360295        rc = ddf_fun_add_to_category(fun, HID_MOUSE_CATEGORY);
    361296        if (rc != EOK) {
     
    363298                    "Could not add DDF function to category %s: %s.\n",
    364299                    HID_MOUSE_CATEGORY, str_error(rc));
     300                FUN_UNBIND_DESTROY(fun);
    365301                return rc;
    366302        }
    367303        mouse->mouse_fun = fun;
    368304
    369         /*
    370          * Special function for acting as keyboard (wheel)
    371          */
    372         usb_log_debug("Creating DDF function %s...\n",
    373                       HID_MOUSE_WHEEL_FUN_NAME);
    374         fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    375             HID_MOUSE_WHEEL_FUN_NAME);
    376         if (fun == NULL) {
    377                 usb_log_error("Could not create DDF function node.\n");
    378                 return ENOMEM;
    379         }
    380 
    381         /*
    382          * Store the initialized HID device and HID ops
    383          * to the DDF function.
    384          */
    385         fun->ops = &mouse->ops;
    386         fun->driver_data = mouse;
    387 
    388         rc = ddf_fun_bind(fun);
    389         if (rc != EOK) {
    390                 usb_log_error("Could not bind DDF function: %s.\n",
    391                     str_error(rc));
    392                 return rc;
    393         }
    394 
    395         usb_log_debug("Adding DDF function to category %s...\n",
    396             HID_MOUSE_WHEEL_CATEGORY);
    397         rc = ddf_fun_add_to_category(fun, HID_MOUSE_WHEEL_CATEGORY);
    398         if (rc != EOK) {
    399                 usb_log_error(
    400                     "Could not add DDF function to category %s: %s.\n",
    401                     HID_MOUSE_WHEEL_CATEGORY, str_error(rc));
    402                 return rc;
    403         }
    404         mouse->wheel_fun = fun;
    405 
    406305        return EOK;
    407306}
    408 
    409 /*----------------------------------------------------------------------------*/
    410307
    411308/** Get highest index of a button mentioned in given report.
     
    448345        return highest_button;
    449346}
    450 
    451 /*----------------------------------------------------------------------------*/
    452 
     347/*----------------------------------------------------------------------------*/
    453348int usb_mouse_init(usb_hid_dev_t *hid_dev, void **data)
    454349{
     
    461356        }
    462357
    463         usb_mouse_t *mouse_dev = usb_mouse_new();
     358        usb_mouse_t *mouse_dev = calloc(1, sizeof(usb_mouse_t));
    464359        if (mouse_dev == NULL) {
    465360                usb_log_error("Error while creating USB/HID Mouse device "
     
    484379        }
    485380
    486 
    487         // save the Mouse device structure into the HID device structure
    488         *data = mouse_dev;
    489 
    490381        // set handler for incoming calls
    491382        mouse_dev->ops.default_handler = default_connection_handler;
    492383
    493384        // TODO: how to know if the device supports the request???
    494         usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 
     385        usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
    495386            hid_dev->usb_dev->interface_no, IDLE_RATE);
    496387
    497388        int rc = usb_mouse_create_function(hid_dev, mouse_dev);
    498389        if (rc != EOK) {
    499                 usb_mouse_destroy(mouse_dev);
     390                free(mouse_dev->buttons);
     391                free(mouse_dev);
    500392                return rc;
    501393        }
    502394
     395        /* Save the Mouse device structure into the HID device structure. */
     396        *data = mouse_dev;
     397
    503398        return EOK;
    504399}
    505 
    506 /*----------------------------------------------------------------------------*/
    507 
     400/*----------------------------------------------------------------------------*/
    508401bool usb_mouse_polling_callback(usb_hid_dev_t *hid_dev, void *data)
    509402{
    510403        if (hid_dev == NULL || data == NULL) {
    511                 usb_log_error("Missing argument to the mouse polling callback."
    512                     "\n");
     404                usb_log_error(
     405                    "Missing argument to the mouse polling callback.\n");
    513406                return false;
    514407        }
    515408
    516         usb_mouse_t *mouse_dev = (usb_mouse_t *)data;
    517                
     409        usb_mouse_t *mouse_dev = data;
     410
    518411        return usb_mouse_process_report(hid_dev, mouse_dev);
    519412}
    520 
    521 /*----------------------------------------------------------------------------*/
    522 
     413/*----------------------------------------------------------------------------*/
    523414void usb_mouse_deinit(usb_hid_dev_t *hid_dev, void *data)
    524415{
    525         if (data != NULL) {
    526                 usb_mouse_destroy(data);
    527         }
    528 }
    529 
    530 /*----------------------------------------------------------------------------*/
    531 
     416        if (data == NULL)
     417                return;
     418
     419        usb_mouse_t *mouse_dev = data;
     420
     421        /* Hangup session to the console */
     422        if (mouse_dev->mouse_sess != NULL) {
     423                const int ret = async_hangup(mouse_dev->mouse_sess);
     424                if (ret != EOK)
     425                        usb_log_warning("Failed to hang up mouse session: "
     426                            "%p, %s.\n", mouse_dev->mouse_sess, str_error(ret));
     427        }
     428
     429        FUN_UNBIND_DESTROY(mouse_dev->mouse_fun);
     430
     431        free(mouse_dev->buttons);
     432        free(mouse_dev);
     433}
     434/*----------------------------------------------------------------------------*/
    532435int usb_mouse_set_boot_protocol(usb_hid_dev_t *hid_dev)
    533436{
    534437        int rc = usb_hid_parse_report_descriptor(
    535438            &hid_dev->report, USB_MOUSE_BOOT_REPORT_DESCRIPTOR,
    536             USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE);
     439            sizeof(USB_MOUSE_BOOT_REPORT_DESCRIPTOR));
    537440
    538441        if (rc != EOK) {
  • uspace/drv/bus/usb/usbhid/mouse/mousedev.h

    rba72f2b r6843a9c  
    4848        /** IPC session to console (consumer). */
    4949        async_sess_t *mouse_sess;
    50         async_sess_t *wheel_sess;
    5150
    5251        /* Mouse buttons statuses. */
     
    5756        /* DDF mouse function */
    5857        ddf_fun_t *mouse_fun;
    59         /* DDF mouse function */
    60         ddf_fun_t *wheel_fun;
    6158} usb_mouse_t;
    6259
  • uspace/drv/bus/usb/usbhid/multimedia/multimedia.c

    rba72f2b r6843a9c  
    6767        /** IPC session to the console device (for sending key events). */
    6868        async_sess_t *console_sess;
    69         /** DDF function */
    70         ddf_fun_t *fun;
    7169} usb_multimedia_t;
    7270
    7371
    7472/*----------------------------------------------------------------------------*/
    75 /** 
     73/**
    7674 * Default handler for IPC methods not handled by DDF.
    7775 *
     
    8886{
    8987        usb_log_debug(NAME " default_connection_handler()\n");
    90 
    91         usb_multimedia_t *multim_dev = (usb_multimedia_t *)fun->driver_data;
    92 
    93         if (multim_dev == NULL) {
     88        if (fun == NULL || fun->driver_data == NULL) {
    9489                async_answer_0(icallid, EINVAL);
    9590                return;
    9691        }
     92
     93        usb_multimedia_t *multim_dev = fun->driver_data;
    9794
    9895        async_sess_t *sess =
     
    109106                async_answer_0(icallid, EINVAL);
    110107}
    111 
    112 /*----------------------------------------------------------------------------*/
    113 
     108/*----------------------------------------------------------------------------*/
    114109static ddf_dev_ops_t multimedia_ops = {
    115110        .default_handler = default_connection_handler
    116111};
    117 
    118112/*----------------------------------------------------------------------------*/
    119113/**
     
    127121 *       sends also these keys to application (otherwise it cannot use those
    128122 *       keys at all).
    129  * 
    130  * @param hid_dev 
    131  * @param lgtch_dev
    132  * @param type Type of the event (press / release). Recognized values: 
     123 *
     124 * @param hid_dev
     125 * @param multim_dev
     126 * @param type Type of the event (press / release). Recognized values:
    133127 *             KEY_PRESS, KEY_RELEASE
    134128 * @param key Key code of the key according to HID Usage Tables.
    135129 */
    136 static void usb_multimedia_push_ev(usb_hid_dev_t *hid_dev,
     130static void usb_multimedia_push_ev(
    137131    usb_multimedia_t *multim_dev, int type, unsigned int key)
    138132{
    139         assert(hid_dev != NULL);
    140133        assert(multim_dev != NULL);
    141134
    142         kbd_event_t ev;
    143 
    144         ev.type = type;
    145         ev.key = key;
    146         ev.mods = 0;
    147         ev.c = 0;
     135        const kbd_event_t ev = {
     136                .type = type,
     137                .key = key,
     138                .mods = 0,
     139                .c = 0,
     140        };
    148141
    149142        usb_log_debug2(NAME " Sending key %d to the console\n", ev.key);
     
    155148
    156149        async_exch_t *exch = async_exchange_begin(multim_dev->console_sess);
    157         async_msg_4(exch, KBDEV_EVENT, ev.type, ev.key, ev.mods, ev.c);
    158         async_exchange_end(exch);
    159 }
    160 
    161 /*----------------------------------------------------------------------------*/
    162 
     150        if (exch != NULL) {
     151                async_msg_4(exch, KBDEV_EVENT, ev.type, ev.key, ev.mods, ev.c);
     152                async_exchange_end(exch);
     153        } else {
     154                usb_log_warning("Failed to send multimedia key.\n");
     155        }
     156}
     157/*----------------------------------------------------------------------------*/
    163158int usb_multimedia_init(struct usb_hid_dev *hid_dev, void **data)
    164159{
    165160        if (hid_dev == NULL || hid_dev->usb_dev == NULL) {
    166                 return EINVAL; /*! @todo Other return code? */
     161                return EINVAL;
    167162        }
    168163
     
    187182
    188183        multim_dev->console_sess = NULL;
    189         multim_dev->fun = fun;
    190184
    191185        //todo Autorepeat?
     
    199193        }
    200194
    201         usb_log_debug("%s function created (handle: %" PRIun ").\n",
    202             NAME, fun->handle);
     195        usb_log_debug(NAME " function created (handle: %" PRIun ").\n",
     196            fun->handle);
    203197
    204198        rc = ddf_fun_add_to_category(fun, "keyboard");
     
    207201                    "Could not add DDF function to category 'keyboard': %s.\n",
    208202                    str_error(rc));
    209                 ddf_fun_destroy(fun);
     203                if (ddf_fun_unbind(fun) != EOK) {
     204                        usb_log_error("Failed to unbind %s, won't destroy.\n",
     205                            fun->name);
     206                } else {
     207                        ddf_fun_destroy(fun);
     208                }
    210209                return rc;
    211210        }
    212211
    213212        /* Save the KBD device structure into the HID device structure. */
    214         *data = multim_dev;
     213        *data = fun;
    215214
    216215        usb_log_debug(NAME " HID/multimedia structure initialized.\n");
    217216        return EOK;
    218217}
    219 
    220 /*----------------------------------------------------------------------------*/
    221 
     218/*----------------------------------------------------------------------------*/
    222219void usb_multimedia_deinit(struct usb_hid_dev *hid_dev, void *data)
    223220{
    224         if (hid_dev == NULL) {
    225                 return;
    226         }
    227 
    228         if (data != NULL) {
    229                 usb_multimedia_t *multim_dev = (usb_multimedia_t *)data;
    230                 // hangup session to the console
    231                 async_hangup(multim_dev->console_sess);
    232                 const int ret = ddf_fun_unbind(multim_dev->fun);
    233                 if (ret != EOK) {
    234                         usb_log_error("Failed to unbind multim function.\n");
     221        ddf_fun_t *fun = data;
     222        if (fun != NULL && fun->driver_data != NULL) {
     223                usb_multimedia_t *multim_dev = fun->driver_data;
     224                /* Hangup session to the console */
     225                if (multim_dev->console_sess)
     226                        async_hangup(multim_dev->console_sess);
     227                if (ddf_fun_unbind(fun) != EOK) {
     228                        usb_log_error("Failed to unbind %s, won't destroy.\n",
     229                            fun->name);
    235230                } else {
    236                         usb_log_debug2("%s unbound.\n", multim_dev->fun->name);
    237                         ddf_fun_destroy(multim_dev->fun);
     231                        usb_log_debug2("%s unbound.\n", fun->name);
     232                        /* This frees multim_dev too as it was stored in
     233                         * fun->data */
     234                        ddf_fun_destroy(fun);
    238235                }
    239         }
    240 }
    241 
    242 /*----------------------------------------------------------------------------*/
    243 
     236        } else {
     237                usb_log_error(
     238                    "Failed to deinit multimedia subdriver, data missing.\n");
     239        }
     240}
     241/*----------------------------------------------------------------------------*/
    244242bool usb_multimedia_polling_callback(struct usb_hid_dev *hid_dev, void *data)
    245243{
    246244        // TODO: checks
    247         if (hid_dev == NULL || data == NULL) {
     245        ddf_fun_t *fun = data;
     246        if (hid_dev == NULL || fun == NULL || fun->driver_data == NULL) {
    248247                return false;
    249248        }
    250249
    251         usb_multimedia_t *multim_dev = (usb_multimedia_t *)data;
     250        usb_multimedia_t *multim_dev = fun->driver_data;
    252251
    253252        usb_hid_report_path_t *path = usb_hid_report_path();
    254         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
     253        if (path == NULL)
     254                return true; /* This might be a temporary failure. */
     255
     256        int ret =
     257            usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
     258        if (ret != EOK) {
     259                usb_hid_report_path_free(path);
     260                return true; /* This might be a temporary failure. */
     261        }
    255262
    256263        usb_hid_report_path_set_report_id(path, hid_dev->report_id);
     
    261268            USB_HID_REPORT_TYPE_INPUT);
    262269
    263         /*! @todo Is this iterating OK if done multiple times?
    264          *  @todo The parsing is not OK
    265          */
     270        //FIXME Is this iterating OK if done multiple times?
     271        //FIXME The parsing is not OK. (what's wrong?)
    266272        while (field != NULL) {
    267                 if(field->value != 0) {
    268                         usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n", 
     273                if (field->value != 0) {
     274                        usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n",
    269275                            field->value, field->usage);
    270                         unsigned int key =
     276                        const unsigned key =
    271277                            usb_multimedia_map_usage(field->usage);
    272                         const char *key_str = 
     278                        const char *key_str =
    273279                            usbhid_multimedia_usage_to_str(field->usage);
    274280                        usb_log_info("Pressed key: %s\n", key_str);
    275                         usb_multimedia_push_ev(hid_dev, multim_dev, KEY_PRESS,
    276                                                key);
     281                        usb_multimedia_push_ev(multim_dev, KEY_PRESS, key);
    277282                }
    278283
    279284                field = usb_hid_report_get_sibling(
    280285                    &hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
    281                     | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
     286                    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    282287                    USB_HID_REPORT_TYPE_INPUT);
    283288        }
     
    287292        return true;
    288293}
    289 
    290294/**
    291295 * @}
  • uspace/drv/bus/usb/usbhid/subdrivers.c

    rba72f2b r6843a9c  
    9898                }
    9999        },
    100         {NULL, -1, 0, -1, -1, {NULL, NULL, NULL, NULL, NULL}}
    101100};
    102101
    103 const int USB_HID_MAX_SUBDRIVERS =
     102const size_t USB_HID_MAX_SUBDRIVERS =
    104103    sizeof(usb_hid_subdrivers) / sizeof(usb_hid_subdrivers[0]);
    105104
  • uspace/drv/bus/usb/usbhid/subdrivers.h

    rba72f2b r6843a9c  
    8484
    8585extern const usb_hid_subdriver_mapping_t usb_hid_subdrivers[];
    86 extern const int USB_HID_MAX_SUBDRIVERS;
     86extern const size_t USB_HID_MAX_SUBDRIVERS;
    8787
    8888/*----------------------------------------------------------------------------*/
  • uspace/drv/bus/usb/usbhid/usbhid.c

    rba72f2b r6843a9c  
    5151#include "subdrivers.h"
    5252
    53 /*----------------------------------------------------------------------------*/
    54 
    5553/* Array of endpoints expected on the device, NULL terminated. */
    5654const usb_endpoint_description_t *usb_hid_endpoints[] = {
     
    6058        NULL
    6159};
    62 
    63 /*----------------------------------------------------------------------------*/
    64 
     60/*----------------------------------------------------------------------------*/
    6561static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev)
    6662{
     
    7874        return EOK;
    7975}
    80 
    81 /*----------------------------------------------------------------------------*/
    82 
     76/*----------------------------------------------------------------------------*/
    8377static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev)
    8478{
     
    9286        hid_dev->subdriver_count = 1;
    9387        // TODO 2 should be mouse, but find a better way
    94         hid_dev->subdrivers[2] = usb_hid_subdrivers[0].subdriver;
     88        hid_dev->subdrivers[0] = usb_hid_subdrivers[2].subdriver;
    9589
    9690        return EOK;
    9791}
    98 
    99 /*----------------------------------------------------------------------------*/
    100 
     92/*----------------------------------------------------------------------------*/
    10193static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev)
    10294{
    103         assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
     95        assert(hid_dev != NULL);
     96        assert(hid_dev->subdriver_count == 0);
    10497
    10598        hid_dev->subdrivers = malloc(sizeof(usb_hid_subdriver_t));
     
    117110        return EOK;
    118111}
    119 
    120 /*----------------------------------------------------------------------------*/
    121 
     112/*----------------------------------------------------------------------------*/
    122113static bool usb_hid_ids_match(const usb_hid_dev_t *hid_dev,
    123114    const usb_hid_subdriver_mapping_t *mapping)
     
    128119        return (hid_dev->usb_dev->descriptors.device.vendor_id
    129120            == mapping->vendor_id
    130             && hid_dev->usb_dev->descriptors.device.product_id 
     121            && hid_dev->usb_dev->descriptors.device.product_id
    131122            == mapping->product_id);
    132123}
    133 
    134 /*----------------------------------------------------------------------------*/
    135 
     124/*----------------------------------------------------------------------------*/
    136125static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev,
    137126    const usb_hid_subdriver_mapping_t *mapping)
     
    145134                return false;
    146135        }
    147         int i = 0;
    148         while (mapping->usage_path[i].usage != 0
    149             || mapping->usage_path[i].usage_page != 0) {
     136
     137        for (int i = 0; mapping->usage_path[i].usage != 0
     138            || mapping->usage_path[i].usage_page != 0; ++i) {
    150139                if (usb_hid_report_path_append_item(usage_path,
    151140                    mapping->usage_path[i].usage_page,
     
    155144                        return false;
    156145                }
    157                 ++i;
    158146        }
    159147
     
    165153        do {
    166154                usb_log_debug("Trying report id %u\n", report_id);
    167 
    168155                if (report_id != 0) {
    169156                        usb_hid_report_path_set_report_id(usage_path,
     
    171158                }
    172159
    173                 usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    174                     &hid_dev->report, NULL, usage_path, mapping->compare,
    175                     USB_HID_REPORT_TYPE_INPUT);
     160                const usb_hid_report_field_t *field =
     161                    usb_hid_report_get_sibling(
     162                        &hid_dev->report, NULL, usage_path, mapping->compare,
     163                        USB_HID_REPORT_TYPE_INPUT);
    176164
    177165                usb_log_debug("Field: %p\n", field);
     
    190178        return matches;
    191179}
    192 
    193 /*----------------------------------------------------------------------------*/
    194 
     180/*----------------------------------------------------------------------------*/
    195181static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev,
    196     const usb_hid_subdriver_t **subdrivers, int count)
    197 {
    198         int i;
    199 
    200         if (count <= 0) {
     182    const usb_hid_subdriver_t **subdrivers, unsigned count)
     183{
     184        assert(hid_dev);
     185        assert(subdrivers);
     186
     187        if (count == 0) {
    201188                hid_dev->subdriver_count = 0;
    202189                hid_dev->subdrivers = NULL;
     
    210197        }
    211198
    212         for (i = 0; i < count; ++i) {
    213                 hid_dev->subdrivers[i].init = subdrivers[i]->init;
    214                 hid_dev->subdrivers[i].deinit = subdrivers[i]->deinit;
    215                 hid_dev->subdrivers[i].poll = subdrivers[i]->poll;
    216                 hid_dev->subdrivers[i].poll_end = subdrivers[i]->poll_end;
     199        for (unsigned i = 0; i < count; ++i) {
     200                hid_dev->subdrivers[i] = *subdrivers[i];
    217201        }
    218202
     
    227211        return EOK;
    228212}
    229 
    230 /*----------------------------------------------------------------------------*/
    231 
     213/*----------------------------------------------------------------------------*/
    232214static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev)
    233215{
     
    235217
    236218        const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS];
    237 
    238         int i = 0, count = 0;
    239         const usb_hid_subdriver_mapping_t *mapping = &usb_hid_subdrivers[i];
    240 
    241         bool ids_matched;
    242         bool matched;
    243 
    244         while (count < USB_HID_MAX_SUBDRIVERS &&
    245             (mapping->usage_path != NULL
    246             || mapping->vendor_id >= 0 || mapping->product_id >= 0)) {
    247                 // check the vendor & product ID
     219        unsigned count = 0;
     220
     221        for (unsigned i = 0; i < USB_HID_MAX_SUBDRIVERS; ++i) {
     222                const usb_hid_subdriver_mapping_t *mapping =
     223                    &usb_hid_subdrivers[i];
     224                /* Check the vendor & product ID. */
    248225                if (mapping->vendor_id >= 0 && mapping->product_id < 0) {
    249                         usb_log_warning("Missing Product ID for Vendor ID %d\n",
    250                             mapping->vendor_id);
    251                         return EINVAL;
     226                        usb_log_warning("Mapping[%d]: Missing Product ID for "
     227                            "Vendor ID %d\n", i, mapping->vendor_id);
    252228                }
    253229                if (mapping->product_id >= 0 && mapping->vendor_id < 0) {
    254                         usb_log_warning("Missing Vendor ID for Product ID %d\n",
    255                             mapping->product_id);
    256                         return EINVAL;
    257                 }
    258 
    259                 ids_matched = false;
    260                 matched = false;
    261 
    262                 if (mapping->vendor_id >= 0) {
    263                         assert(mapping->product_id >= 0);
     230                        usb_log_warning("Mapping[%d]: Missing Vendor ID for "
     231                            "Product ID %d\n", i, mapping->product_id);
     232                }
     233
     234                bool matched = false;
     235
     236                /* Check ID match. */
     237                if (mapping->vendor_id >= 0 && mapping->product_id >= 0) {
    264238                        usb_log_debug("Comparing device against vendor ID %u"
    265239                            " and product ID %u.\n", mapping->vendor_id,
     
    267241                        if (usb_hid_ids_match(hid_dev, mapping)) {
    268242                                usb_log_debug("IDs matched.\n");
    269                                 ids_matched = true;
     243                                matched = true;
    270244                        }
    271245                }
    272246
     247                /* Check usage match. */
    273248                if (mapping->usage_path != NULL) {
    274249                        usb_log_debug("Comparing device against usage path.\n");
    275250                        if (usb_hid_path_matches(hid_dev, mapping)) {
    276                                 // does not matter if IDs were matched
     251                                /* Does not matter if IDs were matched. */
    277252                                matched = true;
    278253                        }
    279                 } else {
    280                         // matched only if IDs were matched and there is no path
    281                         matched = ids_matched;
    282254                }
    283255
     
    286258                        subdrivers[count++] = &mapping->subdriver;
    287259                }
    288 
    289                 mapping = &usb_hid_subdrivers[++i];
    290260        }
    291261
    292262        /* We have all subdrivers determined, save them into the hid device */
    293         // TODO Dowe really need this complicated stuff if there is
    294         // max_subdrivers limitation?
    295263        return usb_hid_save_subdrivers(hid_dev, subdrivers, count);
    296264}
    297 
    298 /*----------------------------------------------------------------------------*/
    299 
     265/*----------------------------------------------------------------------------*/
    300266static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, const usb_device_t *dev)
    301267{
     
    303269        assert(dev);
    304270
    305         if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
    306                 usb_log_debug("Found keyboard endpoint.\n");
    307                 // save the pipe index
    308                 hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
    309         } else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
    310                 usb_log_debug("Found mouse endpoint.\n");
    311                 // save the pipe index
    312                 hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
    313         } else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
    314                 usb_log_debug("Found generic HID endpoint.\n");
    315                 // save the pipe index
    316                 hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
    317         } else {
    318                 usb_log_error("None of supported endpoints found - probably"
    319                     " not a supported device.\n");
    320                 return ENOTSUP;
    321         }
    322 
    323         return EOK;
    324 }
    325 
    326 /*----------------------------------------------------------------------------*/
    327 
     271        static const struct {
     272                unsigned ep_number;
     273                const char* description;
     274        } endpoints[] = {
     275                {USB_HID_KBD_POLL_EP_NO, "Keyboard endpoint"},
     276                {USB_HID_MOUSE_POLL_EP_NO, "Mouse endpoint"},
     277                {USB_HID_GENERIC_POLL_EP_NO, "Generic HID endpoint"},
     278        };
     279
     280        for (unsigned i = 0; i < sizeof(endpoints)/sizeof(endpoints[0]); ++i) {
     281                if (endpoints[i].ep_number >= dev->pipes_count) {
     282                        return EINVAL;
     283                }
     284                if (dev->pipes[endpoints[i].ep_number].present) {
     285                        usb_log_debug("Found: %s.\n", endpoints[i].description);
     286                        hid_dev->poll_pipe_index = endpoints[i].ep_number;
     287                        return EOK;
     288                }
     289        }
     290        return ENOTSUP;
     291}
     292/*----------------------------------------------------------------------------*/
    328293static int usb_hid_init_report(usb_hid_dev_t *hid_dev)
    329294{
     
    357322        return EOK;
    358323}
    359 
    360 /*----------------------------------------------------------------------------*/
    361 
     324/*----------------------------------------------------------------------------*/
     325/*
     326 * This functions initializes required structures from the device's descriptors
     327 * and starts new fibril for polling the keyboard for events and another one for
     328 * handling auto-repeat of keys.
     329 *
     330 * During initialization, the keyboard is switched into boot protocol, the idle
     331 * rate is set to 0 (infinity), resulting in the keyboard only reporting event
     332 * when a key is pressed or released. Finally, the LED lights are turned on
     333 * according to the default setup of lock keys.
     334 *
     335 * @note By default, the keyboards is initialized with Num Lock turned on and
     336 *       other locks turned off.
     337 *
     338 * @param hid_dev Device to initialize, non-NULL.
     339 * @param dev USB device, non-NULL.
     340 * @return Error code.
     341 */
    362342int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev)
    363343{
    364         int rc, i;
     344        assert(hid_dev);
     345        assert(dev);
    365346
    366347        usb_log_debug("Initializing HID structure...\n");
    367 
    368         if (hid_dev == NULL) {
    369                 usb_log_error("Failed to init HID structure: no structure given"
    370                     ".\n");
    371                 return EINVAL;
    372         }
    373 
    374         if (dev == NULL) {
    375                 usb_log_error("Failed to init HID structure: no USB device"
    376                     " given.\n");
    377                 return EINVAL;
    378         }
    379348
    380349        usb_hid_report_init(&hid_dev->report);
     
    384353        hid_dev->poll_pipe_index = -1;
    385354
    386         rc = usb_hid_check_pipes(hid_dev, dev);
     355        int rc = usb_hid_check_pipes(hid_dev, dev);
    387356        if (rc != EOK) {
    388357                return rc;
     
    390359
    391360        /* Get the report descriptor and parse it. */
    392         rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
    393             &hid_dev->report, &hid_dev->report_desc, &hid_dev->report_desc_size);
    394 
    395         bool fallback = false;
    396 
     361        rc = usb_hid_process_report_descriptor(
     362            hid_dev->usb_dev, &hid_dev->report, &hid_dev->report_desc,
     363            &hid_dev->report_desc_size);
     364
     365        /* If report parsing went well, find subdrivers. */
    397366        if (rc == EOK) {
    398                 // try to find subdrivers that may want to handle this device
    399                 rc = usb_hid_find_subdrivers(hid_dev);
    400                 if (rc != EOK || hid_dev->subdriver_count == 0) {
    401                         // try to fall back to the boot protocol if available
    402                         usb_log_info("No subdrivers found to handle this"
    403                             " device.\n");
    404                         fallback = true;
    405                         assert(hid_dev->subdrivers == NULL);
    406                         assert(hid_dev->subdriver_count == 0);
    407                 }
     367                usb_hid_find_subdrivers(hid_dev);
    408368        } else {
    409                 usb_log_error("Failed to parse Report descriptor.\n");
    410                 // try to fall back to the boot protocol if available
    411                 fallback = true;
    412         }
    413 
    414         if (fallback) {
    415                 // fall back to boot protocol
     369                usb_log_error("Failed to parse report descriptor: fallback.\n");
     370                hid_dev->subdrivers = NULL;
     371                hid_dev->subdriver_count = 0;
     372        }
     373
     374        usb_log_debug("Subdriver count(before trying boot protocol): %d\n",
     375            hid_dev->subdriver_count);
     376
     377        /* No subdrivers, fall back to the boot protocol if available. */
     378        if (hid_dev->subdriver_count == 0) {
     379                assert(hid_dev->subdrivers == NULL);
     380                usb_log_info("No subdrivers found to handle device, trying "
     381                    "boot protocol.\n");
     382
    416383                switch (hid_dev->poll_pipe_index) {
    417384                case USB_HID_KBD_POLL_EP_NO:
     
    419386                        rc = usb_kbd_set_boot_protocol(hid_dev);
    420387                        if (rc == EOK) {
    421                                 rc = usb_hid_set_boot_kbd_subdriver(hid_dev);
     388                                usb_hid_set_boot_kbd_subdriver(hid_dev);
    422389                        }
    423390                        break;
     
    426393                        rc = usb_mouse_set_boot_protocol(hid_dev);
    427394                        if (rc == EOK) {
    428                                 rc = usb_hid_set_boot_mouse_subdriver(hid_dev);
     395                                usb_hid_set_boot_mouse_subdriver(hid_dev);
    429396                        }
    430397                        break;
     
    432399                        assert(hid_dev->poll_pipe_index
    433400                            == USB_HID_GENERIC_POLL_EP_NO);
    434 
    435401                        usb_log_info("Falling back to generic HID driver.\n");
    436                         rc = usb_hid_set_generic_hid_subdriver(hid_dev);
    437                 }
    438         }
    439 
    440         if (rc != EOK) {
    441                 usb_log_error("No subdriver for handling this device could be"
    442                     " initialized: %s.\n", str_error(rc));
    443                 usb_log_debug("Subdriver count: %d\n",
    444                     hid_dev->subdriver_count);
    445         } else {
    446                 bool ok = false;
    447 
    448                 usb_log_debug("Subdriver count: %d\n",
    449                     hid_dev->subdriver_count);
    450 
    451                 for (i = 0; i < hid_dev->subdriver_count; ++i) {
    452                         if (hid_dev->subdrivers[i].init != NULL) {
    453                                 usb_log_debug("Initializing subdriver %d.\n",i);
    454                                 rc = hid_dev->subdrivers[i].init(hid_dev,
    455                                     &hid_dev->subdrivers[i].data);
    456                                 if (rc != EOK) {
    457                                         usb_log_warning("Failed to initialize"
    458                                             " HID subdriver structure.\n");
    459                                 } else {
    460                                         // at least one subdriver initialized
    461                                         ok = true;
    462                                 }
     402                        usb_hid_set_generic_hid_subdriver(hid_dev);
     403                }
     404        }
     405
     406        usb_log_debug("Subdriver count(after trying boot protocol): %d\n",
     407            hid_dev->subdriver_count);
     408
     409        /* Still no subdrivers? */
     410        if (hid_dev->subdriver_count == 0) {
     411                assert(hid_dev->subdrivers == NULL);
     412                usb_log_error(
     413                    "No subdriver for handling this device could be found.\n");
     414                return ENOTSUP;
     415        }
     416
     417        /*
     418         * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da
     419         *    do nej.
     420         * 2) do tych ops do .interfaces[DEV_IFACE_USBHID (asi)] priradi
     421         *    vyplnenu strukturu usbhid_iface_t.
     422         * 3) klientska aplikacia - musi si rucne vytvorit telefon
     423         *    (devman_device_connect() - cesta k zariadeniu (/hw/pci0/...) az
     424         *    k tej fcii.
     425         *    pouzit usb/classes/hid/iface.h - prvy int je telefon
     426         */
     427        bool ok = false;
     428        for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) {
     429                if (hid_dev->subdrivers[i].init != NULL) {
     430                        usb_log_debug("Initializing subdriver %d.\n",i);
     431                        const int pret = hid_dev->subdrivers[i].init(hid_dev,
     432                            &hid_dev->subdrivers[i].data);
     433                        if (pret != EOK) {
     434                                usb_log_warning("Failed to initialize"
     435                                    " HID subdriver structure: %s.\n",
     436                                    str_error(pret));
     437                                rc = pret;
    463438                        } else {
     439                                /* At least one subdriver initialized. */
    464440                                ok = true;
    465441                        }
    466                 }
    467 
    468                 rc = (ok) ? EOK : -1;   // what error to report
    469         }
    470 
    471 
    472         if (rc == EOK) {
    473                 // save max input report size and allocate space for the report
     442                } else {
     443                        /* Does not need initialization. */
     444                        ok = true;
     445                }
     446        }
     447
     448        if (ok) {
     449                /* Save max input report size and
     450                 * allocate space for the report */
    474451                rc = usb_hid_init_report(hid_dev);
    475452                if (rc != EOK) {
     
    481458        return rc;
    482459}
    483 
    484 /*----------------------------------------------------------------------------*/
    485 
     460/*----------------------------------------------------------------------------*/
    486461bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
    487462    size_t buffer_size, void *arg)
     
    516491        bool cont = false;
    517492        /* Continue if at least one of the subdrivers want to continue */
    518         for (int i = 0; i < hid_dev->subdriver_count; ++i) {
     493        for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) {
    519494                if (hid_dev->subdrivers[i].poll != NULL) {
    520495                        cont = cont || hid_dev->subdrivers[i].poll(
     
    525500        return cont;
    526501}
    527 
    528 /*----------------------------------------------------------------------------*/
    529 
     502/*----------------------------------------------------------------------------*/
    530503void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, void *arg)
    531504{
     
    535508        usb_hid_dev_t *hid_dev = arg;
    536509
    537         for (int i = 0; i < hid_dev->subdriver_count; ++i) {
     510        for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) {
    538511                if (hid_dev->subdrivers[i].poll_end != NULL) {
    539512                        hid_dev->subdrivers[i].poll_end(
     
    544517        hid_dev->running = false;
    545518}
    546 
    547 /*----------------------------------------------------------------------------*/
    548 
     519/*----------------------------------------------------------------------------*/
    549520void usb_hid_new_report(usb_hid_dev_t *hid_dev)
    550521{
    551522        ++hid_dev->report_nr;
    552523}
    553 
    554 /*----------------------------------------------------------------------------*/
    555 
     524/*----------------------------------------------------------------------------*/
    556525int usb_hid_report_number(const usb_hid_dev_t *hid_dev)
    557526{
    558527        return hid_dev->report_nr;
    559528}
    560 
    561 /*----------------------------------------------------------------------------*/
    562 
     529/*----------------------------------------------------------------------------*/
    563530void usb_hid_deinit(usb_hid_dev_t *hid_dev)
    564531{
     
    570537            hid_dev->subdrivers, hid_dev->subdriver_count);
    571538
    572         for (int i = 0; i < hid_dev->subdriver_count; ++i) {
     539        for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) {
    573540                if (hid_dev->subdrivers[i].deinit != NULL) {
    574541                        hid_dev->subdrivers[i].deinit(hid_dev,
  • uspace/drv/bus/usb/usbhid/usbhid.h

    rba72f2b r6843a9c  
    104104
    105105        /** Index of the polling pipe in usb_hid_endpoints array. */
    106         int poll_pipe_index;
     106        unsigned poll_pipe_index;
    107107
    108108        /** Subdrivers. */
     
    110110
    111111        /** Number of subdrivers. */
    112         int subdriver_count;
     112        unsigned subdriver_count;
    113113
    114114        /** Report descriptor. */
  • uspace/drv/bus/usb/usbhub/main.c

    rba72f2b r6843a9c  
    4747 * For more information see section 11.15.1 of USB 1.1 specification.
    4848 */
    49 static usb_endpoint_description_t hub_status_change_endpoint_description = {
     49static const usb_endpoint_description_t hub_status_change_endpoint_description =
     50{
    5051        .transfer_type = USB_TRANSFER_INTERRUPT,
    5152        .direction = USB_DIRECTION_IN,
     
    5657};
    5758
    58 /**
    59  * USB hub driver operations
    60  *
    61  * The most important one is device_add, which is set to usb_hub_device_add.
    62  */
    63 static usb_driver_ops_t usb_hub_driver_ops = {
     59/** USB hub driver operations. */
     60static const usb_driver_ops_t usb_hub_driver_ops = {
    6461        .device_add = usb_hub_device_add,
     62//      .device_rem = usb_hub_device_remove,
    6563        .device_gone = usb_hub_device_gone,
    6664};
     
    7270};
    7371/** Static usb hub driver information. */
    74 static usb_driver_t usb_hub_driver = {
     72static const usb_driver_t usb_hub_driver = {
    7573        .name = NAME,
    7674        .ops = &usb_hub_driver_ops,
    7775        .endpoints = usb_hub_endpoints
    7876};
    79 
    8077
    8178int main(int argc, char *argv[])
  • uspace/drv/bus/usb/usbhub/port.c

    rba72f2b r6843a9c  
    3535
    3636#include <bool.h>
    37 #include <devman.h>
    3837#include <errno.h>
    3938#include <str_error.h>
     
    288287        port->attached_device.fun = NULL;
    289288
    290         ret = usb_hc_connection_open(&hub->connection);
    291         if (ret == EOK) {
    292                 ret = usb_hc_unregister_device(&hub->connection,
    293                     port->attached_device.address);
    294                 if (ret != EOK) {
    295                         usb_log_warning("Failed to unregister address of the "
    296                             "removed device: %s.\n", str_error(ret));
    297                 }
    298                 ret = usb_hc_connection_close(&hub->connection);
    299                 if (ret != EOK) {
    300                         usb_log_warning("Failed to close hc connection %s.\n",
    301                             str_error(ret));
    302                 }
    303 
    304         } else {
    305                 usb_log_warning("Failed to open hc connection %s.\n",
    306                     str_error(ret));
     289        ret = usb_hub_unregister_device(&hub->usb_device->hc_conn,
     290            &port->attached_device);
     291        if (ret != EOK) {
     292                usb_log_warning("Failed to unregister address of the "
     293                    "removed device: %s.\n", str_error(ret));
    307294        }
    308295
     
    401388{
    402389        usb_hub_port_t *port = arg;
     390        assert(port);
    403391        const int rc =
    404392            usb_hub_port_set_feature(port, USB_HUB_FEATURE_PORT_RESET);
     
    437425
    438426        const int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev,
    439             &data->hub->connection, data->speed, enable_port_callback,
     427            &data->hub->usb_device->hc_conn, data->speed, enable_port_callback,
    440428            data->port, &new_address, NULL, NULL, &child_fun);
    441429
    442         if (rc != EOK) {
     430        if (rc == EOK) {
     431                fibril_mutex_lock(&data->port->mutex);
     432                data->port->attached_device.fun = child_fun;
     433                data->port->attached_device.address = new_address;
     434                fibril_mutex_unlock(&data->port->mutex);
     435
     436                usb_log_info("Detected new device on `%s' (port %zu), "
     437                    "address %d (handle %" PRIun ").\n",
     438                    data->hub->usb_device->ddf_dev->name,
     439                    data->port->port_number, new_address, child_fun->handle);
     440        } else {
    443441                usb_log_error("Failed registering device on port %zu: %s.\n",
    444442                    data->port->port_number, str_error(rc));
    445                 goto leave;
    446         }
    447 
    448         fibril_mutex_lock(&data->port->mutex);
    449         data->port->attached_device.fun = child_fun;
    450         data->port->attached_device.address = new_address;
    451         fibril_mutex_unlock(&data->port->mutex);
    452 
    453         usb_log_info("Detected new device on `%s' (port %zu), "
    454             "address %d (handle %" PRIun ").\n",
    455             data->hub->usb_device->ddf_dev->name, data->port->port_number,
    456             new_address, child_fun->handle);
    457 
    458 leave:
     443        }
     444
     445
    459446        fibril_mutex_lock(&data->hub->pending_ops_mutex);
    460447        assert(data->hub->pending_ops_count > 0);
  • uspace/drv/bus/usb/usbhub/port.h

    rba72f2b r6843a9c  
    4444/** Information about single port on a hub. */
    4545typedef struct {
     46        /* Port number as reported in descriptors. */
    4647        size_t port_number;
     48        /** Device communication pipe. */
    4749        usb_pipe_t *control_pipe;
    4850        /** Mutex needed not only by CV for checking port reset. */
  • uspace/drv/bus/usb/usbhub/usbhub.c

    rba72f2b r6843a9c  
    6868
    6969static int usb_set_first_configuration(usb_device_t *usb_device);
    70 static usb_hub_dev_t * usb_hub_dev_create(usb_device_t *usb_dev);
    7170static int usb_hub_process_hub_specific_info(usb_hub_dev_t *hub_dev);
    7271static void usb_hub_over_current(const usb_hub_dev_t *hub_dev,
     
    7574static void usb_hub_polling_terminated_callback(usb_device_t *device,
    7675    bool was_error, void *data);
    77 /**
    78  * Initialize hub device driver fibril
     76
     77/**
     78 * Initialize hub device driver structure.
    7979 *
    8080 * Creates hub representation and fibril that periodically checks hub's status.
    8181 * Hub representation is passed to the fibril.
     82 * @param usb_dev generic usb device information
     83 * @return error code
     84 */
     85int usb_hub_device_add(usb_device_t *usb_dev)
     86{
     87        assert(usb_dev);
     88        /* Create driver soft-state structure */
     89        usb_hub_dev_t *hub_dev =
     90            usb_device_data_alloc(usb_dev, sizeof(usb_hub_dev_t));
     91        if (hub_dev == NULL) {
     92                usb_log_error("Failed to create hub driver structure.\n");
     93                return ENOMEM;
     94        }
     95        hub_dev->usb_device = usb_dev;
     96        hub_dev->pending_ops_count = 0;
     97        hub_dev->running = false;
     98        fibril_mutex_initialize(&hub_dev->pending_ops_mutex);
     99        fibril_condvar_initialize(&hub_dev->pending_ops_cv);
     100
     101
     102        int opResult = usb_pipe_start_long_transfer(&usb_dev->ctrl_pipe);
     103        if (opResult != EOK) {
     104                usb_log_error("Failed to start long ctrl pipe transfer: %s\n",
     105                    str_error(opResult));
     106                return opResult;
     107        }
     108
     109        /* Set hub's first configuration. (There should be only one) */
     110        opResult = usb_set_first_configuration(usb_dev);
     111        if (opResult != EOK) {
     112                usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
     113                usb_log_error("Could not set hub configuration: %s\n",
     114                    str_error(opResult));
     115                return opResult;
     116        }
     117
     118        /* Get port count and create attached_devices. */
     119        opResult = usb_hub_process_hub_specific_info(hub_dev);
     120        if (opResult != EOK) {
     121                usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
     122                usb_log_error("Could process hub specific info, %s\n",
     123                    str_error(opResult));
     124                return opResult;
     125        }
     126
     127        /* Create hub control function. */
     128        usb_log_debug("Creating DDF function '" HUB_FNC_NAME "'.\n");
     129        hub_dev->hub_fun = ddf_fun_create(hub_dev->usb_device->ddf_dev,
     130            fun_exposed, HUB_FNC_NAME);
     131        if (hub_dev->hub_fun == NULL) {
     132                usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
     133                usb_log_error("Failed to create hub function.\n");
     134                return ENOMEM;
     135        }
     136
     137        /* Bind hub control function. */
     138        opResult = ddf_fun_bind(hub_dev->hub_fun);
     139        if (opResult != EOK) {
     140                usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
     141                usb_log_error("Failed to bind hub function: %s.\n",
     142                   str_error(opResult));
     143                ddf_fun_destroy(hub_dev->hub_fun);
     144                return opResult;
     145        }
     146
     147        /* Start hub operation. */
     148        opResult = usb_device_auto_poll(hub_dev->usb_device, 0,
     149            hub_port_changes_callback, ((hub_dev->port_count + 1 + 8) / 8),
     150            usb_hub_polling_terminated_callback, hub_dev);
     151        if (opResult != EOK) {
     152                usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
     153                /* Function is already bound */
     154                ddf_fun_unbind(hub_dev->hub_fun);
     155                ddf_fun_destroy(hub_dev->hub_fun);
     156                usb_log_error("Failed to create polling fibril: %s.\n",
     157                    str_error(opResult));
     158                return opResult;
     159        }
     160        hub_dev->running = true;
     161        usb_log_info("Controlling hub '%s' (%zu ports).\n",
     162            hub_dev->usb_device->ddf_dev->name, hub_dev->port_count);
     163
     164        usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
     165        return EOK;
     166}
     167/*----------------------------------------------------------------------------*/
     168/**
     169 * Turn off power to all ports.
     170 *
     171 * @param usb_dev generic usb device information
     172 * @return error code
     173 */
     174int usb_hub_device_remove(usb_device_t *usb_dev)
     175{
     176        return ENOTSUP;
     177}
     178/*----------------------------------------------------------------------------*/
     179/**
     180 * Remove all attached devices
    82181 * @param usb_dev generic usb device information
    83182 * @return error code
     
    121220}
    122221/*----------------------------------------------------------------------------*/
    123 /**
    124  * Initialize hub device driver fibril
    125  *
    126  * Creates hub representation and fibril that periodically checks hub's status.
    127  * Hub representation is passed to the fibril.
    128  * @param usb_dev generic usb device information
    129  * @return error code
    130  */
    131 int usb_hub_device_add(usb_device_t *usb_dev)
    132 {
    133         assert(usb_dev);
    134         /* Create driver soft-state structure */
    135         usb_hub_dev_t *hub_dev = usb_hub_dev_create(usb_dev);
    136         if (hub_dev == NULL) {
    137                 usb_log_error("Failed to create hun driver structure.\n");
    138                 return ENOMEM;
    139         }
    140 
    141         /* Create hc connection */
    142         usb_log_debug("Initializing USB wire abstraction.\n");
    143         int opResult = usb_hc_connection_initialize_from_device(
    144             &hub_dev->connection, hub_dev->usb_device->ddf_dev);
    145         if (opResult != EOK) {
    146                 usb_log_error("Could not initialize connection to device: %s\n",
    147                     str_error(opResult));
    148                 free(hub_dev);
    149                 return opResult;
    150         }
    151 
    152         /* Set hub's first configuration. (There should be only one) */
    153         opResult = usb_set_first_configuration(usb_dev);
    154         if (opResult != EOK) {
    155                 usb_log_error("Could not set hub configuration: %s\n",
    156                     str_error(opResult));
    157                 free(hub_dev);
    158                 return opResult;
    159         }
    160 
    161         /* Get port count and create attached_devices. */
    162         opResult = usb_hub_process_hub_specific_info(hub_dev);
    163         if (opResult != EOK) {
    164                 usb_log_error("Could process hub specific info, %s\n",
    165                     str_error(opResult));
    166                 free(hub_dev);
    167                 return opResult;
    168         }
    169 
    170         usb_log_debug("Creating DDF function '" HUB_FNC_NAME "'.\n");
    171         hub_dev->hub_fun = ddf_fun_create(hub_dev->usb_device->ddf_dev,
    172             fun_exposed, HUB_FNC_NAME);
    173         if (hub_dev->hub_fun == NULL) {
    174                 usb_log_error("Failed to create hub function.\n");
    175                 free(hub_dev);
    176                 return ENOMEM;
    177         }
    178 
    179         opResult = ddf_fun_bind(hub_dev->hub_fun);
    180         if (opResult != EOK) {
    181                 usb_log_error("Failed to bind hub function: %s.\n",
    182                    str_error(opResult));
    183                 free(hub_dev);
    184                 ddf_fun_destroy(hub_dev->hub_fun);
    185                 return opResult;
    186         }
    187 
    188         opResult = usb_device_auto_poll(hub_dev->usb_device, 0,
    189             hub_port_changes_callback, ((hub_dev->port_count + 1 + 8) / 8),
    190             usb_hub_polling_terminated_callback, hub_dev);
    191         if (opResult != EOK) {
    192                 /* Function is already bound */
    193                 ddf_fun_unbind(hub_dev->hub_fun);
    194                 ddf_fun_destroy(hub_dev->hub_fun);
    195                 free(hub_dev);
    196                 usb_log_error("Failed to create polling fibril: %s.\n",
    197                     str_error(opResult));
    198                 return opResult;
    199         }
    200         hub_dev->running = true;
    201         usb_log_info("Controlling hub '%s' (%zu ports).\n",
    202             hub_dev->usb_device->ddf_dev->name, hub_dev->port_count);
    203 
    204         return EOK;
    205 }
    206 /*----------------------------------------------------------------------------*/
    207222/** Callback for polling hub for changes.
    208223 *
     
    243258/*----------------------------------------------------------------------------*/
    244259/**
    245  * create usb_hub_dev_t structure
    246  *
    247  * Does only basic copying of known information into new structure.
    248  * @param usb_dev usb device structure
    249  * @return basic usb_hub_dev_t structure
    250  */
    251 static usb_hub_dev_t * usb_hub_dev_create(usb_device_t *usb_dev)
    252 {
    253         assert(usb_dev);
    254         usb_hub_dev_t *hub_dev =
    255             usb_device_data_alloc(usb_dev, sizeof(usb_hub_dev_t));
    256         if (!hub_dev)
    257             return NULL;
    258 
    259         hub_dev->usb_device = usb_dev;
    260         hub_dev->ports = NULL;
    261         hub_dev->port_count = 0;
    262         hub_dev->pending_ops_count = 0;
    263         hub_dev->running = false;
    264         fibril_mutex_initialize(&hub_dev->pending_ops_mutex);
    265         fibril_condvar_initialize(&hub_dev->pending_ops_cv);
    266 
    267         return hub_dev;
    268 }
    269 /*----------------------------------------------------------------------------*/
    270 /**
    271260 * Load hub-specific information into hub_dev structure and process if needed
    272261 *
     
    311300        }
    312301
    313         const bool is_power_switched =
     302        hub_dev->power_switched =
    314303            !(descriptor.characteristics & HUB_CHAR_NO_POWER_SWITCH_FLAG);
    315         if (is_power_switched) {
    316                 usb_log_debug("Hub power switched\n");
    317                 const bool per_port_power = descriptor.characteristics
    318                     & HUB_CHAR_POWER_PER_PORT_FLAG;
    319 
    320                 for (size_t port = 0; port < hub_dev->port_count; ++port) {
    321                         usb_log_debug("Powering port %zu.\n", port);
    322                         opResult = usb_hub_port_set_feature(
    323                             &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER);
    324                         if (opResult != EOK) {
    325                                 usb_log_error("Cannot power on port %zu: %s.\n",
    326                                     port, str_error(opResult));
    327                         } else {
    328                                 if (!per_port_power) {
    329                                         usb_log_debug(
    330                                             "Ganged power switching mode, "
    331                                             "one port is enough.\n");
    332                                         break;
    333                                 }
     304        hub_dev->per_port_power =
     305            descriptor.characteristics & HUB_CHAR_POWER_PER_PORT_FLAG;
     306
     307        if (!hub_dev->power_switched) {
     308                usb_log_info(
     309                   "Power switching not supported, ports always powered.\n");
     310                return EOK;
     311        }
     312
     313        usb_log_info("Hub port power switching enabled.\n");
     314
     315        for (size_t port = 0; port < hub_dev->port_count; ++port) {
     316                usb_log_debug("Powering port %zu.\n", port);
     317                const int ret = usb_hub_port_set_feature(
     318                    &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER);
     319
     320                if (ret != EOK) {
     321                        usb_log_error("Cannot power on port %zu: %s.\n",
     322                            hub_dev->ports[port].port_number, str_error(ret));
     323                } else {
     324                        if (!hub_dev->per_port_power) {
     325                                usb_log_debug("Ganged power switching, "
     326                                    "one port is enough.\n");
     327                                break;
    334328                        }
    335329                }
    336         } else {
    337                 usb_log_debug("Power not switched, ports always powered\n");
    338330        }
    339331        return EOK;
     
    402394                usb_log_warning("Detected hub over-current condition, "
    403395                    "all ports should be powered off.");
    404         } else {
    405                 /* Over-current condition is gone, it is safe to turn the
    406                  * ports on. */
    407                 for (size_t port = 0; port < hub_dev->port_count; ++port) {
    408                         const int opResult = usb_hub_port_set_feature(
    409                             &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER);
    410                         // TODO: consider power policy here
    411                         if (opResult != EOK) {
    412                                 usb_log_warning(
    413                                     "HUB OVER-CURRENT GONE: Cannot power on "
    414                                     "port %zu;  %s\n",
    415                                     port, str_error(opResult));
    416                         }
    417                 }
    418         }
    419         const int opResult = usb_request_clear_feature(
    420             &hub_dev->usb_device->ctrl_pipe, USB_REQUEST_TYPE_CLASS,
    421             USB_REQUEST_RECIPIENT_DEVICE,
    422             USB_HUB_FEATURE_C_HUB_LOCAL_POWER, 0);
    423         if (opResult != EOK) {
    424                 usb_log_error(
    425                     "Failed to clear hub over-current change flag: %s.\n",
    426                     str_error(opResult));
    427         }
     396                return;
     397        }
     398
     399        /* Ports are always powered. */
     400        if (!hub_dev->power_switched)
     401                return;
     402
     403        /* Over-current condition is gone, it is safe to turn the ports on. */
     404        for (size_t port = 0; port < hub_dev->port_count; ++port) {
     405                const int ret = usb_hub_port_set_feature(
     406                    &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER);
     407                if (ret != EOK) {
     408                        usb_log_warning("HUB OVER-CURRENT GONE: Cannot power on"
     409                            " port %zu: %s\n", hub_dev->ports[port].port_number,
     410                            str_error(ret));
     411                } else {
     412                        if (!hub_dev->per_port_power)
     413                                return;
     414                }
     415        }
     416
    428417}
    429418/*----------------------------------------------------------------------------*/
     
    461450        if (status & USB_HUB_STATUS_C_OVER_CURRENT) {
    462451                usb_hub_over_current(hub_dev, status);
     452                /* Ack change in hub OC flag */
     453                const int ret = usb_request_clear_feature(
     454                    &hub_dev->usb_device->ctrl_pipe, USB_REQUEST_TYPE_CLASS,
     455                    USB_REQUEST_RECIPIENT_DEVICE,
     456                    USB_HUB_FEATURE_C_HUB_OVER_CURRENT, 0);
     457                if (ret != EOK) {
     458                        usb_log_error("Failed to clear hub over-current "
     459                            "change flag: %s.\n", str_error(opResult));
     460                }
    463461        }
    464462
     
    477475                 * Just ACK the change.
    478476                 */
    479                 const int opResult = usb_request_clear_feature(
     477                const int ret = usb_request_clear_feature(
    480478                    control_pipe, USB_REQUEST_TYPE_CLASS,
    481479                    USB_REQUEST_RECIPIENT_DEVICE,
    482480                    USB_HUB_FEATURE_C_HUB_LOCAL_POWER, 0);
    483481                if (opResult != EOK) {
    484                         usb_log_error(
    485                             "Failed to clear hub power change flag: %s.\n",
    486                             str_error(opResult));
     482                        usb_log_error("Failed to clear hub power change "
     483                            "flag: %s.\n", str_error(ret));
    487484                }
    488485        }
  • uspace/drv/bus/usb/usbhub/usbhub.h

    rba72f2b r6843a9c  
    5757        /** Port structures, one for each port */
    5858        usb_hub_port_t *ports;
    59         /** Connection to hcd */
    60         usb_hc_connection_t connection;
    6159        /** Generic usb device data*/
    6260        usb_device_t *usb_device;
     
    7775        /** Status indicator */
    7876        bool running;
     77        /** Hub supports port power switching. */
     78        bool power_switched;
     79        /** Each port is switched individually. */
     80        bool per_port_power;
    7981};
    8082
    8183int usb_hub_device_add(usb_device_t *usb_dev);
     84int usb_hub_device_remove(usb_device_t *usb_dev);
    8285int usb_hub_device_gone(usb_device_t *usb_dev);
    8386
  • uspace/drv/bus/usb/usbmast/bo_trans.c

    rba72f2b r6843a9c  
    6767        int retval = EOK;
    6868        size_t act_size;
    69         usb_pipe_t *bulk_in_pipe = mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe;
    70         usb_pipe_t *bulk_out_pipe = mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe;
     69        usb_pipe_t *bulk_in_pipe = &mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe;
     70        usb_pipe_t *bulk_out_pipe = &mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe;
    7171        usb_direction_t ddir;
    7272        void *dbuf;
     
    118118                if (ddir == USB_DIRECTION_IN) {
    119119                        usb_pipe_clear_halt(&mfun->mdev->usb_dev->ctrl_pipe,
    120                             mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe);
     120                            &mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe);
    121121                } else {
    122122                        usb_pipe_clear_halt(&mfun->mdev->usb_dev->ctrl_pipe,
    123                             mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe);
     123                            &mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe);
    124124                }
    125125        } else if (rc != EOK) {
     
    216216        usb_massstor_reset(mdev);
    217217        usb_pipe_clear_halt(&mdev->usb_dev->ctrl_pipe,
    218             mdev->usb_dev->pipes[BULK_IN_EP].pipe);
     218            &mdev->usb_dev->pipes[BULK_IN_EP].pipe);
    219219        usb_pipe_clear_halt(&mdev->usb_dev->ctrl_pipe,
    220             mdev->usb_dev->pipes[BULK_OUT_EP].pipe);
     220            &mdev->usb_dev->pipes[BULK_OUT_EP].pipe);
    221221}
    222222
  • uspace/drv/bus/usb/usbmast/main.c

    rba72f2b r6843a9c  
    5555#define GET_BULK_OUT(dev) ((dev)->pipes[BULK_OUT_EP].pipe)
    5656
    57 static usb_endpoint_description_t bulk_in_ep = {
     57static const usb_endpoint_description_t bulk_in_ep = {
    5858        .transfer_type = USB_TRANSFER_BULK,
    5959        .direction = USB_DIRECTION_IN,
     
    6363        .flags = 0
    6464};
    65 static usb_endpoint_description_t bulk_out_ep = {
     65static const usb_endpoint_description_t bulk_out_ep = {
    6666        .transfer_type = USB_TRANSFER_BULK,
    6767        .direction = USB_DIRECTION_OUT,
     
    106106}
    107107
     108/** Callback when a device is about to be removed.
     109 *
     110 * @param dev Representation of USB device.
     111 * @return Error code.
     112 */
     113static int usbmast_device_remove(usb_device_t *dev)
     114{
     115        //TODO: flush buffers, or whatever.
     116        //TODO: remove device
     117        return ENOTSUP;
     118}
     119
    108120/** Callback when new device is attached and recognized as a mass storage.
    109121 *
    110  * @param dev Representation of a the USB device.
     122 * @param dev Representation of USB device.
    111123 * @return Error code.
    112124 */
     
    128140
    129141        usb_log_info("Initializing mass storage `%s'.\n", dev->ddf_dev->name);
    130         usb_log_debug(" Bulk in endpoint: %d [%zuB].\n",
    131             dev->pipes[BULK_IN_EP].pipe->endpoint_no,
    132             (size_t) dev->pipes[BULK_IN_EP].descriptor->max_packet_size);
     142        usb_log_debug("Bulk in endpoint: %d [%zuB].\n",
     143            dev->pipes[BULK_IN_EP].pipe.endpoint_no,
     144            dev->pipes[BULK_IN_EP].pipe.max_packet_size);
    133145        usb_log_debug("Bulk out endpoint: %d [%zuB].\n",
    134             dev->pipes[BULK_OUT_EP].pipe->endpoint_no,
    135             (size_t) dev->pipes[BULK_OUT_EP].descriptor->max_packet_size);
     146            dev->pipes[BULK_OUT_EP].pipe.endpoint_no,
     147            dev->pipes[BULK_OUT_EP].pipe.max_packet_size);
    136148
    137149        usb_log_debug("Get LUN count...\n");
     
    288300                return;
    289301        }
    290 
    291         comm_buf = as_get_mappable_page(comm_size);
    292         if (comm_buf == NULL) {
     302       
     303        (void) async_share_out_finalize(callid, &comm_buf);
     304        if (comm_buf == AS_MAP_FAILED) {
    293305                async_answer_0(callid, EHANGUP);
    294306                return;
    295307        }
    296 
    297         (void) async_share_out_finalize(callid, comm_buf);
    298 
     308       
    299309        mfun = (usbmast_fun_t *) ((ddf_fun_t *)arg)->driver_data;
    300310
     
    336346
    337347/** USB mass storage driver ops. */
    338 static usb_driver_ops_t usbmast_driver_ops = {
     348static const usb_driver_ops_t usbmast_driver_ops = {
    339349        .device_add = usbmast_device_add,
     350        .device_rem = usbmast_device_remove,
    340351        .device_gone = usbmast_device_gone,
    341352};
    342353
    343354/** USB mass storage driver. */
    344 static usb_driver_t usbmast_driver = {
     355static const usb_driver_t usbmast_driver = {
    345356        .name = NAME,
    346357        .ops = &usbmast_driver_ops,
  • uspace/drv/bus/usb/usbmid/explore.c

    rba72f2b r6843a9c  
    5454 * @return Interface @p interface_no is already present in the list.
    5555 */
    56 static bool interface_in_list(list_t *list, int interface_no)
     56static bool interface_in_list(const list_t *list, int interface_no)
    5757{
    5858        list_foreach(*list, l) {
    59                 usbmid_interface_t *iface
    60                     = list_get_instance(l, usbmid_interface_t, link);
     59                usbmid_interface_t *iface = usbmid_interface_from_link(l);
    6160                if (iface->interface_no == interface_no) {
    6261                        return true;
     
    8281        };
    8382
    84         usb_dp_parser_t parser = {
     83        static const usb_dp_parser_t parser = {
    8584                .nesting = usb_dp_standard_descriptor_nesting
    8685        };
    8786
    8887        const uint8_t *interface_ptr =
    89             usb_dp_get_nested_descriptor(&parser, &data, data.data);
    90         if (interface_ptr == NULL) {
    91                 return;
    92         }
    93 
    94         do {
    95                 if (interface_ptr[1] != USB_DESCTYPE_INTERFACE) {
    96                         goto next_descriptor;
    97                 }
    98 
    99                 usb_standard_interface_descriptor_t *interface
     88            usb_dp_get_nested_descriptor(&parser, &data, config_descriptor);
     89
     90        /* Walk all descriptors nested in the current configuration decriptor;
     91         * i.e. all interface descriptors. */
     92        for (;interface_ptr != NULL;
     93            interface_ptr = usb_dp_get_sibling_descriptor(
     94                &parser, &data, config_descriptor, interface_ptr))
     95        {
     96                /* The second byte is DESCTYPE byte in all desriptors. */
     97                if (interface_ptr[1] != USB_DESCTYPE_INTERFACE)
     98                        continue;
     99
     100                const usb_standard_interface_descriptor_t *interface
    100101                    = (usb_standard_interface_descriptor_t *) interface_ptr;
    101102
    102103                /* Skip alternate interfaces. */
    103                 if (!interface_in_list(list, interface->interface_number)) {
    104                         usbmid_interface_t *iface
    105                             = malloc(sizeof(usbmid_interface_t));
    106                         if (iface == NULL) {
    107                                 break;
    108                         }
    109                         link_initialize(&iface->link);
    110                         iface->fun = NULL;
    111                         iface->interface_no = interface->interface_number;
    112                         iface->interface = interface;
    113 
    114                         list_append(&iface->link, list);
    115                 }
    116 
    117                 /* TODO: add the alternatives and create match ids from them
    118                  * as well.
    119                  */
    120 
    121 next_descriptor:
    122                 interface_ptr = usb_dp_get_sibling_descriptor(&parser, &data,
    123                     data.data, interface_ptr);
    124 
    125         } while (interface_ptr != NULL);
    126 
     104                if (interface_in_list(list, interface->interface_number)) {
     105                        /* TODO: add the alternatives and create match ids
     106                         * for them. */
     107                        continue;
     108                }
     109                usbmid_interface_t *iface = malloc(sizeof(usbmid_interface_t));
     110                if (iface == NULL) {
     111                        //TODO: Do something about that failure.
     112                        break;
     113                }
     114
     115                link_initialize(&iface->link);
     116                iface->fun = NULL;
     117                iface->interface_no = interface->interface_number;
     118                iface->interface = interface;
     119
     120                list_append(&iface->link, list);
     121        }
    127122}
    128123
     
    139134        int rc;
    140135
    141         int dev_class = dev->descriptors.device.device_class;
     136        unsigned dev_class = dev->descriptors.device.device_class;
    142137        if (dev_class != USB_CLASS_USE_INTERFACE) {
    143138                usb_log_warning(
    144                     "Device class: %d (%s), but expected class 0.\n",
    145                     dev_class, usb_str_class(dev_class));
     139                    "Device class: %u (%s), but expected class %u.\n",
     140                    dev_class, usb_str_class(dev_class),
     141                    USB_CLASS_USE_INTERFACE);
    146142                usb_log_error("Not multi interface device, refusing.\n");
    147143                return false;
    148144        }
    149145
    150         /* Short cuts to save on typing ;-). */
     146        /* Shortcuts to save on typing ;-). */
    151147        const void *config_descriptor_raw = dev->descriptors.configuration;
    152148        size_t config_descriptor_size = dev->descriptors.configuration_size;
     
    163159        }
    164160
     161        /* Create driver soft-state. */
    165162        usb_mid_t *usb_mid = usb_device_data_alloc(dev, sizeof(usb_mid_t));
    166163        if (!usb_mid) {
     
    169166        }
    170167
    171         /* Create control function */
     168        /* Create control function. */
    172169        usb_mid->ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, "ctl");
    173170        if (usb_mid->ctl_fun == NULL) {
     
    175172                return false;
    176173        }
    177 
    178174        usb_mid->ctl_fun->ops = &mid_device_ops;
    179175
     176        /* Bind control function. */
    180177        rc = ddf_fun_bind(usb_mid->ctl_fun);
    181178        if (rc != EOK) {
     
    192189            &usb_mid->interface_list);
    193190
     191        /* Start child function for every interface. */
    194192        list_foreach(usb_mid->interface_list, link) {
    195                 usbmid_interface_t *iface = list_get_instance(link,
    196                     usbmid_interface_t, link);
     193                usbmid_interface_t *iface = usbmid_interface_from_link(link);
    197194
    198195                usb_log_info("Creating child for interface %d (%s).\n",
    199                     (int) iface->interface_no,
     196                    iface->interface_no,
    200197                    usb_str_class(iface->interface->interface_class));
    201198
  • uspace/drv/bus/usb/usbmid/main.c

    rba72f2b r6843a9c  
    5353        usb_log_info("Taking care of new MID `%s'.\n", dev->ddf_dev->name);
    5454
    55         usb_pipe_start_long_transfer(&dev->ctrl_pipe);
    56 
    57         bool accept = usbmid_explore_device(dev);
    58 
    59         usb_pipe_end_long_transfer(&dev->ctrl_pipe);
     55        const bool accept = usbmid_explore_device(dev);
    6056
    6157        if (!accept) {
     
    6561        return EOK;
    6662}
     63/*----------------------------------------------------------------------------*/
     64/** Callback when a MID device is about to be removed from the host.
     65 *
     66 * @param dev USB device representing the removed device.
     67 * @return Error code.
     68 */
     69static int usbmid_device_remove(usb_device_t *dev)
     70{
     71        assert(dev);
     72        usb_mid_t *usb_mid = dev->driver_data;
     73        assert(usb_mid);
    6774
     75        /* Remove ctl function */
     76        int ret = ddf_fun_unbind(usb_mid->ctl_fun);
     77        if (ret != EOK) {
     78                usb_log_error("Failed to unbind USB MID ctl function: %s.\n",
     79                    str_error(ret));
     80                return ret;
     81        }
     82        ddf_fun_destroy(usb_mid->ctl_fun);
     83
     84        /* Remove all children */
     85        while (!list_empty(&usb_mid->interface_list)) {
     86                link_t *item = list_first(&usb_mid->interface_list);
     87                list_remove(item);
     88
     89                usbmid_interface_t *iface = usbmid_interface_from_link(item);
     90
     91                usb_log_info("Removing child for interface %d (%s).\n",
     92                    iface->interface_no,
     93                    usb_str_class(iface->interface->interface_class));
     94
     95                /* Tell the child to go off-line. */
     96                int pret = ddf_fun_offline(iface->fun);
     97                if (pret != EOK) {
     98                        usb_log_warning("Failed to turn off child for interface"
     99                            " %d (%s): %s\n", iface->interface_no,
     100                            usb_str_class(iface->interface->interface_class),
     101                            str_error(pret));
     102                        ret = pret;
     103                }
     104
     105                /* Now remove the child. */
     106                pret = usbmid_interface_destroy(iface);
     107                if (pret != EOK) {
     108                        usb_log_error("Failed to destroy child for interface "
     109                            "%d (%s): %s\n", iface->interface_no,
     110                            usb_str_class(iface->interface->interface_class),
     111                            str_error(pret));
     112                        ret = pret;
     113                }
     114        }
     115        return ret;
     116}
     117/*----------------------------------------------------------------------------*/
     118/** Callback when a MID device was removed from the host.
     119 *
     120 * @param dev USB device representing the removed device.
     121 * @return Error code.
     122 */
    68123static int usbmid_device_gone(usb_device_t *dev)
    69124{
    70125        assert(dev);
     126        usb_mid_t *usb_mid = dev->driver_data;
     127        assert(usb_mid);
     128
    71129        usb_log_info("USB MID gone: `%s'.\n", dev->ddf_dev->name);
    72130
    73131        /* Remove ctl function */
    74         usb_mid_t *usb_mid = dev->driver_data;
    75132        int ret = ddf_fun_unbind(usb_mid->ctl_fun);
    76133        if (ret != EOK) {
     
    86143                list_remove(item);
    87144
    88                 usbmid_interface_t *iface = list_get_instance(item,
    89                     usbmid_interface_t, link);
     145                usbmid_interface_t *iface = usbmid_interface_from_link(item);
    90146
    91                 usb_log_info("Removing child for interface %d (%s).\n",
     147                usb_log_info("Child for interface %d (%s) gone.\n",
    92148                    iface->interface_no,
    93149                    usb_str_class(iface->interface->interface_class));
     
    107163
    108164/** USB MID driver ops. */
    109 static usb_driver_ops_t mid_driver_ops = {
     165static const usb_driver_ops_t mid_driver_ops = {
    110166        .device_add = usbmid_device_add,
     167        .device_rem = usbmid_device_remove,
    111168        .device_gone = usbmid_device_gone,
    112169};
    113170
    114171/** USB MID driver. */
    115 static usb_driver_t mid_driver = {
     172static const usb_driver_t mid_driver = {
    116173        .name = NAME,
    117174        .ops = &mid_driver_ops,
  • uspace/drv/bus/usb/usbmid/usbmid.c

    rba72f2b r6843a9c  
    4545
    4646/** Callback for DDF USB interface. */
    47 static int usb_iface_get_interface_impl(ddf_fun_t *fun, devman_handle_t handle,
    48     int *iface_no)
     47static int usb_iface_get_interface_impl(ddf_fun_t *fun, int *iface_no)
    4948{
    5049        assert(fun);
     
    6261/** DDF interface of the child - interface function. */
    6362static usb_iface_t child_usb_iface = {
    64         .get_hc_handle = usb_iface_get_hc_handle_hub_child_impl,
    65         .get_address = usb_iface_get_address_hub_impl,
    66         .get_interface = usb_iface_get_interface_impl
     63        .get_hc_handle = usb_iface_get_hc_handle_device_impl,
     64        .get_my_address = usb_iface_get_my_address_forward_impl,
     65        .get_my_interface = usb_iface_get_interface_impl,
    6766};
    6867
     
    110109         * class name something humanly understandable.
    111110         */
    112         rc = asprintf(&child_name, "%s%d",
     111        rc = asprintf(&child_name, "%s%hhu",
    113112            usb_str_class(interface_descriptor->interface_class),
    114             (int) interface_descriptor->interface_number);
     113            interface_descriptor->interface_number);
    115114        if (rc < 0) {
    116115                return ENOMEM;
     
    123122                return ENOMEM;
    124123        }
    125 
    126         iface->fun = child;
    127 
    128         child->driver_data = iface;
    129         child->ops = &child_device_ops;
    130124
    131125        rc = usb_device_create_match_ids_from_interface(device_descriptor,
     
    143137        }
    144138
     139        iface->fun = child;
     140        child->driver_data = iface;
     141        child->ops = &child_device_ops;
     142
    145143        return EOK;
    146144}
  • uspace/drv/bus/usb/usbmid/usbmid.h

    rba72f2b r6843a9c  
    5151        ddf_fun_t *fun;
    5252        /** Interface descriptor. */
    53         usb_standard_interface_descriptor_t *interface;
     53        const usb_standard_interface_descriptor_t *interface;
    5454        /** Interface number. */
    5555        int interface_no;
     
    7171int usbmid_interface_destroy(usbmid_interface_t *mid_iface);
    7272
     73static inline usbmid_interface_t * usbmid_interface_from_link(link_t *item)
     74{
     75        return list_get_instance(item, usbmid_interface_t, link);
     76}
     77
    7378#endif
    7479/**
  • uspace/drv/bus/usb/vhc/conndev.c

    rba72f2b r6843a9c  
    6969       
    7070        if (data_request == 0) {
    71                 async_wait_for(opening_request, NULL);
     71                async_forget(opening_request);
    7272                return;
    7373        }
  • uspace/drv/bus/usb/vhc/connhost.c

    rba72f2b r6843a9c  
    5757 * @return Error code.
    5858 */
    59 static int request_address(ddf_fun_t *fun, usb_speed_t speed,
    60     usb_address_t *address)
    61 {
    62         VHC_DATA(vhc, fun);
    63 
    64         usb_address_t addr = usb_device_manager_get_free_address(
    65             &vhc->dev_manager, USB_SPEED_HIGH);
    66         if (addr < 0) {
    67                 return addr;
    68         }
    69 
    70         if (address != NULL) {
    71                 *address = addr;
    72         }
    73 
    74         return EOK;
     59static int request_address(ddf_fun_t *fun, usb_address_t *address, bool strict,
     60    usb_speed_t speed)
     61{
     62        VHC_DATA(vhc, fun);
     63
     64        assert(address);
     65        return usb_device_manager_request_address(
     66            &vhc->dev_manager, address, strict, speed);
    7567}
    7668
     
    8880        usb_log_debug("Binding handle %" PRIun " to address %d.\n",
    8981            handle, address);
    90         usb_device_manager_bind(&vhc->dev_manager, address, handle);
     82        usb_device_manager_bind_address(&vhc->dev_manager, address, handle);
    9183
    9284        return EOK;
     
    10496{
    10597        VHC_DATA(vhc, fun);
    106         bool found =
    107             usb_device_manager_find_by_address(&vhc->dev_manager, address, handle);
    108         return found ? EOK : ENOENT;
     98        return usb_device_manager_get_info_by_address(
     99            &vhc->dev_manager, address, handle, NULL);
    109100}
    110101
     
    119110        VHC_DATA(vhc, fun);
    120111        usb_log_debug("Releasing address %d...\n", address);
    121         usb_device_manager_release(&vhc->dev_manager, address);
     112        usb_device_manager_release_address(&vhc->dev_manager, address);
    122113
    123114        return ENOTSUP;
     
    137128 */
    138129static int register_endpoint(ddf_fun_t *fun,
    139     usb_address_t address, usb_speed_t speed, usb_endpoint_t endpoint,
     130    usb_address_t address, usb_endpoint_t endpoint,
    140131    usb_transfer_type_t transfer_type, usb_direction_t direction,
    141132    size_t max_packet_size, unsigned int interval)
    142133{
    143         /* TODO: Use usb_endpoint_manager_add_ep */
    144         VHC_DATA(vhc, fun);
    145 
    146         endpoint_t *ep = endpoint_get(
    147             address, endpoint, direction, transfer_type, USB_SPEED_FULL, 1);
    148         if (ep == NULL) {
    149                 return ENOMEM;
    150         }
    151 
    152         int rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1);
    153         if (rc != EOK) {
    154                 endpoint_destroy(ep);
    155                 return rc;
    156         }
    157 
    158         return EOK;
     134        VHC_DATA(vhc, fun);
     135
     136        return usb_endpoint_manager_add_ep(&vhc->ep_manager,
     137            address, endpoint, direction, transfer_type, USB_SPEED_FULL, 1, 0,
     138            NULL, NULL);
     139
    159140}
    160141
     
    172153        VHC_DATA(vhc, fun);
    173154
    174         int rc = usb_endpoint_manager_unregister_ep(&vhc->ep_manager,
    175             address, endpoint, direction);
     155        int rc = usb_endpoint_manager_remove_ep(&vhc->ep_manager,
     156            address, endpoint, direction, NULL, NULL);
    176157
    177158        return rc;
     
    414395        VHC_DATA(vhc, fun);
    415396
    416         endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager,
    417             target.address, target.endpoint, USB_DIRECTION_IN, NULL);
     397        endpoint_t *ep = usb_endpoint_manager_find_ep(&vhc->ep_manager,
     398            target.address, target.endpoint, USB_DIRECTION_IN);
    418399        if (ep == NULL) {
    419400                return ENOENT;
     
    456437        VHC_DATA(vhc, fun);
    457438
    458         endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager,
    459             target.address, target.endpoint, USB_DIRECTION_OUT, NULL);
     439        endpoint_t *ep = usb_endpoint_manager_find_ep(&vhc->ep_manager,
     440            target.address, target.endpoint, USB_DIRECTION_OUT);
    460441        if (ep == NULL) {
    461442                return ENOENT;
     
    490471}
    491472
    492 static int tell_address(ddf_fun_t *fun, devman_handle_t handle,
    493     usb_address_t *address)
     473static int tell_address(ddf_fun_t *fun, usb_address_t *address)
    494474{
    495475        UNSUPPORTED("tell_address");
     
    508488}
    509489
    510 static int tell_address_rh(ddf_fun_t *root_hub_fun, devman_handle_t handle,
    511     usb_address_t *address)
     490static int tell_address_rh(ddf_fun_t *root_hub_fun, usb_address_t *address)
    512491{
    513492        VHC_DATA(vhc, root_hub_fun);
    514493
    515         if (handle == 0) {
    516                 handle = root_hub_fun->handle;
    517         }
     494        devman_handle_t handle = root_hub_fun->handle;
    518495
    519496        usb_log_debug("tell_address_rh(handle=%" PRIun ")\n", handle);
    520         usb_address_t addr = usb_device_manager_find(&vhc->dev_manager, handle);
     497        const usb_address_t addr =
     498            usb_device_manager_find_address(&vhc->dev_manager, handle);
    521499        if (addr < 0) {
    522500                return addr;
     
    530508        .request_address = request_address,
    531509        .bind_address = bind_address,
    532         .find_by_address = find_by_address,
     510        .get_handle = find_by_address,
    533511        .release_address = release_address,
    534512
     
    542520usb_iface_t vhc_usb_iface = {
    543521        .get_hc_handle = usb_iface_get_hc_handle_hc_impl,
    544         .get_address = tell_address
     522        .get_my_address = tell_address
    545523};
    546524
    547525usb_iface_t rh_usb_iface = {
    548526        .get_hc_handle = usb_iface_get_hc_handle_rh_impl,
    549         .get_address = tell_address_rh
     527        .get_my_address = tell_address_rh
    550528};
    551529
  • uspace/drv/bus/usb/vhc/hub.c

    rba72f2b r6843a9c  
    107107
    108108        usb_hc_connection_t hc_conn;
    109         rc = usb_hc_connection_initialize(&hc_conn, hc_dev->handle);
    110         assert(rc == EOK);
     109        usb_hc_connection_initialize(&hc_conn, hc_dev->handle);
    111110
    112111        rc = usb_hc_connection_open(&hc_conn);
  • uspace/drv/bus/usb/vhc/main.c

    rba72f2b r6843a9c  
    5858};
    5959
    60 static int vhc_add_device(ddf_dev_t *dev)
     60static int vhc_dev_add(ddf_dev_t *dev)
    6161{
    6262        static int vhc_count = 0;
     
    8080                return rc;
    8181        }
    82         usb_device_manager_init(&data->dev_manager);
     82        usb_device_manager_init(&data->dev_manager, USB_SPEED_MAX);
    8383
    8484        ddf_fun_t *hc = ddf_fun_create(dev, fun_exposed, "hc");
     
    131131
    132132static driver_ops_t vhc_driver_ops = {
    133         .add_device = vhc_add_device,
     133        .dev_add = vhc_dev_add,
    134134};
    135135
  • uspace/drv/bus/usb/vhc/vhc.ma

    rba72f2b r6843a9c  
    1110 usb&hc=vhc
    2 
Note: See TracChangeset for help on using the changeset viewer.