Ignore:
Timestamp:
2011-11-10T20:03:48Z (12 years ago)
Author:
Frantisek Princ <frantisek.princ@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade
Children:
fa76f81
Parents:
27ca3a3 (diff), 747ef72 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge with mainline

File:
1 edited

Legend:

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

    r27ca3a3 rc2245a3  
    4141#include <io/keycode.h>
    4242#include <io/console.h>
     43#include <abi/ipc/methods.h>
    4344#include <ipc/kbdev.h>
    4445#include <async.h>
     
    8687
    8788/*----------------------------------------------------------------------------*/
    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 /*----------------------------------------------------------------------------*/
    105 
    106 enum {
    107         USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE = 63
     103/*----------------------------------------------------------------------------*/
     104static 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 */
    108137};
    109 
    110 static 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 
     138/*----------------------------------------------------------------------------*/
    149139typedef enum usb_kbd_flags {
    150140        USB_KBD_STATUS_UNINITIALIZED = 0,
     
    152142        USB_KBD_STATUS_TO_DESTROY = -1
    153143} usb_kbd_flags;
    154 
    155144/*----------------------------------------------------------------------------*/
    156145/* IPC method handler                                                         */
    157146/*----------------------------------------------------------------------------*/
    158 
    159 static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
    160 
    161147/**
    162148 * Default handler for IPC methods not handled by DDF.
    163149 *
    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.
     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.
    167154 *
    168155 * @param fun Device function handling the call.
     
    173160    ipc_callid_t icallid, ipc_call_t *icall)
    174161{
    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");
     162        if (fun == NULL || fun->driver_data == NULL) {
     163                usb_log_error("%s: Missing parameter.\n", __FUNCTION__);
    181164                async_answer_0(icallid, EINVAL);
    182165                return;
    183166        }
    184167
    185         async_sess_t *sess =
    186             async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
    187         if (sess != NULL) {
     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                }
    188189                if (kbd_dev->console_sess == NULL) {
    189190                        kbd_dev->console_sess = sess;
    190                         usb_log_debug("default_connection_handler: OK\n");
     191                        usb_log_debug("%s: OK\n", __FUNCTION__);
    191192                        async_answer_0(icallid, EOK);
    192193                } else {
    193                         usb_log_debug("default_connection_handler: "
    194                             "console session already set\n");
     194                        usb_log_error("%s: console session already set\n",
     195                           __FUNCTION__);
    195196                        async_answer_0(icallid, ELIMIT);
    196197                }
    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");
     198                break;
     199        }
     200        default:
     201                        usb_log_error("%s: Unknown method: %d.\n",
     202                            __FUNCTION__, (int) method);
    206203                        async_answer_0(icallid, EINVAL);
    207204                        break;
    208                 }
    209         }
    210 }
    211 
     205        }
     206
     207}
    212208/*----------------------------------------------------------------------------*/
    213209/* Key processing functions                                                   */
     
    226222 * @param kbd_dev Keyboard device structure.
    227223 */
    228 static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev) 
     224static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev)
    229225{
    230226        if (kbd_dev->output_size == 0) {
     
    274270        }
    275271
    276         usb_log_debug("Output report buffer: %s\n", 
    277             usb_debug_str_buffer(kbd_dev->output_buffer, kbd_dev->output_size, 
     272        usb_log_debug("Output report buffer: %s\n",
     273            usb_debug_str_buffer(kbd_dev->output_buffer, kbd_dev->output_size,
    278274                0));
    279275
    280         usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe,
    281             hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT, 
     276        rc = usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe,
     277            hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT,
    282278            kbd_dev->output_buffer, kbd_dev->output_size);
    283 }
    284 
     279        if (rc != EOK) {
     280                usb_log_warning("Failed to set kbd indicators.\n");
     281        }
     282}
    285283/*----------------------------------------------------------------------------*/
    286284/** Send key event.
     
    291289 * @param key Key code
    292290 */
    293 void usb_kbd_push_ev(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev, int type,
    294     unsigned int key)
     291void usb_kbd_push_ev(usb_kbd_t *kbd_dev, int type, unsigned key)
    295292{
    296293        usb_log_debug2("Sending kbdev event %d/%d to the console\n", type, key);
     
    302299
    303300        async_exch_t *exch = async_exchange_begin(kbd_dev->console_sess);
    304         async_msg_2(exch, KBDEV_EVENT, type, key);
    305         async_exchange_end(exch);
    306 }
    307 
    308 /*----------------------------------------------------------------------------*/
    309 
    310 static inline int usb_kbd_is_lock(unsigned int key_code)
     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/*----------------------------------------------------------------------------*/
     309static inline int usb_kbd_is_lock(unsigned int key_code)
    311310{
    312311        return (key_code == KC_NUM_LOCK
     
    314313            || key_code == KC_CAPS_LOCK);
    315314}
    316 
     315/*----------------------------------------------------------------------------*/
    317316static size_t find_in_array_int32(int32_t val, int32_t *arr, size_t arr_size)
    318317{
     
    325324        return (size_t) -1;
    326325}
    327 
    328326/*----------------------------------------------------------------------------*/
    329327/**
     
    342340 * @sa usb_kbd_push_ev(), usb_kbd_repeat_start(), usb_kbd_repeat_stop()
    343341 */
    344 static void usb_kbd_check_key_changes(usb_hid_dev_t *hid_dev, 
     342static void usb_kbd_check_key_changes(usb_hid_dev_t *hid_dev,
    345343    usb_kbd_t *kbd_dev)
    346344{
    347         unsigned int key;
    348         size_t i;
    349345
    350346        /*
     
    356352         * whole input report.
    357353         */
    358         i = find_in_array_int32(ERROR_ROLLOVER, kbd_dev->keys,
     354        size_t i = find_in_array_int32(ERROR_ROLLOVER, kbd_dev->keys,
    359355            kbd_dev->key_count);
    360356        if (i != (size_t) -1) {
    361                 usb_log_debug("Detected phantom state.\n");
     357                usb_log_error("Detected phantom state.\n");
    362358                return;
    363359        }
     
    367363         */
    368364        for (i = 0; i < kbd_dev->key_count; i++) {
    369                 int32_t old_key = kbd_dev->keys_old[i];
     365                const int32_t old_key = kbd_dev->keys_old[i];
    370366                /* Find the old key among currently pressed keys. */
    371                 size_t pos = find_in_array_int32(old_key, kbd_dev->keys,
     367                const size_t pos = find_in_array_int32(old_key, kbd_dev->keys,
    372368                    kbd_dev->key_count);
    373369                /* If the key was not found, we need to signal release. */
    374370                if (pos == (size_t) -1) {
    375                         key = usbhid_parse_scancode(old_key);
     371                        const unsigned key = usbhid_parse_scancode(old_key);
    376372                        if (!usb_kbd_is_lock(key)) {
    377373                                usb_kbd_repeat_stop(kbd_dev, key);
    378374                        }
    379                         usb_kbd_push_ev(hid_dev, kbd_dev, KEY_RELEASE, key);
     375                        usb_kbd_push_ev(kbd_dev, KEY_RELEASE, key);
    380376                        usb_log_debug2("Key released: %u "
    381377                            "(USB code %" PRIu32 ")\n", key, old_key);
     
    387383         */
    388384        for (i = 0; i < kbd_dev->key_count; ++i) {
    389                 int32_t new_key = kbd_dev->keys[i];
     385                const int32_t new_key = kbd_dev->keys[i];
    390386                /* Find the new key among already pressed keys. */
    391                 size_t pos = find_in_array_int32(new_key, kbd_dev->keys_old,
    392                     kbd_dev->key_count);
     387                const size_t pos = find_in_array_int32(new_key,
     388                    kbd_dev->keys_old, kbd_dev->key_count);
    393389                /* If the key was not found, we need to signal press. */
    394390                if (pos == (size_t) -1) {
    395                         key = usbhid_parse_scancode(kbd_dev->keys[i]);
     391                        unsigned key = usbhid_parse_scancode(kbd_dev->keys[i]);
    396392                        if (!usb_kbd_is_lock(key)) {
    397393                                usb_kbd_repeat_start(kbd_dev, key);
    398394                        }
    399                         usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS, key);
     395                        usb_kbd_push_ev(kbd_dev, KEY_PRESS, key);
    400396                        usb_log_debug2("Key pressed: %u "
    401397                            "(USB code %" PRIu32 ")\n", key, new_key);
     
    405401        memcpy(kbd_dev->keys_old, kbd_dev->keys, kbd_dev->key_count * 4);
    406402
     403        // TODO Get rid of this
    407404        char key_buffer[512];
    408405        ddf_dump_buffer(key_buffer, 512,
     
    410407        usb_log_debug2("Stored keys %s.\n", key_buffer);
    411408}
    412 
    413409/*----------------------------------------------------------------------------*/
    414410/* General kbd functions                                                      */
     
    436432
    437433        usb_hid_report_path_t *path = usb_hid_report_path();
    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 
     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. */
    444449        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    445450            &hid_dev->report, NULL, path,
     
    449454
    450455        while (field != NULL) {
    451                 usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n", 
     456                usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n",
    452457                    field, field->value, field->usage);
    453                
     458
    454459                assert(i < kbd_dev->key_count);
    455460
    456                 // save the key usage
     461                /* Save the key usage. */
    457462                if (field->value != 0) {
    458463                        kbd_dev->keys[i] = field->usage;
     
    474479        usb_kbd_check_key_changes(hid_dev, kbd_dev);
    475480}
    476 
    477481/*----------------------------------------------------------------------------*/
    478482/* HID/KBD structure manipulation                                             */
    479483/*----------------------------------------------------------------------------*/
    480 
    481 static 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  */
    497 static 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 
    515484static int usb_kbd_create_function(usb_kbd_t *kbd_dev)
    516485{
     
    528497        }
    529498
    530         /*
    531          * Store the initialized HID device and HID ops
    532          * to the DDF function.
    533          */
     499        /* Store the initialized HID device and HID ops
     500         * to the DDF function. */
    534501        fun->ops = &kbd_dev->ops;
    535502        fun->driver_data = kbd_dev;
     
    539506                usb_log_error("Could not bind DDF function: %s.\n",
    540507                    str_error(rc));
    541                 fun->driver_data = NULL; /* We need this later */
     508                fun->driver_data = NULL; /* We did not allocate this. */
    542509                ddf_fun_destroy(fun);
    543510                return rc;
     
    547514            HID_KBD_FUN_NAME, fun->handle);
    548515
    549         usb_log_debug("Adding DDF function to category %s...\n", 
     516        usb_log_debug("Adding DDF function to category %s...\n",
    550517            HID_KBD_CLASS_NAME);
    551518        rc = ddf_fun_add_to_category(fun, HID_KBD_CATEGORY_NAME);
     
    554521                    "Could not add DDF function to category %s: %s.\n",
    555522                    HID_KBD_CLASS_NAME, str_error(rc));
    556                 fun->driver_data = NULL; /* We need this later */
    557                 ddf_fun_destroy(fun);
     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                }
    558531                return rc;
    559532        }
     
    562535        return EOK;
    563536}
    564 
    565537/*----------------------------------------------------------------------------*/
    566538/* API functions                                                              */
     
    591563
    592564        if (hid_dev == NULL) {
    593                 usb_log_error("Failed to init keyboard structure: no structure"
    594                     " given.\n");
     565                usb_log_error(
     566                    "Failed to init keyboard structure: no structure given.\n");
    595567                return EINVAL;
    596568        }
    597569
    598         usb_kbd_t *kbd_dev = usb_kbd_new();
     570        usb_kbd_t *kbd_dev = calloc(1, sizeof(usb_kbd_t));
    599571        if (kbd_dev == NULL) {
    600                 usb_log_error("Error while creating USB/HID KBD device "
    601                     "structure.\n");
    602                 return ENOMEM;  // TODO: some other code??
    603         }
     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;
    604579
    605580        /* Store link to HID device */
    606581        kbd_dev->hid_dev = hid_dev;
    607582
    608         /*
    609          * TODO: make more general
    610          */
     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
    611592        usb_hid_report_path_t *path = usb_hid_report_path();
    612         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
     593        if (path == NULL) {
     594                usb_log_error("Failed to create kbd report path.\n");
     595                usb_kbd_destroy(kbd_dev);
     596                return ENOMEM;
     597        }
     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        }
    613607
    614608        usb_hid_report_path_set_report_id(path, 0);
    615609
    616         kbd_dev->key_count = usb_hid_report_size(
    617             &hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT);
     610        kbd_dev->key_count =
     611            usb_hid_report_size(&hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT);
     612
    618613        usb_hid_report_path_free(path);
    619614
     
    621616
    622617        kbd_dev->keys = calloc(kbd_dev->key_count, sizeof(int32_t));
    623 
    624618        if (kbd_dev->keys == NULL) {
    625                 usb_log_error("No memory!\n");
    626                 free(kbd_dev);
     619                usb_log_error("Failed to allocate key buffer.\n");
     620                usb_kbd_destroy(kbd_dev);
    627621                return ENOMEM;
    628622        }
    629623
    630         kbd_dev->keys_old =
    631                 (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
    632 
     624        kbd_dev->keys_old = calloc(kbd_dev->key_count, sizeof(int32_t));
    633625        if (kbd_dev->keys_old == NULL) {
    634                 usb_log_error("No memory!\n");
    635                 free(kbd_dev->keys);
    636                 free(kbd_dev);
     626                usb_log_error("Failed to allocate old_key buffer.\n");
     627                usb_kbd_destroy(kbd_dev);
    637628                return ENOMEM;
    638629        }
    639630
    640         /*
    641          * Output report
    642          */
     631        /* Output report */
    643632        kbd_dev->output_size = 0;
    644633        kbd_dev->output_buffer = usb_hid_report_output(&hid_dev->report,
    645634            &kbd_dev->output_size, 0);
    646635        if (kbd_dev->output_buffer == NULL) {
    647                 usb_log_warning("Error creating output report buffer.\n");
    648                 free(kbd_dev->keys);
     636                usb_log_error("Error creating output report buffer.\n");
     637                usb_kbd_destroy(kbd_dev);
    649638                return ENOMEM;
    650639        }
     
    653642
    654643        kbd_dev->led_path = usb_hid_report_path();
    655         usb_hid_report_path_append_item(
     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(
    656651            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 = (int32_t *)calloc(
    665             kbd_dev->led_output_size, sizeof(int32_t));
    666 
     664        kbd_dev->led_data = calloc(kbd_dev->led_output_size, sizeof(int32_t));
    667665        if (kbd_dev->led_data == NULL) {
    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);
     666                usb_log_error("Error creating buffer for LED output report.\n");
     667                usb_kbd_destroy(kbd_dev);
    673668                return ENOMEM;
    674669        }
    675670
    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
     671        /* Set LEDs according to initial setup.
     672         * Set Idle rate */
     673        usb_kbd_set_led(hid_dev, kbd_dev);
     674
     675        usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
     676            hid_dev->usb_dev->interface_no, IDLE_RATE);
     677
     678        /* Save the KBD device structure into the HID device structure. */
    694679        *data = kbd_dev;
    695680
    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          */
    703         usb_kbd_set_led(hid_dev, kbd_dev);
    704 
    705         usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
    706             hid_dev->usb_dev->interface_no, IDLE_RATE);
    707 
    708         /*
    709          * Create new fibril for auto-repeat
    710          */
     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. */
    711692        fid_t fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev);
    712693        if (fid == 0) {
    713694                usb_log_error("Failed to start fibril for KBD auto-repeat");
     695                usb_kbd_destroy(kbd_dev);
    714696                return ENOMEM;
    715697        }
    716698        fibril_add_ready(fid);
    717699
    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) {
    724                 usb_kbd_destroy(kbd_dev);
    725                 return rc;
    726         }
    727 
    728700        return EOK;
    729701}
    730 
    731 /*----------------------------------------------------------------------------*/
    732 
     702/*----------------------------------------------------------------------------*/
    733703bool usb_kbd_polling_callback(usb_hid_dev_t *hid_dev, void *data)
    734704{
    735         if (hid_dev == NULL/* || buffer == NULL*/ || data == NULL) {
    736                 // do not continue polling (???)
     705        if (hid_dev == NULL || data == NULL) {
     706                /* This means something serious */
    737707                return false;
    738708        }
    739709
    740         usb_kbd_t *kbd_dev = (usb_kbd_t *)data;
    741         assert(kbd_dev != NULL);
    742 
     710        usb_kbd_t *kbd_dev = data;
    743711        // TODO: add return value from this function
    744712        usb_kbd_process_data(hid_dev, kbd_dev);
     
    746714        return true;
    747715}
    748 
    749 /*----------------------------------------------------------------------------*/
    750 
     716/*----------------------------------------------------------------------------*/
    751717int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev)
    752718{
    753719        return (kbd_dev->initialized == USB_KBD_STATUS_INITIALIZED);
    754720}
    755 
    756 /*----------------------------------------------------------------------------*/
    757 
     721/*----------------------------------------------------------------------------*/
    758722int usb_kbd_is_ready_to_destroy(const usb_kbd_t *kbd_dev)
    759723{
    760724        return (kbd_dev->initialized == USB_KBD_STATUS_TO_DESTROY);
    761725}
    762 
    763726/*----------------------------------------------------------------------------*/
    764727/**
     
    773736        }
    774737
    775         // hangup session to the console
    776         async_hangup(kbd_dev->console_sess);
     738        /* Hangup session to the console. */
     739        if (kbd_dev->console_sess)
     740                async_hangup(kbd_dev->console_sess);
    777741
    778742        //assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
     
    781745        while (fibril_mutex_is_locked(&kbd_dev->repeat_mtx)) {}
    782746
    783         // free all buffers
     747        /* Free all buffers. */
    784748        free(kbd_dev->keys);
    785749        free(kbd_dev->keys_old);
    786750        free(kbd_dev->led_data);
    787751
    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 
     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/*----------------------------------------------------------------------------*/
    806768void usb_kbd_deinit(usb_hid_dev_t *hid_dev, void *data)
    807769{
    808         if (hid_dev == NULL) {
    809                 return;
    810         }
    811 
    812770        if (data != NULL) {
    813771                usb_kbd_t *kbd_dev = data;
    814772                if (usb_kbd_is_initialized(kbd_dev)) {
    815                         usb_kbd_mark_unusable(kbd_dev);
    816                         /* wait for autorepeat */
     773                        kbd_dev->initialized = USB_KBD_STATUS_TO_DESTROY;
     774                        /* Wait for autorepeat */
    817775                        async_usleep(CHECK_DELAY);
    818                         usb_kbd_destroy(kbd_dev);
    819                 }
    820         }
    821 }
    822 
    823 /*----------------------------------------------------------------------------*/
    824 
     776                }
     777                usb_kbd_destroy(kbd_dev);
     778        }
     779}
     780/*----------------------------------------------------------------------------*/
    825781int usb_kbd_set_boot_protocol(usb_hid_dev_t *hid_dev)
    826782{
     783        assert(hid_dev);
    827784        int rc = usb_hid_parse_report_descriptor(
    828785            &hid_dev->report, USB_KBD_BOOT_REPORT_DESCRIPTOR,
    829             USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE);
     786            sizeof(USB_KBD_BOOT_REPORT_DESCRIPTOR));
    830787
    831788        if (rc != EOK) {
     
    846803        return EOK;
    847804}
    848 
    849805/**
    850806 * @}
Note: See TracChangeset for help on using the changeset viewer.