Ignore:
File:
1 edited

Legend:

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

    r2d1ba51 rb803845  
    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>
     
    8786
    8887/*----------------------------------------------------------------------------*/
     88
    8989/** Keyboard polling endpoint description for boot protocol class. */
    9090const usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description = {
     
    101101
    102102static 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 */
     103
     104/*----------------------------------------------------------------------------*/
     105
     106enum {
     107        USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE = 63
    137108};
    138 /*----------------------------------------------------------------------------*/
     109
     110static const uint8_t USB_KBD_BOOT_REPORT_DESCRIPTOR[
     111    USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE] = {
     112        0x05, 0x01,  // Usage Page (Generic Desktop),
     113        0x09, 0x06,  // Usage (Keyboard),
     114        0xA1, 0x01,  // Collection (Application),
     115        0x75, 0x01,  //   Report Size (1),
     116        0x95, 0x08,  //   Report Count (8),       
     117        0x05, 0x07,  //   Usage Page (Key Codes);
     118        0x19, 0xE0,  //   Usage Minimum (224),
     119        0x29, 0xE7,  //   Usage Maximum (231),
     120        0x15, 0x00,  //   Logical Minimum (0),
     121        0x25, 0x01,  //   Logical Maximum (1),
     122        0x81, 0x02,  //   Input (Data, Variable, Absolute),   ; Modifier byte
     123        0x95, 0x01,  //   Report Count (1),
     124        0x75, 0x08,  //   Report Size (8),
     125        0x81, 0x01,  //   Input (Constant),                   ; Reserved byte
     126        0x95, 0x05,  //   Report Count (5),
     127        0x75, 0x01,  //   Report Size (1),
     128        0x05, 0x08,  //   Usage Page (Page# for LEDs),
     129        0x19, 0x01,  //   Usage Minimum (1),
     130        0x29, 0x05,  //   Usage Maxmimum (5),
     131        0x91, 0x02,  //   Output (Data, Variable, Absolute),  ; LED report
     132        0x95, 0x01,  //   Report Count (1),
     133        0x75, 0x03,  //   Report Size (3),
     134        0x91, 0x01,  //   Output (Constant),              ; LED report padding
     135        0x95, 0x06,  //   Report Count (6),
     136        0x75, 0x08,  //   Report Size (8),
     137        0x15, 0x00,  //   Logical Minimum (0),
     138        0x25, 0xff,  //   Logical Maximum (255),
     139        0x05, 0x07,  //   Usage Page (Key Codes),
     140        0x19, 0x00,  //   Usage Minimum (0),
     141        0x29, 0xff,  //   Usage Maximum (255),
     142        0x81, 0x00,  //   Input (Data, Array),            ; Key arrays (6 bytes)
     143        0xC0           // End Collection
     144
     145};
     146
     147/*----------------------------------------------------------------------------*/
     148
    139149typedef enum usb_kbd_flags {
    140150        USB_KBD_STATUS_UNINITIALIZED = 0,
     
    142152        USB_KBD_STATUS_TO_DESTROY = -1
    143153} usb_kbd_flags;
     154
    144155/*----------------------------------------------------------------------------*/
    145156/* IPC method handler                                                         */
    146157/*----------------------------------------------------------------------------*/
     158
     159static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
     160
    147161/**
    148162 * Default handler for IPC methods not handled by DDF.
    149163 *
    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.
     164 * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it
     165 * assumes the caller is the console and thus it stores IPC session to it for
     166 * later use by the driver to notify about key events.
    154167 *
    155168 * @param fun Device function handling the call.
     
    160173    ipc_callid_t icallid, ipc_call_t *icall)
    161174{
    162         if (fun == NULL || fun->driver_data == NULL) {
    163                 usb_log_error("%s: Missing parameter.\n", __FUNCTION__);
     175        sysarg_t method = IPC_GET_IMETHOD(*icall);
     176
     177        usb_kbd_t *kbd_dev = (usb_kbd_t *) fun->driver_data;
     178        if (kbd_dev == NULL) {
     179                usb_log_debug("default_connection_handler: "
     180                    "Missing parameter.\n");
    164181                async_answer_0(icallid, EINVAL);
    165182                return;
    166183        }
    167184
    168         const sysarg_t method = IPC_GET_IMETHOD(*icall);
    169         usb_kbd_t *kbd_dev = fun->driver_data;
    170 
    171         switch (method) {
    172         case KBDEV_SET_IND:
    173                 kbd_dev->mods = IPC_GET_ARG1(*icall);
    174                 usb_kbd_set_led(kbd_dev->hid_dev, kbd_dev);
    175                 async_answer_0(icallid, EOK);
    176                 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                 }
     185        async_sess_t *sess =
     186            async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
     187        if (sess != NULL) {
    189188                if (kbd_dev->console_sess == NULL) {
    190189                        kbd_dev->console_sess = sess;
    191                         usb_log_debug("%s: OK\n", __FUNCTION__);
     190                        usb_log_debug("default_connection_handler: OK\n");
    192191                        async_answer_0(icallid, EOK);
    193192                } else {
    194                         usb_log_error("%s: console session already set\n",
    195                            __FUNCTION__);
     193                        usb_log_debug("default_connection_handler: "
     194                            "console session already set\n");
    196195                        async_answer_0(icallid, ELIMIT);
    197196                }
    198                 break;
    199         }
    200         default:
    201                         usb_log_error("%s: Unknown method: %d.\n",
    202                             __FUNCTION__, (int) method);
     197        } else {
     198                switch (method) {
     199                case KBDEV_SET_IND:
     200                        kbd_dev->mods = IPC_GET_ARG1(*icall);
     201                        usb_kbd_set_led(kbd_dev->hid_dev, kbd_dev);
     202                        async_answer_0(icallid, EOK);
     203                        break;
     204                default:
     205                        usb_log_debug("default_connection_handler: Wrong function.\n");
    203206                        async_answer_0(icallid, EINVAL);
    204207                        break;
    205         }
    206 
    207 }
     208                }
     209        }
     210}
     211
    208212/*----------------------------------------------------------------------------*/
    209213/* Key processing functions                                                   */
     
    222226 * @param kbd_dev Keyboard device structure.
    223227 */
    224 static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev)
     228static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev) 
    225229{
    226230        if (kbd_dev->output_size == 0) {
     
    270274        }
    271275
    272         usb_log_debug("Output report buffer: %s\n",
    273             usb_debug_str_buffer(kbd_dev->output_buffer, kbd_dev->output_size,
     276        usb_log_debug("Output report buffer: %s\n", 
     277            usb_debug_str_buffer(kbd_dev->output_buffer, kbd_dev->output_size, 
    274278                0));
    275279
    276         rc = usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe,
    277             hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT,
     280        usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe,
     281            hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT, 
    278282            kbd_dev->output_buffer, kbd_dev->output_size);
    279         if (rc != EOK) {
    280                 usb_log_warning("Failed to set kbd indicators.\n");
    281         }
    282 }
     283}
     284
    283285/*----------------------------------------------------------------------------*/
    284286/** Send key event.
     
    289291 * @param key Key code
    290292 */
    291 void usb_kbd_push_ev(usb_kbd_t *kbd_dev, int type, unsigned key)
     293void usb_kbd_push_ev(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev, int type,
     294    unsigned int key)
    292295{
    293296        usb_log_debug2("Sending kbdev event %d/%d to the console\n", type, key);
     
    299302
    300303        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)
     304        async_msg_2(exch, KBDEV_EVENT, type, key);
     305        async_exchange_end(exch);
     306}
     307
     308/*----------------------------------------------------------------------------*/
     309
     310static inline int usb_kbd_is_lock(unsigned int key_code)
    310311{
    311312        return (key_code == KC_NUM_LOCK
     
    313314            || key_code == KC_CAPS_LOCK);
    314315}
    315 /*----------------------------------------------------------------------------*/
     316
    316317static size_t find_in_array_int32(int32_t val, int32_t *arr, size_t arr_size)
    317318{
     
    324325        return (size_t) -1;
    325326}
     327
    326328/*----------------------------------------------------------------------------*/
    327329/**
     
    340342 * @sa usb_kbd_push_ev(), usb_kbd_repeat_start(), usb_kbd_repeat_stop()
    341343 */
    342 static void usb_kbd_check_key_changes(usb_hid_dev_t *hid_dev,
     344static void usb_kbd_check_key_changes(usb_hid_dev_t *hid_dev, 
    343345    usb_kbd_t *kbd_dev)
    344346{
     347        unsigned int key;
     348        size_t i;
    345349
    346350        /*
     
    352356         * whole input report.
    353357         */
    354         size_t i = find_in_array_int32(ERROR_ROLLOVER, kbd_dev->keys,
     358        i = find_in_array_int32(ERROR_ROLLOVER, kbd_dev->keys,
    355359            kbd_dev->key_count);
    356360        if (i != (size_t) -1) {
    357                 usb_log_error("Detected phantom state.\n");
     361                usb_log_debug("Detected phantom state.\n");
    358362                return;
    359363        }
     
    363367         */
    364368        for (i = 0; i < kbd_dev->key_count; i++) {
    365                 const int32_t old_key = kbd_dev->keys_old[i];
     369                int32_t old_key = kbd_dev->keys_old[i];
    366370                /* Find the old key among currently pressed keys. */
    367                 const size_t pos = find_in_array_int32(old_key, kbd_dev->keys,
     371                size_t pos = find_in_array_int32(old_key, kbd_dev->keys,
    368372                    kbd_dev->key_count);
    369373                /* If the key was not found, we need to signal release. */
    370374                if (pos == (size_t) -1) {
    371                         const unsigned key = usbhid_parse_scancode(old_key);
     375                        key = usbhid_parse_scancode(old_key);
    372376                        if (!usb_kbd_is_lock(key)) {
    373377                                usb_kbd_repeat_stop(kbd_dev, key);
    374378                        }
    375                         usb_kbd_push_ev(kbd_dev, KEY_RELEASE, key);
     379                        usb_kbd_push_ev(hid_dev, kbd_dev, KEY_RELEASE, key);
    376380                        usb_log_debug2("Key released: %u "
    377381                            "(USB code %" PRIu32 ")\n", key, old_key);
     
    383387         */
    384388        for (i = 0; i < kbd_dev->key_count; ++i) {
    385                 const int32_t new_key = kbd_dev->keys[i];
     389                int32_t new_key = kbd_dev->keys[i];
    386390                /* 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);
     391                size_t pos = find_in_array_int32(new_key, kbd_dev->keys_old,
     392                    kbd_dev->key_count);
    389393                /* If the key was not found, we need to signal press. */
    390394                if (pos == (size_t) -1) {
    391                         unsigned key = usbhid_parse_scancode(kbd_dev->keys[i]);
     395                        key = usbhid_parse_scancode(kbd_dev->keys[i]);
    392396                        if (!usb_kbd_is_lock(key)) {
    393397                                usb_kbd_repeat_start(kbd_dev, key);
    394398                        }
    395                         usb_kbd_push_ev(kbd_dev, KEY_PRESS, key);
     399                        usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS, key);
    396400                        usb_log_debug2("Key pressed: %u "
    397401                            "(USB code %" PRIu32 ")\n", key, new_key);
     
    401405        memcpy(kbd_dev->keys_old, kbd_dev->keys, kbd_dev->key_count * 4);
    402406
    403         // TODO Get rid of this
    404407        char key_buffer[512];
    405408        ddf_dump_buffer(key_buffer, 512,
     
    407410        usb_log_debug2("Stored keys %s.\n", key_buffer);
    408411}
     412
    409413/*----------------------------------------------------------------------------*/
    410414/* General kbd functions                                                      */
     
    432436
    433437        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. */
     438        usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
     439
     440        usb_hid_report_path_set_report_id (path, hid_dev->report_id);
     441
     442        // fill in the currently pressed keys
     443
    449444        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    450445            &hid_dev->report, NULL, path,
     
    454449
    455450        while (field != NULL) {
    456                 usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n",
     451                usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n", 
    457452                    field, field->value, field->usage);
    458 
     453               
    459454                assert(i < kbd_dev->key_count);
    460455
    461                 /* Save the key usage. */
     456                // save the key usage
    462457                if (field->value != 0) {
    463458                        kbd_dev->keys[i] = field->usage;
     
    479474        usb_kbd_check_key_changes(hid_dev, kbd_dev);
    480475}
     476
    481477/*----------------------------------------------------------------------------*/
    482478/* HID/KBD structure manipulation                                             */
    483479/*----------------------------------------------------------------------------*/
     480
     481static void usb_kbd_mark_unusable(usb_kbd_t *kbd_dev)
     482{
     483        kbd_dev->initialized = USB_KBD_STATUS_TO_DESTROY;
     484}
     485
     486/*----------------------------------------------------------------------------*/
     487
     488/**
     489 * Creates a new USB/HID keyboard structure.
     490 *
     491 * The structure returned by this function is not initialized. Use
     492 * usb_kbd_init() to initialize it prior to polling.
     493 *
     494 * @return New uninitialized structure for representing a USB/HID keyboard or
     495 *         NULL if not successful (memory error).
     496 */
     497static usb_kbd_t *usb_kbd_new(void)
     498{
     499        usb_kbd_t *kbd_dev =
     500            (usb_kbd_t *)calloc(1, sizeof(usb_kbd_t));
     501
     502        if (kbd_dev == NULL) {
     503                usb_log_error("No memory!\n");
     504                return NULL;
     505        }
     506
     507        kbd_dev->console_sess = NULL;
     508        kbd_dev->initialized = USB_KBD_STATUS_UNINITIALIZED;
     509
     510        return kbd_dev;
     511}
     512
     513/*----------------------------------------------------------------------------*/
     514
    484515static int usb_kbd_create_function(usb_kbd_t *kbd_dev)
    485516{
     
    497528        }
    498529
    499         /* Store the initialized HID device and HID ops
    500          * to the DDF function. */
     530        /*
     531         * Store the initialized HID device and HID ops
     532         * to the DDF function.
     533         */
    501534        fun->ops = &kbd_dev->ops;
    502535        fun->driver_data = kbd_dev;
     
    506539                usb_log_error("Could not bind DDF function: %s.\n",
    507540                    str_error(rc));
    508                 fun->driver_data = NULL; /* We did not allocate this. */
     541                fun->driver_data = NULL; /* We need this later */
    509542                ddf_fun_destroy(fun);
    510543                return rc;
     
    514547            HID_KBD_FUN_NAME, fun->handle);
    515548
    516         usb_log_debug("Adding DDF function to category %s...\n",
     549        usb_log_debug("Adding DDF function to category %s...\n", 
    517550            HID_KBD_CLASS_NAME);
    518551        rc = ddf_fun_add_to_category(fun, HID_KBD_CATEGORY_NAME);
     
    521554                    "Could not add DDF function to category %s: %s.\n",
    522555                    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                 }
     556                fun->driver_data = NULL; /* We need this later */
     557                ddf_fun_destroy(fun);
    531558                return rc;
    532559        }
     
    535562        return EOK;
    536563}
     564
    537565/*----------------------------------------------------------------------------*/
    538566/* API functions                                                              */
     
    563591
    564592        if (hid_dev == NULL) {
    565                 usb_log_error(
    566                     "Failed to init keyboard structure: no structure given.\n");
     593                usb_log_error("Failed to init keyboard structure: no structure"
     594                    " given.\n");
    567595                return EINVAL;
    568596        }
    569597
    570         usb_kbd_t *kbd_dev = calloc(1, sizeof(usb_kbd_t));
     598        usb_kbd_t *kbd_dev = usb_kbd_new();
    571599        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;
     600                usb_log_error("Error while creating USB/HID KBD device "
     601                    "structure.\n");
     602                return ENOMEM;  // TODO: some other code??
     603        }
    579604
    580605        /* Store link to HID device */
    581606        kbd_dev->hid_dev = hid_dev;
    582607
    583         /* Modifiers and locks */
    584         kbd_dev->mods = DEFAULT_ACTIVE_MODS;
    585 
    586         /* Autorepeat */
    587         kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;
    588         kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
    589 
    590 
    591         // TODO: make more general
     608        /*
     609         * TODO: make more general
     610         */
    592611        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);
     612        usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
     613
     614        usb_hid_report_path_set_report_id(path, 0);
     615
     616        kbd_dev->key_count = usb_hid_report_size(
     617            &hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT);
     618        usb_hid_report_path_free(path);
     619
     620        usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count);
     621
     622        kbd_dev->keys = calloc(kbd_dev->key_count, sizeof(int32_t));
     623
     624        if (kbd_dev->keys == NULL) {
     625                usb_log_error("No memory!\n");
     626                free(kbd_dev);
    596627                return ENOMEM;
    597628        }
    598629
    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);
     630        kbd_dev->keys_old =
     631                (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
     632
     633        if (kbd_dev->keys_old == NULL) {
     634                usb_log_error("No memory!\n");
     635                free(kbd_dev->keys);
     636                free(kbd_dev);
    621637                return ENOMEM;
    622638        }
    623639
    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 */
     640        /*
     641         * Output report
     642         */
    632643        kbd_dev->output_size = 0;
    633644        kbd_dev->output_buffer = usb_hid_report_output(&hid_dev->report,
    634645            &kbd_dev->output_size, 0);
    635646        if (kbd_dev->output_buffer == NULL) {
    636                 usb_log_error("Error creating output report buffer.\n");
    637                 usb_kbd_destroy(kbd_dev);
     647                usb_log_warning("Error creating output report buffer.\n");
     648                free(kbd_dev->keys);
    638649                return ENOMEM;
    639650        }
     
    642653
    643654        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(
     655        usb_hid_report_path_append_item(
    651656            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         }
    657657
    658658        kbd_dev->led_output_size = usb_hid_report_size(
    659659            &hid_dev->report, 0, USB_HID_REPORT_TYPE_OUTPUT);
    660660
    661         usb_log_debug("Output report size (in items): %zu\n",
     661        usb_log_debug("Output report size (in items): %zu\n", 
    662662            kbd_dev->led_output_size);
    663663
    664         kbd_dev->led_data = calloc(kbd_dev->led_output_size, sizeof(int32_t));
     664        kbd_dev->led_data = (int32_t *)calloc(
     665            kbd_dev->led_output_size, sizeof(int32_t));
     666
    665667        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                usb_log_warning("Error creating buffer for LED output report."
     669                    "\n");
     670                free(kbd_dev->keys);
     671                usb_hid_report_output_free(kbd_dev->output_buffer);
     672                free(kbd_dev);
    668673                return ENOMEM;
    669674        }
    670675
    671         /* Set LEDs according to initial setup.
    672          * Set Idle rate */
     676        /*
     677         * Modifiers and locks
     678         */
     679        kbd_dev->modifiers = 0;
     680        kbd_dev->mods = DEFAULT_ACTIVE_MODS;
     681        kbd_dev->lock_keys = 0;
     682
     683        /*
     684         * Autorepeat
     685         */
     686        kbd_dev->repeat.key_new = 0;
     687        kbd_dev->repeat.key_repeated = 0;
     688        kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;
     689        kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
     690
     691        fibril_mutex_initialize(&kbd_dev->repeat_mtx);
     692
     693        // save the KBD device structure into the HID device structure
     694        *data = kbd_dev;
     695
     696        // set handler for incoming calls
     697        kbd_dev->ops.default_handler = default_connection_handler;
     698
     699        /*
     700         * Set LEDs according to initial setup.
     701         * Set Idle rate
     702         */
    673703        usb_kbd_set_led(hid_dev, kbd_dev);
    674704
    675         usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
     705        usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 
    676706            hid_dev->usb_dev->interface_no, IDLE_RATE);
    677707
    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. */
     708        /*
     709         * Create new fibril for auto-repeat
     710         */
    692711        fid_t fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev);
    693712        if (fid == 0) {
    694713                usb_log_error("Failed to start fibril for KBD auto-repeat");
     714                return ENOMEM;
     715        }
     716        fibril_add_ready(fid);
     717
     718        kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;
     719        usb_log_debug("HID/KBD device structure initialized.\n");
     720
     721        usb_log_debug("Creating KBD function...\n");
     722        int rc = usb_kbd_create_function(kbd_dev);
     723        if (rc != EOK) {
    695724                usb_kbd_destroy(kbd_dev);
    696                 return ENOMEM;
    697         }
    698         fibril_add_ready(fid);
     725                return rc;
     726        }
    699727
    700728        return EOK;
    701729}
    702 /*----------------------------------------------------------------------------*/
     730
     731/*----------------------------------------------------------------------------*/
     732
    703733bool usb_kbd_polling_callback(usb_hid_dev_t *hid_dev, void *data)
    704734{
    705         if (hid_dev == NULL || data == NULL) {
    706                 /* This means something serious */
     735        if (hid_dev == NULL/* || buffer == NULL*/ || data == NULL) {
     736                // do not continue polling (???)
    707737                return false;
    708738        }
    709739
    710         usb_kbd_t *kbd_dev = data;
     740        usb_kbd_t *kbd_dev = (usb_kbd_t *)data;
     741        assert(kbd_dev != NULL);
     742
    711743        // TODO: add return value from this function
    712744        usb_kbd_process_data(hid_dev, kbd_dev);
     
    714746        return true;
    715747}
    716 /*----------------------------------------------------------------------------*/
     748
     749/*----------------------------------------------------------------------------*/
     750
    717751int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev)
    718752{
    719753        return (kbd_dev->initialized == USB_KBD_STATUS_INITIALIZED);
    720754}
    721 /*----------------------------------------------------------------------------*/
     755
     756/*----------------------------------------------------------------------------*/
     757
    722758int usb_kbd_is_ready_to_destroy(const usb_kbd_t *kbd_dev)
    723759{
    724760        return (kbd_dev->initialized == USB_KBD_STATUS_TO_DESTROY);
    725761}
     762
    726763/*----------------------------------------------------------------------------*/
    727764/**
     
    736773        }
    737774
    738         /* Hangup session to the console. */
    739         if (kbd_dev->console_sess)
    740                 async_hangup(kbd_dev->console_sess);
     775        // hangup session to the console
     776        async_hangup(kbd_dev->console_sess);
    741777
    742778        //assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
     
    745781        while (fibril_mutex_is_locked(&kbd_dev->repeat_mtx)) {}
    746782
    747         /* Free all buffers. */
     783        // free all buffers
    748784        free(kbd_dev->keys);
    749785        free(kbd_dev->keys_old);
    750786        free(kbd_dev->led_data);
    751787
    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);
    759                 } 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 /*----------------------------------------------------------------------------*/
     788        if (kbd_dev->led_path != NULL) {
     789                usb_hid_report_path_free(kbd_dev->led_path);
     790        }
     791        if (kbd_dev->output_buffer != NULL) {
     792                usb_hid_report_output_free(kbd_dev->output_buffer);
     793        }
     794
     795        if (ddf_fun_unbind(kbd_dev->fun) != EOK) {
     796                usb_log_warning("Failed to unbind kbd function.\n");
     797        } else {
     798                usb_log_debug2("%s unbound.\n", kbd_dev->fun->name);
     799                kbd_dev->fun->driver_data = NULL;
     800                ddf_fun_destroy(kbd_dev->fun);
     801        }
     802}
     803
     804/*----------------------------------------------------------------------------*/
     805
    768806void usb_kbd_deinit(usb_hid_dev_t *hid_dev, void *data)
    769807{
     808        if (hid_dev == NULL) {
     809                return;
     810        }
     811
    770812        if (data != NULL) {
    771813                usb_kbd_t *kbd_dev = data;
    772814                if (usb_kbd_is_initialized(kbd_dev)) {
    773                         kbd_dev->initialized = USB_KBD_STATUS_TO_DESTROY;
    774                         /* Wait for autorepeat */
     815                        usb_kbd_mark_unusable(kbd_dev);
     816                        /* wait for autorepeat */
    775817                        async_usleep(CHECK_DELAY);
    776                 }
    777                 usb_kbd_destroy(kbd_dev);
    778         }
    779 }
    780 /*----------------------------------------------------------------------------*/
     818                        usb_kbd_destroy(kbd_dev);
     819                }
     820        }
     821}
     822
     823/*----------------------------------------------------------------------------*/
     824
    781825int usb_kbd_set_boot_protocol(usb_hid_dev_t *hid_dev)
    782826{
    783         assert(hid_dev);
    784827        int rc = usb_hid_parse_report_descriptor(
    785828            &hid_dev->report, USB_KBD_BOOT_REPORT_DESCRIPTOR,
    786             sizeof(USB_KBD_BOOT_REPORT_DESCRIPTOR));
     829            USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE);
    787830
    788831        if (rc != EOK) {
     
    803846        return EOK;
    804847}
     848
    805849/**
    806850 * @}
Note: See TracChangeset for help on using the changeset viewer.