Changeset 54464f6a in mainline for uspace/drv/bus


Ignore:
Timestamp:
2011-11-11T19:48:33Z (14 years ago)
Author:
Maurizio Lombardi <m.lombardi85@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
50a01a9
Parents:
c2e50d7 (diff), 747ef72 (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

Location:
uspace/drv/bus
Files:
30 edited

Legend:

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

    rc2e50d7 r54464f6a  
    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{
     
    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                       
     
    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

    rc2e50d7 r54464f6a  
    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/hc_iface.c

    rc2e50d7 r54464f6a  
    5656 * @return Error code.
    5757 */
    58 static int request_address(ddf_fun_t *fun, usb_speed_t speed,
    59     usb_address_t *address)
     58static int request_address(ddf_fun_t *fun, usb_address_t *address, bool strict,
     59    usb_speed_t speed)
    6060{
    6161        UNSUPPORTED("request_address");
     
    120120 */
    121121static int register_endpoint(ddf_fun_t *fun,
    122     usb_address_t address, usb_speed_t speed, usb_endpoint_t endpoint,
     122    usb_address_t address, usb_endpoint_t endpoint,
    123123    usb_transfer_type_t transfer_type, usb_direction_t direction,
    124124    size_t max_packet_size, unsigned int interval)
  • uspace/drv/bus/usb/ohci/hc.c

    rc2e50d7 r54464f6a  
    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        }
     139        usb_device_manager_bind_address(&instance->generic.dev_manager,
     140            instance->rh.address, hub_fun->handle);
    140141
    141142#define CHECK_RET_UNREG_RETURN(ret, message...) \
     
    143144        usb_log_error(message); \
    144145        usb_endpoint_manager_remove_ep( \
    145             &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH, \
    146             NULL, NULL);\
    147         usb_device_manager_release( \
    148             &instance->generic.dev_manager, hub_address); \
     146            &instance->generic.ep_manager, instance->rh.address, 0, \
     147            USB_DIRECTION_BOTH, NULL, NULL); \
     148        usb_device_manager_release_address( \
     149            &instance->generic.dev_manager, instance->rh.address); \
    149150        return ret; \
    150151} else (void)0
    151         int ret = usb_endpoint_manager_add_ep(
    152             &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH,
    153             USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64, 0, NULL, NULL);
     152        ret = usb_endpoint_manager_add_ep(
     153            &instance->generic.ep_manager, instance->rh.address, 0,
     154            USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64,
     155            0, NULL, NULL);
    154156        CHECK_RET_UNREG_RETURN(ret,
    155157            "Failed to register root hub control endpoint: %s.\n",
     
    193195        list_initialize(&instance->pending_batches);
    194196
    195         hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,
    196             bandwidth_count_usb11);
     197        hcd_init(&instance->generic, USB_SPEED_FULL,
     198            BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11);
    197199        instance->generic.private_data = instance;
    198200        instance->generic.schedule = hc_schedule;
  • uspace/drv/bus/usb/ohci/ohci.c

    rc2e50d7 r54464f6a  
    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 =
    92             usb_device_manager_find_address(manager, handle);
    93         if (addr < 0) {
    94                 return addr;
    95         }
    9687
    9788        if (address != NULL) {
    98                 *address = addr;
     89                *address = dev_to_ohci(fun->dev)->hc.rh.address;
    9990        }
    10091
     
    10899 * @return Error code.
    109100 */
    110 static int usb_iface_get_hc_handle(
     101static int rh_get_hc_handle(
    111102    ddf_fun_t *fun, devman_handle_t *handle)
    112103{
     
    122113/** Root hub USB interface */
    123114static usb_iface_t usb_iface = {
    124         .get_hc_handle = usb_iface_get_hc_handle,
    125         .get_address = usb_iface_get_address
     115        .get_hc_handle = rh_get_hc_handle,
     116        .get_my_address = rh_get_my_address,
    126117};
    127118/*----------------------------------------------------------------------------*/
  • uspace/drv/bus/usb/uhci/hc.c

    rc2e50d7 r54464f6a  
    199199#undef CHECK_RET_RETURN
    200200
    201         hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,
    202             bandwidth_count_usb11);
     201        hcd_init(&instance->generic, USB_SPEED_FULL,
     202            BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11);
    203203
    204204        instance->generic.private_data = instance;
  • uspace/drv/bus/usb/uhci/uhci.c

    rc2e50d7 r54464f6a  
    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 =
    104             usb_device_manager_find_address(manager, handle);
    105 
    106         if (addr < 0) {
    107                 return addr;
    108         }
    109 
    110         if (address != NULL) {
    111                 *address = addr;
    112         }
    113 
    114         return EOK;
    115 }
    116 /*----------------------------------------------------------------------------*/
    11791/** Gets handle of the respective hc.
    11892 *
     
    135109static usb_iface_t usb_iface = {
    136110        .get_hc_handle = usb_iface_get_hc_handle,
    137         .get_address = usb_iface_get_address
    138111};
    139112/*----------------------------------------------------------------------------*/
  • uspace/drv/bus/usb/usbflbk/main.c

    rc2e50d7 r54464f6a  
    7474}
    7575
    76 /** Callback when new device is about to be removed.
    77  *
    78  * @param dev Representation of a generic DDF device.
    79  * @return Error code.
    80  */
    81 static int usbfallback_device_remove(usb_device_t *dev)
    82 {
    83         return EOK;
    84 }
    85 
    8676/** Callback when new device is removed and recognized as gone by DDF.
    8777 *
     
    10797static const usb_driver_ops_t usbfallback_driver_ops = {
    10898        .device_add = usbfallback_device_add,
    109         .device_rem = usbfallback_device_remove,
     99        .device_rem = usbfallback_device_gone,
    110100        .device_gone = usbfallback_device_gone,
    111101};
  • uspace/drv/bus/usb/usbhid/generic/hiddev.c

    rc2e50d7 r54464f6a  
    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

    rc2e50d7 r54464f6a  
    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

    rc2e50d7 r54464f6a  
    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

    rc2e50d7 r54464f6a  
    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

    rc2e50d7 r54464f6a  
    4949
    5050/**
    51  * Function for adding a new device of type USB/HID/keyboard.
     51 * Callback for passing a new device to the driver.
    5252 *
    53  * This functions initializes required structures from the device's descriptors
    54  * and starts new fibril for polling the keyboard for events and another one for
    55  * handling auto-repeat of keys.
     53 * @note Currently, only boot-protocol keyboards are supported by this driver.
    5654 *
    57  * During initialization, the keyboard is switched into boot protocol, the idle
    58  * rate is set to 0 (infinity), resulting in the keyboard only reporting event
    59  * when a key is pressed or released. Finally, the LED lights are turned on
    60  * according to the default setup of lock keys.
    61  *
    62  * @note By default, the keyboards is initialized with Num Lock turned on and
    63  *       other locks turned off.
    64  * @note Currently supports only boot-protocol keyboards.
    65  *
    66  * @param dev Device to add.
     55 * @param dev Structure representing the new device.
    6756 * @return Error code.
    6857 */
    69 static int usb_hid_try_add_device(usb_device_t *dev)
     58static int usb_hid_device_add(usb_device_t *dev)
    7059{
    71         assert(dev != NULL);
     60        usb_log_debug("%s\n", __FUNCTION__);
    7261
    73         /* Initialize device (get and process descriptors, get address, etc.) */
    74         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        }
    7566
     67        if (dev->interface_no < 0) {
     68                usb_log_error("Failed to add HID device: endpoints not found."
     69                    "\n");
     70                return ENOTSUP;
     71        }
    7672        usb_hid_dev_t *hid_dev =
    7773            usb_device_data_alloc(dev, sizeof(usb_hid_dev_t));
    7874        if (hid_dev == NULL) {
    79                 usb_log_error("Error while creating USB/HID device "
    80                     "structure.\n");
     75                usb_log_error("Failed to create USB/HID device structure.\n");
    8176                return ENOMEM;
    8277        }
    8378
    8479        int rc = usb_hid_init(hid_dev, dev);
    85 
    8680        if (rc != EOK) {
    8781                usb_log_error("Failed to initialize USB/HID device.\n");
     
    9286        usb_log_debug("USB/HID device structure initialized.\n");
    9387
    94         /*
    95          * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da
    96          *    do nej.
    97          * 2) do tych ops do .interfaces[DEV_IFACE_USBHID (asi)] priradi
    98          *    vyplnenu strukturu usbhid_iface_t.
    99          * 3) klientska aplikacia - musi si rucne vytvorit telefon
    100          *    (devman_device_connect() - cesta k zariadeniu (/hw/pci0/...) az
    101          *    k tej fcii.
    102          *    pouzit usb/classes/hid/iface.h - prvy int je telefon
    103          */
    104 
    10588        /* Start automated polling function.
    10689         * This will create a separate fibril that will query the device
    107          * for the data continuously
    108          */
     90         * for the data continuously. */
    10991       rc = usb_device_auto_poll(dev,
    11092           /* Index of the polling pipe. */
     
    11395           usb_hid_polling_callback,
    11496           /* How much data to request. */
    115            dev->pipes[hid_dev->poll_pipe_index].pipe->max_packet_size,
     97           dev->pipes[hid_dev->poll_pipe_index].pipe.max_packet_size,
    11698           /* Callback when the polling ends. */
    11799           usb_hid_polling_ended_callback,
     
    126108        }
    127109        hid_dev->running = true;
    128 
    129         /*
    130          * Hurrah, device is initialized.
    131          */
    132         return EOK;
    133 }
    134 /*----------------------------------------------------------------------------*/
    135 /**
    136  * Callback for passing a new device to the driver.
    137  *
    138  * @note Currently, only boot-protocol keyboards are supported by this driver.
    139  *
    140  * @param dev Structure representing the new device.
    141  * @return Error code.
    142  */
    143 static int usb_hid_device_add(usb_device_t *dev)
    144 {
    145         usb_log_debug("usb_hid_device_add()\n");
    146 
    147         if (dev == NULL) {
    148                 usb_log_warning("Wrong parameter given for add_device().\n");
    149                 return EINVAL;
    150         }
    151 
    152         if (dev->interface_no < 0) {
    153                 usb_log_warning("Device is not a supported HID device.\n");
    154                 usb_log_error("Failed to add HID device: endpoints not found."
    155                     "\n");
    156                 return ENOTSUP;
    157         }
    158 
    159         int rc = usb_hid_try_add_device(dev);
    160 
    161         if (rc != EOK) {
    162                 usb_log_warning("Device is not a supported HID device.\n");
    163                 usb_log_error("Failed to add HID device: %s.\n",
    164                     str_error(rc));
    165                 return rc;
    166         }
    167110
    168111        usb_log_info("HID device `%s' ready to use.\n", dev->ddf_dev->name);
     
    179122static int usb_hid_device_rem(usb_device_t *dev)
    180123{
    181         return EOK;
     124        // TODO: Stop device polling
     125        // TODO: Call deinit (stops autorepeat too)
     126        return ENOTSUP;
    182127}
    183128/*----------------------------------------------------------------------------*/
     
    190135static int usb_hid_device_gone(usb_device_t *dev)
    191136{
     137        assert(dev);
     138        assert(dev->driver_data);
    192139        usb_hid_dev_t *hid_dev = dev->driver_data;
    193         unsigned tries = 10;
    194         while (hid_dev->running) {
     140        unsigned tries = 100;
     141        /* Wait for fail. */
     142        while (hid_dev->running && tries--) {
    195143                async_usleep(100000);
    196                 if (!tries--) {
    197                         usb_log_error("Can't remove hub, still running.\n");
    198                         return EBUSY;
    199                 }
     144        }
     145        if (hid_dev->running) {
     146                usb_log_error("Can't remove hid, still running.\n");
     147                return EBUSY;
    200148        }
    201149
    202         assert(!hid_dev->running);
    203150        usb_hid_deinit(hid_dev);
    204151        usb_log_debug2("%s destruction complete.\n", dev->ddf_dev->name);
  • uspace/drv/bus/usb/usbhid/mouse/mousedev.c

    rc2e50d7 r54464f6a  
    5555#define ARROWS_PER_SINGLE_WHEEL 3
    5656
    57 #define NAME  "mouse"
     57#define NAME "mouse"
    5858
    5959/*----------------------------------------------------------------------------*/
     
    7777
    7878/*----------------------------------------------------------------------------*/
    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] = {
     79static const uint8_t USB_MOUSE_BOOT_REPORT_DESCRIPTOR[] = {
    8680        0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    8781        0x09, 0x02,                    // USAGE (Mouse)
     
    123117    ipc_callid_t icallid, ipc_call_t *icall)
    124118{
    125         usb_mouse_t *mouse_dev = (usb_mouse_t *) fun->driver_data;
     119        usb_mouse_t *mouse_dev = fun->driver_data;
    126120
    127121        if (mouse_dev == NULL) {
    128                 usb_log_debug("default_connection_handler: Missing "
    129                     "parameters.\n");
     122                usb_log_debug("%s: Missing parameters.\n", __FUNCTION__);
    130123                async_answer_0(icallid, EINVAL);
    131124                return;
    132125        }
    133126
    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) ?
     127        usb_log_debug("%s: fun->name: %s\n", __FUNCTION__, fun->name);
     128        usb_log_debug("%s: mouse_sess: %p, wheel_sess: %p\n",
     129            __FUNCTION__, mouse_dev->mouse_sess, mouse_dev->wheel_sess);
     130
     131        async_sess_t **sess_ptr = (fun == mouse_dev->mouse_fun) ?
    141132            &mouse_dev->mouse_sess : &mouse_dev->wheel_sess;
    142133
     
    146137                if (*sess_ptr == NULL) {
    147138                        *sess_ptr = sess;
    148                         usb_log_debug("Console session to mouse set ok (%p).\n",
    149                             sess);
     139                        usb_log_debug("Console session to %s set ok (%p).\n",
     140                            fun->name, sess);
    150141                        async_answer_0(icallid, EOK);
    151142                } else {
    152                         usb_log_debug("default_connection_handler: Console "
    153                             "session to mouse already set.\n");
     143                        usb_log_error("Console session to %s already set.\n",
     144                            fun->name);
    154145                        async_answer_0(icallid, ELIMIT);
    155146                }
    156147        } else {
    157                 usb_log_debug("default_connection_handler: Invalid function.\n");
     148                usb_log_debug("%s: Invalid function.\n", __FUNCTION__);
    158149                async_answer_0(icallid, EINVAL);
    159         }
    160 }
    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);
    202150        }
    203151}
     
    215163        }
    216164
    217         int count = ((wheel < 0) ? -wheel : wheel) * ARROWS_PER_SINGLE_WHEEL;
    218         int i;
    219 
    220         for (i = 0; i < count; i++) {
     165        const unsigned count =
     166            ((wheel < 0) ? -wheel : wheel) * ARROWS_PER_SINGLE_WHEEL;
     167        for (unsigned i = 0; i < count; i++) {
    221168                /* Send arrow press and release. */
    222169                usb_log_debug2("Sending key %d to the console\n", key);
     
    267214        }
    268215
    269         int shift_x = get_mouse_axis_move_value(hid_dev->report_id,
     216        const int shift_x = get_mouse_axis_move_value(hid_dev->report_id,
    270217            &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_X);
    271         int shift_y = get_mouse_axis_move_value(hid_dev->report_id,
     218        const int shift_y = get_mouse_axis_move_value(hid_dev->report_id,
    272219            &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_Y);
    273         int wheel = get_mouse_axis_move_value(hid_dev->report_id,
     220        const int wheel = get_mouse_axis_move_value(hid_dev->report_id,
    274221            &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL);
    275222
     
    277224                async_exch_t *exch =
    278225                    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);
     226                if (exch != NULL) {
     227                        async_req_2_0(exch, MOUSEEV_MOVE_EVENT, shift_x, shift_y);
     228                        async_exchange_end(exch);
     229                }
    281230        }
    282231
     
    284233                usb_mouse_send_wheel(mouse_dev, wheel);
    285234
    286         /*
    287          * Buttons
    288          */
     235        /* Buttons */
    289236        usb_hid_report_path_t *path = usb_hid_report_path();
    290         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_BUTTON, 0);
     237        if (path == NULL) {
     238                usb_log_warning("Failed to create USB HID report path.\n");
     239                return true;
     240        }
     241        int ret =
     242           usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_BUTTON, 0);
     243        if (ret != EOK) {
     244                usb_hid_report_path_free(path);
     245                usb_log_warning("Failed to add buttons to report path.\n");
     246                return true;
     247        }
    291248        usb_hid_report_path_set_report_id(path, hid_dev->report_id);
    292249
     
    298255                usb_log_debug2(NAME " VALUE(%X) USAGE(%X)\n", field->value,
    299256                    field->usage);
    300                
    301                 if (mouse_dev->buttons[field->usage - field->usage_minimum] == 0
    302                     && field->value != 0) {
     257                assert(field->usage > field->usage_minimum);
     258                const unsigned index = field->usage - field->usage_minimum;
     259                assert(index < mouse_dev->buttons_count);
     260
     261                if (mouse_dev->buttons[index] == 0 && field->value != 0) {
    303262                        async_exch_t *exch =
    304263                            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) {
     264                        if (exch != NULL) {
     265                                async_req_2_0(exch, MOUSEEV_BUTTON_EVENT,
     266                                    field->usage, 1);
     267                                async_exchange_end(exch);
     268                                mouse_dev->buttons[index] = field->value;
     269                        }
     270
     271                } else if (mouse_dev->buttons[index] != 0 && field->value == 0) {
    312272                        async_exch_t *exch =
    313273                            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;
     274                        if (exch != NULL) {
     275                                async_req_2_0(exch, MOUSEEV_BUTTON_EVENT,
     276                                    field->usage, 0);
     277                                async_exchange_end(exch);
     278                                mouse_dev->buttons[index] = field->value;
     279                        }
    319280                }
    320281
     
    329290        return true;
    330291}
    331 
    332 /*----------------------------------------------------------------------------*/
    333 
     292/*----------------------------------------------------------------------------*/
     293#define FUN_UNBIND_DESTROY(fun) \
     294if (fun) { \
     295        if (ddf_fun_unbind((fun)) == EOK) { \
     296                (fun)->driver_data = NULL; \
     297                ddf_fun_destroy((fun)); \
     298        } else { \
     299                usb_log_error("Could not unbind function `%s', it " \
     300                    "will not be destroyed.\n", (fun)->name); \
     301        } \
     302} else (void)0
     303/*----------------------------------------------------------------------------*/
    334304static int usb_mouse_create_function(usb_hid_dev_t *hid_dev, usb_mouse_t *mouse)
    335305{
     
    339309        /* Create the exposed function. */
    340310        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, 
     311        ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    342312            HID_MOUSE_FUN_NAME);
    343313        if (fun == NULL) {
    344                 usb_log_error("Could not create DDF function node.\n");
     314                usb_log_error("Could not create DDF function node `%s'.\n",
     315                    HID_MOUSE_FUN_NAME);
    345316                return ENOMEM;
    346317        }
     
    351322        int rc = ddf_fun_bind(fun);
    352323        if (rc != EOK) {
    353                 usb_log_error("Could not bind DDF function: %s.\n",
    354                     str_error(rc));
    355                 return rc;
    356         }
    357 
    358         usb_log_debug("Adding DDF function to category %s...\n",
    359             HID_MOUSE_CATEGORY);
     324                usb_log_error("Could not bind DDF function `%s': %s.\n",
     325                    fun->name, str_error(rc));
     326                fun->driver_data = NULL;
     327                ddf_fun_destroy(fun);
     328                return rc;
     329        }
     330
     331        usb_log_debug("Adding DDF function `%s' to category %s...\n",
     332            fun->name, HID_MOUSE_CATEGORY);
    360333        rc = ddf_fun_add_to_category(fun, HID_MOUSE_CATEGORY);
    361334        if (rc != EOK) {
     
    363336                    "Could not add DDF function to category %s: %s.\n",
    364337                    HID_MOUSE_CATEGORY, str_error(rc));
     338                FUN_UNBIND_DESTROY(fun);
    365339                return rc;
    366340        }
     
    370344         * Special function for acting as keyboard (wheel)
    371345         */
    372         usb_log_debug("Creating DDF function %s...\n", 
     346        usb_log_debug("Creating DDF function %s...\n",
    373347                      HID_MOUSE_WHEEL_FUN_NAME);
    374         fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
     348        fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    375349            HID_MOUSE_WHEEL_FUN_NAME);
    376350        if (fun == NULL) {
    377                 usb_log_error("Could not create DDF function node.\n");
     351                usb_log_error("Could not create DDF function node `%s'.\n",
     352                    HID_MOUSE_WHEEL_FUN_NAME);
     353                FUN_UNBIND_DESTROY(mouse->mouse_fun);
     354                mouse->mouse_fun = NULL;
    378355                return ENOMEM;
    379356        }
     
    388365        rc = ddf_fun_bind(fun);
    389366        if (rc != EOK) {
    390                 usb_log_error("Could not bind DDF function: %s.\n",
    391                     str_error(rc));
     367                usb_log_error("Could not bind DDF function `%s': %s.\n",
     368                    fun->name, str_error(rc));
     369                FUN_UNBIND_DESTROY(mouse->mouse_fun);
     370                mouse->mouse_fun = NULL;
     371
     372                fun->driver_data = NULL;
     373                ddf_fun_destroy(fun);
    392374                return rc;
    393375        }
     
    400382                    "Could not add DDF function to category %s: %s.\n",
    401383                    HID_MOUSE_WHEEL_CATEGORY, str_error(rc));
     384
     385                FUN_UNBIND_DESTROY(mouse->mouse_fun);
     386                mouse->mouse_fun = NULL;
     387                FUN_UNBIND_DESTROY(fun);
    402388                return rc;
    403389        }
     
    448434        return highest_button;
    449435}
    450 
    451 /*----------------------------------------------------------------------------*/
    452 
     436/*----------------------------------------------------------------------------*/
    453437int usb_mouse_init(usb_hid_dev_t *hid_dev, void **data)
    454438{
     
    461445        }
    462446
    463         usb_mouse_t *mouse_dev = usb_mouse_new();
     447        usb_mouse_t *mouse_dev = calloc(1, sizeof(usb_mouse_t));
    464448        if (mouse_dev == NULL) {
    465449                usb_log_error("Error while creating USB/HID Mouse device "
     
    484468        }
    485469
    486 
    487         // save the Mouse device structure into the HID device structure
    488         *data = mouse_dev;
    489 
    490470        // set handler for incoming calls
    491471        mouse_dev->ops.default_handler = default_connection_handler;
    492472
    493473        // TODO: how to know if the device supports the request???
    494         usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 
     474        usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
    495475            hid_dev->usb_dev->interface_no, IDLE_RATE);
    496476
    497477        int rc = usb_mouse_create_function(hid_dev, mouse_dev);
    498478        if (rc != EOK) {
    499                 usb_mouse_destroy(mouse_dev);
    500                 return rc;
    501         }
     479                free(mouse_dev->buttons);
     480                free(mouse_dev);
     481                return rc;
     482        }
     483
     484        /* Save the Mouse device structure into the HID device structure. */
     485        *data = mouse_dev;
    502486
    503487        return EOK;
    504488}
    505 
    506 /*----------------------------------------------------------------------------*/
    507 
     489/*----------------------------------------------------------------------------*/
    508490bool usb_mouse_polling_callback(usb_hid_dev_t *hid_dev, void *data)
    509491{
    510492        if (hid_dev == NULL || data == NULL) {
    511                 usb_log_error("Missing argument to the mouse polling callback."
    512                     "\n");
     493                usb_log_error(
     494                    "Missing argument to the mouse polling callback.\n");
    513495                return false;
    514496        }
    515497
    516         usb_mouse_t *mouse_dev = (usb_mouse_t *)data;
    517                
     498        usb_mouse_t *mouse_dev = data;
     499
    518500        return usb_mouse_process_report(hid_dev, mouse_dev);
    519501}
    520 
    521 /*----------------------------------------------------------------------------*/
    522 
     502/*----------------------------------------------------------------------------*/
    523503void usb_mouse_deinit(usb_hid_dev_t *hid_dev, void *data)
    524504{
    525         if (data != NULL) {
    526                 usb_mouse_destroy(data);
    527         }
    528 }
    529 
    530 /*----------------------------------------------------------------------------*/
    531 
     505        if (data == NULL)
     506                return;
     507
     508        usb_mouse_t *mouse_dev = data;
     509
     510        /* Hangup session to the console */
     511        if (mouse_dev->mouse_sess != NULL) {
     512                const int ret = async_hangup(mouse_dev->mouse_sess);
     513                if (ret != EOK)
     514                        usb_log_warning("Failed to hang up mouse session: "
     515                            "%p, %s.\n", mouse_dev->mouse_sess, str_error(ret));
     516        }
     517
     518        if (mouse_dev->wheel_sess != NULL) {
     519                const int ret = async_hangup(mouse_dev->wheel_sess);
     520                if (ret != EOK)
     521                        usb_log_warning("Failed to hang up wheel session: "
     522                            "%p, %s.\n", mouse_dev->wheel_sess, str_error(ret));
     523        }
     524
     525        FUN_UNBIND_DESTROY(mouse_dev->mouse_fun);
     526        FUN_UNBIND_DESTROY(mouse_dev->wheel_fun);
     527
     528        free(mouse_dev->buttons);
     529        free(mouse_dev);
     530}
     531/*----------------------------------------------------------------------------*/
    532532int usb_mouse_set_boot_protocol(usb_hid_dev_t *hid_dev)
    533533{
    534534        int rc = usb_hid_parse_report_descriptor(
    535535            &hid_dev->report, USB_MOUSE_BOOT_REPORT_DESCRIPTOR,
    536             USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE);
     536            sizeof(USB_MOUSE_BOOT_REPORT_DESCRIPTOR));
    537537
    538538        if (rc != EOK) {
  • uspace/drv/bus/usb/usbhid/multimedia/multimedia.c

    rc2e50d7 r54464f6a  
    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

    rc2e50d7 r54464f6a  
    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

    rc2e50d7 r54464f6a  
    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

    rc2e50d7 r54464f6a  
    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

    rc2e50d7 r54464f6a  
    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/port.c

    rc2e50d7 r54464f6a  
    401401{
    402402        usb_hub_port_t *port = arg;
     403        assert(port);
    403404        const int rc =
    404405            usb_hub_port_set_feature(port, USB_HUB_FEATURE_PORT_RESET);
     
    440441            data->port, &new_address, NULL, NULL, &child_fun);
    441442
    442         if (rc != EOK) {
     443        if (rc == EOK) {
     444                fibril_mutex_lock(&data->port->mutex);
     445                data->port->attached_device.fun = child_fun;
     446                data->port->attached_device.address = new_address;
     447                fibril_mutex_unlock(&data->port->mutex);
     448
     449                usb_log_info("Detected new device on `%s' (port %zu), "
     450                    "address %d (handle %" PRIun ").\n",
     451                    data->hub->usb_device->ddf_dev->name,
     452                    data->port->port_number, new_address, child_fun->handle);
     453        } else {
    443454                usb_log_error("Failed registering device on port %zu: %s.\n",
    444455                    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:
     456        }
     457
     458
    459459        fibril_mutex_lock(&data->hub->pending_ops_mutex);
    460460        assert(data->hub->pending_ops_count > 0);
  • uspace/drv/bus/usb/usbhub/port.h

    rc2e50d7 r54464f6a  
    4444/** Information about single port on a hub. */
    4545typedef struct {
    46         /* Port number as reporteed in descriptors. */
     46        /* Port number as reported in descriptors. */
    4747        size_t port_number;
    4848        /** Device communication pipe. */
  • uspace/drv/bus/usb/usbhub/usbhub.c

    rc2e50d7 r54464f6a  
    170170int usb_hub_device_remove(usb_device_t *usb_dev)
    171171{
    172         assert(usb_dev);
    173         usb_hub_dev_t *hub_dev = usb_dev->driver_data;
    174         assert(hub_dev);
    175         //TODO: Cascade the call here.
    176         //TODO: Enable after cascading is implemented.
    177172        return ENOTSUP;
    178         if (!hub_dev->power_switched) {
    179                 /* That is all we can do. */
    180                 return EOK;
    181         }
    182         int ret = EOK;
    183         usb_log_info("Hub is about to be removed, powering down all ports.\n");
    184         for (size_t port = 0; port < hub_dev->port_count; ++port) {
    185                 usb_log_debug("Powering down port %zu.\n", port);
    186                 int pret = usb_hub_port_clear_feature(
    187                     &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER);
    188                 if (pret != EOK) {
    189                         usb_log_error("Cannot power down port %zu: %s.\n",
    190                             hub_dev->ports[port].port_number, str_error(pret));
    191                         ret = pret;
    192                 } else {
    193                         if (!hub_dev->per_port_power) {
    194                                 usb_log_debug("Ganged power switching mode, "
    195                                    "one port is enough.\n");
    196                                 break;
    197                         }
    198                 }
    199         }
    200         return ret;
    201173}
    202174/*----------------------------------------------------------------------------*/
  • uspace/drv/bus/usb/usbmast/bo_trans.c

    rc2e50d7 r54464f6a  
    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

    rc2e50d7 r54464f6a  
    114114{
    115115        //TODO: flush buffers, or whatever.
     116        //TODO: remove device
    116117        return ENOTSUP;
    117118}
     
    139140
    140141        usb_log_info("Initializing mass storage `%s'.\n", dev->ddf_dev->name);
    141         usb_log_debug(" Bulk in endpoint: %d [%zuB].\n",
    142             dev->pipes[BULK_IN_EP].pipe->endpoint_no,
    143             (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);
    144145        usb_log_debug("Bulk out endpoint: %d [%zuB].\n",
    145             dev->pipes[BULK_OUT_EP].pipe->endpoint_no,
    146             (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);
    147148
    148149        usb_log_debug("Get LUN count...\n");
  • uspace/drv/bus/usb/usbmid/explore.c

    rc2e50d7 r54464f6a  
    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

    rc2e50d7 r54464f6a  
    6868/** Callback when a MID device is about to be removed from the host.
    6969 *
    70  * @param gen_dev Generic DDF device representing the removed device.
     70 * @param dev USB device representing the removed device.
    7171 * @return Error code.
    7272 */
     
    7474{
    7575        assert(dev);
    76         int ret = ENOTSUP;
    7776        usb_mid_t *usb_mid = dev->driver_data;
    7877        assert(usb_mid);
    7978
    80         /* Signal all interface functions */
    81         list_foreach(usb_mid->interface_list, item) {
     79        /* Remove ctl function */
     80        int ret = ddf_fun_unbind(usb_mid->ctl_fun);
     81        if (ret != EOK) {
     82                usb_log_error("Failed to unbind USB MID ctl function: %s.\n",
     83                    str_error(ret));
     84                return ret;
     85        }
     86        ddf_fun_destroy(usb_mid->ctl_fun);
     87
     88        /* Remove all children */
     89        while (!list_empty(&usb_mid->interface_list)) {
     90                link_t *item = list_first(&usb_mid->interface_list);
     91                list_remove(item);
     92
    8293                usbmid_interface_t *iface = usbmid_interface_from_link(item);
    8394
    84                 usb_log_info("Signaling remove to child for interface "
    85                     "%d (%s).\n", iface->interface_no,
     95                usb_log_info("Removing child for interface %d (%s).\n",
     96                    iface->interface_no,
    8697                    usb_str_class(iface->interface->interface_class));
    87                 // TODO cascade the call.
     98
     99                /* Tell the child to go off-line. */
     100                int pret = ddf_fun_offline(iface->fun);
     101                if (pret != EOK) {
     102                        usb_log_warning("Failed to turn off child for interface"
     103                            " %d (%s): %s\n", iface->interface_no,
     104                            usb_str_class(iface->interface->interface_class),
     105                            str_error(pret));
     106                        ret = pret;
     107                }
     108
     109                /* Now remove the child. */
     110                pret = usbmid_interface_destroy(iface);
     111                if (pret != EOK) {
     112                        usb_log_error("Failed to destroy child for interface "
     113                            "%d (%s): %s\n", iface->interface_no,
     114                            usb_str_class(iface->interface->interface_class),
     115                            str_error(pret));
     116                        ret = pret;
     117                }
    88118        }
    89119        return ret;
     
    92122/** Callback when a MID device was removed from the host.
    93123 *
    94  * @param gen_dev Generic DDF device representing the removed device.
     124 * @param dev USB device representing the removed device.
    95125 * @return Error code.
    96126 */
     
    98128{
    99129        assert(dev);
     130        usb_mid_t *usb_mid = dev->driver_data;
     131        assert(usb_mid);
     132
    100133        usb_log_info("USB MID gone: `%s'.\n", dev->ddf_dev->name);
    101134
    102135        /* Remove ctl function */
    103         usb_mid_t *usb_mid = dev->driver_data;
    104136        int ret = ddf_fun_unbind(usb_mid->ctl_fun);
    105137        if (ret != EOK) {
     
    117149                usbmid_interface_t *iface = usbmid_interface_from_link(item);
    118150
    119                 usb_log_info("Removing child for interface %d (%s).\n",
     151                usb_log_info("Child for interface %d (%s) gone.\n",
    120152                    iface->interface_no,
    121153                    usb_str_class(iface->interface->interface_class));
  • uspace/drv/bus/usb/usbmid/usbmid.c

    rc2e50d7 r54464f6a  
    6262/** DDF interface of the child - interface function. */
    6363static 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
     64        .get_hc_handle = usb_iface_get_hc_handle_device_impl,
     65        .get_my_address = usb_iface_get_my_address_forward_impl,
     66        .get_interface = usb_iface_get_interface_impl,
    6767};
    6868
     
    110110         * class name something humanly understandable.
    111111         */
    112         rc = asprintf(&child_name, "%s%d",
     112        rc = asprintf(&child_name, "%s%hhu",
    113113            usb_str_class(interface_descriptor->interface_class),
    114             (int) interface_descriptor->interface_number);
     114            interface_descriptor->interface_number);
    115115        if (rc < 0) {
    116116                return ENOMEM;
     
    123123                return ENOMEM;
    124124        }
    125 
    126         iface->fun = child;
    127 
    128         child->driver_data = iface;
    129         child->ops = &child_device_ops;
    130125
    131126        rc = usb_device_create_match_ids_from_interface(device_descriptor,
     
    143138        }
    144139
     140        iface->fun = child;
     141        child->driver_data = iface;
     142        child->ops = &child_device_ops;
     143
    145144        return EOK;
    146145}
  • uspace/drv/bus/usb/usbmid/usbmid.h

    rc2e50d7 r54464f6a  
    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;
  • uspace/drv/bus/usb/vhc/connhost.c

    rc2e50d7 r54464f6a  
    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;
     
    118110        VHC_DATA(vhc, fun);
    119111        usb_log_debug("Releasing address %d...\n", address);
    120         usb_device_manager_release(&vhc->dev_manager, address);
     112        usb_device_manager_release_address(&vhc->dev_manager, address);
    121113
    122114        return ENOTSUP;
     
    136128 */
    137129static int register_endpoint(ddf_fun_t *fun,
    138     usb_address_t address, usb_speed_t speed, usb_endpoint_t endpoint,
     130    usb_address_t address, usb_endpoint_t endpoint,
    139131    usb_transfer_type_t transfer_type, usb_direction_t direction,
    140132    size_t max_packet_size, unsigned int interval)
     
    479471}
    480472
    481 static int tell_address(ddf_fun_t *fun, devman_handle_t handle,
    482     usb_address_t *address)
     473static int tell_address(ddf_fun_t *fun, usb_address_t *address)
    483474{
    484475        UNSUPPORTED("tell_address");
     
    497488}
    498489
    499 static int tell_address_rh(ddf_fun_t *root_hub_fun, devman_handle_t handle,
    500     usb_address_t *address)
     490static int tell_address_rh(ddf_fun_t *root_hub_fun, usb_address_t *address)
    501491{
    502492        VHC_DATA(vhc, root_hub_fun);
    503493
    504         if (handle == 0) {
    505                 handle = root_hub_fun->handle;
    506         }
     494        devman_handle_t handle = root_hub_fun->handle;
    507495
    508496        usb_log_debug("tell_address_rh(handle=%" PRIun ")\n", handle);
     
    532520usb_iface_t vhc_usb_iface = {
    533521        .get_hc_handle = usb_iface_get_hc_handle_hc_impl,
    534         .get_address = tell_address
     522        .get_my_address = tell_address
    535523};
    536524
    537525usb_iface_t rh_usb_iface = {
    538526        .get_hc_handle = usb_iface_get_hc_handle_rh_impl,
    539         .get_address = tell_address_rh
     527        .get_my_address = tell_address_rh
    540528};
    541529
  • uspace/drv/bus/usb/vhc/main.c

    rc2e50d7 r54464f6a  
    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");
Note: See TracChangeset for help on using the changeset viewer.