Ignore:
File:
1 edited

Legend:

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

    rb20de1d 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 /**
    63  * Default handler for IPC methods not handled by DDF.
    64  *
    65  * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it
    66  * assumes the caller is the console and thus it stores IPC phone to it for
    67  * later use by the driver to notify about key events.
    68  *
    69  * @param fun Device function handling the call.
    70  * @param icallid Call id.
    71  * @param icall Call data.
    72  */
    73 static void default_connection_handler(ddf_fun_t *fun,
    74     ipc_callid_t icallid, ipc_call_t *icall)
    75 {
    76         usb_log_debug(NAME " default_connection_handler()\n");
    77        
    78         sysarg_t method = IPC_GET_IMETHOD(*icall);
    79        
    80         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
    81        
    82         if (hid_dev == NULL || hid_dev->data == NULL) {
    83                 async_answer_0(icallid, EINVAL);
    84                 return;
    85         }
    86        
    87         assert(hid_dev != NULL);
    88         assert(hid_dev->data != NULL);
    89         usb_lgtch_ultrax_t *lgtch_dev = (usb_lgtch_ultrax_t *)hid_dev->data;
    90 
    91         if (method == IPC_M_CONNECT_TO_ME) {
    92                 int callback = IPC_GET_ARG5(*icall);
    93 
    94                 if (lgtch_dev->console_phone != -1) {
    95                         async_answer_0(icallid, ELIMIT);
    96                         return;
    97                 }
    98 
    99                 lgtch_dev->console_phone = callback;
    100                 usb_log_debug(NAME " Saved phone to console: %d\n", callback);
    101                 async_answer_0(icallid, EOK);
    102                 return;
    103         }
    104        
    105         async_answer_0(icallid, EINVAL);
    106 }
    10747
    10848/*----------------------------------------------------------------------------*/
    10949
    110 static ddf_dev_ops_t lgtch_ultrax_ops = {
    111         .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
    11255};
    11356
    11457/*----------------------------------------------------------------------------*/
    11558
    116 //static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count,
    117 //    uint8_t report_id, void *arg);
    118 
    119 //static const usb_hid_report_in_callbacks_t usb_lgtch_parser_callbacks = {
    120 //      .keyboard = usb_lgtch_process_keycodes
    121 //};
    122 
    123 ///*----------------------------------------------------------------------------*/
    124 
    125 //static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count,
    126 //    uint8_t report_id, void *arg)
    127 //{
    128 //      // 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
    12963       
    130 //      usb_log_debug(NAME " Got keys from parser (report id: %u): %s\n",
    131 //          report_id, usb_debug_str_buffer(key_codes, count, 0));
    132 //}
    133 
    134 /*----------------------------------------------------------------------------*/
    135 /**
    136  * Processes key events.
    137  *
    138  * @note This function was copied from AT keyboard driver and modified to suit
    139  *       USB keyboard.
    140  *
    141  * @note Lock keys are not sent to the console, as they are completely handled
    142  *       in the driver. It may, however, be required later that the driver
    143  *       sends also these keys to application (otherwise it cannot use those
    144  *       keys at all).
    145  *
    146  * @param hid_dev
    147  * @param lgtch_dev
    148  * @param type Type of the event (press / release). Recognized values:
    149  *             KEY_PRESS, KEY_RELEASE
    150  * @param key Key code of the key according to HID Usage Tables.
    151  */
    152 static void usb_lgtch_push_ev(usb_hid_dev_t *hid_dev, int type,
    153     unsigned int key)
    154 {
    155         assert(hid_dev != NULL);
    156         assert(hid_dev->data != NULL);
    157        
    158         usb_lgtch_ultrax_t *lgtch_dev = (usb_lgtch_ultrax_t *)hid_dev->data;
    159        
    160         console_event_t ev;
    161        
    162         ev.type = type;
    163         ev.key = key;
    164         ev.mods = 0;
    165 
    166         ev.c = 0;
    167 
    168         usb_log_debug2(NAME " Sending key %d to the console\n", ev.key);
    169         if (lgtch_dev->console_phone < 0) {
    170                 usb_log_warning(
    171                     "Connection to console not ready, key discarded.\n");
    172                 return;
    173         }
    174        
    175         async_msg_4(lgtch_dev->console_phone, KBD_EVENT, ev.type, ev.key,
    176             ev.mods, ev.c);
    177 }
    178 
    179 /*----------------------------------------------------------------------------*/
    180 
    181 static void usb_lgtch_free(usb_lgtch_ultrax_t **lgtch_dev)
    182 {
    183         if (lgtch_dev == NULL || *lgtch_dev == NULL) {
    184                 return;
    185         }
    186        
    187         // hangup phone to the console
    188         async_hangup((*lgtch_dev)->console_phone);
    189        
    190 //      if ((*lgtch_dev)->repeat_mtx != NULL) {
    191 //              /* TODO: replace by some check and wait */
    192 //              assert(!fibril_mutex_is_locked((*lgtch_dev)->repeat_mtx));
    193 //              free((*lgtch_dev)->repeat_mtx);
    194 //      }
    195        
    196         // free all buffers
    197         if ((*lgtch_dev)->keys != NULL) {
    198                 free((*lgtch_dev)->keys);
    199         }
    200         if ((*lgtch_dev)->keys_old != NULL) {
    201                 free((*lgtch_dev)->keys_old);
    202         }
    203 
    204         free(*lgtch_dev);
    205         *lgtch_dev = NULL;
    206 }
    207 
    208 /*----------------------------------------------------------------------------*/
    209 
    210 int usb_lgtch_init(struct usb_hid_dev *hid_dev)
    211 {
    212         if (hid_dev == NULL || hid_dev->usb_dev == NULL) {
    213                 return EINVAL; /*! @todo Other return code? */
    214         }
    215        
    216         usb_log_debug(NAME " Initializing HID/lgtch_ultrax structure...\n");
    217        
    218         usb_lgtch_ultrax_t *lgtch_dev = (usb_lgtch_ultrax_t *)malloc(
    219             sizeof(usb_lgtch_ultrax_t));
    220         if (lgtch_dev == NULL) {
    221                 return ENOMEM;
    222         }
    223        
    224         lgtch_dev->console_phone = -1;
    225        
    226         usb_hid_report_path_t *path = usb_hid_report_path();
    227         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
    228        
    229         usb_hid_report_path_set_report_id(path, 1);
    230        
    231         lgtch_dev->key_count = usb_hid_report_input_length(
    232             hid_dev->report, path,
    233             USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);
    234         usb_hid_report_path_free(path);
    235        
    236         usb_log_debug(NAME " Size of the input report: %zu\n",
    237             lgtch_dev->key_count);
    238        
    239         lgtch_dev->keys = (int32_t *)calloc(lgtch_dev->key_count,
    240             sizeof(int32_t));
    241        
    242         if (lgtch_dev->keys == NULL) {
    243                 usb_log_fatal("No memory!\n");
    244                 free(lgtch_dev);
    245                 return ENOMEM;
    246         }
    247        
    248         lgtch_dev->keys_old =
    249                 (int32_t *)calloc(lgtch_dev->key_count, sizeof(int32_t));
    250        
    251         if (lgtch_dev->keys_old == NULL) {
    252                 usb_log_fatal("No memory!\n");
    253                 free(lgtch_dev->keys);
    254                 free(lgtch_dev);
    255                 return ENOMEM;
    256         }
    257        
    258         /*! @todo Autorepeat */
    259        
    260         // save the KBD device structure into the HID device structure
    261         hid_dev->data = lgtch_dev;
    262        
    263         /* Create the function exposed under /dev/devices. */
    264         ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    265             NAME);
    266         if (fun == NULL) {
    267                 usb_log_error("Could not create DDF function node.\n");
    268                 return ENOMEM;
    269         }
    270        
    271         lgtch_dev->initialized = USB_LGTCH_STATUS_INITIALIZED;
    272         usb_log_debug(NAME " HID/lgtch_ultrax device structure initialized.\n");
    273        
    274         /*
    275          * Store the initialized HID device and HID ops
    276          * to the DDF function.
    277          */
    278         fun->ops = &lgtch_ultrax_ops;
    279         fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
    280        
    281         /*
    282          * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da
    283          *    do nej.
    284          * 2) do tych ops do .interfaces[DEV_IFACE_USBHID (asi)] priradi
    285          *    vyplnenu strukturu usbhid_iface_t.
    286          * 3) klientska aplikacia - musi si rucne vytvorit telefon
    287          *    (devman_device_connect() - cesta k zariadeniu (/hw/pci0/...) az
    288          *    k tej fcii.
    289          *    pouzit usb/classes/hid/iface.h - prvy int je telefon
    290          */
    291 
    292         int rc = ddf_fun_bind(fun);
    293         if (rc != EOK) {
    294                 usb_log_error("Could not bind DDF function: %s.\n",
    295                     str_error(rc));
    296                 // TODO: Can / should I destroy the DDF function?
    297                 ddf_fun_destroy(fun);
    298                 usb_lgtch_free(&lgtch_dev);
    299                 return rc;
    300         }
    301        
    302         rc = ddf_fun_add_to_class(fun, "keyboard");
    303         if (rc != EOK) {
    304                 usb_log_error(
    305                     "Could not add DDF function to class 'keyboard': %s.\n",
    306                     str_error(rc));
    307                 // TODO: Can / should I destroy the DDF function?
    308                 ddf_fun_destroy(fun);
    309                 usb_lgtch_free(&lgtch_dev);
    310                 return rc;
    311         }
    312        
    313         usb_log_debug(NAME " HID/lgtch_ultrax structure initialized.\n");
    314        
    315         return EOK;
    316 }
    317 
    318 /*----------------------------------------------------------------------------*/
    319 
    320 void usb_lgtch_deinit(struct usb_hid_dev *hid_dev)
    321 {
    322         if (hid_dev == NULL) {
    323                 return;
    324         }
    325        
    326         if (hid_dev->data != NULL) {
    327                 usb_lgtch_ultrax_t *lgtch_dev =
    328                     (usb_lgtch_ultrax_t *)hid_dev->data;
    329 //              if (usb_kbd_is_initialized(kbd_dev)) {
    330 //                      usb_kbd_mark_unusable(kbd_dev);
    331 //              } else {
    332                         usb_lgtch_free(&lgtch_dev);
    333                         hid_dev->data = NULL;
    334 //              }
    335         }
     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));
    33666}
    33767
     
    35181        usb_hid_report_path_t *path = usb_hid_report_path();
    35282        usb_hid_report_path_append_item(path, 0xc, 0);
    353 
    354         uint8_t report_id;
     83        usb_hid_report_path_set_report_id(path, 1);
    35584       
    356         int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size,
    357             &report_id);
    358         usb_hid_report_path_set_report_id(path, report_id);
    359 
    360         usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    361             hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END
    362             | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    363             USB_HID_REPORT_TYPE_INPUT);
    364        
    365         unsigned int key;
    366        
    367         /*! @todo Is this iterating OK if done multiple times?
    368          *  @todo The parsing is not OK
    369          */
    370         while (field != NULL) {
    371                 usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n", field->value,
    372                     field->usage);
    373                
    374                 key = usb_lgtch_map_usage(field->usage);
    375                 usb_lgtch_push_ev(hid_dev, KEY_PRESS, key);
    376                
    377                 field = usb_hid_report_get_sibling(
    378                     hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
    379                     | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    380                     USB_HID_REPORT_TYPE_INPUT);
    381         }       
     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);
    38289
    38390        usb_hid_report_path_free(path);
    38491       
    38592        if (rc != EOK) {
    386                 usb_log_warning(NAME "Error in usb_hid_boot_keyboard_input_report():"
     93                usb_log_warning("Error in usb_hid_boot_keyboard_input_report():"
    38794                    "%s\n", str_error(rc));
    38895        }
Note: See TracChangeset for help on using the changeset viewer.