Ignore:
File:
1 edited

Legend:

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

    r5f6e25e 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>
    45 #include <async_obsolete.h>
    4646#include <fibril.h>
    4747#include <fibril_synch.h>
     
    7171#include "../usbhid.h"
    7272
    73 // FIXME: remove this header
    74 #include <abi/ipc/methods.h>
    75 
    7673/*----------------------------------------------------------------------------*/
    7774
     
    9087
    9188/*----------------------------------------------------------------------------*/
    92 
    9389/** Keyboard polling endpoint description for boot protocol class. */
    94 usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description = {
     90const usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description = {
    9591        .transfer_type = USB_TRANSFER_INTERRUPT,
    9692        .direction = USB_DIRECTION_IN,
     
    105101
    106102static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev);
    107 
    108 /*----------------------------------------------------------------------------*/
    109 
    110 enum {
    111         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 */
    112137};
    113 
    114 static const uint8_t USB_KBD_BOOT_REPORT_DESCRIPTOR[
    115     USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE] = {
    116         0x05, 0x01,  // Usage Page (Generic Desktop),
    117         0x09, 0x06,  // Usage (Keyboard),
    118         0xA1, 0x01,  // Collection (Application),
    119         0x75, 0x01,  //   Report Size (1),
    120         0x95, 0x08,  //   Report Count (8),       
    121         0x05, 0x07,  //   Usage Page (Key Codes);
    122         0x19, 0xE0,  //   Usage Minimum (224),
    123         0x29, 0xE7,  //   Usage Maximum (231),
    124         0x15, 0x00,  //   Logical Minimum (0),
    125         0x25, 0x01,  //   Logical Maximum (1),
    126         0x81, 0x02,  //   Input (Data, Variable, Absolute),   ; Modifier byte
    127         0x95, 0x01,  //   Report Count (1),
    128         0x75, 0x08,  //   Report Size (8),
    129         0x81, 0x01,  //   Input (Constant),                   ; Reserved byte
    130         0x95, 0x05,  //   Report Count (5),
    131         0x75, 0x01,  //   Report Size (1),
    132         0x05, 0x08,  //   Usage Page (Page# for LEDs),
    133         0x19, 0x01,  //   Usage Minimum (1),
    134         0x29, 0x05,  //   Usage Maxmimum (5),
    135         0x91, 0x02,  //   Output (Data, Variable, Absolute),  ; LED report
    136         0x95, 0x01,  //   Report Count (1),
    137         0x75, 0x03,  //   Report Size (3),
    138         0x91, 0x01,  //   Output (Constant),              ; LED report padding
    139         0x95, 0x06,  //   Report Count (6),
    140         0x75, 0x08,  //   Report Size (8),
    141         0x15, 0x00,  //   Logical Minimum (0),
    142         0x25, 0xff,  //   Logical Maximum (255),
    143         0x05, 0x07,  //   Usage Page (Key Codes),
    144         0x19, 0x00,  //   Usage Minimum (0),
    145         0x29, 0xff,  //   Usage Maximum (255),
    146         0x81, 0x00,  //   Input (Data, Array),            ; Key arrays (6 bytes)
    147         0xC0           // End Collection
    148 
    149 };
    150 
    151 /*----------------------------------------------------------------------------*/
    152 
     138/*----------------------------------------------------------------------------*/
    153139typedef enum usb_kbd_flags {
    154140        USB_KBD_STATUS_UNINITIALIZED = 0,
     
    156142        USB_KBD_STATUS_TO_DESTROY = -1
    157143} usb_kbd_flags;
    158 
    159144/*----------------------------------------------------------------------------*/
    160145/* IPC method handler                                                         */
    161146/*----------------------------------------------------------------------------*/
    162 
    163 static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
    164 
    165147/**
    166148 * Default handler for IPC methods not handled by DDF.
    167149 *
    168  * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it
    169  * assumes the caller is the console and thus it stores IPC phone to it for
    170  * later use by the driver to notify about key events.
     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.
    171154 *
    172155 * @param fun Device function handling the call.
     
    177160    ipc_callid_t icallid, ipc_call_t *icall)
    178161{
    179         sysarg_t method = IPC_GET_IMETHOD(*icall);
    180         int callback;
    181        
    182         usb_kbd_t *kbd_dev = (usb_kbd_t *)fun->driver_data;
    183         if (kbd_dev == NULL) {
    184                 usb_log_debug("default_connection_handler: "
    185                     "Missing parameter.\n");
     162        if (fun == NULL || fun->driver_data == NULL) {
     163                usb_log_error("%s: Missing parameter.\n", __FUNCTION__);
    186164                async_answer_0(icallid, EINVAL);
    187165                return;
    188166        }
    189167
     168        const sysarg_t method = IPC_GET_IMETHOD(*icall);
     169        usb_kbd_t *kbd_dev = fun->driver_data;
     170
    190171        switch (method) {
    191         case IPC_M_CONNECT_TO_ME:
    192                 callback = IPC_GET_ARG5(*icall);
    193 
    194                 if (kbd_dev->console_phone != -1) {
    195                         usb_log_debug("default_connection_handler: "
    196                             "console phone already set\n");
    197                         async_answer_0(icallid, ELIMIT);
    198                         return;
    199                 }
    200 
    201                 kbd_dev->console_phone = callback;
    202                
    203                 usb_log_debug("default_connection_handler: OK\n");
    204                 async_answer_0(icallid, EOK);
    205                 break;
    206172        case KBDEV_SET_IND:
    207173                kbd_dev->mods = IPC_GET_ARG1(*icall);
     
    209175                async_answer_0(icallid, EOK);
    210176                break;
     177        /* This might be ugly but async_callback_receive_start makes no
     178         * difference for incorrect call and malloc failure. */
     179        case IPC_M_CONNECT_TO_ME: {
     180                async_sess_t *sess =
     181                    async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
     182                /* Probably ENOMEM error, try again. */
     183                if (sess == NULL) {
     184                        usb_log_warning(
     185                            "Failed to create start console session.\n");
     186                        async_answer_0(icallid, EAGAIN);
     187                        break;
     188                }
     189                if (kbd_dev->console_sess == NULL) {
     190                        kbd_dev->console_sess = sess;
     191                        usb_log_debug("%s: OK\n", __FUNCTION__);
     192                        async_answer_0(icallid, EOK);
     193                } else {
     194                        usb_log_error("%s: console session already set\n",
     195                           __FUNCTION__);
     196                        async_answer_0(icallid, ELIMIT);
     197                }
     198                break;
     199        }
    211200        default:
    212                 usb_log_debug("default_connection_handler: Wrong function.\n");
    213                 async_answer_0(icallid, EINVAL);
    214                 break;
    215         }
    216 }
    217 
     201                        usb_log_error("%s: Unknown method: %d.\n",
     202                            __FUNCTION__, (int) method);
     203                        async_answer_0(icallid, EINVAL);
     204                        break;
     205        }
     206
     207}
    218208/*----------------------------------------------------------------------------*/
    219209/* Key processing functions                                                   */
     
    232222 * @param kbd_dev Keyboard device structure.
    233223 */
    234 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)
    235225{
    236226        if (kbd_dev->output_size == 0) {
     
    243233
    244234        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    245             hid_dev->report, NULL, kbd_dev->led_path,
     235            &hid_dev->report, NULL, kbd_dev->led_path,
    246236            USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    247237            USB_HID_REPORT_TYPE_OUTPUT);
    248        
     238
    249239        while (field != NULL) {
    250                
    251                 if ((field->usage == USB_HID_LED_NUM_LOCK) 
     240
     241                if ((field->usage == USB_HID_LED_NUM_LOCK)
    252242                    && (kbd_dev->mods & KM_NUM_LOCK)){
    253243                        field->value = 1;
    254244                }
    255245
    256                 if ((field->usage == USB_HID_LED_CAPS_LOCK) 
     246                if ((field->usage == USB_HID_LED_CAPS_LOCK)
    257247                    && (kbd_dev->mods & KM_CAPS_LOCK)){
    258248                        field->value = 1;
    259249                }
    260250
    261                 if ((field->usage == USB_HID_LED_SCROLL_LOCK) 
     251                if ((field->usage == USB_HID_LED_SCROLL_LOCK)
    262252                    && (kbd_dev->mods & KM_SCROLL_LOCK)){
    263253                        field->value = 1;
    264254                }
    265                
    266                 field = usb_hid_report_get_sibling(hid_dev->report, field,
    267                     kbd_dev->led_path, 
    268                 USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    269                         USB_HID_REPORT_TYPE_OUTPUT);
    270         }
    271        
     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
    272262        // TODO: what about the Report ID?
    273         int rc = usb_hid_report_output_translate(hid_dev->report, 0,
     263        int rc = usb_hid_report_output_translate(&hid_dev->report, 0,
    274264            kbd_dev->output_buffer, kbd_dev->output_size);
    275        
     265
    276266        if (rc != EOK) {
    277267                usb_log_warning("Error translating LED output to output report"
     
    279269                return;
    280270        }
    281        
    282         usb_log_debug("Output report buffer: %s\n", 
    283             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,
    284274                0));
    285        
    286         usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe,
    287             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,
    288278            kbd_dev->output_buffer, kbd_dev->output_size);
    289 }
    290 
     279        if (rc != EOK) {
     280                usb_log_warning("Failed to set kbd indicators.\n");
     281        }
     282}
    291283/*----------------------------------------------------------------------------*/
    292284/** Send key event.
     
    297289 * @param key Key code
    298290 */
    299 void usb_kbd_push_ev(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev, int type,
    300     unsigned int key)
     291void usb_kbd_push_ev(usb_kbd_t *kbd_dev, int type, unsigned key)
    301292{
    302293        usb_log_debug2("Sending kbdev event %d/%d to the console\n", type, key);
    303         if (kbd_dev->console_phone < 0) {
     294        if (kbd_dev->console_sess == NULL) {
    304295                usb_log_warning(
    305296                    "Connection to console not ready, key discarded.\n");
    306297                return;
    307298        }
    308        
    309         async_obsolete_msg_2(kbd_dev->console_phone, KBDEV_EVENT, type, key);
    310 }
    311 
    312 /*----------------------------------------------------------------------------*/
    313 
    314 static inline int usb_kbd_is_lock(unsigned int key_code)
     299
     300        async_exch_t *exch = async_exchange_begin(kbd_dev->console_sess);
     301        if (exch != NULL) {
     302                async_msg_2(exch, KBDEV_EVENT, type, key);
     303                async_exchange_end(exch);
     304        } else {
     305                usb_log_warning("Failed to send key to console.\n");
     306        }
     307}
     308/*----------------------------------------------------------------------------*/
     309static inline int usb_kbd_is_lock(unsigned int key_code)
    315310{
    316311        return (key_code == KC_NUM_LOCK
     
    318313            || key_code == KC_CAPS_LOCK);
    319314}
    320 
     315/*----------------------------------------------------------------------------*/
    321316static size_t find_in_array_int32(int32_t val, int32_t *arr, size_t arr_size)
    322317{
     
    329324        return (size_t) -1;
    330325}
    331 
    332326/*----------------------------------------------------------------------------*/
    333327/**
     
    346340 * @sa usb_kbd_push_ev(), usb_kbd_repeat_start(), usb_kbd_repeat_stop()
    347341 */
    348 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,
    349343    usb_kbd_t *kbd_dev)
    350344{
    351         unsigned int key;
    352         size_t i;
    353        
     345
    354346        /*
    355347         * First of all, check if the kbd have reported phantom state.
     
    360352         * whole input report.
    361353         */
    362         i = find_in_array_int32(ERROR_ROLLOVER, kbd_dev->keys,
     354        size_t i = find_in_array_int32(ERROR_ROLLOVER, kbd_dev->keys,
    363355            kbd_dev->key_count);
    364356        if (i != (size_t) -1) {
    365                 usb_log_debug("Detected phantom state.\n");
     357                usb_log_error("Detected phantom state.\n");
    366358                return;
    367359        }
    368        
     360
    369361        /*
    370362         * Key releases
    371363         */
    372364        for (i = 0; i < kbd_dev->key_count; i++) {
    373                 int32_t old_key = kbd_dev->keys_old[i];
     365                const int32_t old_key = kbd_dev->keys_old[i];
    374366                /* Find the old key among currently pressed keys. */
    375                 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,
    376368                    kbd_dev->key_count);
    377369                /* If the key was not found, we need to signal release. */
    378370                if (pos == (size_t) -1) {
    379                         key = usbhid_parse_scancode(old_key);
     371                        const unsigned key = usbhid_parse_scancode(old_key);
    380372                        if (!usb_kbd_is_lock(key)) {
    381373                                usb_kbd_repeat_stop(kbd_dev, key);
    382374                        }
    383                         usb_kbd_push_ev(hid_dev, kbd_dev, KEY_RELEASE, key);
     375                        usb_kbd_push_ev(kbd_dev, KEY_RELEASE, key);
    384376                        usb_log_debug2("Key released: %u "
    385377                            "(USB code %" PRIu32 ")\n", key, old_key);
    386378                }
    387379        }
    388        
     380
    389381        /*
    390382         * Key presses
    391383         */
    392384        for (i = 0; i < kbd_dev->key_count; ++i) {
    393                 int32_t new_key = kbd_dev->keys[i];
     385                const int32_t new_key = kbd_dev->keys[i];
    394386                /* Find the new key among already pressed keys. */
    395                 size_t pos = find_in_array_int32(new_key, kbd_dev->keys_old,
    396                     kbd_dev->key_count);
     387                const size_t pos = find_in_array_int32(new_key,
     388                    kbd_dev->keys_old, kbd_dev->key_count);
    397389                /* If the key was not found, we need to signal press. */
    398390                if (pos == (size_t) -1) {
    399                         key = usbhid_parse_scancode(kbd_dev->keys[i]);
     391                        unsigned key = usbhid_parse_scancode(kbd_dev->keys[i]);
    400392                        if (!usb_kbd_is_lock(key)) {
    401393                                usb_kbd_repeat_start(kbd_dev, key);
    402394                        }
    403                         usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS, key);
     395                        usb_kbd_push_ev(kbd_dev, KEY_PRESS, key);
    404396                        usb_log_debug2("Key pressed: %u "
    405397                            "(USB code %" PRIu32 ")\n", key, new_key);
    406398                }
    407399        }
    408        
     400
    409401        memcpy(kbd_dev->keys_old, kbd_dev->keys, kbd_dev->key_count * 4);
    410        
     402
     403        // TODO Get rid of this
    411404        char key_buffer[512];
    412405        ddf_dump_buffer(key_buffer, 512,
     
    414407        usb_log_debug2("Stored keys %s.\n", key_buffer);
    415408}
    416 
    417409/*----------------------------------------------------------------------------*/
    418410/* General kbd functions                                                      */
     
    436428static void usb_kbd_process_data(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev)
    437429{
    438         assert(hid_dev->report != NULL);
    439430        assert(hid_dev != NULL);
    440431        assert(kbd_dev != NULL);
    441        
     432
    442433        usb_hid_report_path_t *path = usb_hid_report_path();
    443         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
    444 
    445         usb_hid_report_path_set_report_id (path, hid_dev->report_id);
    446        
    447         // fill in the currently pressed keys
    448        
     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. */
    449449        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    450             hid_dev->report, NULL, path,
    451             USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
     450            &hid_dev->report, NULL, path,
     451            USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    452452            USB_HID_REPORT_TYPE_INPUT);
    453453        unsigned i = 0;
    454        
     454
    455455        while (field != NULL) {
    456                 usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n", 
     456                usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n",
    457457                    field, field->value, field->usage);
    458                
     458
    459459                assert(i < kbd_dev->key_count);
    460                
    461                 // save the key usage
     460
     461                /* Save the key usage. */
    462462                if (field->value != 0) {
    463463                        kbd_dev->keys[i] = field->usage;
     
    467467                }
    468468                usb_log_debug2("Saved %u. key usage %d\n", i, kbd_dev->keys[i]);
    469                
     469
    470470                ++i;
    471                 field = usb_hid_report_get_sibling(hid_dev->report, field, path,
    472                     USB_HID_PATH_COMPARE_END
    473                     | 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,
    474474                    USB_HID_REPORT_TYPE_INPUT);
    475475        }
    476        
     476
    477477        usb_hid_report_path_free(path);
    478        
     478
    479479        usb_kbd_check_key_changes(hid_dev, kbd_dev);
    480480}
    481 
    482481/*----------------------------------------------------------------------------*/
    483482/* HID/KBD structure manipulation                                             */
    484483/*----------------------------------------------------------------------------*/
    485 
    486 static void usb_kbd_mark_unusable(usb_kbd_t *kbd_dev)
    487 {
    488         kbd_dev->initialized = USB_KBD_STATUS_TO_DESTROY;
    489 }
    490 
    491 /*----------------------------------------------------------------------------*/
    492 
    493 /**
    494  * Creates a new USB/HID keyboard structure.
    495  *
    496  * The structure returned by this function is not initialized. Use
    497  * usb_kbd_init() to initialize it prior to polling.
    498  *
    499  * @return New uninitialized structure for representing a USB/HID keyboard or
    500  *         NULL if not successful (memory error).
    501  */
    502 static usb_kbd_t *usb_kbd_new(void)
    503 {
    504         usb_kbd_t *kbd_dev =
    505             (usb_kbd_t *)calloc(1, sizeof(usb_kbd_t));
    506 
    507         if (kbd_dev == NULL) {
    508                 usb_log_fatal("No memory!\n");
    509                 return NULL;
    510         }
    511        
    512         kbd_dev->console_phone = -1;
    513         kbd_dev->initialized = USB_KBD_STATUS_UNINITIALIZED;
    514        
    515         return kbd_dev;
    516 }
    517 
    518 /*----------------------------------------------------------------------------*/
    519 
    520 static int usb_kbd_create_function(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev)
    521 {
    522         assert(hid_dev != NULL);
    523         assert(hid_dev->usb_dev != NULL);
     484static int usb_kbd_create_function(usb_kbd_t *kbd_dev)
     485{
    524486        assert(kbd_dev != NULL);
    525        
     487        assert(kbd_dev->hid_dev != NULL);
     488        assert(kbd_dev->hid_dev->usb_dev != NULL);
     489
    526490        /* Create the exposed function. */
    527491        usb_log_debug("Creating DDF function %s...\n", HID_KBD_FUN_NAME);
    528         ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    529             HID_KBD_FUN_NAME);
     492        ddf_fun_t *fun = ddf_fun_create(kbd_dev->hid_dev->usb_dev->ddf_dev,
     493            fun_exposed, HID_KBD_FUN_NAME);
    530494        if (fun == NULL) {
    531495                usb_log_error("Could not create DDF function node.\n");
    532496                return ENOMEM;
    533497        }
    534        
    535         /*
    536          * Store the initialized HID device and HID ops
    537          * to the DDF function.
    538          */
     498
     499        /* Store the initialized HID device and HID ops
     500         * to the DDF function. */
    539501        fun->ops = &kbd_dev->ops;
    540502        fun->driver_data = kbd_dev;
     
    544506                usb_log_error("Could not bind DDF function: %s.\n",
    545507                    str_error(rc));
     508                fun->driver_data = NULL; /* We did not allocate this. */
    546509                ddf_fun_destroy(fun);
    547510                return rc;
    548511        }
    549        
     512
    550513        usb_log_debug("%s function created. Handle: %" PRIun "\n",
    551514            HID_KBD_FUN_NAME, fun->handle);
    552        
    553         usb_log_debug("Adding DDF function to category %s...\n", 
     515
     516        usb_log_debug("Adding DDF function to category %s...\n",
    554517            HID_KBD_CLASS_NAME);
    555518        rc = ddf_fun_add_to_category(fun, HID_KBD_CATEGORY_NAME);
     
    558521                    "Could not add DDF function to category %s: %s.\n",
    559522                    HID_KBD_CLASS_NAME, str_error(rc));
    560                 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                }
    561531                return rc;
    562532        }
    563        
     533        kbd_dev->fun = fun;
     534
    564535        return EOK;
    565536}
    566 
    567537/*----------------------------------------------------------------------------*/
    568538/* API functions                                                              */
     
    591561{
    592562        usb_log_debug("Initializing HID/KBD structure...\n");
    593        
     563
    594564        if (hid_dev == NULL) {
    595                 usb_log_error("Failed to init keyboard structure: no structure"
    596                     " given.\n");
     565                usb_log_error(
     566                    "Failed to init keyboard structure: no structure given.\n");
    597567                return EINVAL;
    598568        }
    599        
    600         usb_kbd_t *kbd_dev = usb_kbd_new();
     569
     570        usb_kbd_t *kbd_dev = calloc(1, sizeof(usb_kbd_t));
    601571        if (kbd_dev == NULL) {
    602                 usb_log_error("Error while creating USB/HID KBD device "
    603                     "structure.\n");
    604                 return ENOMEM;  // TODO: some other code??
    605         }
     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;
    606579
    607580        /* Store link to HID device */
    608581        kbd_dev->hid_dev = hid_dev;
    609        
    610         /*
    611          * TODO: make more general
    612          */
     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
    613592        usb_hid_report_path_t *path = usb_hid_report_path();
    614         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
    615        
     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
    616608        usb_hid_report_path_set_report_id(path, 0);
    617        
    618         kbd_dev->key_count = usb_hid_report_size(
    619             hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT);
     609
     610        kbd_dev->key_count =
     611            usb_hid_report_size(&hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT);
     612
    620613        usb_hid_report_path_free(path);
    621        
     614
    622615        usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count);
    623        
    624         kbd_dev->keys = (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
    625        
     616
     617        kbd_dev->keys = calloc(kbd_dev->key_count, sizeof(int32_t));
    626618        if (kbd_dev->keys == NULL) {
    627                 usb_log_fatal("No memory!\n");
    628                 free(kbd_dev);
     619                usb_log_error("Failed to allocate key buffer.\n");
     620                usb_kbd_destroy(kbd_dev);
    629621                return ENOMEM;
    630622        }
    631        
    632         kbd_dev->keys_old =
    633                 (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
    634        
     623
     624        kbd_dev->keys_old = calloc(kbd_dev->key_count, sizeof(int32_t));
    635625        if (kbd_dev->keys_old == NULL) {
    636                 usb_log_fatal("No memory!\n");
    637                 free(kbd_dev->keys);
    638                 free(kbd_dev);
     626                usb_log_error("Failed to allocate old_key buffer.\n");
     627                usb_kbd_destroy(kbd_dev);
    639628                return ENOMEM;
    640629        }
    641        
    642         /*
    643          * Output report
    644          */
     630
     631        /* Output report */
    645632        kbd_dev->output_size = 0;
    646         kbd_dev->output_buffer = usb_hid_report_output(hid_dev->report,
     633        kbd_dev->output_buffer = usb_hid_report_output(&hid_dev->report,
    647634            &kbd_dev->output_size, 0);
    648635        if (kbd_dev->output_buffer == NULL) {
    649                 usb_log_warning("Error creating output report buffer.\n");
    650                 free(kbd_dev->keys);
     636                usb_log_error("Error creating output report buffer.\n");
     637                usb_kbd_destroy(kbd_dev);
    651638                return ENOMEM;
    652639        }
    653        
     640
    654641        usb_log_debug("Output buffer size: %zu\n", kbd_dev->output_size);
    655        
     642
    656643        kbd_dev->led_path = usb_hid_report_path();
    657         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(
    658651            kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
    659        
    660         kbd_dev->led_output_size = usb_hid_report_size(hid_dev->report,
    661             0, USB_HID_REPORT_TYPE_OUTPUT);
    662        
    663         usb_log_debug("Output report size (in items): %zu\n",
     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",
    664662            kbd_dev->led_output_size);
    665        
    666         kbd_dev->led_data = (int32_t *)calloc(
    667             kbd_dev->led_output_size, sizeof(int32_t));
    668        
     663
     664        kbd_dev->led_data = calloc(kbd_dev->led_output_size, sizeof(int32_t));
    669665        if (kbd_dev->led_data == NULL) {
    670                 usb_log_warning("Error creating buffer for LED output report."
    671                     "\n");
    672                 free(kbd_dev->keys);
    673                 usb_hid_report_output_free(kbd_dev->output_buffer);
    674                 free(kbd_dev);
     666                usb_log_error("Error creating buffer for LED output report.\n");
     667                usb_kbd_destroy(kbd_dev);
    675668                return ENOMEM;
    676669        }
    677        
    678         /*
    679          * Modifiers and locks
    680          */
    681         kbd_dev->modifiers = 0;
    682         kbd_dev->mods = DEFAULT_ACTIVE_MODS;
    683         kbd_dev->lock_keys = 0;
    684        
    685         /*
    686          * Autorepeat
    687          */
    688         kbd_dev->repeat.key_new = 0;
    689         kbd_dev->repeat.key_repeated = 0;
    690         kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;
    691         kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
    692        
    693         kbd_dev->repeat_mtx = (fibril_mutex_t *)(
    694             malloc(sizeof(fibril_mutex_t)));
    695         if (kbd_dev->repeat_mtx == NULL) {
    696                 usb_log_fatal("No memory!\n");
    697                 free(kbd_dev->keys);
    698                 usb_hid_report_output_free(kbd_dev->output_buffer);
    699                 free(kbd_dev);
    700                 return ENOMEM;
    701         }
    702        
    703         fibril_mutex_initialize(kbd_dev->repeat_mtx);
    704        
    705         // 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. */
    706679        *data = kbd_dev;
    707        
    708         // set handler for incoming calls
    709         kbd_dev->ops.default_handler = default_connection_handler;
    710        
    711         /*
    712          * Set LEDs according to initial setup.
    713          * Set Idle rate
    714          */
    715         usb_kbd_set_led(hid_dev, kbd_dev);
    716        
    717         usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
    718             hid_dev->usb_dev->interface_no, IDLE_RATE);
    719        
    720         /*
    721          * Create new fibril for auto-repeat
    722          */
     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. */
    723692        fid_t fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev);
    724693        if (fid == 0) {
    725694                usb_log_error("Failed to start fibril for KBD auto-repeat");
     695                usb_kbd_destroy(kbd_dev);
    726696                return ENOMEM;
    727697        }
    728698        fibril_add_ready(fid);
    729        
    730         kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;
    731         usb_log_debug("HID/KBD device structure initialized.\n");
    732        
    733         usb_log_debug("Creating KBD function...\n");
    734         int rc = usb_kbd_create_function(hid_dev, kbd_dev);
    735         if (rc != EOK) {
    736                 usb_kbd_destroy(kbd_dev);
    737                 return rc;
    738         }
    739        
     699
    740700        return EOK;
    741701}
    742 
    743 /*----------------------------------------------------------------------------*/
    744 
     702/*----------------------------------------------------------------------------*/
    745703bool usb_kbd_polling_callback(usb_hid_dev_t *hid_dev, void *data)
    746704{
    747         if (hid_dev == NULL/* || buffer == NULL*/ || data == NULL) {
    748                 // do not continue polling (???)
     705        if (hid_dev == NULL || data == NULL) {
     706                /* This means something serious */
    749707                return false;
    750708        }
    751        
    752         usb_kbd_t *kbd_dev = (usb_kbd_t *)data;
    753         assert(kbd_dev != NULL);
    754        
     709
     710        usb_kbd_t *kbd_dev = data;
    755711        // TODO: add return value from this function
    756712        usb_kbd_process_data(hid_dev, kbd_dev);
    757        
     713
    758714        return true;
    759715}
    760 
    761 /*----------------------------------------------------------------------------*/
    762 
     716/*----------------------------------------------------------------------------*/
    763717int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev)
    764718{
    765719        return (kbd_dev->initialized == USB_KBD_STATUS_INITIALIZED);
    766720}
    767 
    768 /*----------------------------------------------------------------------------*/
    769 
     721/*----------------------------------------------------------------------------*/
    770722int usb_kbd_is_ready_to_destroy(const usb_kbd_t *kbd_dev)
    771723{
    772724        return (kbd_dev->initialized == USB_KBD_STATUS_TO_DESTROY);
    773725}
    774 
    775726/*----------------------------------------------------------------------------*/
    776727/**
     
    784735                return;
    785736        }
    786        
    787         // hangup phone to the console
    788         async_obsolete_hangup(kbd_dev->console_phone);
    789        
    790         if (kbd_dev->repeat_mtx != NULL) {
    791                 //assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
    792                 // FIXME - the fibril_mutex_is_locked may not cause
    793                 // fibril scheduling
    794                 while (fibril_mutex_is_locked(kbd_dev->repeat_mtx)) {}
    795                 free(kbd_dev->repeat_mtx);
    796         }
    797        
    798         // free all buffers
    799         if (kbd_dev->keys != NULL) {
    800                 free(kbd_dev->keys);
    801         }
    802         if (kbd_dev->keys_old != NULL) {
    803                 free(kbd_dev->keys_old);
    804         }
    805         if (kbd_dev->led_data != NULL) {
    806                 free(kbd_dev->led_data);
    807         }
    808         if (kbd_dev->led_path != NULL) {
    809                 usb_hid_report_path_free(kbd_dev->led_path);
    810         }
    811         if (kbd_dev->output_buffer != NULL) {
    812                 usb_hid_report_output_free(kbd_dev->output_buffer);
    813         }
    814 }
    815 
    816 /*----------------------------------------------------------------------------*/
    817 
     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/*----------------------------------------------------------------------------*/
    818768void usb_kbd_deinit(usb_hid_dev_t *hid_dev, void *data)
    819769{
    820         if (hid_dev == NULL) {
    821                 return;
    822         }
    823        
    824770        if (data != NULL) {
    825                 usb_kbd_t *kbd_dev = (usb_kbd_t *)data;
     771                usb_kbd_t *kbd_dev = data;
    826772                if (usb_kbd_is_initialized(kbd_dev)) {
    827                         usb_kbd_mark_unusable(kbd_dev);
    828                 } else {
    829                         usb_kbd_destroy(kbd_dev);
    830                 }
    831         }
    832 }
    833 
    834 /*----------------------------------------------------------------------------*/
    835 
     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/*----------------------------------------------------------------------------*/
    836781int usb_kbd_set_boot_protocol(usb_hid_dev_t *hid_dev)
    837782{
    838         int rc = usb_hid_parse_report_descriptor(hid_dev->report,
    839             USB_KBD_BOOT_REPORT_DESCRIPTOR,
    840             USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE);
    841        
     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
    842788        if (rc != EOK) {
    843789                usb_log_error("Failed to parse boot report descriptor: %s\n",
     
    845791                return rc;
    846792        }
    847        
    848         rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe, 
     793
     794        rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe,
    849795            hid_dev->usb_dev->interface_no, USB_HID_PROTOCOL_BOOT);
    850        
     796
    851797        if (rc != EOK) {
    852798                usb_log_warning("Failed to set boot protocol to the device: "
     
    854800                return rc;
    855801        }
    856        
     802
    857803        return EOK;
    858804}
    859 
    860805/**
    861806 * @}
Note: See TracChangeset for help on using the changeset viewer.