Ignore:
File:
1 edited

Legend:

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

    r5da7199 r2d1ba51  
    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. */
    90 usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description = {
     90const usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description = {
    9191        .transfer_type = USB_TRANSFER_INTERRUPT,
    9292        .direction = USB_DIRECTION_IN,
     
    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        }
    184        
    185         async_sess_t *sess =
    186             async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
    187         if (sess != NULL) {
     167
     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) {
     
    237233
    238234        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    239             hid_dev->report, NULL, kbd_dev->led_path,
     235            &hid_dev->report, NULL, kbd_dev->led_path,
    240236            USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    241237            USB_HID_REPORT_TYPE_OUTPUT);
    242        
     238
    243239        while (field != NULL) {
    244                
    245                 if ((field->usage == USB_HID_LED_NUM_LOCK) 
     240
     241                if ((field->usage == USB_HID_LED_NUM_LOCK)
    246242                    && (kbd_dev->mods & KM_NUM_LOCK)){
    247243                        field->value = 1;
    248244                }
    249245
    250                 if ((field->usage == USB_HID_LED_CAPS_LOCK) 
     246                if ((field->usage == USB_HID_LED_CAPS_LOCK)
    251247                    && (kbd_dev->mods & KM_CAPS_LOCK)){
    252248                        field->value = 1;
    253249                }
    254250
    255                 if ((field->usage == USB_HID_LED_SCROLL_LOCK) 
     251                if ((field->usage == USB_HID_LED_SCROLL_LOCK)
    256252                    && (kbd_dev->mods & KM_SCROLL_LOCK)){
    257253                        field->value = 1;
    258254                }
    259                
    260                 field = usb_hid_report_get_sibling(hid_dev->report, field,
    261                     kbd_dev->led_path, 
    262                 USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    263                         USB_HID_REPORT_TYPE_OUTPUT);
    264         }
    265        
     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
    266262        // TODO: what about the Report ID?
    267         int rc = usb_hid_report_output_translate(hid_dev->report, 0,
     263        int rc = usb_hid_report_output_translate(&hid_dev->report, 0,
    268264            kbd_dev->output_buffer, kbd_dev->output_size);
    269        
     265
    270266        if (rc != EOK) {
    271267                usb_log_warning("Error translating LED output to output report"
     
    273269                return;
    274270        }
    275        
    276         usb_log_debug("Output report buffer: %s\n", 
    277             usb_debug_str_buffer(kbd_dev->output_buffer, kbd_dev->output_size, 
     271
     272        usb_log_debug("Output report buffer: %s\n",
     273            usb_debug_str_buffer(kbd_dev->output_buffer, kbd_dev->output_size,
    278274                0));
    279        
    280         usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe,
    281             hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT, 
     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,
    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);
     
    300297                return;
    301298        }
    302        
     299
    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;
    349        
     345
    350346        /*
    351347         * First of all, check if the kbd have reported phantom state.
     
    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        }
    364        
     360
    365361        /*
    366362         * Key releases
    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);
    382378                }
    383379        }
    384        
     380
    385381        /*
    386382         * Key presses
    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);
    402398                }
    403399        }
    404        
     400
    405401        memcpy(kbd_dev->keys_old, kbd_dev->keys, kbd_dev->key_count * 4);
    406        
     402
     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                                                      */
     
    432428static void usb_kbd_process_data(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev)
    433429{
    434         assert(hid_dev->report != NULL);
    435430        assert(hid_dev != NULL);
    436431        assert(kbd_dev != NULL);
    437        
     432
    438433        usb_hid_report_path_t *path = usb_hid_report_path();
    439         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
    440 
    441         usb_hid_report_path_set_report_id (path, hid_dev->report_id);
    442        
    443         // fill in the currently pressed keys
    444        
     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. */
    445449        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    446             hid_dev->report, NULL, path,
    447             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,
    448452            USB_HID_REPORT_TYPE_INPUT);
    449453        unsigned i = 0;
    450        
     454
    451455        while (field != NULL) {
    452                 usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n", 
     456                usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n",
    453457                    field, field->value, field->usage);
    454                
     458
    455459                assert(i < kbd_dev->key_count);
    456                
    457                 // save the key usage
     460
     461                /* Save the key usage. */
    458462                if (field->value != 0) {
    459463                        kbd_dev->keys[i] = field->usage;
     
    463467                }
    464468                usb_log_debug2("Saved %u. key usage %d\n", i, kbd_dev->keys[i]);
    465                
     469
    466470                ++i;
    467                 field = usb_hid_report_get_sibling(hid_dev->report, field, path,
    468                     USB_HID_PATH_COMPARE_END
    469                     | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
     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,
    470474                    USB_HID_REPORT_TYPE_INPUT);
    471475        }
    472        
     476
    473477        usb_hid_report_path_free(path);
    474        
     478
    475479        usb_kbd_check_key_changes(hid_dev, kbd_dev);
    476480}
    477 
    478481/*----------------------------------------------------------------------------*/
    479482/* HID/KBD structure manipulation                                             */
    480483/*----------------------------------------------------------------------------*/
    481 
    482 static void usb_kbd_mark_unusable(usb_kbd_t *kbd_dev)
    483 {
    484         kbd_dev->initialized = USB_KBD_STATUS_TO_DESTROY;
    485 }
    486 
    487 /*----------------------------------------------------------------------------*/
    488 
    489 /**
    490  * Creates a new USB/HID keyboard structure.
    491  *
    492  * The structure returned by this function is not initialized. Use
    493  * usb_kbd_init() to initialize it prior to polling.
    494  *
    495  * @return New uninitialized structure for representing a USB/HID keyboard or
    496  *         NULL if not successful (memory error).
    497  */
    498 static usb_kbd_t *usb_kbd_new(void)
    499 {
    500         usb_kbd_t *kbd_dev =
    501             (usb_kbd_t *)calloc(1, sizeof(usb_kbd_t));
    502 
    503         if (kbd_dev == NULL) {
    504                 usb_log_fatal("No memory!\n");
    505                 return NULL;
    506         }
    507        
    508         kbd_dev->console_sess = NULL;
    509         kbd_dev->initialized = USB_KBD_STATUS_UNINITIALIZED;
    510        
    511         return kbd_dev;
    512 }
    513 
    514 /*----------------------------------------------------------------------------*/
    515 
    516 static int usb_kbd_create_function(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev)
    517 {
    518         assert(hid_dev != NULL);
    519         assert(hid_dev->usb_dev != NULL);
     484static int usb_kbd_create_function(usb_kbd_t *kbd_dev)
     485{
    520486        assert(kbd_dev != NULL);
    521        
     487        assert(kbd_dev->hid_dev != NULL);
     488        assert(kbd_dev->hid_dev->usb_dev != NULL);
     489
    522490        /* Create the exposed function. */
    523491        usb_log_debug("Creating DDF function %s...\n", HID_KBD_FUN_NAME);
    524         ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    525             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);
    526494        if (fun == NULL) {
    527495                usb_log_error("Could not create DDF function node.\n");
    528496                return ENOMEM;
    529497        }
    530        
    531         /*
    532          * Store the initialized HID device and HID ops
    533          * to the DDF function.
    534          */
     498
     499        /* Store the initialized HID device and HID ops
     500         * to the DDF function. */
    535501        fun->ops = &kbd_dev->ops;
    536502        fun->driver_data = kbd_dev;
     
    540506                usb_log_error("Could not bind DDF function: %s.\n",
    541507                    str_error(rc));
     508                fun->driver_data = NULL; /* We did not allocate this. */
    542509                ddf_fun_destroy(fun);
    543510                return rc;
    544511        }
    545        
     512
    546513        usb_log_debug("%s function created. Handle: %" PRIun "\n",
    547514            HID_KBD_FUN_NAME, fun->handle);
    548        
    549         usb_log_debug("Adding DDF function to category %s...\n", 
     515
     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                 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                }
    557531                return rc;
    558532        }
    559        
     533        kbd_dev->fun = fun;
     534
    560535        return EOK;
    561536}
    562 
    563537/*----------------------------------------------------------------------------*/
    564538/* API functions                                                              */
     
    587561{
    588562        usb_log_debug("Initializing HID/KBD structure...\n");
    589        
     563
    590564        if (hid_dev == NULL) {
    591                 usb_log_error("Failed to init keyboard structure: no structure"
    592                     " given.\n");
     565                usb_log_error(
     566                    "Failed to init keyboard structure: no structure given.\n");
    593567                return EINVAL;
    594568        }
    595        
    596         usb_kbd_t *kbd_dev = usb_kbd_new();
     569
     570        usb_kbd_t *kbd_dev = calloc(1, sizeof(usb_kbd_t));
    597571        if (kbd_dev == NULL) {
    598                 usb_log_error("Error while creating USB/HID KBD device "
    599                     "structure.\n");
    600                 return ENOMEM;  // TODO: some other code??
    601         }
     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;
    602579
    603580        /* Store link to HID device */
    604581        kbd_dev->hid_dev = hid_dev;
    605        
    606         /*
    607          * TODO: make more general
    608          */
     582
     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
    609592        usb_hid_report_path_t *path = usb_hid_report_path();
    610         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
    611        
     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        }
     607
    612608        usb_hid_report_path_set_report_id(path, 0);
    613        
    614         kbd_dev->key_count = usb_hid_report_size(
    615             hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT);
     609
     610        kbd_dev->key_count =
     611            usb_hid_report_size(&hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT);
     612
    616613        usb_hid_report_path_free(path);
    617        
     614
    618615        usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count);
    619        
    620         kbd_dev->keys = (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
    621        
     616
     617        kbd_dev->keys = calloc(kbd_dev->key_count, sizeof(int32_t));
    622618        if (kbd_dev->keys == NULL) {
    623                 usb_log_fatal("No memory!\n");
    624                 free(kbd_dev);
     619                usb_log_error("Failed to allocate key buffer.\n");
     620                usb_kbd_destroy(kbd_dev);
    625621                return ENOMEM;
    626622        }
    627        
    628         kbd_dev->keys_old =
    629                 (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
    630        
     623
     624        kbd_dev->keys_old = calloc(kbd_dev->key_count, sizeof(int32_t));
    631625        if (kbd_dev->keys_old == NULL) {
    632                 usb_log_fatal("No memory!\n");
    633                 free(kbd_dev->keys);
    634                 free(kbd_dev);
     626                usb_log_error("Failed to allocate old_key buffer.\n");
     627                usb_kbd_destroy(kbd_dev);
    635628                return ENOMEM;
    636629        }
    637        
    638         /*
    639          * Output report
    640          */
     630
     631        /* Output report */
    641632        kbd_dev->output_size = 0;
    642         kbd_dev->output_buffer = usb_hid_report_output(hid_dev->report,
     633        kbd_dev->output_buffer = usb_hid_report_output(&hid_dev->report,
    643634            &kbd_dev->output_size, 0);
    644635        if (kbd_dev->output_buffer == NULL) {
    645                 usb_log_warning("Error creating output report buffer.\n");
    646                 free(kbd_dev->keys);
     636                usb_log_error("Error creating output report buffer.\n");
     637                usb_kbd_destroy(kbd_dev);
    647638                return ENOMEM;
    648639        }
    649        
     640
    650641        usb_log_debug("Output buffer size: %zu\n", kbd_dev->output_size);
    651        
     642
    652643        kbd_dev->led_path = usb_hid_report_path();
    653         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(
    654651            kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
    655        
    656         kbd_dev->led_output_size = usb_hid_report_size(hid_dev->report,
    657             0, USB_HID_REPORT_TYPE_OUTPUT);
    658        
    659         usb_log_debug("Output report size (in items): %zu\n",
     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",
    660662            kbd_dev->led_output_size);
    661        
    662         kbd_dev->led_data = (int32_t *)calloc(
    663             kbd_dev->led_output_size, sizeof(int32_t));
    664        
     663
     664        kbd_dev->led_data = calloc(kbd_dev->led_output_size, sizeof(int32_t));
    665665        if (kbd_dev->led_data == NULL) {
    666                 usb_log_warning("Error creating buffer for LED output report."
    667                     "\n");
    668                 free(kbd_dev->keys);
    669                 usb_hid_report_output_free(kbd_dev->output_buffer);
    670                 free(kbd_dev);
     666                usb_log_error("Error creating buffer for LED output report.\n");
     667                usb_kbd_destroy(kbd_dev);
    671668                return ENOMEM;
    672669        }
    673        
    674         /*
    675          * Modifiers and locks
    676          */
    677         kbd_dev->modifiers = 0;
    678         kbd_dev->mods = DEFAULT_ACTIVE_MODS;
    679         kbd_dev->lock_keys = 0;
    680        
    681         /*
    682          * Autorepeat
    683          */
    684         kbd_dev->repeat.key_new = 0;
    685         kbd_dev->repeat.key_repeated = 0;
    686         kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;
    687         kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
    688        
    689         kbd_dev->repeat_mtx = (fibril_mutex_t *)(
    690             malloc(sizeof(fibril_mutex_t)));
    691         if (kbd_dev->repeat_mtx == NULL) {
    692                 usb_log_fatal("No memory!\n");
    693                 free(kbd_dev->keys);
    694                 usb_hid_report_output_free(kbd_dev->output_buffer);
    695                 free(kbd_dev);
    696                 return ENOMEM;
    697         }
    698        
    699         fibril_mutex_initialize(kbd_dev->repeat_mtx);
    700        
    701         // save the KBD device structure into the HID device structure
     670
     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. */
    702679        *data = kbd_dev;
    703        
    704         // set handler for incoming calls
    705         kbd_dev->ops.default_handler = default_connection_handler;
    706        
    707         /*
    708          * Set LEDs according to initial setup.
    709          * Set Idle rate
    710          */
    711         usb_kbd_set_led(hid_dev, kbd_dev);
    712        
    713         usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
    714             hid_dev->usb_dev->interface_no, IDLE_RATE);
    715        
    716         /*
    717          * Create new fibril for auto-repeat
    718          */
     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. */
    719692        fid_t fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev);
    720693        if (fid == 0) {
    721694                usb_log_error("Failed to start fibril for KBD auto-repeat");
     695                usb_kbd_destroy(kbd_dev);
    722696                return ENOMEM;
    723697        }
    724698        fibril_add_ready(fid);
    725        
    726         kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;
    727         usb_log_debug("HID/KBD device structure initialized.\n");
    728        
    729         usb_log_debug("Creating KBD function...\n");
    730         int rc = usb_kbd_create_function(hid_dev, kbd_dev);
    731         if (rc != EOK) {
    732                 usb_kbd_destroy(kbd_dev);
    733                 return rc;
    734         }
    735        
     699
    736700        return EOK;
    737701}
    738 
    739 /*----------------------------------------------------------------------------*/
    740 
     702/*----------------------------------------------------------------------------*/
    741703bool usb_kbd_polling_callback(usb_hid_dev_t *hid_dev, void *data)
    742704{
    743         if (hid_dev == NULL/* || buffer == NULL*/ || data == NULL) {
    744                 // do not continue polling (???)
     705        if (hid_dev == NULL || data == NULL) {
     706                /* This means something serious */
    745707                return false;
    746708        }
    747        
    748         usb_kbd_t *kbd_dev = (usb_kbd_t *)data;
    749         assert(kbd_dev != NULL);
    750        
     709
     710        usb_kbd_t *kbd_dev = data;
    751711        // TODO: add return value from this function
    752712        usb_kbd_process_data(hid_dev, kbd_dev);
    753        
     713
    754714        return true;
    755715}
    756 
    757 /*----------------------------------------------------------------------------*/
    758 
     716/*----------------------------------------------------------------------------*/
    759717int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev)
    760718{
    761719        return (kbd_dev->initialized == USB_KBD_STATUS_INITIALIZED);
    762720}
    763 
    764 /*----------------------------------------------------------------------------*/
    765 
     721/*----------------------------------------------------------------------------*/
    766722int usb_kbd_is_ready_to_destroy(const usb_kbd_t *kbd_dev)
    767723{
    768724        return (kbd_dev->initialized == USB_KBD_STATUS_TO_DESTROY);
    769725}
    770 
    771726/*----------------------------------------------------------------------------*/
    772727/**
     
    780735                return;
    781736        }
    782        
    783         // hangup session to the console
    784         async_hangup(kbd_dev->console_sess);
    785        
    786         if (kbd_dev->repeat_mtx != NULL) {
    787                 //assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
    788                 // FIXME - the fibril_mutex_is_locked may not cause
    789                 // fibril scheduling
    790                 while (fibril_mutex_is_locked(kbd_dev->repeat_mtx)) {}
    791                 free(kbd_dev->repeat_mtx);
    792         }
    793        
    794         // free all buffers
    795         if (kbd_dev->keys != NULL) {
    796                 free(kbd_dev->keys);
    797         }
    798         if (kbd_dev->keys_old != NULL) {
    799                 free(kbd_dev->keys_old);
    800         }
    801         if (kbd_dev->led_data != NULL) {
    802                 free(kbd_dev->led_data);
    803         }
    804         if (kbd_dev->led_path != NULL) {
    805                 usb_hid_report_path_free(kbd_dev->led_path);
    806         }
    807         if (kbd_dev->output_buffer != NULL) {
    808                 usb_hid_report_output_free(kbd_dev->output_buffer);
    809         }
    810 }
    811 
    812 /*----------------------------------------------------------------------------*/
    813 
     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);
     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/*----------------------------------------------------------------------------*/
    814768void usb_kbd_deinit(usb_hid_dev_t *hid_dev, void *data)
    815769{
    816         if (hid_dev == NULL) {
    817                 return;
    818         }
    819        
    820770        if (data != NULL) {
    821                 usb_kbd_t *kbd_dev = (usb_kbd_t *)data;
     771                usb_kbd_t *kbd_dev = data;
    822772                if (usb_kbd_is_initialized(kbd_dev)) {
    823                         usb_kbd_mark_unusable(kbd_dev);
    824                 } else {
    825                         usb_kbd_destroy(kbd_dev);
    826                 }
    827         }
    828 }
    829 
    830 /*----------------------------------------------------------------------------*/
    831 
     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/*----------------------------------------------------------------------------*/
    832781int usb_kbd_set_boot_protocol(usb_hid_dev_t *hid_dev)
    833782{
    834         int rc = usb_hid_parse_report_descriptor(hid_dev->report,
    835             USB_KBD_BOOT_REPORT_DESCRIPTOR,
    836             USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE);
    837        
     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
    838788        if (rc != EOK) {
    839789                usb_log_error("Failed to parse boot report descriptor: %s\n",
     
    841791                return rc;
    842792        }
    843        
    844         rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe, 
     793
     794        rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe,
    845795            hid_dev->usb_dev->interface_no, USB_HID_PROTOCOL_BOOT);
    846        
     796
    847797        if (rc != EOK) {
    848798                usb_log_warning("Failed to set boot protocol to the device: "
     
    850800                return rc;
    851801        }
    852        
     802
    853803        return EOK;
    854804}
    855 
    856805/**
    857806 * @}
Note: See TracChangeset for help on using the changeset viewer.