Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/usbhid/kbddev.c

    rb05e2fe rd477734  
    3737#include <errno.h>
    3838#include <str_error.h>
     39#include <fibril.h>
    3940#include <stdio.h>
    4041
     
    4243#include <ipc/kbd.h>
    4344#include <async.h>
    44 #include <fibril.h>
    45 #include <fibril_synch.h>
    4645
    4746#include <usb/usb.h>
     
    5756#include "layout.h"
    5857#include "conv.h"
    59 #include "kbdrepeat.h"
    60 
    61 /*----------------------------------------------------------------------------*/
    62 /** Default modifiers when the keyboard is initialized. */
     58
     59/*----------------------------------------------------------------------------*/
     60
    6361static const unsigned DEFAULT_ACTIVE_MODS = KM_NUM_LOCK;
    64 
    65 /** Boot protocol report size (key part). */
    6662static const size_t BOOTP_REPORT_SIZE = 6;
    67 
    68 /** Boot protocol total report size. */
    6963static const size_t BOOTP_BUFFER_SIZE = 8;
    70 
    71 /** Boot protocol output report size. */
    7264static const size_t BOOTP_BUFFER_OUT_SIZE = 1;
    73 
    74 /** Boot protocol error key code. */
    7565static const uint8_t BOOTP_ERROR_ROLLOVER = 1;
    76 
    77 /** Default idle rate for keyboards. */
    7866static const uint8_t IDLE_RATE = 0;
    79 
    80 /** Delay before a pressed key starts auto-repeating. */
    81 static const unsigned int DEFAULT_DELAY_BEFORE_FIRST_REPEAT = 500 * 1000;
    82 
    83 /** Delay between two repeats of a pressed key when auto-repeating. */
    84 static const unsigned int DEFAULT_REPEAT_DELAY = 50 * 1000;
    8567
    8668/** Keyboard polling endpoint description for boot protocol class. */
     
    10082#define NUM_LAYOUTS 3
    10183
    102 /** Keyboard layout map. */
    10384static layout_op_t *layout[NUM_LAYOUTS] = {
    10485        &us_qwerty_op,
     
    11293/* Modifier constants                                                         */
    11394/*----------------------------------------------------------------------------*/
    114 /** Mapping of USB modifier key codes to generic modifier key codes. */
     95
    11596static const keycode_t usbhid_modifiers_keycodes[USB_HID_MOD_COUNT] = {
    11697        KC_LCTRL,         /* USB_HID_MOD_LCTRL */
     
    133114};
    134115
    135 /**
    136  * Default handler for IPC methods not handled by DDF.
     116/** Default handler for IPC methods not handled by DDF.
    137117 *
    138  * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it
    139  * assumes the caller is the console and thus it stores IPC phone to it for
    140  * later use by the driver to notify about key events.
    141  *
    142  * @param fun Device function handling the call.
     118 * @param dev Device handling the call.
    143119 * @param icallid Call id.
    144120 * @param icall Call data.
     
    171147/* Key processing functions                                                   */
    172148/*----------------------------------------------------------------------------*/
    173 /**
    174  * Handles turning of LED lights on and off.
    175  *
    176  * In case of USB keyboards, the LEDs are handled in the driver, not in the
    177  * device. When there should be a change (lock key was pressed), the driver
    178  * uses a Set_Report request sent to the device to set the state of the LEDs.
    179  *
    180  * This functions sets the LED lights according to current settings of modifiers
    181  * kept in the keyboard device structure.
    182  *
    183  * @param kbd_dev Keyboard device structure.
    184  */
     149
    185150static void usbhid_kbd_set_led(usbhid_kbd_t *kbd_dev)
    186151{
     
    224189
    225190/*----------------------------------------------------------------------------*/
    226 /**
    227  * Processes key events.
    228  *
    229  * @note This function was copied from AT keyboard driver and modified to suit
    230  *       USB keyboard.
    231  *
    232  * @note Lock keys are not sent to the console, as they are completely handled
    233  *       in the driver. It may, however, be required later that the driver
    234  *       sends also these keys to application (otherwise it cannot use those
    235  *       keys at all).
    236  *
    237  * @param kbd_dev Keyboard device structure.
    238  * @param type Type of the event (press / release). Recognized values:
    239  *             KEY_PRESS, KEY_RELEASE
    240  * @param key Key code of the key according to HID Usage Tables.
    241  */
    242 void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, unsigned int key)
     191
     192static void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type,
     193    unsigned int key)
    243194{
    244195        console_event_t ev;
    245196        unsigned mod_mask;
    246197
    247         /*
    248          * These parts are copy-pasted from the AT keyboard driver.
    249          *
    250          * They definitely require some refactoring, but will keep it for later
    251          * when the console and keyboard system is changed in HelenOS.
    252          */
     198        // TODO: replace by our own parsing?? or are the key codes identical??
    253199        switch (key) {
    254200        case KC_LCTRL: mod_mask = KM_LCTRL; break;
     
    282228                         * up the lock state.
    283229                         */
    284                         unsigned int locks_old = kbd_dev->lock_keys;
    285                        
    286230                        kbd_dev->mods =
    287231                            kbd_dev->mods ^ (mod_mask & ~kbd_dev->lock_keys);
     
    289233
    290234                        /* Update keyboard lock indicator lights. */
    291                         if (kbd_dev->lock_keys != locks_old) {
    292                                 usbhid_kbd_set_led(kbd_dev);
    293                         }
     235                        usbhid_kbd_set_led(kbd_dev);
    294236                } else {
    295237                        kbd_dev->lock_keys = kbd_dev->lock_keys & ~mod_mask;
     
    338280
    339281/*----------------------------------------------------------------------------*/
    340 /**
    341  * Checks if modifiers were pressed or released and generates key events.
    342  *
    343  * @param kbd_dev Keyboard device structure.
    344  * @param modifiers Bitmap of modifiers.
    345  *
    346  * @sa usbhid_kbd_push_ev()
    347  */
     282
    348283static void usbhid_kbd_check_modifier_changes(usbhid_kbd_t *kbd_dev,
    349284    uint8_t modifiers)
     
    381316
    382317/*----------------------------------------------------------------------------*/
    383 /**
    384  * Checks if some keys were pressed or released and generates key events.
    385  *
    386  * An event is created only when key is pressed or released. Besides handling
    387  * the events (usbhid_kbd_push_ev()), the auto-repeat fibril is notified about
    388  * key presses and releases (see usbhid_kbd_repeat_start() and
    389  * usbhid_kbd_repeat_stop()).
    390  *
    391  * @param kbd_dev Keyboard device structure.
    392  * @param key_codes Parsed keyboard report - codes of currently pressed keys
    393  *                  according to HID Usage Tables.
    394  * @param count Number of key codes in report (size of the report).
    395  *
    396  * @sa usbhid_kbd_push_ev(), usbhid_kbd_repeat_start(), usbhid_kbd_repeat_stop()
    397  */
     318
    398319static void usbhid_kbd_check_key_changes(usbhid_kbd_t *kbd_dev,
    399     const uint8_t *key_codes, size_t count)
     320    const uint8_t *key_codes)
    400321{
    401322        unsigned int key;
     
    407328        i = 0;
    408329        // all fields should report Error Rollover
    409         while (i < count &&
     330        while (i < kbd_dev->keycode_count &&
    410331            key_codes[i] == BOOTP_ERROR_ROLLOVER) {
    411332                ++i;
    412333        }
    413         if (i == count) {
     334        if (i == kbd_dev->keycode_count) {
    414335                usb_log_debug("Phantom state occured.\n");
    415336                // phantom state, do nothing
     
    417338        }
    418339       
    419         /* TODO: quite dummy right now, think of better implementation */
    420         assert(count == kbd_dev->key_count);
     340        // TODO: quite dummy right now, think of better implementation
    421341       
    422342        /*
    423343         * 1) Key releases
    424344         */
    425         for (j = 0; j < count; ++j) {
     345        for (j = 0; j < kbd_dev->keycode_count; ++j) {
    426346                // try to find the old key in the new key list
    427347                i = 0;
    428                 while (i < kbd_dev->key_count
    429                     && key_codes[i] != kbd_dev->keys[j]) {
     348                while (i < kbd_dev->keycode_count
     349                    && key_codes[i] != kbd_dev->keycodes[j]) {
    430350                        ++i;
    431351                }
    432352               
    433                 if (i == count) {
     353                if (i == kbd_dev->keycode_count) {
    434354                        // not found, i.e. the key was released
    435                         key = usbhid_parse_scancode(kbd_dev->keys[j]);
    436                         usbhid_kbd_repeat_stop(kbd_dev, key);
     355                        key = usbhid_parse_scancode(kbd_dev->keycodes[j]);
    437356                        usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, key);
    438357                        usb_log_debug2("Key released: %d\n", key);
     
    445364         * 1) Key presses
    446365         */
    447         for (i = 0; i < kbd_dev->key_count; ++i) {
     366        for (i = 0; i < kbd_dev->keycode_count; ++i) {
    448367                // try to find the new key in the old key list
    449368                j = 0;
    450                 while (j < count && kbd_dev->keys[j] != key_codes[i]) {
     369                while (j < kbd_dev->keycode_count
     370                    && kbd_dev->keycodes[j] != key_codes[i]) {
    451371                        ++j;
    452372                }
    453373               
    454                 if (j == count) {
     374                if (j == kbd_dev->keycode_count) {
    455375                        // not found, i.e. new key pressed
    456376                        key = usbhid_parse_scancode(key_codes[i]);
     
    458378                            key_codes[i]);
    459379                        usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, key);
    460                         usbhid_kbd_repeat_start(kbd_dev, key);
    461380                } else {
    462381                        // found, nothing happens
    463382                }
    464383        }
    465        
    466         memcpy(kbd_dev->keys, key_codes, count);
     384//      // report all currently pressed keys
     385//      for (i = 0; i < kbd_dev->keycode_count; ++i) {
     386//              if (key_codes[i] != 0) {
     387//                      key = usbhid_parse_scancode(key_codes[i]);
     388//                      usb_log_debug2("Key pressed: %d (keycode: %d)\n", key,
     389//                          key_codes[i]);
     390//                      usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, key);
     391//              }
     392//      }
     393       
     394        memcpy(kbd_dev->keycodes, key_codes, kbd_dev->keycode_count);
    467395
    468396        usb_log_debug("New stored keycodes: %s\n",
    469             usb_debug_str_buffer(kbd_dev->keys, kbd_dev->key_count, 0));
     397            usb_debug_str_buffer(kbd_dev->keycodes, kbd_dev->keycode_count, 0));
    470398}
    471399
     
    473401/* Callbacks for parser                                                       */
    474402/*----------------------------------------------------------------------------*/
    475 /**
    476  * Callback function for the HID report parser.
    477  *
    478  * This function is called by the HID report parser with the parsed report.
    479  * The parsed report is used to check if any events occured (key was pressed or
    480  * released, modifier was pressed or released).
    481  *
    482  * @param key_codes Parsed keyboard report - codes of currently pressed keys
    483  *                  according to HID Usage Tables.
    484  * @param count Number of key codes in report (size of the report).
    485  * @param modifiers Bitmap of modifiers (Ctrl, Alt, Shift, GUI).
    486  * @param arg User-specified argument. Expects pointer to the keyboard device
    487  *            structure representing the keyboard.
    488  *
    489  * @sa usbhid_kbd_check_key_changes(), usbhid_kbd_check_modifier_changes()
    490  */
     403
    491404static void usbhid_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
    492405    uint8_t modifiers, void *arg)
     
    502415
    503416        usb_log_debug("Got keys from parser: %s\n",
    504             usb_debug_str_buffer(key_codes, kbd_dev->key_count, 0));
    505        
    506         if (count != kbd_dev->key_count) {
     417            usb_debug_str_buffer(key_codes, kbd_dev->keycode_count, 0));
     418       
     419        if (count != kbd_dev->keycode_count) {
    507420                usb_log_warning("Number of received keycodes (%d) differs from"
    508                     " expected number (%d).\n", count, kbd_dev->key_count);
     421                    " expected number (%d).\n", count, kbd_dev->keycode_count);
    509422                return;
    510423        }
    511424       
    512425        usbhid_kbd_check_modifier_changes(kbd_dev, modifiers);
    513         usbhid_kbd_check_key_changes(kbd_dev, key_codes, count);
     426        usbhid_kbd_check_key_changes(kbd_dev, key_codes);
    514427}
    515428
     
    517430/* General kbd functions                                                      */
    518431/*----------------------------------------------------------------------------*/
    519 /**
    520  * Processes data received from the device in form of report.
    521  *
    522  * This function uses the HID report parser to translate the data received from
    523  * the device into generic USB HID key codes and into generic modifiers bitmap.
    524  * The parser then calls the given callback (usbhid_kbd_process_keycodes()).
    525  *
    526  * @note Currently, only the boot protocol is supported.
    527  *
    528  * @param kbd_dev Keyboard device structure (must be initialized).
    529  * @param buffer Data from the keyboard (i.e. the report).
    530  * @param actual_size Size of the data from keyboard (report size) in bytes.
    531  *
    532  * @sa usbhid_kbd_process_keycodes(), usb_hid_boot_keyboard_input_report().
    533  */
     432
    534433static void usbhid_kbd_process_data(usbhid_kbd_t *kbd_dev,
    535434                                    uint8_t *buffer, size_t actual_size)
     
    556455/* HID/KBD structure manipulation                                             */
    557456/*----------------------------------------------------------------------------*/
    558 /**
    559  * Creates a new USB/HID keyboard structure.
    560  *
    561  * The structure returned by this function is not initialized. Use
    562  * usbhid_kbd_init() to initialize it prior to polling.
    563  *
    564  * @return New uninitialized structure for representing a USB/HID keyboard or
    565  *         NULL if not successful (memory error).
    566  */
     457
    567458static usbhid_kbd_t *usbhid_kbd_new(void)
    568459{
     
    590481
    591482/*----------------------------------------------------------------------------*/
    592 /**
    593  * Properly destroys the USB/HID keyboard structure.
    594  *
    595  * @param kbd_dev Pointer to the structure to be destroyed.
    596  */
     483
    597484static void usbhid_kbd_free(usbhid_kbd_t **kbd_dev)
    598485{
     
    609496        }
    610497       
    611         if ((*kbd_dev)->repeat_mtx != NULL) {
    612                 /* TODO: replace by some check and wait */
    613                 assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
    614                 free((*kbd_dev)->repeat_mtx);
    615         }
    616        
    617498        free(*kbd_dev);
    618499        *kbd_dev = NULL;
     
    620501
    621502/*----------------------------------------------------------------------------*/
    622 /**
    623  * Initialization of the USB/HID keyboard structure.
    624  *
    625  * This functions initializes required structures from the device's descriptors.
    626  *
    627  * During initialization, the keyboard is switched into boot protocol, the idle
    628  * rate is set to 0 (infinity), resulting in the keyboard only reporting event
    629  * when a key is pressed or released. Finally, the LED lights are turned on
    630  * according to the default setup of lock keys.
    631  *
    632  * @note By default, the keyboards is initialized with Num Lock turned on and
    633  *       other locks turned off.
    634  *
    635  * @param kbd_dev Keyboard device structure to be initialized.
    636  * @param dev DDF device structure of the keyboard.
    637  *
    638  * @retval EOK if successful.
    639  * @retval EINVAL if some parameter is not given.
    640  * @return Other value inherited from function usbhid_dev_init().
    641  */
     503
    642504static int usbhid_kbd_init(usbhid_kbd_t *kbd_dev, ddf_dev_t *dev)
    643505{
     
    674536       
    675537        // save the size of the report (boot protocol report by default)
    676         kbd_dev->key_count = BOOTP_REPORT_SIZE;
    677         kbd_dev->keys = (uint8_t *)calloc(
    678             kbd_dev->key_count, sizeof(uint8_t));
    679        
    680         if (kbd_dev->keys == NULL) {
     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) {
    681543                usb_log_fatal("No memory!\n");
    682                 return ENOMEM;
     544                return rc;
    683545        }
    684546       
     
    687549        kbd_dev->lock_keys = 0;
    688550       
    689         kbd_dev->repeat.key_new = 0;
    690         kbd_dev->repeat.key_repeated = 0;
    691         kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;
    692         kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
    693        
    694         kbd_dev->repeat_mtx = (fibril_mutex_t *)(
    695             malloc(sizeof(fibril_mutex_t)));
    696         if (kbd_dev->repeat_mtx == NULL) {
    697                 usb_log_fatal("No memory!\n");
    698                 free(kbd_dev->keys);
    699                 return ENOMEM;
    700         }
    701        
    702         fibril_mutex_initialize(kbd_dev->repeat_mtx);
    703        
    704551        /*
    705552         * Set boot protocol.
     
    724571/* HID/KBD polling                                                            */
    725572/*----------------------------------------------------------------------------*/
    726 /**
    727  * Main keyboard polling function.
    728  *
    729  * This function uses the Interrupt In pipe of the keyboard to poll for events.
    730  * The keyboard is initialized in a way that it reports only when a key is
    731  * pressed or released, so there is no actual need for any sleeping between
    732  * polls (see usbhid_kbd_try_add_device() or usbhid_kbd_init()).
    733  *
    734  * @param kbd_dev Initialized keyboard structure representing the device to
    735  *                poll.
    736  *
    737  * @sa usbhid_kbd_process_data()
    738  */
     573
    739574static void usbhid_kbd_poll(usbhid_kbd_t *kbd_dev)
    740575{
     
    759594                        usb_log_warning("Failed to start a session: %s.\n",
    760595                            str_error(sess_rc));
    761                         break;
     596                        continue;
    762597                }
    763598
     
    771606                        usb_log_warning("Error polling the keyboard: %s.\n",
    772607                            str_error(rc));
    773                         break;
     608                        continue;
    774609                }
    775610
     
    777612                        usb_log_warning("Error closing session: %s.\n",
    778613                            str_error(sess_rc));
    779                         break;
     614                        continue;
    780615                }
    781616
     
    798633                //async_usleep(kbd_dev->hid_dev->poll_interval);
    799634        }
    800 }
    801 
    802 /*----------------------------------------------------------------------------*/
    803 /**
    804  * Function executed by the main driver fibril.
    805  *
    806  * Just starts polling the keyboard for events.
    807  *
    808  * @param arg Initialized keyboard device structure (of type usbhid_kbd_t)
    809  *            representing the device.
    810  *
    811  * @retval EOK if the fibril finished polling the device.
    812  * @retval EINVAL if no device was given in the argument.
    813  *
    814  * @sa usbhid_kbd_poll()
    815  *
    816  * @todo Change return value - only case when the fibril finishes is in case
    817  *       of some error, so the error should probably be propagated from function
    818  *       usbhid_kbd_poll() to here and up.
    819  */
     635
     636        // not reached
     637        assert(0);
     638}
     639
     640/*----------------------------------------------------------------------------*/
     641
    820642static int usbhid_kbd_fibril(void *arg)
    821643{
     
    839661/* API functions                                                              */
    840662/*----------------------------------------------------------------------------*/
    841 /**
    842  * Function for adding a new device of type USB/HID/keyboard.
    843  *
    844  * This functions initializes required structures from the device's descriptors
    845  * and starts new fibril for polling the keyboard for events and another one for
    846  * handling auto-repeat of keys.
    847  *
    848  * During initialization, the keyboard is switched into boot protocol, the idle
    849  * rate is set to 0 (infinity), resulting in the keyboard only reporting event
    850  * when a key is pressed or released. Finally, the LED lights are turned on
    851  * according to the default setup of lock keys.
    852  *
    853  * @note By default, the keyboards is initialized with Num Lock turned on and
    854  *       other locks turned off.
    855  * @note Currently supports only boot-protocol keyboards.
    856  *
    857  * @param dev Device to add.
    858  *
    859  * @retval EOK if successful.
    860  * @retval ENOMEM if there
    861  * @return Other error code inherited from one of functions usbhid_kbd_init(),
    862  *         ddf_fun_bind() and ddf_fun_add_to_class().
    863  *
    864  * @sa usbhid_kbd_fibril(), usbhid_kbd_repeat_fibril()
    865  */
     663
    866664int usbhid_kbd_try_add_device(ddf_dev_t *dev)
    867665{
     
    885683                    "structure.\n");
    886684                ddf_fun_destroy(kbd_fun);
    887                 return ENOMEM;  // TODO: some other code??
     685                return EINVAL;  // TODO: some other code??
    888686        }
    889687       
     
    934732        }
    935733        fibril_add_ready(fid);
    936        
    937         /*
    938          * Create new fibril for auto-repeat
    939          */
    940         fid = fibril_create(usbhid_kbd_repeat_fibril, kbd_dev);
    941         if (fid == 0) {
    942                 usb_log_error("Failed to start fibril for KBD auto-repeat");
    943                 return ENOMEM;
    944         }
    945         fibril_add_ready(fid);
    946734
    947735        (void)keyboard_ops;
Note: See TracChangeset for help on using the changeset viewer.