Changeset 8a02ff3 in mainline


Ignore:
Timestamp:
2011-03-10T10:52:34Z (13 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f4cf2813
Parents:
f8c190e (diff), dfe53af (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:

Merged auto-repeat + some doxygen comments of kbd functions.

Location:
uspace/drv/usbhid
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/usbhid/Makefile

    rf8c190e r8a02ff3  
    4242        hidreq.c \
    4343        kbddev.c \
     44        kbdrepeat.c \
    4445        hiddev.c \
    4546        $(STOLEN_LAYOUT_SOURCES)
  • uspace/drv/usbhid/kbddev.c

    rf8c190e r8a02ff3  
    3737#include <errno.h>
    3838#include <str_error.h>
    39 #include <fibril.h>
    4039#include <stdio.h>
    4140
     
    4342#include <ipc/kbd.h>
    4443#include <async.h>
     44#include <fibril.h>
     45#include <fibril_synch.h>
    4546
    4647#include <usb/usb.h>
     
    5657#include "layout.h"
    5758#include "conv.h"
     59#include "kbdrepeat.h"
    5860
    5961/*----------------------------------------------------------------------------*/
     
    6567static const uint8_t BOOTP_ERROR_ROLLOVER = 1;
    6668static const uint8_t IDLE_RATE = 0;
     69static const unsigned int DEFAULT_DELAY_BEFORE_FIRST_REPEAT = 500 * 1000;
     70static const unsigned int DEFAULT_REPEAT_DELAY = 50 * 1000;
    6771
    6872/** Keyboard polling endpoint description for boot protocol class. */
     
    190194/*----------------------------------------------------------------------------*/
    191195
    192 static void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type,
    193     unsigned int key)
     196void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, unsigned int key)
    194197{
    195198        console_event_t ev;
    196199        unsigned mod_mask;
    197200
    198         // TODO: replace by our own parsing?? or are the key codes identical??
     201        /*
     202         * These parts are copy-pasted from the AT keyboard driver.
     203         *
     204         * They definitely require some refactoring, but will keep it for later
     205         * when the console and keyboard system is changed in HelenOS.
     206         */
    199207        switch (key) {
    200208        case KC_LCTRL: mod_mask = KM_LCTRL; break;
     
    228236                         * up the lock state.
    229237                         */
     238                        unsigned int locks_old = kbd_dev->lock_keys;
     239                       
    230240                        kbd_dev->mods =
    231241                            kbd_dev->mods ^ (mod_mask & ~kbd_dev->lock_keys);
     
    233243
    234244                        /* Update keyboard lock indicator lights. */
    235                         usbhid_kbd_set_led(kbd_dev);
     245                        if (kbd_dev->lock_keys != locks_old) {
     246                                usbhid_kbd_set_led(kbd_dev);
     247                        }
    236248                } else {
    237249                        kbd_dev->lock_keys = kbd_dev->lock_keys & ~mod_mask;
     
    328340        i = 0;
    329341        // all fields should report Error Rollover
    330         while (i < kbd_dev->keycode_count &&
     342        while (i < kbd_dev->key_count &&
    331343            key_codes[i] == BOOTP_ERROR_ROLLOVER) {
    332344                ++i;
    333345        }
    334         if (i == kbd_dev->keycode_count) {
     346        if (i == kbd_dev->key_count) {
    335347                usb_log_debug("Phantom state occured.\n");
    336348                // phantom state, do nothing
     
    343355         * 1) Key releases
    344356         */
    345         for (j = 0; j < kbd_dev->keycode_count; ++j) {
     357        for (j = 0; j < kbd_dev->key_count; ++j) {
    346358                // try to find the old key in the new key list
    347359                i = 0;
    348                 while (i < kbd_dev->keycode_count
    349                     && key_codes[i] != kbd_dev->keycodes[j]) {
     360                while (i < kbd_dev->key_count
     361                    && key_codes[i] != kbd_dev->keys[j]) {
    350362                        ++i;
    351363                }
    352364               
    353                 if (i == kbd_dev->keycode_count) {
     365                if (i == kbd_dev->key_count) {
    354366                        // not found, i.e. the key was released
    355                         key = usbhid_parse_scancode(kbd_dev->keycodes[j]);
     367                        key = usbhid_parse_scancode(kbd_dev->keys[j]);
     368                        usbhid_kbd_repeat_stop(kbd_dev, key);
    356369                        usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, key);
    357370                        usb_log_debug2("Key released: %d\n", key);
     
    364377         * 1) Key presses
    365378         */
    366         for (i = 0; i < kbd_dev->keycode_count; ++i) {
     379        for (i = 0; i < kbd_dev->key_count; ++i) {
    367380                // try to find the new key in the old key list
    368381                j = 0;
    369                 while (j < kbd_dev->keycode_count
    370                     && kbd_dev->keycodes[j] != key_codes[i]) {
     382                while (j < kbd_dev->key_count
     383                    && kbd_dev->keys[j] != key_codes[i]) {
    371384                        ++j;
    372385                }
    373386               
    374                 if (j == kbd_dev->keycode_count) {
     387                if (j == kbd_dev->key_count) {
    375388                        // not found, i.e. new key pressed
    376389                        key = usbhid_parse_scancode(key_codes[i]);
     
    378391                            key_codes[i]);
    379392                        usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, key);
     393                        usbhid_kbd_repeat_start(kbd_dev, key);
    380394                } else {
    381395                        // found, nothing happens
     
    392406//      }
    393407       
    394         memcpy(kbd_dev->keycodes, key_codes, kbd_dev->keycode_count);
     408        memcpy(kbd_dev->keys, key_codes, kbd_dev->key_count);
    395409
    396410        usb_log_debug("New stored keycodes: %s\n",
    397             usb_debug_str_buffer(kbd_dev->keycodes, kbd_dev->keycode_count, 0));
     411            usb_debug_str_buffer(kbd_dev->keys, kbd_dev->key_count, 0));
    398412}
    399413
     
    415429
    416430        usb_log_debug("Got keys from parser: %s\n",
    417             usb_debug_str_buffer(key_codes, kbd_dev->keycode_count, 0));
    418        
    419         if (count != kbd_dev->keycode_count) {
     431            usb_debug_str_buffer(key_codes, kbd_dev->key_count, 0));
     432       
     433        if (count != kbd_dev->key_count) {
    420434                usb_log_warning("Number of received keycodes (%d) differs from"
    421                     " expected number (%d).\n", count, kbd_dev->keycode_count);
     435                    " expected number (%d).\n", count, kbd_dev->key_count);
    422436                return;
    423437        }
     
    430444/* General kbd functions                                                      */
    431445/*----------------------------------------------------------------------------*/
    432 
     446/**
     447 * Processes data received from the device in form of report.
     448 *
     449 * This function uses the HID report parser to translate the data received from
     450 * the device into generic USB HID key codes and into generic modifiers bitmap.
     451 * The parser then calls the given callback (usbhid_kbd_process_keycodes()).
     452 *
     453 * @note Currently, only the boot protocol is supported.
     454 *
     455 * @param kbd_dev Keyboard device structure (must be initialized).
     456 * @param buffer Data from the keyboard (i.e. the report).
     457 * @param actual_size Size of the data from keyboard (report size) in bytes.
     458 *
     459 * @sa usbhid_kbd_process_keycodes(), usb_hid_boot_keyboard_input_report().
     460 */
    433461static void usbhid_kbd_process_data(usbhid_kbd_t *kbd_dev,
    434462                                    uint8_t *buffer, size_t actual_size)
     
    455483/* HID/KBD structure manipulation                                             */
    456484/*----------------------------------------------------------------------------*/
    457 
     485/**
     486 * Creates a new USB/HID keyboard structure.
     487 *
     488 * The structure returned by this function is not initialized. Use
     489 * usbhid_kbd_init() to initialize it prior to polling.
     490 *
     491 * @return New uninitialized structure for representing a USB/HID keyboard or
     492 *         NULL if not successful (memory error).
     493 */
    458494static usbhid_kbd_t *usbhid_kbd_new(void)
    459495{
     
    481517
    482518/*----------------------------------------------------------------------------*/
    483 
     519/**
     520 * Properly destroys the USB/HID keyboard structure.
     521 *
     522 * @param kbd_dev Pointer to the structure to be destroyed.
     523 */
    484524static void usbhid_kbd_free(usbhid_kbd_t **kbd_dev)
    485525{
     
    496536        }
    497537       
     538        if ((*kbd_dev)->repeat_mtx != NULL) {
     539                /* TODO: replace by some check and wait */
     540                assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
     541                free((*kbd_dev)->repeat_mtx);
     542        }
     543       
    498544        free(*kbd_dev);
    499545        *kbd_dev = NULL;
     
    501547
    502548/*----------------------------------------------------------------------------*/
    503 
     549/**
     550 * Initialization of the USB/HID keyboard structure.
     551 *
     552 * This functions initializes required structures from the device's descriptors.
     553 *
     554 * During initialization, the keyboard is switched into boot protocol, the idle
     555 * rate is set to 0 (infinity), resulting in the keyboard only reporting event
     556 * when a key is pressed or released. Finally, the LED lights are turned on
     557 * according to the default setup of lock keys.
     558 *
     559 * @note By default, the keyboards is initialized with Num Lock turned on and
     560 *       other locks turned off.
     561 *
     562 * @param kbd_dev Keyboard device structure to be initialized.
     563 * @param dev DDF device structure of the keyboard.
     564 *
     565 * @retval EOK if successful.
     566 * @retval EINVAL if some parameter is not given.
     567 * @return Other value inherited from function usbhid_dev_init().
     568 */
    504569static int usbhid_kbd_init(usbhid_kbd_t *kbd_dev, ddf_dev_t *dev)
    505570{
     
    536601       
    537602        // save the size of the report (boot protocol report by default)
    538         kbd_dev->keycode_count = BOOTP_REPORT_SIZE;
    539         kbd_dev->keycodes = (uint8_t *)calloc(
    540             kbd_dev->keycode_count, sizeof(uint8_t));
    541        
    542         if (kbd_dev->keycodes == NULL) {
     603        kbd_dev->key_count = BOOTP_REPORT_SIZE;
     604        kbd_dev->keys = (uint8_t *)calloc(
     605            kbd_dev->key_count, sizeof(uint8_t));
     606       
     607        if (kbd_dev->keys == NULL) {
    543608                usb_log_fatal("No memory!\n");
    544                 return rc;
     609                return ENOMEM;
    545610        }
    546611       
     
    549614        kbd_dev->lock_keys = 0;
    550615       
     616        kbd_dev->repeat.key_new = 0;
     617        kbd_dev->repeat.key_repeated = 0;
     618        kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;
     619        kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
     620       
     621        kbd_dev->repeat_mtx = (fibril_mutex_t *)(
     622            malloc(sizeof(fibril_mutex_t)));
     623        if (kbd_dev->repeat_mtx == NULL) {
     624                usb_log_fatal("No memory!\n");
     625                free(kbd_dev->keys);
     626                return ENOMEM;
     627        }
     628       
     629        fibril_mutex_initialize(kbd_dev->repeat_mtx);
     630       
    551631        /*
    552632         * Set boot protocol.
     
    571651/* HID/KBD polling                                                            */
    572652/*----------------------------------------------------------------------------*/
    573 
     653/**
     654 * Main keyboard polling function.
     655 *
     656 * This function uses the Interrupt In pipe of the keyboard to poll for events.
     657 * The keyboard is initialized in a way that it reports only when a key is
     658 * pressed or released, so there is no actual need for any sleeping between
     659 * polls (see usbhid_kbd_try_add_device() or usbhid_kbd_init()).
     660 *
     661 * @param kbd_dev Initialized keyboard structure representing the device to
     662 *                poll.
     663 *
     664 * @sa usbhid_kbd_process_data()
     665 */
    574666static void usbhid_kbd_poll(usbhid_kbd_t *kbd_dev)
    575667{
     
    639731
    640732/*----------------------------------------------------------------------------*/
    641 
     733/**
     734 * Function executed by the main driver fibril.
     735 *
     736 * Just starts polling the keyboard for events.
     737 *
     738 * @param arg Initialized keyboard device structure (of type usbhid_kbd_t)
     739 *            representing the device.
     740 *
     741 * @retval EOK if the fibril finished polling the device.
     742 * @retval EINVAL if no device was given in the argument.
     743 *
     744 * @sa usbhid_kbd_poll()
     745 *
     746 * @todo Change return value - only case when the fibril finishes is in case
     747 *       of some error, so the error should probably be propagated from function
     748 *       usbhid_kbd_poll() to here and up.
     749 */
    642750static int usbhid_kbd_fibril(void *arg)
    643751{
     
    661769/* API functions                                                              */
    662770/*----------------------------------------------------------------------------*/
    663 
     771/**
     772 * Function for adding a new device of type USB/HID/keyboard.
     773 *
     774 * This functions initializes required structures from the device's descriptors
     775 * and starts a new fibril for polling the keyboard for events.
     776 *
     777 * During initialization, the keyboard is switched into boot protocol, the idle
     778 * rate is set to 0 (infinity), resulting in the keyboard only reporting event
     779 * when a key is pressed or released. Finally, the LED lights are turned on
     780 * according to the default setup of lock keys.
     781 *
     782 * @note By default, the keyboards is initialized with Num Lock turned on and
     783 *       other locks turned off.
     784 * @note Currently supports only boot-protocol keyboards.
     785 *
     786 * @param dev Device to add.
     787 *
     788 * @retval EOK if successful.
     789 * @retval ENOMEM if there
     790 * @return Other error code inherited from one of functions usbhid_kbd_init(),
     791 *         ddf_fun_bind() and ddf_fun_add_to_class().
     792 *
     793 * @sa usbhid_kbd_fibril()
     794 */
    664795int usbhid_kbd_try_add_device(ddf_dev_t *dev)
    665796{
     
    683814                    "structure.\n");
    684815                ddf_fun_destroy(kbd_fun);
    685                 return EINVAL;  // TODO: some other code??
     816                return ENOMEM;  // TODO: some other code??
    686817        }
    687818       
     
    732863        }
    733864        fibril_add_ready(fid);
     865       
     866        /*
     867         * Create new fibril for auto-repeat
     868         */
     869        fid = fibril_create(usbhid_kbd_repeat_fibril, kbd_dev);
     870        if (fid == 0) {
     871                usb_log_error("Failed to start fibril for KBD auto-repeat");
     872                return ENOMEM;
     873        }
     874        fibril_add_ready(fid);
    734875
    735876        (void)keyboard_ops;
  • uspace/drv/usbhid/kbddev.h

    rf8c190e r8a02ff3  
    3939#include <stdint.h>
    4040
     41#include <fibril_synch.h>
     42
    4143#include <usb/classes/hid.h>
    4244#include <ddf/driver.h>
     
    4648
    4749/*----------------------------------------------------------------------------*/
     50/**
     51 * Structure for keeping information needed for auto-repeat of keys.
     52 */
     53typedef struct {
     54        /** Last pressed key. */
     55        unsigned int key_new;
     56        /** Key to be repeated. */
     57        unsigned int key_repeated;
     58        /** Delay before first repeat in microseconds. */
     59        unsigned int delay_before;
     60        /** Delay between repeats in microseconds. */
     61        unsigned int delay_between;
     62} usbhid_kbd_repeat_t;
    4863
    4964/**
    50  * @brief USB/HID keyboard device type.
     65 * USB/HID keyboard device type.
     66 *
     67 * Holds a reference to generic USB/HID device structure and keyboard-specific
     68 * data, such as currently pressed keys, modifiers and lock keys.
     69 *
     70 * Also holds a IPC phone to the console (since there is now no other way to
     71 * communicate with it).
     72 *
     73 * @note Storing active lock keys in this structure results in their setting
     74 *       being device-specific.
    5175 */
    5276typedef struct {
     77        /** Structure holding generic USB/HID device information. */
    5378        usbhid_dev_t *hid_dev;
    5479       
    55         uint8_t *keycodes;
    56         size_t keycode_count;
     80        /** Currently pressed keys (not translated to key codes). */
     81        uint8_t *keys;
     82        /** Count of stored keys (i.e. number of keys in the report). */
     83        size_t key_count;
     84        /** Currently pressed modifiers (bitmap). */
    5785        uint8_t modifiers;
    5886       
     87        /** Currently active modifiers including locks. Sent to the console. */
    5988        unsigned mods;
     89       
     90        /** Currently active lock keys. */
    6091        unsigned lock_keys;
    6192       
     93        /** IPC phone to the console device (for sending key events). */
    6294        int console_phone;
    6395       
     96        /** Information for auto-repeat of keys. */
     97        usbhid_kbd_repeat_t repeat;
     98       
     99        /** Mutex for accessing the information about auto-repeat. */
     100        fibril_mutex_t *repeat_mtx;
     101       
     102        /** State of the structure (for checking before use). */
    64103        int initialized;
    65104} usbhid_kbd_t;
     
    69108int usbhid_kbd_try_add_device(ddf_dev_t *dev);
    70109
     110void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, unsigned int key);
     111
    71112#endif /* USBHID_KBDDEV_H_ */
    72113
  • uspace/drv/usbhid/main.c

    rf8c190e r8a02ff3  
    4747
    4848/*----------------------------------------------------------------------------*/
    49 
     49/**
     50 * Callback for passing a new device to the driver.
     51 *
     52 * @note Currently, only boot-protocol keyboards are supported by this driver.
     53 *
     54 * @param dev Structure representing the new device.
     55 *
     56 * @retval EOK if successful.
     57 * @retval EREFUSED if the device is not supported.
     58 */
    5059static int usbhid_add_device(ddf_dev_t *dev)
    5160{
Note: See TracChangeset for help on using the changeset viewer.