Changeset df6ded8 in mainline for uspace/drv/hid/usbhid


Ignore:
Timestamp:
2018-02-28T16:37:50Z (8 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1b20da0
Parents:
f5e5f73 (diff), b2dca8de (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.
git-author:
Jakub Jermar <jakub@…> (2018-02-28 16:06:42)
git-committer:
Jakub Jermar <jakub@…> (2018-02-28 16:37:50)
Message:

Merge github.com:helenos-xhci-team/helenos

This commit merges support for USB 3 and generally refactors, fixes,
extends and cleans up the existing USB framework.

Notable additions and features:

  • new host controller driver has been implemented to control various xHC models (among others, NEC Renesas uPD720200)
  • isochronous data transfer mode
  • support for explicit USB device removal
  • USB tablet driver
Location:
uspace/drv/hid/usbhid
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/hid/usbhid/blink1/blink1.c

    rf5e5f73 rdf6ded8  
    6464        usb_blink1_t *blink1_dev = (usb_blink1_t *) ddf_fun_data_get(fun);
    6565        if (blink1_dev == NULL) {
    66                 usb_log_debug("Missing parameters.\n");
     66                usb_log_debug("Missing parameters.");
    6767                return EINVAL;
    6868        }
     
    105105            fun_exposed, HID_BLINK1_FUN_NAME);
    106106        if (fun == NULL) {
    107                 usb_log_error("Could not create DDF function node `%s'.\n",
     107                usb_log_error("Could not create DDF function node `%s'.",
    108108                    HID_BLINK1_FUN_NAME);
    109109                return ENOMEM;
     
    123123        errno_t rc = ddf_fun_bind(fun);
    124124        if (rc != EOK) {
    125                 usb_log_error("Could not bind DDF function `%s': %s.\n",
     125                usb_log_error("Could not bind DDF function `%s': %s.",
    126126                    ddf_fun_get_name(fun), str_error(rc));
    127127                ddf_fun_destroy(fun);
     
    131131        rc = ddf_fun_add_to_category(fun, HID_BLINK1_CATEGORY);
    132132        if (rc != EOK) {
    133                 usb_log_error("Could not add DDF function to category %s: %s.\n",
     133                usb_log_error("Could not add DDF function to category %s: %s.",
    134134                    HID_BLINK1_CATEGORY, str_error(rc));
    135135               
  • uspace/drv/hid/usbhid/generic/hiddev.c

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Lubos Slovak
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    9697        const usb_hid_dev_t *hid_dev = fun_hid_dev(fun);
    9798
    98         usb_log_debug2("hid_dev: %p, Max input report size (%zu).\n",
     99        usb_log_debug2("hid_dev: %p, Max input report size (%zu).",
    99100            hid_dev, hid_dev->max_input_report_size);
    100101
     
    105106    size_t size, size_t *act_size, int *event_nr, unsigned int flags)
    106107{
    107         usb_log_debug2("Generic HID: Get event.\n");
     108        usb_log_debug2("Generic HID: Get event.");
    108109
    109110        if (buffer == NULL || act_size == NULL || event_nr == NULL) {
     
    115116
    116117        if (hid_dev->input_report_size > size) {
    117                 usb_log_debug("input_report_size > size (%zu, %zu)\n",
     118                usb_log_debug("input_report_size > size (%zu, %zu)",
    118119                    hid_dev->input_report_size, size);
    119120                return EINVAL;  // TODO: other error code
     
    126127        *event_nr = usb_hid_report_number(hid_dev);
    127128
    128         usb_log_debug2("OK\n");
     129        usb_log_debug2("OK");
    129130
    130131        return EOK;
     
    133134static size_t usb_generic_get_report_descriptor_length(ddf_fun_t *fun)
    134135{
    135         usb_log_debug("Generic HID: Get report descriptor length.\n");
    136 
    137         const usb_hid_dev_t *hid_dev = fun_hid_dev(fun);
    138 
    139         usb_log_debug2("hid_dev->report_desc_size = %zu\n",
     136        usb_log_debug("Generic HID: Get report descriptor length.");
     137
     138        const usb_hid_dev_t *hid_dev = fun_hid_dev(fun);
     139
     140        usb_log_debug2("hid_dev->report_desc_size = %zu",
    140141            hid_dev->report_desc_size);
    141142
     
    146147    size_t size, size_t *actual_size)
    147148{
    148         usb_log_debug2("Generic HID: Get report descriptor.\n");
     149        usb_log_debug2("Generic HID: Get report descriptor.");
    149150
    150151        const usb_hid_dev_t *hid_dev = fun_hid_dev(fun);
     
    162163static errno_t usb_generic_hid_client_connected(ddf_fun_t *fun)
    163164{
    164         usb_log_debug("Generic HID: Client connected.\n");
     165        usb_log_debug("Generic HID: Client connected.");
    165166        return EOK;
    166167}
     
    173174
    174175        if (ddf_fun_unbind(fun) != EOK) {
    175                 usb_log_error("Failed to unbind generic hid fun.\n");
     176                usb_log_error("Failed to unbind generic hid fun.");
    176177                return;
    177178        }
    178         usb_log_debug2("%s unbound.\n", ddf_fun_get_name(fun));
     179        usb_log_debug2("%s unbound.", ddf_fun_get_name(fun));
    179180        ddf_fun_destroy(fun);
    180181}
     
    189190
    190191        /* Create the exposed function. */
    191         usb_log_debug("Creating DDF function %s...\n", HID_GENERIC_FUN_NAME);
     192        usb_log_debug("Creating DDF function %s...", HID_GENERIC_FUN_NAME);
    192193        ddf_fun_t *fun = usb_device_ddf_fun_create(hid_dev->usb_dev,
    193194            fun_exposed, HID_GENERIC_FUN_NAME);
    194195        if (fun == NULL) {
    195                 usb_log_error("Could not create DDF function node.\n");
     196                usb_log_error("Could not create DDF function node.");
    196197                return ENOMEM;
    197198        }
     
    204205        errno_t rc = ddf_fun_bind(fun);
    205206        if (rc != EOK) {
    206                 usb_log_error("Could not bind DDF function: %s.\n",
     207                usb_log_error("Could not bind DDF function: %s.",
    207208                    str_error(rc));
    208209                ddf_fun_destroy(fun);
     
    210211        }
    211212
    212         usb_log_debug("HID function created. Handle: %" PRIun "\n",
     213        usb_log_debug("HID function created. Handle: %" PRIun "",
    213214            ddf_fun_get_handle(fun));
    214215        *data = fun;
     
    219220bool usb_generic_hid_polling_callback(usb_hid_dev_t *hid_dev, void *data)
    220221{
     222        /* Continue polling until the device is about to be removed. */
    221223        return true;
    222224}
  • uspace/drv/hid/usbhid/kbd/kbddev.c

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Lubos Slovak
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    185186                if (kbd_dev->client_sess == NULL) {
    186187                        kbd_dev->client_sess = sess;
    187                         usb_log_debug("%s: OK\n", __FUNCTION__);
     188                        usb_log_debug("%s: OK", __FUNCTION__);
    188189                        async_answer_0(icallid, EOK);
    189190                } else {
    190                         usb_log_error("%s: console session already set\n",
     191                        usb_log_error("%s: console session already set",
    191192                           __FUNCTION__);
    192193                        async_answer_0(icallid, ELIMIT);
     
    195196        }
    196197        default:
    197                         usb_log_error("%s: Unknown method: %d.\n",
     198                        usb_log_error("%s: Unknown method: %d.",
    198199                            __FUNCTION__, (int) method);
    199200                        async_answer_0(icallid, EINVAL);
     
    226227        /* Reset the LED data. */
    227228        memset(kbd_dev->led_data, 0, kbd_dev->led_output_size * sizeof(int32_t));
    228         usb_log_debug("Creating output report:\n");
     229        usb_log_debug("Creating output report:");
    229230
    230231        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
     
    266267        }
    267268
    268         usb_log_debug("Output report buffer: %s\n",
     269        usb_log_debug("Output report buffer: %s",
    269270            usb_debug_str_buffer(kbd_dev->output_buffer, kbd_dev->output_size,
    270271                0));
     
    276277            kbd_dev->output_buffer, kbd_dev->output_size);
    277278        if (rc != EOK) {
    278                 usb_log_warning("Failed to set kbd indicators.\n");
     279                usb_log_warning("Failed to set kbd indicators.");
    279280        }
    280281}
     
    289290void usb_kbd_push_ev(usb_kbd_t *kbd_dev, int type, unsigned key)
    290291{
    291         usb_log_debug2("Sending kbdev event %d/%d to the console\n", type, key);
     292        usb_log_debug2("Sending kbdev event %d/%d to the console", type, key);
    292293        if (kbd_dev->client_sess == NULL) {
    293294                usb_log_warning(
     
    301302                async_exchange_end(exch);
    302303        } else {
    303                 usb_log_warning("Failed to send key to console.\n");
     304                usb_log_warning("Failed to send key to console.");
    304305        }
    305306}
     
    328329 * An event is created only when key is pressed or released. Besides handling
    329330 * the events (usb_kbd_push_ev()), the auto-repeat fibril is notified about
    330  * key presses and releases (see usb_kbd_repeat_start() and 
     331 * key presses and releases (see usb_kbd_repeat_start() and
    331332 * usb_kbd_repeat_stop()).
    332333 *
    333334 * @param kbd_dev Keyboard device structure.
    334  * @param key_codes Parsed keyboard report - codes of currently pressed keys 
     335 * @param key_codes Parsed keyboard report - codes of currently pressed keys
    335336 *                  according to HID Usage Tables.
    336337 * @param count Number of key codes in report (size of the report).
     
    353354            kbd_dev->key_count);
    354355        if (i != (size_t) -1) {
    355                 usb_log_error("Detected phantom state.\n");
     356                usb_log_error("Detected phantom state.");
    356357                return;
    357358        }
     
    403404        ddf_dump_buffer(key_buffer, 512,
    404405            kbd_dev->keys_old, 4, kbd_dev->key_count, 0);
    405         usb_log_debug2("Stored keys %s.\n", key_buffer);
     406        usb_log_debug2("Stored keys %s.", key_buffer);
    406407}
    407408
     
    431432        usb_hid_report_path_t *path = usb_hid_report_path();
    432433        if (path == NULL) {
    433                 usb_log_error("Failed to create hid/kbd report path.\n");
     434                usb_log_error("Failed to create hid/kbd report path.");
    434435                return;
    435436        }
     
    438439           usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
    439440        if (ret != EOK) {
    440                 usb_log_error("Failed to append to hid/kbd report path.\n");
     441                usb_log_error("Failed to append to hid/kbd report path.");
    441442                return;
    442443        }
     
    452453
    453454        while (field != NULL) {
    454                 usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n",
     455                usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)",
    455456                    field, field->value, field->usage);
    456457
     
    464465                        kbd_dev->keys[i] = 0;
    465466                }
    466                 usb_log_debug2("Saved %u. key usage %d\n", i, kbd_dev->keys[i]);
     467                usb_log_debug2("Saved %u. key usage %d", i, kbd_dev->keys[i]);
    467468
    468469                ++i;
     
    502503        usb_hid_report_path_t *path = usb_hid_report_path();
    503504        if (path == NULL) {
    504                 usb_log_error("Failed to create kbd report path.\n");
     505                usb_log_error("Failed to create kbd report path.");
    505506                usb_kbd_destroy(kbd_dev);
    506507                return ENOMEM;
     
    510511            usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
    511512        if (ret != EOK) {
    512                 usb_log_error("Failed to append item to kbd report path.\n");
     513                usb_log_error("Failed to append item to kbd report path.");
    513514                usb_hid_report_path_free(path);
    514515                usb_kbd_destroy(kbd_dev);
     
    523524        usb_hid_report_path_free(path);
    524525
    525         usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count);
     526        usb_log_debug("Size of the input report: %zu", kbd_dev->key_count);
    526527
    527528        kbd_dev->keys = calloc(kbd_dev->key_count, sizeof(int32_t));
    528529        if (kbd_dev->keys == NULL) {
    529                 usb_log_error("Failed to allocate key buffer.\n");
     530                usb_log_error("Failed to allocate key buffer.");
    530531                usb_kbd_destroy(kbd_dev);
    531532                return ENOMEM;
     
    534535        kbd_dev->keys_old = calloc(kbd_dev->key_count, sizeof(int32_t));
    535536        if (kbd_dev->keys_old == NULL) {
    536                 usb_log_error("Failed to allocate old_key buffer.\n");
     537                usb_log_error("Failed to allocate old_key buffer.");
    537538                usb_kbd_destroy(kbd_dev);
    538539                return ENOMEM;
     
    544545            &kbd_dev->output_size, 0);
    545546        if (kbd_dev->output_buffer == NULL) {
    546                 usb_log_error("Error creating output report buffer.\n");
     547                usb_log_error("Error creating output report buffer.");
    547548                usb_kbd_destroy(kbd_dev);
    548549                return ENOMEM;
    549550        }
    550551
    551         usb_log_debug("Output buffer size: %zu\n", kbd_dev->output_size);
     552        usb_log_debug("Output buffer size: %zu", kbd_dev->output_size);
    552553
    553554        kbd_dev->led_path = usb_hid_report_path();
    554555        if (kbd_dev->led_path == NULL) {
    555                 usb_log_error("Failed to create kbd led report path.\n");
     556                usb_log_error("Failed to create kbd led report path.");
    556557                usb_kbd_destroy(kbd_dev);
    557558                return ENOMEM;
     
    561562            kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
    562563        if (ret != EOK) {
    563                 usb_log_error("Failed to append to kbd/led report path.\n");
     564                usb_log_error("Failed to append to kbd/led report path.");
    564565                usb_kbd_destroy(kbd_dev);
    565566                return ret;
     
    569570            &hid_dev->report, 0, USB_HID_REPORT_TYPE_OUTPUT);
    570571
    571         usb_log_debug("Output report size (in items): %zu\n",
     572        usb_log_debug("Output report size (in items): %zu",
    572573            kbd_dev->led_output_size);
    573574
    574575        kbd_dev->led_data = calloc(kbd_dev->led_output_size, sizeof(int32_t));
    575576        if (kbd_dev->led_data == NULL) {
    576                 usb_log_error("Error creating buffer for LED output report.\n");
     577                usb_log_error("Error creating buffer for LED output report.");
    577578                usb_kbd_destroy(kbd_dev);
    578579                return ENOMEM;
     
    588589
    589590        kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;
    590         usb_log_debug("HID/KBD device structure initialized.\n");
     591        usb_log_debug("HID/KBD device structure initialized.");
    591592
    592593        return EOK;
     
    618619errno_t usb_kbd_init(usb_hid_dev_t *hid_dev, void **data)
    619620{
    620         usb_log_debug("Initializing HID/KBD structure...\n");
     621        usb_log_debug("Initializing HID/KBD structure...");
    621622
    622623        if (hid_dev == NULL) {
     
    627628
    628629        /* Create the exposed function. */
    629         usb_log_debug("Creating DDF function %s...\n", HID_KBD_FUN_NAME);
     630        usb_log_debug("Creating DDF function %s...", HID_KBD_FUN_NAME);
    630631        ddf_fun_t *fun = usb_device_ddf_fun_create(hid_dev->usb_dev,
    631632            fun_exposed, HID_KBD_FUN_NAME);
    632633        if (fun == NULL) {
    633                 usb_log_error("Could not create DDF function node.\n");
     634                usb_log_error("Could not create DDF function node.");
    634635                return ENOMEM;
    635636        }
     
    637638        usb_kbd_t *kbd_dev = ddf_fun_data_alloc(fun, sizeof(usb_kbd_t));
    638639        if (kbd_dev == NULL) {
    639                 usb_log_error("Failed to allocate KBD device structure.\n");
     640                usb_log_error("Failed to allocate KBD device structure.");
    640641                ddf_fun_destroy(fun);
    641642                return ENOMEM;
     
    644645        errno_t ret = kbd_dev_init(kbd_dev, hid_dev);
    645646        if (ret != EOK) {
    646                 usb_log_error("Failed to initialize KBD device  structure.\n");
     647                usb_log_error("Failed to initialize KBD device  structure.");
    647648                ddf_fun_destroy(fun);
    648649                return ret;
     
    655656        ret = ddf_fun_bind(fun);
    656657        if (ret != EOK) {
    657                 usb_log_error("Could not bind DDF function: %s.\n",
     658                usb_log_error("Could not bind DDF function: %s.",
    658659                    str_error(ret));
    659660                usb_kbd_destroy(kbd_dev);
     
    662663        }
    663664
    664         usb_log_debug("%s function created. Handle: %" PRIun "\n",
     665        usb_log_debug("%s function created. Handle: %" PRIun "",
    665666            HID_KBD_FUN_NAME, ddf_fun_get_handle(fun));
    666667
    667         usb_log_debug("Adding DDF function to category %s...\n",
     668        usb_log_debug("Adding DDF function to category %s...",
    668669            HID_KBD_CATEGORY_NAME);
    669670        ret = ddf_fun_add_to_category(fun, HID_KBD_CATEGORY_NAME);
     
    709710        usb_kbd_process_data(hid_dev, kbd_dev);
    710711
     712        /* Continue polling until the device is about to be removed. */
    711713        return true;
    712714}
     
    752754        if (kbd_dev->fun) {
    753755                if (ddf_fun_unbind(kbd_dev->fun) != EOK) {
    754                         usb_log_warning("Failed to unbind %s.\n",
     756                        usb_log_warning("Failed to unbind %s.",
    755757                            ddf_fun_get_name(kbd_dev->fun));
    756758                } else {
    757                         usb_log_debug2("%s unbound.\n",
     759                        usb_log_debug2("%s unbound.",
    758760                            ddf_fun_get_name(kbd_dev->fun));
    759761                        ddf_fun_destroy(kbd_dev->fun);
     
    783785
    784786        if (rc != EOK) {
    785                 usb_log_error("Failed to parse boot report descriptor: %s\n",
     787                usb_log_error("Failed to parse boot report descriptor: %s",
    786788                    str_error(rc));
    787789                return rc;
  • uspace/drv/hid/usbhid/kbd/kbdrepeat.c

    rf5e5f73 rdf6ded8  
    6969        unsigned int delay = 0;
    7070
    71         usb_log_debug("Starting autorepeat loop.\n");
     71        usb_log_debug("Starting autorepeat loop.");
    7272
    7373        while (true) {
    7474                /* Check if the kbd structure is usable. */
    7575                if (!usb_kbd_is_initialized(kbd)) {
    76                         usb_log_warning("kbd not ready, exiting autorepeat.\n");
     76                        usb_log_warning("kbd not ready, exiting autorepeat.");
    7777                        return;
    7878                }
     
    8282                if (kbd->repeat.key_new > 0) {
    8383                        if (kbd->repeat.key_new == kbd->repeat.key_repeated) {
    84                                 usb_log_debug2("Repeating key: %u.\n",
     84                                usb_log_debug2("Repeating key: %u.",
    8585                                    kbd->repeat.key_repeated);
    8686                                usb_kbd_push_ev(kbd, KEY_PRESS,
     
    8888                                delay = kbd->repeat.delay_between;
    8989                        } else {
    90                                 usb_log_debug2("New key to repeat: %u.\n",
     90                                usb_log_debug2("New key to repeat: %u.",
    9191                                    kbd->repeat.key_new);
    9292                                kbd->repeat.key_repeated = kbd->repeat.key_new;
     
    9595                } else {
    9696                        if (kbd->repeat.key_repeated > 0) {
    97                                 usb_log_debug2("Stopping to repeat key: %u.\n",
     97                                usb_log_debug2("Stopping to repeat key: %u.",
    9898                                    kbd->repeat.key_repeated);
    9999                                kbd->repeat.key_repeated = 0;
     
    119119errno_t usb_kbd_repeat_fibril(void *arg)
    120120{
    121         usb_log_debug("Autorepeat fibril spawned.\n");
     121        usb_log_debug("Autorepeat fibril spawned.");
    122122
    123123        if (arg == NULL) {
    124                 usb_log_error("No device!\n");
     124                usb_log_error("No device!");
    125125                return EINVAL;
    126126        }
  • uspace/drv/hid/usbhid/main.c

    rf5e5f73 rdf6ded8  
    22 * Copyright (c) 2010 Vojtech Horky
    33 * Copyright (c) 2011 Lubos Slovak
     4 * Copyright (c) 2018 Petr Manek, Ondrej Hlavaty
    45 * All rights reserved.
    56 *
     
    5859static errno_t usb_hid_device_add(usb_device_t *dev)
    5960{
    60         usb_log_debug("%s\n", __FUNCTION__);
     61        usb_log_debug("%s", __FUNCTION__);
    6162
    6263        if (dev == NULL) {
    63                 usb_log_error("Wrong parameter given for add_device().\n");
     64                usb_log_error("Wrong parameter given for add_device().");
    6465                return EINVAL;
    6566        }
     
    7374            usb_device_data_alloc(dev, sizeof(usb_hid_dev_t));
    7475        if (hid_dev == NULL) {
    75                 usb_log_error("Failed to create USB/HID device structure.\n");
     76                usb_log_error("Failed to create USB/HID device structure.");
    7677                return ENOMEM;
    7778        }
     
    7980        errno_t rc = usb_hid_init(hid_dev, dev);
    8081        if (rc != EOK) {
    81                 usb_log_error("Failed to initialize USB/HID device.\n");
     82                usb_log_error("Failed to initialize USB/HID device.");
    8283                usb_hid_deinit(hid_dev);
    8384                return rc;
    8485        }
    8586
    86         usb_log_debug("USB/HID device structure initialized.\n");
     87        usb_log_debug("USB/HID device structure initialized.");
    8788
    8889        /* Start automated polling function.
    8990         * This will create a separate fibril that will query the device
    9091         * for the data continuously. */
    91         rc = usb_device_auto_poll_desc(dev,
    92            /* Index of the polling pipe. */
    93            hid_dev->poll_pipe_mapping->description,
    94            /* Callback when data arrives. */
    95            usb_hid_polling_callback,
    96            /* How much data to request. */
    97            hid_dev->poll_pipe_mapping->pipe.max_packet_size,
    98            /* Delay */
    99            -1,
    100            /* Callback when the polling ends. */
    101            usb_hid_polling_ended_callback,
    102            /* Custom argument. */
    103            hid_dev);
     92        rc = usb_polling_start(&hid_dev->polling);
    10493
    10594        if (rc != EOK) {
    106                 usb_log_error("Failed to start polling fibril for `%s'.\n",
     95                usb_log_error("Failed to start polling fibril for `%s'.",
    10796                    usb_device_get_name(dev));
    10897                usb_hid_deinit(hid_dev);
     
    111100        hid_dev->running = true;
    112101
    113         usb_log_info("HID device `%s' ready.\n", usb_device_get_name(dev));
     102        usb_log_info("HID device `%s' ready.", usb_device_get_name(dev));
     103
     104        return EOK;
     105}
     106
     107static errno_t join_and_clean(usb_device_t *dev)
     108{
     109        assert(dev);
     110        usb_hid_dev_t *hid_dev = usb_device_data_get(dev);
     111        assert(hid_dev);
     112
     113        /* Join polling fibril (ignoring error code). */
     114        usb_polling_join(&hid_dev->polling);
     115
     116        /* Clean up. */
     117        usb_hid_deinit(hid_dev);
     118        usb_log_info("%s destruction complete.", usb_device_get_name(dev));
    114119
    115120        return EOK;
     
    122127 * @return Error code.
    123128 */
    124 static errno_t usb_hid_device_rem(usb_device_t *dev)
     129static errno_t usb_hid_device_remove(usb_device_t *dev)
    125130{
    126         // TODO: Stop device polling
    127         // TODO: Call deinit (stops autorepeat too)
    128         return ENOTSUP;
     131        assert(dev);
     132        usb_hid_dev_t *hid_dev = usb_device_data_get(dev);
     133        assert(hid_dev);
     134
     135        usb_log_info("Device %s removed.", usb_device_get_name(dev));
     136        return join_and_clean(dev);
    129137}
    130138
     
    140148        usb_hid_dev_t *hid_dev = usb_device_data_get(dev);
    141149        assert(hid_dev);
    142         unsigned tries = 100;
    143         /* Wait for fail. */
    144         while (hid_dev->running && tries--) {
    145                 async_usleep(100000);
    146         }
    147         if (hid_dev->running) {
    148                 usb_log_error("Can't remove hid, still running.\n");
    149                 return EBUSY;
    150         }
    151150
    152         usb_hid_deinit(hid_dev);
    153         usb_log_debug2("%s destruction complete.\n", usb_device_get_name(dev));
    154         return EOK;
     151        usb_log_info("Device %s gone.", usb_device_get_name(dev));
     152        return join_and_clean(dev);
    155153}
    156154
     
    158156static const usb_driver_ops_t usb_hid_driver_ops = {
    159157        .device_add = usb_hid_device_add,
    160         .device_rem = usb_hid_device_rem,
     158        .device_remove = usb_hid_device_remove,
    161159        .device_gone = usb_hid_device_gone,
    162160};
  • uspace/drv/hid/usbhid/mouse/mousedev.c

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Lubos Slovak, Vojtech Horky
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    118119
    119120        if (mouse_dev == NULL) {
    120                 usb_log_debug("%s: Missing parameters.\n", __FUNCTION__);
     121                usb_log_debug("%s: Missing parameters.", __FUNCTION__);
    121122                async_answer_0(icallid, EINVAL);
    122123                return;
    123124        }
    124125
    125         usb_log_debug("%s: fun->name: %s\n", __FUNCTION__, ddf_fun_get_name(fun));
    126         usb_log_debug("%s: mouse_sess: %p\n",
     126        usb_log_debug("%s: fun->name: %s", __FUNCTION__, ddf_fun_get_name(fun));
     127        usb_log_debug("%s: mouse_sess: %p",
    127128            __FUNCTION__, mouse_dev->mouse_sess);
    128129
     
    132133                if (mouse_dev->mouse_sess == NULL) {
    133134                        mouse_dev->mouse_sess = sess;
    134                         usb_log_debug("Console session to %s set ok (%p).\n",
     135                        usb_log_debug("Console session to %s set ok (%p).",
    135136                            ddf_fun_get_name(fun), sess);
    136137                        async_answer_0(icallid, EOK);
    137138                } else {
    138                         usb_log_error("Console session to %s already set.\n",
     139                        usb_log_error("Console session to %s already set.",
    139140                            ddf_fun_get_name(fun));
    140141                        async_answer_0(icallid, ELIMIT);
     
    142143                }
    143144        } else {
    144                 usb_log_debug("%s: Invalid function.\n", __FUNCTION__);
     145                usb_log_debug("%s: Invalid function.", __FUNCTION__);
    145146                async_answer_0(icallid, EINVAL);
    146147        }
    147148}
    148149
    149 static int get_mouse_axis_move_value(uint8_t rid, usb_hid_report_t *report,
     150static const usb_hid_report_field_t *get_mouse_axis_move_field(uint8_t rid, usb_hid_report_t *report,
    150151    int32_t usage)
    151152{
    152         int result = 0;
    153 
    154153        usb_hid_report_path_t *path = usb_hid_report_path();
    155154        usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_GENERIC_DESKTOP,
     
    158157        usb_hid_report_path_set_report_id(path, rid);
    159158
    160         usb_hid_report_field_t *field = usb_hid_report_get_sibling(
     159        const usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    161160            report, NULL, path, USB_HID_PATH_COMPARE_END,
    162161            USB_HID_REPORT_TYPE_INPUT);
    163162
    164         if (field != NULL) {
    165                 result = field->value;
    166         }
    167 
    168163        usb_hid_report_path_free(path);
    169164
    170         return result;
    171 }
    172 
    173 static bool usb_mouse_process_report(usb_hid_dev_t *hid_dev,
     165        return field;
     166}
     167
     168static void usb_mouse_process_report(usb_hid_dev_t *hid_dev,
    174169    usb_mouse_t *mouse_dev)
    175170{
     
    177172
    178173        if (mouse_dev->mouse_sess == NULL) {
    179                 usb_log_warning(NAME " No console session.\n");
    180                 return true;
    181         }
    182 
    183         const int shift_x = get_mouse_axis_move_value(hid_dev->report_id,
    184             &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_X);
    185         const int shift_y = get_mouse_axis_move_value(hid_dev->report_id,
    186             &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_Y);
    187         const int wheel = get_mouse_axis_move_value(hid_dev->report_id,
    188             &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL);
    189 
    190         if (shift_x || shift_y || wheel) {
     174                usb_log_warning(NAME " No console session.");
     175                return;
     176        }
     177
     178        const usb_hid_report_field_t *move_x = get_mouse_axis_move_field(
     179            hid_dev->report_id, &hid_dev->report,
     180            USB_HIDUT_USAGE_GENERIC_DESKTOP_X);
     181        const usb_hid_report_field_t *move_y = get_mouse_axis_move_field(
     182            hid_dev->report_id, &hid_dev->report,
     183            USB_HIDUT_USAGE_GENERIC_DESKTOP_Y);
     184        const usb_hid_report_field_t *wheel= get_mouse_axis_move_field(
     185            hid_dev->report_id, &hid_dev->report,
     186            USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL);
     187
     188        bool absolute_x = move_x && !USB_HID_ITEM_FLAG_RELATIVE(move_x->item_flags);
     189        bool absolute_y = move_y && !USB_HID_ITEM_FLAG_RELATIVE(move_y->item_flags);
     190
     191        /* Tablet shall always report both X and Y */
     192        if (absolute_x != absolute_y) {
     193                usb_log_error(NAME " cannot handle mix of absolute and relative mouse move.");
     194                return;
     195        }
     196
     197        int shift_x = move_x ? move_x->value : 0;
     198        int shift_y = move_y ? move_y->value : 0;
     199        int shift_z =  wheel ?  wheel->value : 0;
     200
     201        if (absolute_x && absolute_y) {
     202                async_exch_t *exch =
     203                    async_exchange_begin(mouse_dev->mouse_sess);
     204                if (exch != NULL) {
     205                        async_msg_4(exch, MOUSEEV_ABS_MOVE_EVENT,
     206                            shift_x, shift_y, move_x->logical_maximum, move_y->logical_maximum);
     207                        async_exchange_end(exch);
     208                }
     209
     210                // Even if we move the mouse absolutely, we need to resolve wheel
     211                shift_x = shift_y = 0;
     212        }
     213
     214
     215        if (shift_x || shift_y || shift_z) {
    191216                async_exch_t *exch =
    192217                    async_exchange_begin(mouse_dev->mouse_sess);
    193218                if (exch != NULL) {
    194219                        async_msg_3(exch, MOUSEEV_MOVE_EVENT,
    195                             shift_x, shift_y, wheel);
     220                            shift_x, shift_y, shift_z);
    196221                        async_exchange_end(exch);
    197222                }
     
    201226        usb_hid_report_path_t *path = usb_hid_report_path();
    202227        if (path == NULL) {
    203                 usb_log_warning("Failed to create USB HID report path.\n");
    204                 return true;
     228                usb_log_warning("Failed to create USB HID report path.");
     229                return;
    205230        }
    206231        errno_t ret =
     
    208233        if (ret != EOK) {
    209234                usb_hid_report_path_free(path);
    210                 usb_log_warning("Failed to add buttons to report path.\n");
    211                 return true;
     235                usb_log_warning("Failed to add buttons to report path.");
     236                return;
    212237        }
    213238        usb_hid_report_path_set_report_id(path, hid_dev->report_id);
     
    218243
    219244        while (field != NULL) {
    220                 usb_log_debug2(NAME " VALUE(%X) USAGE(%X)\n", field->value,
     245                usb_log_debug2(NAME " VALUE(%X) USAGE(%X)", field->value,
    221246                    field->usage);
    222247                assert(field->usage > field->usage_minimum);
     
    242267
    243268        usb_hid_report_path_free(path);
    244 
    245         return true;
    246269}
    247270
     
    309332
    310333        if (mouse_dev->buttons == NULL) {
    311                 usb_log_error(NAME ": out of memory, giving up on device!\n");
     334                usb_log_error(NAME ": out of memory, giving up on device!");
    312335                free(mouse_dev);
    313336                return ENOMEM;
     
    322345errno_t usb_mouse_init(usb_hid_dev_t *hid_dev, void **data)
    323346{
    324         usb_log_debug("Initializing HID/Mouse structure...\n");
     347        usb_log_debug("Initializing HID/Mouse structure...");
    325348
    326349        if (hid_dev == NULL) {
     
    331354
    332355        /* Create the exposed function. */
    333         usb_log_debug("Creating DDF function %s...\n", HID_MOUSE_FUN_NAME);
     356        usb_log_debug("Creating DDF function %s...", HID_MOUSE_FUN_NAME);
    334357        ddf_fun_t *fun = usb_device_ddf_fun_create(hid_dev->usb_dev,
    335358            fun_exposed, HID_MOUSE_FUN_NAME);
    336359        if (fun == NULL) {
    337                 usb_log_error("Could not create DDF function node `%s'.\n",
     360                usb_log_error("Could not create DDF function node `%s'.",
    338361                    HID_MOUSE_FUN_NAME);
    339362                return ENOMEM;
     
    342365        usb_mouse_t *mouse_dev = ddf_fun_data_alloc(fun, sizeof(usb_mouse_t));
    343366        if (mouse_dev == NULL) {
    344                 usb_log_error("Failed to alloc HID mouse device structure.\n");
     367                usb_log_error("Failed to alloc HID mouse device structure.");
    345368                ddf_fun_destroy(fun);
    346369                return ENOMEM;
     
    349372        errno_t ret = mouse_dev_init(mouse_dev, hid_dev);
    350373        if (ret != EOK) {
    351                 usb_log_error("Failed to init HID mouse device structure.\n");
     374                usb_log_error("Failed to init HID mouse device structure.");
    352375                return ret;
    353376        }
     
    357380        ret = ddf_fun_bind(fun);
    358381        if (ret != EOK) {
    359                 usb_log_error("Could not bind DDF function `%s': %s.\n",
     382                usb_log_error("Could not bind DDF function `%s': %s.",
    360383                    ddf_fun_get_name(fun), str_error(ret));
    361384                ddf_fun_destroy(fun);
     
    363386        }
    364387
    365         usb_log_debug("Adding DDF function `%s' to category %s...\n",
     388        usb_log_debug("Adding DDF function `%s' to category %s...",
    366389            ddf_fun_get_name(fun), HID_MOUSE_CATEGORY);
    367390        ret = ddf_fun_add_to_category(fun, HID_MOUSE_CATEGORY);
     
    390413
    391414        usb_mouse_t *mouse_dev = data;
    392 
    393         return usb_mouse_process_report(hid_dev, mouse_dev);
     415        usb_mouse_process_report(hid_dev, mouse_dev);
     416
     417        /* Continue polling until the device is about to be removed. */
     418        return true;
    394419}
    395420
     
    420445
    421446        if (rc != EOK) {
    422                 usb_log_error("Failed to parse boot report descriptor: %s\n",
     447                usb_log_error("Failed to parse boot report descriptor: %s",
    423448                    str_error(rc));
    424449                return rc;
  • uspace/drv/hid/usbhid/multimedia/multimedia.c

    rf5e5f73 rdf6ded8  
    22 * Copyright (c) 2011 Lubos Slovak
    33 * Copyright (c) 2011 Vojtech Horky
     4 * Copyright (c) 2018 Ondrej Hlavaty
    45 * All rights reserved.
    56 *
     
    8687    ipc_callid_t icallid, ipc_call_t *icall)
    8788{
    88         usb_log_debug(NAME " default_connection_handler()\n");
     89        usb_log_debug(NAME " default_connection_handler()");
    8990
    9091        usb_multimedia_t *multim_dev = ddf_fun_data_get(fun);
     
    9596                if (multim_dev->console_sess == NULL) {
    9697                        multim_dev->console_sess = sess;
    97                         usb_log_debug(NAME " Saved session to console: %p\n",
     98                        usb_log_debug(NAME " Saved session to console: %p",
    9899                            sess);
    99100                        async_answer_0(icallid, EOK);
     
    137138        };
    138139
    139         usb_log_debug2(NAME " Sending key %d to the console\n", ev.key);
     140        usb_log_debug2(NAME " Sending key %d to the console", ev.key);
    140141        if (multim_dev->console_sess == NULL) {
    141142                usb_log_warning(
     
    149150                async_exchange_end(exch);
    150151        } else {
    151                 usb_log_warning("Failed to send multimedia key.\n");
     152                usb_log_warning("Failed to send multimedia key.");
    152153        }
    153154}
     
    159160        }
    160161
    161         usb_log_debug(NAME " Initializing HID/multimedia structure...\n");
     162        usb_log_debug(NAME " Initializing HID/multimedia structure...");
    162163
    163164        /* Create the exposed function. */
     
    165166            hid_dev->usb_dev, fun_exposed, NAME);
    166167        if (fun == NULL) {
    167                 usb_log_error("Could not create DDF function node.\n");
     168                usb_log_error("Could not create DDF function node.");
    168169                return ENOMEM;
    169170        }
     
    184185        errno_t rc = ddf_fun_bind(fun);
    185186        if (rc != EOK) {
    186                 usb_log_error("Could not bind DDF function: %s.\n",
     187                usb_log_error("Could not bind DDF function: %s.",
    187188                    str_error(rc));
    188189                ddf_fun_destroy(fun);
     
    190191        }
    191192
    192         usb_log_debug(NAME " function created (handle: %" PRIun ").\n",
     193        usb_log_debug(NAME " function created (handle: %" PRIun ").",
    193194            ddf_fun_get_handle(fun));
    194195
     
    199200                    str_error(rc));
    200201                if (ddf_fun_unbind(fun) != EOK) {
    201                         usb_log_error("Failed to unbind %s, won't destroy.\n",
     202                        usb_log_error("Failed to unbind %s, won't destroy.",
    202203                            ddf_fun_get_name(fun));
    203204                } else {
     
    210211        *data = fun;
    211212
    212         usb_log_debug(NAME " HID/multimedia structure initialized.\n");
     213        usb_log_debug(NAME " HID/multimedia structure initialized.");
    213214        return EOK;
    214215}
     
    224225                async_hangup(multim_dev->console_sess);
    225226        if (ddf_fun_unbind(fun) != EOK) {
    226                 usb_log_error("Failed to unbind %s, won't destroy.\n",
     227                usb_log_error("Failed to unbind %s, won't destroy.",
    227228                    ddf_fun_get_name(fun));
    228229        } else {
    229                 usb_log_debug2("%s unbound.\n", ddf_fun_get_name(fun));
     230                usb_log_debug2("%s unbound.", ddf_fun_get_name(fun));
    230231                /* This frees multim_dev too as it was stored in
    231232                 * fun->data */
     
    266267        while (field != NULL) {
    267268                if (field->value != 0) {
    268                         usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n",
     269                        usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)",
    269270                            field->value, field->usage);
    270271                        const unsigned key =
     
    272273                        const char *key_str =
    273274                            usbhid_multimedia_usage_to_str(field->usage);
    274                         usb_log_info("Pressed key: %s\n", key_str);
     275                        usb_log_info("Pressed key: %s", key_str);
    275276                        usb_multimedia_push_ev(multim_dev, KEY_PRESS, key);
    276277                }
  • uspace/drv/hid/usbhid/usbhid.c

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Lubos Slovak
     3 * Copyright (c) 2018 Petr Manek, Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    134135        usb_hid_report_path_t *usage_path = usb_hid_report_path();
    135136        if (usage_path == NULL) {
    136                 usb_log_debug("Failed to create usage path.\n");
     137                usb_log_debug("Failed to create usage path.");
    137138                return false;
    138139        }
     
    143144                    mapping->usage_path[i].usage_page,
    144145                    mapping->usage_path[i].usage) != EOK) {
    145                         usb_log_debug("Failed to append to usage path.\n");
     146                        usb_log_debug("Failed to append to usage path.");
    146147                        usb_hid_report_path_free(usage_path);
    147148                        return false;
     
    149150        }
    150151
    151         usb_log_debug("Compare flags: %d\n", mapping->compare);
     152        usb_log_debug("Compare flags: %d", mapping->compare);
    152153
    153154        bool matches = false;
     
    155156
    156157        do {
    157                 usb_log_debug("Trying report id %u\n", report_id);
     158                usb_log_debug("Trying report id %u", report_id);
    158159                if (report_id != 0) {
    159160                        usb_hid_report_path_set_report_id(usage_path,
     
    166167                        USB_HID_REPORT_TYPE_INPUT);
    167168
    168                 usb_log_debug("Field: %p\n", field);
     169                usb_log_debug("Field: %p", field);
    169170
    170171                if (field != NULL) {
     
    243244                            mapping->product_id);
    244245                        if (usb_hid_ids_match(hid_dev, mapping)) {
    245                                 usb_log_debug("IDs matched.\n");
     246                                usb_log_debug("IDs matched.");
    246247                                matched = true;
    247248                        }
     
    250251                /* Check usage match. */
    251252                if (mapping->usage_path != NULL) {
    252                         usb_log_debug("Comparing device against usage path.\n");
     253                        usb_log_debug("Comparing device against usage path.");
    253254                        if (usb_hid_path_matches(hid_dev, mapping)) {
    254255                                /* Does not matter if IDs were matched. */
     
    258259
    259260                if (matched) {
    260                         usb_log_debug("Subdriver matched.\n");
     261                        usb_log_debug("Subdriver matched.");
    261262                        subdrivers[count++] = &mapping->subdriver;
    262263                }
     
    285286                    usb_device_get_mapped_ep_desc(dev, endpoints[i].desc);
    286287                if (epm && epm->present) {
    287                         usb_log_debug("Found: %s.\n", endpoints[i].description);
     288                        usb_log_debug("Found: %s.", endpoints[i].description);
    288289                        hid_dev->poll_pipe_mapping = epm;
    289290                        return EOK;
     
    301302
    302303        do {
    303                 usb_log_debug("Getting size of the report.\n");
     304                usb_log_debug("Getting size of the report.");
    304305                const size_t size =
    305306                    usb_hid_report_byte_size(&hid_dev->report, report_id,
    306307                        USB_HID_REPORT_TYPE_INPUT);
    307                 usb_log_debug("Report ID: %u, size: %zu\n", report_id, size);
     308                usb_log_debug("Report ID: %u, size: %zu", report_id, size);
    308309                max_size = (size > max_size) ? size : max_size;
    309                 usb_log_debug("Getting next report ID\n");
     310                usb_log_debug("Getting next report ID");
    310311                report_id = usb_hid_get_next_report_id(&hid_dev->report,
    311312                    report_id, USB_HID_REPORT_TYPE_INPUT);
    312313        } while (report_id != 0);
    313314
    314         usb_log_debug("Max size of input report: %zu\n", max_size);
     315        usb_log_debug("Max size of input report: %zu", max_size);
    315316
    316317        assert(hid_dev->input_report == NULL);
     
    323324
    324325        return EOK;
     326}
     327
     328static bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
     329    size_t buffer_size, void *arg)
     330{
     331        if (dev == NULL || arg == NULL || buffer == NULL) {
     332                usb_log_error("Missing arguments to polling callback.");
     333                return false;
     334        }
     335        usb_hid_dev_t *hid_dev = arg;
     336
     337        assert(hid_dev->input_report != NULL);
     338
     339        usb_log_debug("New data [%zu/%zu]: %s", buffer_size,
     340            hid_dev->max_input_report_size,
     341            usb_debug_str_buffer(buffer, buffer_size, 0));
     342
     343        if (hid_dev->max_input_report_size >= buffer_size) {
     344                /*! @todo This should probably be atomic. */
     345                memcpy(hid_dev->input_report, buffer, buffer_size);
     346                hid_dev->input_report_size = buffer_size;
     347                usb_hid_new_report(hid_dev);
     348        }
     349
     350        /* Parse the input report */
     351        const errno_t rc = usb_hid_parse_report(
     352            &hid_dev->report, buffer, buffer_size, &hid_dev->report_id);
     353        if (rc != EOK) {
     354                usb_log_warning("Failure in usb_hid_parse_report():"
     355                    "%s\n", str_error(rc));
     356        }
     357
     358        bool cont = false;
     359        /* Continue if at least one of the subdrivers want to continue */
     360        for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) {
     361                if (hid_dev->subdrivers[i].poll != NULL) {
     362                        cont = cont || hid_dev->subdrivers[i].poll(
     363                            hid_dev, hid_dev->subdrivers[i].data);
     364                }
     365        }
     366
     367        return cont;
     368}
     369
     370static bool usb_hid_polling_error_callback(usb_device_t *dev, errno_t err_code, void *arg)
     371{
     372        assert(dev);
     373        assert(arg);
     374        usb_hid_dev_t *hid_dev = arg;
     375
     376        usb_log_error("Device %s polling error: %s", usb_device_get_name(dev),
     377            str_error(err_code));
     378
     379        /* Continue polling until the device is about to be removed. */
     380        return hid_dev->running;
     381}
     382
     383static void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, void *arg)
     384{
     385        assert(dev);
     386        assert(arg);
     387
     388        usb_hid_dev_t *hid_dev = arg;
     389
     390        for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) {
     391                if (hid_dev->subdrivers[i].poll_end != NULL) {
     392                        hid_dev->subdrivers[i].poll_end(
     393                            hid_dev, hid_dev->subdrivers[i].data, reason);
     394                }
     395        }
     396
     397        hid_dev->running = false;
    325398}
    326399
     
    332405 * During initialization, the keyboard is switched into boot protocol, the idle
    333406 * rate is set to 0 (infinity), resulting in the keyboard only reporting event
    334  * when a key is pressed or released. Finally, the LED lights are turned on 
     407 * when a key is pressed or released. Finally, the LED lights are turned on
    335408 * according to the default setup of lock keys.
    336409 *
    337  * @note By default, the keyboards is initialized with Num Lock turned on and 
     410 * @note By default, the keyboards is initialized with Num Lock turned on and
    338411 *       other locks turned off.
    339412 *
     
    347420        assert(dev);
    348421
    349         usb_log_debug("Initializing HID structure...\n");
     422        usb_log_debug("Initializing HID structure...");
    350423
    351424        usb_hid_report_init(&hid_dev->report);
     
    369442                usb_hid_find_subdrivers(hid_dev);
    370443        } else {
    371                 usb_log_error("Failed to parse report descriptor: fallback.\n");
     444                usb_log_error("Failed to parse report descriptor: fallback.");
    372445                hid_dev->subdrivers = NULL;
    373446                hid_dev->subdriver_count = 0;
    374447        }
    375448
    376         usb_log_debug("Subdriver count(before trying boot protocol): %d\n",
     449        usb_log_debug("Subdriver count(before trying boot protocol): %d",
    377450            hid_dev->subdriver_count);
    378451
     
    385458                switch (hid_dev->poll_pipe_mapping->interface->interface_protocol) {
    386459                case USB_HID_PROTOCOL_KEYBOARD:
    387                         usb_log_info("Falling back to kbd boot protocol.\n");
     460                        usb_log_info("Falling back to kbd boot protocol.");
    388461                        rc = usb_kbd_set_boot_protocol(hid_dev);
    389462                        if (rc == EOK) {
     
    392465                        break;
    393466                case USB_HID_PROTOCOL_MOUSE:
    394                         usb_log_info("Falling back to mouse boot protocol.\n");
     467                        usb_log_info("Falling back to mouse boot protocol.");
    395468                        rc = usb_mouse_set_boot_protocol(hid_dev);
    396469                        if (rc == EOK) {
     
    399472                        break;
    400473                default:
    401                         usb_log_info("Falling back to generic HID driver.\n");
     474                        usb_log_info("Falling back to generic HID driver.");
    402475                        usb_hid_set_generic_hid_subdriver(hid_dev);
    403476                }
    404477        }
    405478
    406         usb_log_debug("Subdriver count(after trying boot protocol): %d\n",
     479        usb_log_debug("Subdriver count(after trying boot protocol): %d",
    407480            hid_dev->subdriver_count);
    408481
     
    419492        for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) {
    420493                if (hid_dev->subdrivers[i].init != NULL) {
    421                         usb_log_debug("Initializing subdriver %d.\n",i);
     494                        usb_log_debug("Initializing subdriver %d.",i);
    422495                        const errno_t pret = hid_dev->subdrivers[i].init(hid_dev,
    423496                            &hid_dev->subdrivers[i].data);
     
    442515                rc = usb_hid_init_report(hid_dev);
    443516                if (rc != EOK) {
    444                         usb_log_error("Failed to initialize input report buffer"
    445                             ".\n");
    446                 }
     517                        usb_log_error("Failed to initialize input report buffer: %s", str_error(rc));
     518                        // FIXME: What happens now?
     519                }
     520
     521                usb_polling_t *polling = &hid_dev->polling;
     522                if ((rc = usb_polling_init(polling))) {
     523                        usb_log_error("Failed to initialize polling: %s", str_error(rc));
     524                        // FIXME: What happens now?
     525                }
     526
     527                polling->device = hid_dev->usb_dev;
     528                polling->ep_mapping = hid_dev->poll_pipe_mapping;
     529                polling->request_size = hid_dev->poll_pipe_mapping->pipe.desc.max_transfer_size;
     530                polling->buffer = malloc(polling->request_size);
     531                polling->on_data = usb_hid_polling_callback;
     532                polling->on_polling_end = usb_hid_polling_ended_callback;
     533                polling->on_error = usb_hid_polling_error_callback;
     534                polling->arg = hid_dev;
    447535        }
    448536
    449537        return rc;
    450 }
    451 
    452 bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
    453     size_t buffer_size, void *arg)
    454 {
    455         if (dev == NULL || arg == NULL || buffer == NULL) {
    456                 usb_log_error("Missing arguments to polling callback.\n");
    457                 return false;
    458         }
    459         usb_hid_dev_t *hid_dev = arg;
    460 
    461         assert(hid_dev->input_report != NULL);
    462 
    463         usb_log_debug("New data [%zu/%zu]: %s\n", buffer_size,
    464             hid_dev->max_input_report_size,
    465             usb_debug_str_buffer(buffer, buffer_size, 0));
    466 
    467         if (hid_dev->max_input_report_size >= buffer_size) {
    468                 /*! @todo This should probably be atomic. */
    469                 memcpy(hid_dev->input_report, buffer, buffer_size);
    470                 hid_dev->input_report_size = buffer_size;
    471                 usb_hid_new_report(hid_dev);
    472         }
    473 
    474         /* Parse the input report */
    475         const errno_t rc = usb_hid_parse_report(
    476             &hid_dev->report, buffer, buffer_size, &hid_dev->report_id);
    477         if (rc != EOK) {
    478                 usb_log_warning("Failure in usb_hid_parse_report():"
    479                     "%s\n", str_error(rc));
    480         }
    481 
    482         bool cont = false;
    483         /* Continue if at least one of the subdrivers want to continue */
    484         for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) {
    485                 if (hid_dev->subdrivers[i].poll != NULL) {
    486                         cont = cont || hid_dev->subdrivers[i].poll(
    487                             hid_dev, hid_dev->subdrivers[i].data);
    488                 }
    489         }
    490 
    491         return cont;
    492 }
    493 
    494 void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, void *arg)
    495 {
    496         assert(dev);
    497         assert(arg);
    498 
    499         usb_hid_dev_t *hid_dev = arg;
    500 
    501         for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) {
    502                 if (hid_dev->subdrivers[i].poll_end != NULL) {
    503                         hid_dev->subdrivers[i].poll_end(
    504                             hid_dev, hid_dev->subdrivers[i].data, reason);
    505                 }
    506         }
    507 
    508         hid_dev->running = false;
    509538}
    510539
     
    524553        assert(hid_dev->subdrivers != NULL || hid_dev->subdriver_count == 0);
    525554
    526 
    527         usb_log_debug("Subdrivers: %p, subdriver count: %d\n",
     555        free(hid_dev->polling.buffer);
     556        usb_polling_fini(&hid_dev->polling);
     557
     558        usb_log_debug("Subdrivers: %p, subdriver count: %d",
    528559            hid_dev->subdrivers, hid_dev->subdriver_count);
    529560
     
    541572        /* Destroy the parser */
    542573        usb_hid_report_deinit(&hid_dev->report);
    543 
    544574}
    545575
  • uspace/drv/hid/usbhid/usbhid.h

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Lubos Slovak
     3 * Copyright (c) 2018 Petr Manek
    34 * All rights reserved.
    45 *
     
    4344#include <usb/dev/pipes.h>
    4445#include <usb/dev/driver.h>
     46#include <usb/dev/poll.h>
    4547#include <usb/hid/hid.h>
    4648#include <stdbool.h>
     
    106108        usb_endpoint_mapping_t *poll_pipe_mapping;
    107109
     110        /** Device polling structure. */
     111        usb_polling_t polling;
     112
    108113        /** Subdrivers. */
    109114        usb_hid_subdriver_t *subdrivers;
     
    138143void usb_hid_deinit(usb_hid_dev_t *hid_dev);
    139144
    140 bool usb_hid_polling_callback(usb_device_t *dev,
    141     uint8_t *buffer, size_t buffer_size, void *arg);
    142 
    143 void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, void *arg);
    144 
    145145void usb_hid_new_report(usb_hid_dev_t *hid_dev);
    146146
Note: See TracChangeset for help on using the changeset viewer.