Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/usbhid/kbd/kbddev.c

    r2d1ba51 r5f6e25e  
    4141#include <io/keycode.h>
    4242#include <io/console.h>
    43 #include <abi/ipc/methods.h>
    4443#include <ipc/kbdev.h>
    4544#include <async.h>
     45#include <async_obsolete.h>
    4646#include <fibril.h>
    4747#include <fibril_synch.h>
     
    7171#include "../usbhid.h"
    7272
     73// FIXME: remove this header
     74#include <abi/ipc/methods.h>
     75
    7376/*----------------------------------------------------------------------------*/
    7477
     
    8790
    8891/*----------------------------------------------------------------------------*/
     92
    8993/** Keyboard polling endpoint description for boot protocol class. */
    90 const usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description = {
     94usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description = {
    9195        .transfer_type = USB_TRANSFER_INTERRUPT,
    9296        .direction = USB_DIRECTION_IN,
     
    101105
    102106static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev);
    103 /*----------------------------------------------------------------------------*/
    104 static const uint8_t USB_KBD_BOOT_REPORT_DESCRIPTOR[] = {
    105         0x05, 0x01,  /* Usage Page (Generic Desktop), */
    106         0x09, 0x06,  /* Usage (Keyboard), */
    107         0xA1, 0x01,  /* Collection (Application), */
    108         0x75, 0x01,  /*   Report Size (1), */
    109         0x95, 0x08,  /*   Report Count (8), */
    110         0x05, 0x07,  /*   Usage Page (Key Codes); */
    111         0x19, 0xE0,  /*   Usage Minimum (224), */
    112         0x29, 0xE7,  /*   Usage Maximum (231), */
    113         0x15, 0x00,  /*   Logical Minimum (0), */
    114         0x25, 0x01,  /*   Logical Maximum (1), */
    115         0x81, 0x02,  /*   Input (Data, Variable, Absolute),  ; Modifier byte */
    116         0x95, 0x01,  /*   Report Count (1), */
    117         0x75, 0x08,  /*   Report Size (8), */
    118         0x81, 0x01,  /*   Input (Constant),                  ; Reserved byte */
    119         0x95, 0x05,  /*   Report Count (5), */
    120         0x75, 0x01,  /*   Report Size (1), */
    121         0x05, 0x08,  /*   Usage Page (Page# for LEDs), */
    122         0x19, 0x01,  /*   Usage Minimum (1), */
    123         0x29, 0x05,  /*   Usage Maxmimum (5), */
    124         0x91, 0x02,  /*   Output (Data, Variable, Absolute),  ; LED report */
    125         0x95, 0x01,  /*   Report Count (1), */
    126         0x75, 0x03,  /*   Report Size (3), */
    127         0x91, 0x01,  /*   Output (Constant),            ; LED report padding */
    128         0x95, 0x06,  /*   Report Count (6), */
    129         0x75, 0x08,  /*   Report Size (8), */
    130         0x15, 0x00,  /*   Logical Minimum (0), */
    131         0x25, 0xff,  /*   Logical Maximum (255), */
    132         0x05, 0x07,  /*   Usage Page (Key Codes), */
    133         0x19, 0x00,  /*   Usage Minimum (0), */
    134         0x29, 0xff,  /*   Usage Maximum (255), */
    135         0x81, 0x00,  /*   Input (Data, Array),   ; Key arrays (6 bytes) */
    136         0xC0         /* End Collection */
     107
     108/*----------------------------------------------------------------------------*/
     109
     110enum {
     111        USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE = 63
    137112};
    138 /*----------------------------------------------------------------------------*/
     113
     114static const uint8_t USB_KBD_BOOT_REPORT_DESCRIPTOR[
     115    USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE] = {
     116        0x05, 0x01,  // Usage Page (Generic Desktop),
     117        0x09, 0x06,  // Usage (Keyboard),
     118        0xA1, 0x01,  // Collection (Application),
     119        0x75, 0x01,  //   Report Size (1),
     120        0x95, 0x08,  //   Report Count (8),       
     121        0x05, 0x07,  //   Usage Page (Key Codes);
     122        0x19, 0xE0,  //   Usage Minimum (224),
     123        0x29, 0xE7,  //   Usage Maximum (231),
     124        0x15, 0x00,  //   Logical Minimum (0),
     125        0x25, 0x01,  //   Logical Maximum (1),
     126        0x81, 0x02,  //   Input (Data, Variable, Absolute),   ; Modifier byte
     127        0x95, 0x01,  //   Report Count (1),
     128        0x75, 0x08,  //   Report Size (8),
     129        0x81, 0x01,  //   Input (Constant),                   ; Reserved byte
     130        0x95, 0x05,  //   Report Count (5),
     131        0x75, 0x01,  //   Report Size (1),
     132        0x05, 0x08,  //   Usage Page (Page# for LEDs),
     133        0x19, 0x01,  //   Usage Minimum (1),
     134        0x29, 0x05,  //   Usage Maxmimum (5),
     135        0x91, 0x02,  //   Output (Data, Variable, Absolute),  ; LED report
     136        0x95, 0x01,  //   Report Count (1),
     137        0x75, 0x03,  //   Report Size (3),
     138        0x91, 0x01,  //   Output (Constant),              ; LED report padding
     139        0x95, 0x06,  //   Report Count (6),
     140        0x75, 0x08,  //   Report Size (8),
     141        0x15, 0x00,  //   Logical Minimum (0),
     142        0x25, 0xff,  //   Logical Maximum (255),
     143        0x05, 0x07,  //   Usage Page (Key Codes),
     144        0x19, 0x00,  //   Usage Minimum (0),
     145        0x29, 0xff,  //   Usage Maximum (255),
     146        0x81, 0x00,  //   Input (Data, Array),            ; Key arrays (6 bytes)
     147        0xC0           // End Collection
     148
     149};
     150
     151/*----------------------------------------------------------------------------*/
     152
    139153typedef enum usb_kbd_flags {
    140154        USB_KBD_STATUS_UNINITIALIZED = 0,
     
    142156        USB_KBD_STATUS_TO_DESTROY = -1
    143157} usb_kbd_flags;
     158
    144159/*----------------------------------------------------------------------------*/
    145160/* IPC method handler                                                         */
    146161/*----------------------------------------------------------------------------*/
     162
     163static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
     164
    147165/**
    148166 * Default handler for IPC methods not handled by DDF.
    149167 *
    150  * Currently recognizes only two methods (IPC_M_CONNECT_TO_ME and KBDEV_SET_IND)
    151  * IPC_M_CONNECT_TO_ME assumes the caller is the console and  stores IPC
    152  * session to it for later use by the driver to notify about key events.
    153  * KBDEV_SET_IND sets LED keyboard indicators.
     168 * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it
     169 * assumes the caller is the console and thus it stores IPC phone to it for
     170 * later use by the driver to notify about key events.
    154171 *
    155172 * @param fun Device function handling the call.
     
    160177    ipc_callid_t icallid, ipc_call_t *icall)
    161178{
    162         if (fun == NULL || fun->driver_data == NULL) {
    163                 usb_log_error("%s: Missing parameter.\n", __FUNCTION__);
     179        sysarg_t method = IPC_GET_IMETHOD(*icall);
     180        int callback;
     181       
     182        usb_kbd_t *kbd_dev = (usb_kbd_t *)fun->driver_data;
     183        if (kbd_dev == NULL) {
     184                usb_log_debug("default_connection_handler: "
     185                    "Missing parameter.\n");
    164186                async_answer_0(icallid, EINVAL);
    165187                return;
    166188        }
    167189
    168         const sysarg_t method = IPC_GET_IMETHOD(*icall);
    169         usb_kbd_t *kbd_dev = fun->driver_data;
    170 
    171190        switch (method) {
     191        case IPC_M_CONNECT_TO_ME:
     192                callback = IPC_GET_ARG5(*icall);
     193
     194                if (kbd_dev->console_phone != -1) {
     195                        usb_log_debug("default_connection_handler: "
     196                            "console phone already set\n");
     197                        async_answer_0(icallid, ELIMIT);
     198                        return;
     199                }
     200
     201                kbd_dev->console_phone = callback;
     202               
     203                usb_log_debug("default_connection_handler: OK\n");
     204                async_answer_0(icallid, EOK);
     205                break;
    172206        case KBDEV_SET_IND:
    173207                kbd_dev->mods = IPC_GET_ARG1(*icall);
     
    175209                async_answer_0(icallid, EOK);
    176210                break;
    177         /* This might be ugly but async_callback_receive_start makes no
    178          * difference for incorrect call and malloc failure. */
    179         case IPC_M_CONNECT_TO_ME: {
    180                 async_sess_t *sess =
    181                     async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
    182                 /* Probably ENOMEM error, try again. */
    183                 if (sess == NULL) {
    184                         usb_log_warning(
    185                             "Failed to create start console session.\n");
    186                         async_answer_0(icallid, EAGAIN);
    187                         break;
    188                 }
    189                 if (kbd_dev->console_sess == NULL) {
    190                         kbd_dev->console_sess = sess;
    191                         usb_log_debug("%s: OK\n", __FUNCTION__);
    192                         async_answer_0(icallid, EOK);
    193                 } else {
    194                         usb_log_error("%s: console session already set\n",
    195                            __FUNCTION__);
    196                         async_answer_0(icallid, ELIMIT);
    197                 }
     211        default:
     212                usb_log_debug("default_connection_handler: Wrong function.\n");
     213                async_answer_0(icallid, EINVAL);
    198214                break;
    199215        }
    200         default:
    201                         usb_log_error("%s: Unknown method: %d.\n",
    202                             __FUNCTION__, (int) method);
    203                         async_answer_0(icallid, EINVAL);
    204                         break;
    205         }
    206 
    207 }
     216}
     217
    208218/*----------------------------------------------------------------------------*/
    209219/* Key processing functions                                                   */
     
    222232 * @param kbd_dev Keyboard device structure.
    223233 */
    224 static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev)
     234static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev) 
    225235{
    226236        if (kbd_dev->output_size == 0) {
     
    233243
    234244        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    235             &hid_dev->report, NULL, kbd_dev->led_path,
     245            hid_dev->report, NULL, kbd_dev->led_path,
    236246            USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    237247            USB_HID_REPORT_TYPE_OUTPUT);
    238 
     248       
    239249        while (field != NULL) {
    240 
    241                 if ((field->usage == USB_HID_LED_NUM_LOCK)
     250               
     251                if ((field->usage == USB_HID_LED_NUM_LOCK) 
    242252                    && (kbd_dev->mods & KM_NUM_LOCK)){
    243253                        field->value = 1;
    244254                }
    245255
    246                 if ((field->usage == USB_HID_LED_CAPS_LOCK)
     256                if ((field->usage == USB_HID_LED_CAPS_LOCK) 
    247257                    && (kbd_dev->mods & KM_CAPS_LOCK)){
    248258                        field->value = 1;
    249259                }
    250260
    251                 if ((field->usage == USB_HID_LED_SCROLL_LOCK)
     261                if ((field->usage == USB_HID_LED_SCROLL_LOCK) 
    252262                    && (kbd_dev->mods & KM_SCROLL_LOCK)){
    253263                        field->value = 1;
    254264                }
    255 
    256                 field = usb_hid_report_get_sibling(
    257                     &hid_dev->report, field, kbd_dev->led_path,
    258                 USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    259                     USB_HID_REPORT_TYPE_OUTPUT);
    260         }
    261 
     265               
     266                field = usb_hid_report_get_sibling(hid_dev->report, field,
     267                    kbd_dev->led_path, 
     268                USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
     269                        USB_HID_REPORT_TYPE_OUTPUT);
     270        }
     271       
    262272        // TODO: what about the Report ID?
    263         int rc = usb_hid_report_output_translate(&hid_dev->report, 0,
     273        int rc = usb_hid_report_output_translate(hid_dev->report, 0,
    264274            kbd_dev->output_buffer, kbd_dev->output_size);
    265 
     275       
    266276        if (rc != EOK) {
    267277                usb_log_warning("Error translating LED output to output report"
     
    269279                return;
    270280        }
    271 
    272         usb_log_debug("Output report buffer: %s\n",
    273             usb_debug_str_buffer(kbd_dev->output_buffer, kbd_dev->output_size,
     281       
     282        usb_log_debug("Output report buffer: %s\n", 
     283            usb_debug_str_buffer(kbd_dev->output_buffer, kbd_dev->output_size, 
    274284                0));
    275 
    276         rc = usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe,
    277             hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT,
     285       
     286        usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe,
     287            hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT, 
    278288            kbd_dev->output_buffer, kbd_dev->output_size);
    279         if (rc != EOK) {
    280                 usb_log_warning("Failed to set kbd indicators.\n");
    281         }
    282 }
     289}
     290
    283291/*----------------------------------------------------------------------------*/
    284292/** Send key event.
     
    289297 * @param key Key code
    290298 */
    291 void usb_kbd_push_ev(usb_kbd_t *kbd_dev, int type, unsigned key)
     299void usb_kbd_push_ev(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev, int type,
     300    unsigned int key)
    292301{
    293302        usb_log_debug2("Sending kbdev event %d/%d to the console\n", type, key);
    294         if (kbd_dev->console_sess == NULL) {
     303        if (kbd_dev->console_phone < 0) {
    295304                usb_log_warning(
    296305                    "Connection to console not ready, key discarded.\n");
    297306                return;
    298307        }
    299 
    300         async_exch_t *exch = async_exchange_begin(kbd_dev->console_sess);
    301         if (exch != NULL) {
    302                 async_msg_2(exch, KBDEV_EVENT, type, key);
    303                 async_exchange_end(exch);
    304         } else {
    305                 usb_log_warning("Failed to send key to console.\n");
    306         }
    307 }
    308 /*----------------------------------------------------------------------------*/
    309 static inline int usb_kbd_is_lock(unsigned int key_code)
     308       
     309        async_obsolete_msg_2(kbd_dev->console_phone, KBDEV_EVENT, type, key);
     310}
     311
     312/*----------------------------------------------------------------------------*/
     313
     314static inline int usb_kbd_is_lock(unsigned int key_code)
    310315{
    311316        return (key_code == KC_NUM_LOCK
     
    313318            || key_code == KC_CAPS_LOCK);
    314319}
    315 /*----------------------------------------------------------------------------*/
     320
    316321static size_t find_in_array_int32(int32_t val, int32_t *arr, size_t arr_size)
    317322{
     
    324329        return (size_t) -1;
    325330}
     331
    326332/*----------------------------------------------------------------------------*/
    327333/**
     
    340346 * @sa usb_kbd_push_ev(), usb_kbd_repeat_start(), usb_kbd_repeat_stop()
    341347 */
    342 static void usb_kbd_check_key_changes(usb_hid_dev_t *hid_dev,
     348static void usb_kbd_check_key_changes(usb_hid_dev_t *hid_dev, 
    343349    usb_kbd_t *kbd_dev)
    344350{
    345 
     351        unsigned int key;
     352        size_t i;
     353       
    346354        /*
    347355         * First of all, check if the kbd have reported phantom state.
     
    352360         * whole input report.
    353361         */
    354         size_t i = find_in_array_int32(ERROR_ROLLOVER, kbd_dev->keys,
     362        i = find_in_array_int32(ERROR_ROLLOVER, kbd_dev->keys,
    355363            kbd_dev->key_count);
    356364        if (i != (size_t) -1) {
    357                 usb_log_error("Detected phantom state.\n");
     365                usb_log_debug("Detected phantom state.\n");
    358366                return;
    359367        }
    360 
     368       
    361369        /*
    362370         * Key releases
    363371         */
    364372        for (i = 0; i < kbd_dev->key_count; i++) {
    365                 const int32_t old_key = kbd_dev->keys_old[i];
     373                int32_t old_key = kbd_dev->keys_old[i];
    366374                /* Find the old key among currently pressed keys. */
    367                 const size_t pos = find_in_array_int32(old_key, kbd_dev->keys,
     375                size_t pos = find_in_array_int32(old_key, kbd_dev->keys,
    368376                    kbd_dev->key_count);
    369377                /* If the key was not found, we need to signal release. */
    370378                if (pos == (size_t) -1) {
    371                         const unsigned key = usbhid_parse_scancode(old_key);
     379                        key = usbhid_parse_scancode(old_key);
    372380                        if (!usb_kbd_is_lock(key)) {
    373381                                usb_kbd_repeat_stop(kbd_dev, key);
    374382                        }
    375                         usb_kbd_push_ev(kbd_dev, KEY_RELEASE, key);
     383                        usb_kbd_push_ev(hid_dev, kbd_dev, KEY_RELEASE, key);
    376384                        usb_log_debug2("Key released: %u "
    377385                            "(USB code %" PRIu32 ")\n", key, old_key);
    378386                }
    379387        }
    380 
     388       
    381389        /*
    382390         * Key presses
    383391         */
    384392        for (i = 0; i < kbd_dev->key_count; ++i) {
    385                 const int32_t new_key = kbd_dev->keys[i];
     393                int32_t new_key = kbd_dev->keys[i];
    386394                /* Find the new key among already pressed keys. */
    387                 const size_t pos = find_in_array_int32(new_key,
    388                     kbd_dev->keys_old, kbd_dev->key_count);
     395                size_t pos = find_in_array_int32(new_key, kbd_dev->keys_old,
     396                    kbd_dev->key_count);
    389397                /* If the key was not found, we need to signal press. */
    390398                if (pos == (size_t) -1) {
    391                         unsigned key = usbhid_parse_scancode(kbd_dev->keys[i]);
     399                        key = usbhid_parse_scancode(kbd_dev->keys[i]);
    392400                        if (!usb_kbd_is_lock(key)) {
    393401                                usb_kbd_repeat_start(kbd_dev, key);
    394402                        }
    395                         usb_kbd_push_ev(kbd_dev, KEY_PRESS, key);
     403                        usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS, key);
    396404                        usb_log_debug2("Key pressed: %u "
    397405                            "(USB code %" PRIu32 ")\n", key, new_key);
    398406                }
    399407        }
    400 
     408       
    401409        memcpy(kbd_dev->keys_old, kbd_dev->keys, kbd_dev->key_count * 4);
    402 
    403         // TODO Get rid of this
     410       
    404411        char key_buffer[512];
    405412        ddf_dump_buffer(key_buffer, 512,
     
    407414        usb_log_debug2("Stored keys %s.\n", key_buffer);
    408415}
     416
    409417/*----------------------------------------------------------------------------*/
    410418/* General kbd functions                                                      */
     
    428436static void usb_kbd_process_data(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev)
    429437{
     438        assert(hid_dev->report != NULL);
    430439        assert(hid_dev != NULL);
    431440        assert(kbd_dev != NULL);
    432 
     441       
    433442        usb_hid_report_path_t *path = usb_hid_report_path();
    434         if (path == NULL) {
    435                 usb_log_error("Failed to create hid/kbd report path.\n");
    436                 return;
    437         }
    438 
    439         int ret =
    440            usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
    441         if (ret != EOK) {
    442                 usb_log_error("Failed to append to hid/kbd report path.\n");
    443                 return;
    444         }
    445 
    446         usb_hid_report_path_set_report_id(path, hid_dev->report_id);
    447 
    448         /* Fill in the currently pressed keys. */
     443        usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
     444
     445        usb_hid_report_path_set_report_id (path, hid_dev->report_id);
     446       
     447        // fill in the currently pressed keys
     448       
    449449        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    450             &hid_dev->report, NULL, path,
    451             USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
     450            hid_dev->report, NULL, path,
     451            USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
    452452            USB_HID_REPORT_TYPE_INPUT);
    453453        unsigned i = 0;
    454 
     454       
    455455        while (field != NULL) {
    456                 usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n",
     456                usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n", 
    457457                    field, field->value, field->usage);
    458 
     458               
    459459                assert(i < kbd_dev->key_count);
    460 
    461                 /* Save the key usage. */
     460               
     461                // save the key usage
    462462                if (field->value != 0) {
    463463                        kbd_dev->keys[i] = field->usage;
     
    467467                }
    468468                usb_log_debug2("Saved %u. key usage %d\n", i, kbd_dev->keys[i]);
    469 
     469               
    470470                ++i;
    471                 field = usb_hid_report_get_sibling(
    472                     &hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
    473                         | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
     471                field = usb_hid_report_get_sibling(hid_dev->report, field, path,
     472                    USB_HID_PATH_COMPARE_END
     473                    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    474474                    USB_HID_REPORT_TYPE_INPUT);
    475475        }
    476 
     476       
    477477        usb_hid_report_path_free(path);
    478 
     478       
    479479        usb_kbd_check_key_changes(hid_dev, kbd_dev);
    480480}
     481
    481482/*----------------------------------------------------------------------------*/
    482483/* HID/KBD structure manipulation                                             */
    483484/*----------------------------------------------------------------------------*/
    484 static int usb_kbd_create_function(usb_kbd_t *kbd_dev)
    485 {
     485
     486static void usb_kbd_mark_unusable(usb_kbd_t *kbd_dev)
     487{
     488        kbd_dev->initialized = USB_KBD_STATUS_TO_DESTROY;
     489}
     490
     491/*----------------------------------------------------------------------------*/
     492
     493/**
     494 * Creates a new USB/HID keyboard structure.
     495 *
     496 * The structure returned by this function is not initialized. Use
     497 * usb_kbd_init() to initialize it prior to polling.
     498 *
     499 * @return New uninitialized structure for representing a USB/HID keyboard or
     500 *         NULL if not successful (memory error).
     501 */
     502static usb_kbd_t *usb_kbd_new(void)
     503{
     504        usb_kbd_t *kbd_dev =
     505            (usb_kbd_t *)calloc(1, sizeof(usb_kbd_t));
     506
     507        if (kbd_dev == NULL) {
     508                usb_log_fatal("No memory!\n");
     509                return NULL;
     510        }
     511       
     512        kbd_dev->console_phone = -1;
     513        kbd_dev->initialized = USB_KBD_STATUS_UNINITIALIZED;
     514       
     515        return kbd_dev;
     516}
     517
     518/*----------------------------------------------------------------------------*/
     519
     520static int usb_kbd_create_function(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev)
     521{
     522        assert(hid_dev != NULL);
     523        assert(hid_dev->usb_dev != NULL);
    486524        assert(kbd_dev != NULL);
    487         assert(kbd_dev->hid_dev != NULL);
    488         assert(kbd_dev->hid_dev->usb_dev != NULL);
    489 
     525       
    490526        /* Create the exposed function. */
    491527        usb_log_debug("Creating DDF function %s...\n", HID_KBD_FUN_NAME);
    492         ddf_fun_t *fun = ddf_fun_create(kbd_dev->hid_dev->usb_dev->ddf_dev,
    493             fun_exposed, HID_KBD_FUN_NAME);
     528        ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
     529            HID_KBD_FUN_NAME);
    494530        if (fun == NULL) {
    495531                usb_log_error("Could not create DDF function node.\n");
    496532                return ENOMEM;
    497533        }
    498 
    499         /* Store the initialized HID device and HID ops
    500          * to the DDF function. */
     534       
     535        /*
     536         * Store the initialized HID device and HID ops
     537         * to the DDF function.
     538         */
    501539        fun->ops = &kbd_dev->ops;
    502540        fun->driver_data = kbd_dev;
     
    506544                usb_log_error("Could not bind DDF function: %s.\n",
    507545                    str_error(rc));
    508                 fun->driver_data = NULL; /* We did not allocate this. */
    509546                ddf_fun_destroy(fun);
    510547                return rc;
    511548        }
    512 
     549       
    513550        usb_log_debug("%s function created. Handle: %" PRIun "\n",
    514551            HID_KBD_FUN_NAME, fun->handle);
    515 
    516         usb_log_debug("Adding DDF function to category %s...\n",
     552       
     553        usb_log_debug("Adding DDF function to category %s...\n", 
    517554            HID_KBD_CLASS_NAME);
    518555        rc = ddf_fun_add_to_category(fun, HID_KBD_CATEGORY_NAME);
     
    521558                    "Could not add DDF function to category %s: %s.\n",
    522559                    HID_KBD_CLASS_NAME, str_error(rc));
    523                 if (ddf_fun_unbind(fun) == EOK) {
    524                         fun->driver_data = NULL; /* We did not allocate this. */
    525                         ddf_fun_destroy(fun);
    526                 } else {
    527                         usb_log_error(
    528                             "Failed to unbind `%s', will not destroy.\n",
    529                             fun->name);
    530                 }
     560                ddf_fun_destroy(fun);
    531561                return rc;
    532562        }
    533         kbd_dev->fun = fun;
    534 
     563       
    535564        return EOK;
    536565}
     566
    537567/*----------------------------------------------------------------------------*/
    538568/* API functions                                                              */
     
    561591{
    562592        usb_log_debug("Initializing HID/KBD structure...\n");
    563 
     593       
    564594        if (hid_dev == NULL) {
    565                 usb_log_error(
    566                     "Failed to init keyboard structure: no structure given.\n");
     595                usb_log_error("Failed to init keyboard structure: no structure"
     596                    " given.\n");
    567597                return EINVAL;
    568598        }
    569 
    570         usb_kbd_t *kbd_dev = calloc(1, sizeof(usb_kbd_t));
     599       
     600        usb_kbd_t *kbd_dev = usb_kbd_new();
    571601        if (kbd_dev == NULL) {
    572                 usb_log_error("Failed to allocate KBD device structure.\n");
    573                 return ENOMEM;
    574         }
    575         /* Default values */
    576         fibril_mutex_initialize(&kbd_dev->repeat_mtx);
    577         kbd_dev->initialized = USB_KBD_STATUS_UNINITIALIZED;
    578         kbd_dev->ops.default_handler = default_connection_handler;
     602                usb_log_error("Error while creating USB/HID KBD device "
     603                    "structure.\n");
     604                return ENOMEM;  // TODO: some other code??
     605        }
    579606
    580607        /* Store link to HID device */
    581608        kbd_dev->hid_dev = hid_dev;
    582 
    583         /* Modifiers and locks */
     609       
     610        /*
     611         * TODO: make more general
     612         */
     613        usb_hid_report_path_t *path = usb_hid_report_path();
     614        usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
     615       
     616        usb_hid_report_path_set_report_id(path, 0);
     617       
     618        kbd_dev->key_count = usb_hid_report_size(
     619            hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT);
     620        usb_hid_report_path_free(path);
     621       
     622        usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count);
     623       
     624        kbd_dev->keys = (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
     625       
     626        if (kbd_dev->keys == NULL) {
     627                usb_log_fatal("No memory!\n");
     628                free(kbd_dev);
     629                return ENOMEM;
     630        }
     631       
     632        kbd_dev->keys_old =
     633                (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
     634       
     635        if (kbd_dev->keys_old == NULL) {
     636                usb_log_fatal("No memory!\n");
     637                free(kbd_dev->keys);
     638                free(kbd_dev);
     639                return ENOMEM;
     640        }
     641       
     642        /*
     643         * Output report
     644         */
     645        kbd_dev->output_size = 0;
     646        kbd_dev->output_buffer = usb_hid_report_output(hid_dev->report,
     647            &kbd_dev->output_size, 0);
     648        if (kbd_dev->output_buffer == NULL) {
     649                usb_log_warning("Error creating output report buffer.\n");
     650                free(kbd_dev->keys);
     651                return ENOMEM;
     652        }
     653       
     654        usb_log_debug("Output buffer size: %zu\n", kbd_dev->output_size);
     655       
     656        kbd_dev->led_path = usb_hid_report_path();
     657        usb_hid_report_path_append_item(
     658            kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
     659       
     660        kbd_dev->led_output_size = usb_hid_report_size(hid_dev->report,
     661            0, USB_HID_REPORT_TYPE_OUTPUT);
     662       
     663        usb_log_debug("Output report size (in items): %zu\n",
     664            kbd_dev->led_output_size);
     665       
     666        kbd_dev->led_data = (int32_t *)calloc(
     667            kbd_dev->led_output_size, sizeof(int32_t));
     668       
     669        if (kbd_dev->led_data == NULL) {
     670                usb_log_warning("Error creating buffer for LED output report."
     671                    "\n");
     672                free(kbd_dev->keys);
     673                usb_hid_report_output_free(kbd_dev->output_buffer);
     674                free(kbd_dev);
     675                return ENOMEM;
     676        }
     677       
     678        /*
     679         * Modifiers and locks
     680         */
     681        kbd_dev->modifiers = 0;
    584682        kbd_dev->mods = DEFAULT_ACTIVE_MODS;
    585 
    586         /* Autorepeat */
     683        kbd_dev->lock_keys = 0;
     684       
     685        /*
     686         * Autorepeat
     687         */
     688        kbd_dev->repeat.key_new = 0;
     689        kbd_dev->repeat.key_repeated = 0;
    587690        kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;
    588691        kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
    589 
    590 
    591         // TODO: make more general
    592         usb_hid_report_path_t *path = usb_hid_report_path();
    593         if (path == NULL) {
    594                 usb_log_error("Failed to create kbd report path.\n");
    595                 usb_kbd_destroy(kbd_dev);
     692       
     693        kbd_dev->repeat_mtx = (fibril_mutex_t *)(
     694            malloc(sizeof(fibril_mutex_t)));
     695        if (kbd_dev->repeat_mtx == NULL) {
     696                usb_log_fatal("No memory!\n");
     697                free(kbd_dev->keys);
     698                usb_hid_report_output_free(kbd_dev->output_buffer);
     699                free(kbd_dev);
    596700                return ENOMEM;
    597701        }
    598 
    599         int ret =
    600             usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
    601         if (ret != EOK) {
    602                 usb_log_error("Failed to append item to kbd report path.\n");
    603                 usb_hid_report_path_free(path);
    604                 usb_kbd_destroy(kbd_dev);
    605                 return ret;
    606         }
    607 
    608         usb_hid_report_path_set_report_id(path, 0);
    609 
    610         kbd_dev->key_count =
    611             usb_hid_report_size(&hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT);
    612 
    613         usb_hid_report_path_free(path);
    614 
    615         usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count);
    616 
    617         kbd_dev->keys = calloc(kbd_dev->key_count, sizeof(int32_t));
    618         if (kbd_dev->keys == NULL) {
    619                 usb_log_error("Failed to allocate key buffer.\n");
    620                 usb_kbd_destroy(kbd_dev);
    621                 return ENOMEM;
    622         }
    623 
    624         kbd_dev->keys_old = calloc(kbd_dev->key_count, sizeof(int32_t));
    625         if (kbd_dev->keys_old == NULL) {
    626                 usb_log_error("Failed to allocate old_key buffer.\n");
    627                 usb_kbd_destroy(kbd_dev);
    628                 return ENOMEM;
    629         }
    630 
    631         /* Output report */
    632         kbd_dev->output_size = 0;
    633         kbd_dev->output_buffer = usb_hid_report_output(&hid_dev->report,
    634             &kbd_dev->output_size, 0);
    635         if (kbd_dev->output_buffer == NULL) {
    636                 usb_log_error("Error creating output report buffer.\n");
    637                 usb_kbd_destroy(kbd_dev);
    638                 return ENOMEM;
    639         }
    640 
    641         usb_log_debug("Output buffer size: %zu\n", kbd_dev->output_size);
    642 
    643         kbd_dev->led_path = usb_hid_report_path();
    644         if (kbd_dev->led_path == NULL) {
    645                 usb_log_error("Failed to create kbd led report path.\n");
    646                 usb_kbd_destroy(kbd_dev);
    647                 return ENOMEM;
    648         }
    649 
    650         ret = usb_hid_report_path_append_item(
    651             kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
    652         if (ret != EOK) {
    653                 usb_log_error("Failed to append to kbd/led report path.\n");
    654                 usb_kbd_destroy(kbd_dev);
    655                 return ret;
    656         }
    657 
    658         kbd_dev->led_output_size = usb_hid_report_size(
    659             &hid_dev->report, 0, USB_HID_REPORT_TYPE_OUTPUT);
    660 
    661         usb_log_debug("Output report size (in items): %zu\n",
    662             kbd_dev->led_output_size);
    663 
    664         kbd_dev->led_data = calloc(kbd_dev->led_output_size, sizeof(int32_t));
    665         if (kbd_dev->led_data == NULL) {
    666                 usb_log_error("Error creating buffer for LED output report.\n");
    667                 usb_kbd_destroy(kbd_dev);
    668                 return ENOMEM;
    669         }
    670 
    671         /* Set LEDs according to initial setup.
    672          * Set Idle rate */
     702       
     703        fibril_mutex_initialize(kbd_dev->repeat_mtx);
     704       
     705        // save the KBD device structure into the HID device structure
     706        *data = kbd_dev;
     707       
     708        // set handler for incoming calls
     709        kbd_dev->ops.default_handler = default_connection_handler;
     710       
     711        /*
     712         * Set LEDs according to initial setup.
     713         * Set Idle rate
     714         */
    673715        usb_kbd_set_led(hid_dev, kbd_dev);
    674 
    675         usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
     716       
     717        usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 
    676718            hid_dev->usb_dev->interface_no, IDLE_RATE);
    677 
    678         /* Save the KBD device structure into the HID device structure. */
    679         *data = kbd_dev;
    680 
    681         kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;
    682         usb_log_debug("HID/KBD device structure initialized.\n");
    683 
    684         usb_log_debug("Creating KBD function...\n");
    685         ret = usb_kbd_create_function(kbd_dev);
    686         if (ret != EOK) {
    687                 usb_kbd_destroy(kbd_dev);
    688                 return ret;
    689         }
    690 
    691         /* Create new fibril for auto-repeat. */
     719       
     720        /*
     721         * Create new fibril for auto-repeat
     722         */
    692723        fid_t fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev);
    693724        if (fid == 0) {
    694725                usb_log_error("Failed to start fibril for KBD auto-repeat");
     726                return ENOMEM;
     727        }
     728        fibril_add_ready(fid);
     729       
     730        kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;
     731        usb_log_debug("HID/KBD device structure initialized.\n");
     732       
     733        usb_log_debug("Creating KBD function...\n");
     734        int rc = usb_kbd_create_function(hid_dev, kbd_dev);
     735        if (rc != EOK) {
    695736                usb_kbd_destroy(kbd_dev);
    696                 return ENOMEM;
    697         }
    698         fibril_add_ready(fid);
    699 
     737                return rc;
     738        }
     739       
    700740        return EOK;
    701741}
    702 /*----------------------------------------------------------------------------*/
     742
     743/*----------------------------------------------------------------------------*/
     744
    703745bool usb_kbd_polling_callback(usb_hid_dev_t *hid_dev, void *data)
    704746{
    705         if (hid_dev == NULL || data == NULL) {
    706                 /* This means something serious */
     747        if (hid_dev == NULL/* || buffer == NULL*/ || data == NULL) {
     748                // do not continue polling (???)
    707749                return false;
    708750        }
    709 
    710         usb_kbd_t *kbd_dev = data;
     751       
     752        usb_kbd_t *kbd_dev = (usb_kbd_t *)data;
     753        assert(kbd_dev != NULL);
     754       
    711755        // TODO: add return value from this function
    712756        usb_kbd_process_data(hid_dev, kbd_dev);
    713 
     757       
    714758        return true;
    715759}
    716 /*----------------------------------------------------------------------------*/
     760
     761/*----------------------------------------------------------------------------*/
     762
    717763int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev)
    718764{
    719765        return (kbd_dev->initialized == USB_KBD_STATUS_INITIALIZED);
    720766}
    721 /*----------------------------------------------------------------------------*/
     767
     768/*----------------------------------------------------------------------------*/
     769
    722770int usb_kbd_is_ready_to_destroy(const usb_kbd_t *kbd_dev)
    723771{
    724772        return (kbd_dev->initialized == USB_KBD_STATUS_TO_DESTROY);
    725773}
     774
    726775/*----------------------------------------------------------------------------*/
    727776/**
     
    735784                return;
    736785        }
    737 
    738         /* Hangup session to the console. */
    739         if (kbd_dev->console_sess)
    740                 async_hangup(kbd_dev->console_sess);
    741 
    742         //assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
    743         // FIXME - the fibril_mutex_is_locked may not cause
    744         // fibril scheduling
    745         while (fibril_mutex_is_locked(&kbd_dev->repeat_mtx)) {}
    746 
    747         /* Free all buffers. */
    748         free(kbd_dev->keys);
    749         free(kbd_dev->keys_old);
    750         free(kbd_dev->led_data);
    751 
    752         usb_hid_report_path_free(kbd_dev->led_path);
    753         usb_hid_report_output_free(kbd_dev->output_buffer);
    754 
    755         if (kbd_dev->fun) {
    756                 if (ddf_fun_unbind(kbd_dev->fun) != EOK) {
    757                         usb_log_warning("Failed to unbind %s.\n",
    758                             kbd_dev->fun->name);
     786       
     787        // hangup phone to the console
     788        async_obsolete_hangup(kbd_dev->console_phone);
     789       
     790        if (kbd_dev->repeat_mtx != NULL) {
     791                //assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
     792                // FIXME - the fibril_mutex_is_locked may not cause
     793                // fibril scheduling
     794                while (fibril_mutex_is_locked(kbd_dev->repeat_mtx)) {}
     795                free(kbd_dev->repeat_mtx);
     796        }
     797       
     798        // free all buffers
     799        if (kbd_dev->keys != NULL) {
     800                free(kbd_dev->keys);
     801        }
     802        if (kbd_dev->keys_old != NULL) {
     803                free(kbd_dev->keys_old);
     804        }
     805        if (kbd_dev->led_data != NULL) {
     806                free(kbd_dev->led_data);
     807        }
     808        if (kbd_dev->led_path != NULL) {
     809                usb_hid_report_path_free(kbd_dev->led_path);
     810        }
     811        if (kbd_dev->output_buffer != NULL) {
     812                usb_hid_report_output_free(kbd_dev->output_buffer);
     813        }
     814}
     815
     816/*----------------------------------------------------------------------------*/
     817
     818void usb_kbd_deinit(usb_hid_dev_t *hid_dev, void *data)
     819{
     820        if (hid_dev == NULL) {
     821                return;
     822        }
     823       
     824        if (data != NULL) {
     825                usb_kbd_t *kbd_dev = (usb_kbd_t *)data;
     826                if (usb_kbd_is_initialized(kbd_dev)) {
     827                        usb_kbd_mark_unusable(kbd_dev);
    759828                } else {
    760                         usb_log_debug2("%s unbound.\n", kbd_dev->fun->name);
    761                         kbd_dev->fun->driver_data = NULL;
    762                         ddf_fun_destroy(kbd_dev->fun);
    763                 }
    764         }
    765         free(kbd_dev);
    766 }
    767 /*----------------------------------------------------------------------------*/
    768 void usb_kbd_deinit(usb_hid_dev_t *hid_dev, void *data)
    769 {
    770         if (data != NULL) {
    771                 usb_kbd_t *kbd_dev = data;
    772                 if (usb_kbd_is_initialized(kbd_dev)) {
    773                         kbd_dev->initialized = USB_KBD_STATUS_TO_DESTROY;
    774                         /* Wait for autorepeat */
    775                         async_usleep(CHECK_DELAY);
    776                 }
    777                 usb_kbd_destroy(kbd_dev);
    778         }
    779 }
    780 /*----------------------------------------------------------------------------*/
     829                        usb_kbd_destroy(kbd_dev);
     830                }
     831        }
     832}
     833
     834/*----------------------------------------------------------------------------*/
     835
    781836int usb_kbd_set_boot_protocol(usb_hid_dev_t *hid_dev)
    782837{
    783         assert(hid_dev);
    784         int rc = usb_hid_parse_report_descriptor(
    785             &hid_dev->report, USB_KBD_BOOT_REPORT_DESCRIPTOR,
    786             sizeof(USB_KBD_BOOT_REPORT_DESCRIPTOR));
    787 
     838        int rc = usb_hid_parse_report_descriptor(hid_dev->report,
     839            USB_KBD_BOOT_REPORT_DESCRIPTOR,
     840            USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE);
     841       
    788842        if (rc != EOK) {
    789843                usb_log_error("Failed to parse boot report descriptor: %s\n",
     
    791845                return rc;
    792846        }
    793 
    794         rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe,
     847       
     848        rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe, 
    795849            hid_dev->usb_dev->interface_no, USB_HID_PROTOCOL_BOOT);
    796 
     850       
    797851        if (rc != EOK) {
    798852                usb_log_warning("Failed to set boot protocol to the device: "
     
    800854                return rc;
    801855        }
    802 
     856       
    803857        return EOK;
    804858}
     859
    805860/**
    806861 * @}
Note: See TracChangeset for help on using the changeset viewer.