Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.c

    r31cfee16 re3b5129  
    3838#include "lgtch-ultrax.h"
    3939#include "../usbhid.h"
    40 #include "keymap.h"
    4140
    4241#include <usb/classes/hidparser.h>
    4342#include <usb/debug.h>
    44 #include <usb/classes/hidut.h>
    45 
    4643#include <errno.h>
    4744#include <str_error.h>
    4845
    49 #include <ipc/kbd.h>
    50 #include <io/console.h>
    51 
    5246#define NAME "lgtch-ultrax"
    53 
    54 typedef enum usb_lgtch_flags {
    55         USB_LGTCH_STATUS_UNINITIALIZED = 0,
    56         USB_LGTCH_STATUS_INITIALIZED = 1,
    57         USB_LGTCH_STATUS_TO_DESTROY = -1
    58 } usb_lgtch_flags;
    59 
    60 /*----------------------------------------------------------------------------*/
    61 /**
    62  * Logitech UltraX device type.
    63  */
    64 typedef struct usb_lgtch_ultrax_t {
    65         /** Previously pressed keys (not translated to key codes). */
    66         int32_t *keys_old;
    67         /** Currently pressed keys (not translated to key codes). */
    68         int32_t *keys;
    69         /** Count of stored keys (i.e. number of keys in the report). */
    70         size_t key_count;
    71        
    72         /** IPC phone to the console device (for sending key events). */
    73         int console_phone;
    74 
    75         /** Information for auto-repeat of keys. */
    76 //      usb_kbd_repeat_t repeat;
    77        
    78         /** Mutex for accessing the information about auto-repeat. */
    79 //      fibril_mutex_t *repeat_mtx;
    80 
    81         /** State of the structure (for checking before use).
    82          *
    83          * 0 - not initialized
    84          * 1 - initialized
    85          * -1 - ready for destroying
    86          */
    87         int initialized;
    88 } usb_lgtch_ultrax_t;
    89 
    90 
    91 /*----------------------------------------------------------------------------*/
    92 /**
    93  * Default handler for IPC methods not handled by DDF.
    94  *
    95  * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it
    96  * assumes the caller is the console and thus it stores IPC phone to it for
    97  * later use by the driver to notify about key events.
    98  *
    99  * @param fun Device function handling the call.
    100  * @param icallid Call id.
    101  * @param icall Call data.
    102  */
    103 static void default_connection_handler(ddf_fun_t *fun,
    104     ipc_callid_t icallid, ipc_call_t *icall)
    105 {
    106         usb_log_debug(NAME " default_connection_handler()\n");
    107        
    108         sysarg_t method = IPC_GET_IMETHOD(*icall);
    109        
    110         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
    111        
    112         if (hid_dev == NULL || hid_dev->data == NULL) {
    113                 async_answer_0(icallid, EINVAL);
    114                 return;
    115         }
    116        
    117         assert(hid_dev != NULL);
    118         assert(hid_dev->data != NULL);
    119         usb_lgtch_ultrax_t *lgtch_dev = (usb_lgtch_ultrax_t *)hid_dev->data;
    120 
    121         if (method == IPC_M_CONNECT_TO_ME) {
    122                 int callback = IPC_GET_ARG5(*icall);
    123 
    124                 if (lgtch_dev->console_phone != -1) {
    125                         async_answer_0(icallid, ELIMIT);
    126                         return;
    127                 }
    128 
    129                 lgtch_dev->console_phone = callback;
    130                 usb_log_debug(NAME " Saved phone to console: %d\n", callback);
    131                 async_answer_0(icallid, EOK);
    132                 return;
    133         }
    134        
    135         async_answer_0(icallid, EINVAL);
    136 }
    13747
    13848/*----------------------------------------------------------------------------*/
    13949
    140 static ddf_dev_ops_t lgtch_ultrax_ops = {
    141         .default_handler = default_connection_handler
     50static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count,
     51    uint8_t report_id, void *arg);
     52
     53static const usb_hid_report_in_callbacks_t usb_lgtch_parser_callbacks = {
     54        .keyboard = usb_lgtch_process_keycodes
    14255};
    14356
    14457/*----------------------------------------------------------------------------*/
    14558
    146 //static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count,
    147 //    uint8_t report_id, void *arg);
    148 
    149 //static const usb_hid_report_in_callbacks_t usb_lgtch_parser_callbacks = {
    150 //      .keyboard = usb_lgtch_process_keycodes
    151 //};
    152 
    153 ///*----------------------------------------------------------------------------*/
    154 
    155 //static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count,
    156 //    uint8_t report_id, void *arg)
    157 //{
    158 //      // TODO: checks
     59static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count,
     60    uint8_t report_id, void *arg)
     61{
     62        // TODO: checks
    15963       
    160 //      usb_log_debug(NAME " Got keys from parser (report id: %u): %s\n",
    161 //          report_id, usb_debug_str_buffer(key_codes, count, 0));
    162 //}
    163 
    164 /*----------------------------------------------------------------------------*/
    165 /**
    166  * Processes key events.
    167  *
    168  * @note This function was copied from AT keyboard driver and modified to suit
    169  *       USB keyboard.
    170  *
    171  * @note Lock keys are not sent to the console, as they are completely handled
    172  *       in the driver. It may, however, be required later that the driver
    173  *       sends also these keys to application (otherwise it cannot use those
    174  *       keys at all).
    175  *
    176  * @param hid_dev
    177  * @param lgtch_dev
    178  * @param type Type of the event (press / release). Recognized values:
    179  *             KEY_PRESS, KEY_RELEASE
    180  * @param key Key code of the key according to HID Usage Tables.
    181  */
    182 static void usb_lgtch_push_ev(usb_hid_dev_t *hid_dev, int type,
    183     unsigned int key)
    184 {
    185         assert(hid_dev != NULL);
    186         assert(hid_dev->data != NULL);
    187        
    188         usb_lgtch_ultrax_t *lgtch_dev = (usb_lgtch_ultrax_t *)hid_dev->data;
    189        
    190         console_event_t ev;
    191        
    192         ev.type = type;
    193         ev.key = key;
    194         ev.mods = 0;
    195 
    196         ev.c = 0;
    197 
    198         usb_log_debug2(NAME " Sending key %d to the console\n", ev.key);
    199         if (lgtch_dev->console_phone < 0) {
    200                 usb_log_warning(
    201                     "Connection to console not ready, key discarded.\n");
    202                 return;
    203         }
    204        
    205         async_msg_4(lgtch_dev->console_phone, KBD_EVENT, ev.type, ev.key,
    206             ev.mods, ev.c);
    207 }
    208 
    209 /*----------------------------------------------------------------------------*/
    210 
    211 static void usb_lgtch_free(usb_lgtch_ultrax_t **lgtch_dev)
    212 {
    213         if (lgtch_dev == NULL || *lgtch_dev == NULL) {
    214                 return;
    215         }
    216        
    217         // hangup phone to the console
    218         async_hangup((*lgtch_dev)->console_phone);
    219        
    220 //      if ((*lgtch_dev)->repeat_mtx != NULL) {
    221 //              /* TODO: replace by some check and wait */
    222 //              assert(!fibril_mutex_is_locked((*lgtch_dev)->repeat_mtx));
    223 //              free((*lgtch_dev)->repeat_mtx);
    224 //      }
    225        
    226         // free all buffers
    227         if ((*lgtch_dev)->keys != NULL) {
    228                 free((*lgtch_dev)->keys);
    229         }
    230         if ((*lgtch_dev)->keys_old != NULL) {
    231                 free((*lgtch_dev)->keys_old);
    232         }
    233 
    234         free(*lgtch_dev);
    235         *lgtch_dev = NULL;
    236 }
    237 
    238 /*----------------------------------------------------------------------------*/
    239 
    240 static int usb_lgtch_create_function(usb_hid_dev_t *hid_dev)
    241 {
    242         /* Create the function exposed under /dev/devices. */
    243         ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    244             NAME);
    245         if (fun == NULL) {
    246                 usb_log_error("Could not create DDF function node.\n");
    247                 return ENOMEM;
    248         }
    249        
    250         /*
    251          * Store the initialized HID device and HID ops
    252          * to the DDF function.
    253          */
    254         fun->ops = &lgtch_ultrax_ops;
    255         fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
    256        
    257         int rc = ddf_fun_bind(fun);
    258         if (rc != EOK) {
    259                 usb_log_error("Could not bind DDF function: %s.\n",
    260                     str_error(rc));
    261                 // TODO: Can / should I destroy the DDF function?
    262                 ddf_fun_destroy(fun);
    263                 return rc;
    264         }
    265        
    266         rc = ddf_fun_add_to_class(fun, "keyboard");
    267         if (rc != EOK) {
    268                 usb_log_error(
    269                     "Could not add DDF function to class 'keyboard': %s.\n",
    270                     str_error(rc));
    271                 // TODO: Can / should I destroy the DDF function?
    272                 ddf_fun_destroy(fun);
    273                 return rc;
    274         }
    275        
    276         return EOK;
    277 }
    278 
    279 /*----------------------------------------------------------------------------*/
    280 
    281 int usb_lgtch_init(struct usb_hid_dev *hid_dev)
    282 {
    283         if (hid_dev == NULL || hid_dev->usb_dev == NULL) {
    284                 return EINVAL; /*! @todo Other return code? */
    285         }
    286        
    287         usb_log_debug(NAME " Initializing HID/lgtch_ultrax structure...\n");
    288        
    289         usb_lgtch_ultrax_t *lgtch_dev = (usb_lgtch_ultrax_t *)malloc(
    290             sizeof(usb_lgtch_ultrax_t));
    291         if (lgtch_dev == NULL) {
    292                 return ENOMEM;
    293         }
    294        
    295         lgtch_dev->console_phone = -1;
    296        
    297         usb_hid_report_path_t *path = usb_hid_report_path();
    298         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
    299        
    300         usb_hid_report_path_set_report_id(path, 1);
    301        
    302         lgtch_dev->key_count = usb_hid_report_input_length(
    303             hid_dev->report, path,
    304             USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);
    305         usb_hid_report_path_free(path);
    306        
    307         usb_log_debug(NAME " Size of the input report: %zu\n",
    308             lgtch_dev->key_count);
    309        
    310         lgtch_dev->keys = (int32_t *)calloc(lgtch_dev->key_count,
    311             sizeof(int32_t));
    312        
    313         if (lgtch_dev->keys == NULL) {
    314                 usb_log_fatal("No memory!\n");
    315                 free(lgtch_dev);
    316                 return ENOMEM;
    317         }
    318        
    319         lgtch_dev->keys_old =
    320                 (int32_t *)calloc(lgtch_dev->key_count, sizeof(int32_t));
    321        
    322         if (lgtch_dev->keys_old == NULL) {
    323                 usb_log_fatal("No memory!\n");
    324                 free(lgtch_dev->keys);
    325                 free(lgtch_dev);
    326                 return ENOMEM;
    327         }
    328        
    329         /*! @todo Autorepeat */
    330        
    331         // save the KBD device structure into the HID device structure
    332         hid_dev->data = lgtch_dev;
    333        
    334         lgtch_dev->initialized = USB_LGTCH_STATUS_INITIALIZED;
    335         usb_log_debug(NAME " HID/lgtch_ultrax device structure initialized.\n");
    336        
    337         int rc = usb_lgtch_create_function(hid_dev);
    338         if (rc != EOK) {
    339                 usb_lgtch_free(&lgtch_dev);
    340                 return rc;
    341         }
    342        
    343         usb_log_debug(NAME " HID/lgtch_ultrax structure initialized.\n");
    344        
    345         return EOK;
    346 }
    347 
    348 /*----------------------------------------------------------------------------*/
    349 
    350 void usb_lgtch_deinit(struct usb_hid_dev *hid_dev)
    351 {
    352         if (hid_dev == NULL) {
    353                 return;
    354         }
    355        
    356         if (hid_dev->data != NULL) {
    357                 usb_lgtch_ultrax_t *lgtch_dev =
    358                     (usb_lgtch_ultrax_t *)hid_dev->data;
    359 //              if (usb_kbd_is_initialized(kbd_dev)) {
    360 //                      usb_kbd_mark_unusable(kbd_dev);
    361 //              } else {
    362                         usb_lgtch_free(&lgtch_dev);
    363                         hid_dev->data = NULL;
    364 //              }
    365         }
     64        usb_log_debug(NAME " Got keys from parser (report id: %u): %s\n",
     65            report_id, usb_debug_str_buffer(key_codes, count, 0));
    36666}
    36767
     
    38181        usb_hid_report_path_t *path = usb_hid_report_path();
    38282        usb_hid_report_path_append_item(path, 0xc, 0);
     83        usb_hid_report_path_set_report_id(path, 1);
     84       
     85        int rc = usb_hid_parse_report(hid_dev->parser, buffer,
     86            buffer_size, path,
     87            USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
     88            &usb_lgtch_parser_callbacks, hid_dev);
    38389
    384         uint8_t report_id;
    385        
    386         int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size,
    387             &report_id);
     90        usb_hid_report_path_free(path);
    38891       
    38992        if (rc != EOK) {
    390                 usb_log_warning(NAME "Error in usb_hid_parse_report(): %s\n",
    391                     str_error(rc));
    392                 return true;
     93                usb_log_warning("Error in usb_hid_boot_keyboard_input_report():"
     94                    "%s\n", str_error(rc));
    39395        }
    394        
    395         usb_hid_report_path_set_report_id(path, report_id);
    396 
    397         usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    398             hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END
    399             | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    400             USB_HID_REPORT_TYPE_INPUT);
    401        
    402         unsigned int key;
    403        
    404         /*! @todo Is this iterating OK if done multiple times?
    405          *  @todo The parsing is not OK
    406          */
    407         while (field != NULL) {
    408                 usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n", field->value,
    409                     field->usage);
    410                
    411                 key = usb_lgtch_map_usage(field->usage);
    412                 usb_lgtch_push_ev(hid_dev, KEY_PRESS, key);
    413                
    414                 field = usb_hid_report_get_sibling(
    415                     hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
    416                     | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    417                     USB_HID_REPORT_TYPE_INPUT);
    418         }       
    419 
    420         usb_hid_report_path_free(path);
    42196       
    42297        return true;
Note: See TracChangeset for help on using the changeset viewer.