Ignore:
Timestamp:
2011-11-10T11:29:10Z (12 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
54464f6a, c2245a3, c6f189f7
Parents:
2e1b9dc (diff), 2d1ba51 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge USB changes.

Interface changes:

  • GET_ADDRESS has been renamed to GET_MY_ADDRESS and the handle parameter was dropped. Tis call no longer cascades up to the root hub, but it is answered in the first place the information is available (nearest hub)
  • Reintroduced address reservation for USB_DEFAULT_ADDRESS. The interface now enables device drivers to request specific address on initialization and either insists on that address or accept any other if the address is not available. Note that it is not possible to get the default address if the driver does not insist.
  • Any endpoint registered is removed when address is released and a warning is produced if there were any such endpoints.
  • It is no longer necessary or possible to pass device speed information when registering endpoints.

Driver fixes: memory leaks and crashes (not only) in error paths.
Fixes or removes flaky device_remove implementation in device drivers.

File:
1 edited

Legend:

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

    r2e1b9dc r747ef72  
    4141#include <io/keycode.h>
    4242#include <io/console.h>
     43#include <abi/ipc/methods.h>
    4344#include <ipc/kbdev.h>
    4445#include <async.h>
     
    8687
    8788/*----------------------------------------------------------------------------*/
    88 
    8989/** Keyboard polling endpoint description for boot protocol class. */
    9090const usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description = {
     
    101101
    102102static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev);
    103 
    104 /*----------------------------------------------------------------------------*/
    105 
    106 enum {
    107         USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE = 63
     103/*----------------------------------------------------------------------------*/
     104static const uint8_t USB_KBD_BOOT_REPORT_DESCRIPTOR[] = {
     105        0x05, 0x01,  /* Usage Page (Generic Desktop), */
     106        0x09, 0x06,  /* Usage (Keyboard), */
     107        0xA1, 0x01,  /* Collection (Application), */
     108        0x75, 0x01,  /*   Report Size (1), */
     109        0x95, 0x08,  /*   Report Count (8), */
     110        0x05, 0x07,  /*   Usage Page (Key Codes); */
     111        0x19, 0xE0,  /*   Usage Minimum (224), */
     112        0x29, 0xE7,  /*   Usage Maximum (231), */
     113        0x15, 0x00,  /*   Logical Minimum (0), */
     114        0x25, 0x01,  /*   Logical Maximum (1), */
     115        0x81, 0x02,  /*   Input (Data, Variable, Absolute),  ; Modifier byte */
     116        0x95, 0x01,  /*   Report Count (1), */
     117        0x75, 0x08,  /*   Report Size (8), */
     118        0x81, 0x01,  /*   Input (Constant),                  ; Reserved byte */
     119        0x95, 0x05,  /*   Report Count (5), */
     120        0x75, 0x01,  /*   Report Size (1), */
     121        0x05, 0x08,  /*   Usage Page (Page# for LEDs), */
     122        0x19, 0x01,  /*   Usage Minimum (1), */
     123        0x29, 0x05,  /*   Usage Maxmimum (5), */
     124        0x91, 0x02,  /*   Output (Data, Variable, Absolute),  ; LED report */
     125        0x95, 0x01,  /*   Report Count (1), */
     126        0x75, 0x03,  /*   Report Size (3), */
     127        0x91, 0x01,  /*   Output (Constant),            ; LED report padding */
     128        0x95, 0x06,  /*   Report Count (6), */
     129        0x75, 0x08,  /*   Report Size (8), */
     130        0x15, 0x00,  /*   Logical Minimum (0), */
     131        0x25, 0xff,  /*   Logical Maximum (255), */
     132        0x05, 0x07,  /*   Usage Page (Key Codes), */
     133        0x19, 0x00,  /*   Usage Minimum (0), */
     134        0x29, 0xff,  /*   Usage Maximum (255), */
     135        0x81, 0x00,  /*   Input (Data, Array),   ; Key arrays (6 bytes) */
     136        0xC0         /* End Collection */
    108137};
    109 
    110 static const uint8_t USB_KBD_BOOT_REPORT_DESCRIPTOR[
    111     USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE] = {
    112         0x05, 0x01,  // Usage Page (Generic Desktop),
    113         0x09, 0x06,  // Usage (Keyboard),
    114         0xA1, 0x01,  // Collection (Application),
    115         0x75, 0x01,  //   Report Size (1),
    116         0x95, 0x08,  //   Report Count (8),       
    117         0x05, 0x07,  //   Usage Page (Key Codes);
    118         0x19, 0xE0,  //   Usage Minimum (224),
    119         0x29, 0xE7,  //   Usage Maximum (231),
    120         0x15, 0x00,  //   Logical Minimum (0),
    121         0x25, 0x01,  //   Logical Maximum (1),
    122         0x81, 0x02,  //   Input (Data, Variable, Absolute),   ; Modifier byte
    123         0x95, 0x01,  //   Report Count (1),
    124         0x75, 0x08,  //   Report Size (8),
    125         0x81, 0x01,  //   Input (Constant),                   ; Reserved byte
    126         0x95, 0x05,  //   Report Count (5),
    127         0x75, 0x01,  //   Report Size (1),
    128         0x05, 0x08,  //   Usage Page (Page# for LEDs),
    129         0x19, 0x01,  //   Usage Minimum (1),
    130         0x29, 0x05,  //   Usage Maxmimum (5),
    131         0x91, 0x02,  //   Output (Data, Variable, Absolute),  ; LED report
    132         0x95, 0x01,  //   Report Count (1),
    133         0x75, 0x03,  //   Report Size (3),
    134         0x91, 0x01,  //   Output (Constant),              ; LED report padding
    135         0x95, 0x06,  //   Report Count (6),
    136         0x75, 0x08,  //   Report Size (8),
    137         0x15, 0x00,  //   Logical Minimum (0),
    138         0x25, 0xff,  //   Logical Maximum (255),
    139         0x05, 0x07,  //   Usage Page (Key Codes),
    140         0x19, 0x00,  //   Usage Minimum (0),
    141         0x29, 0xff,  //   Usage Maximum (255),
    142         0x81, 0x00,  //   Input (Data, Array),            ; Key arrays (6 bytes)
    143         0xC0           // End Collection
    144 
    145 };
    146 
    147 /*----------------------------------------------------------------------------*/
    148 
     138/*----------------------------------------------------------------------------*/
    149139typedef enum usb_kbd_flags {
    150140        USB_KBD_STATUS_UNINITIALIZED = 0,
     
    152142        USB_KBD_STATUS_TO_DESTROY = -1
    153143} usb_kbd_flags;
    154 
    155144/*----------------------------------------------------------------------------*/
    156145/* IPC method handler                                                         */
    157146/*----------------------------------------------------------------------------*/
    158 
    159 static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
    160 
    161147/**
    162148 * Default handler for IPC methods not handled by DDF.
    163149 *
    164  * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it
    165  * assumes the caller is the console and thus it stores IPC session to it for
    166  * later use by the driver to notify about key events.
     150 * Currently recognizes only two methods (IPC_M_CONNECT_TO_ME and KBDEV_SET_IND)
     151 * IPC_M_CONNECT_TO_ME assumes the caller is the console and  stores IPC
     152 * session to it for later use by the driver to notify about key events.
     153 * KBDEV_SET_IND sets LED keyboard indicators.
    167154 *
    168155 * @param fun Device function handling the call.
     
    173160    ipc_callid_t icallid, ipc_call_t *icall)
    174161{
    175         sysarg_t method = IPC_GET_IMETHOD(*icall);
    176 
    177         usb_kbd_t *kbd_dev = (usb_kbd_t *) fun->driver_data;
    178         if (kbd_dev == NULL) {
    179                 usb_log_debug("default_connection_handler: "
    180                     "Missing parameter.\n");
     162        if (fun == NULL || fun->driver_data == NULL) {
     163                usb_log_error("%s: Missing parameter.\n", __FUNCTION__);
    181164                async_answer_0(icallid, EINVAL);
    182165                return;
    183166        }
    184167
    185         async_sess_t *sess =
    186             async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
    187         if (sess != NULL) {
     168        const sysarg_t method = IPC_GET_IMETHOD(*icall);
     169        usb_kbd_t *kbd_dev = fun->driver_data;
     170
     171        switch (method) {
     172        case KBDEV_SET_IND:
     173                kbd_dev->mods = IPC_GET_ARG1(*icall);
     174                usb_kbd_set_led(kbd_dev->hid_dev, kbd_dev);
     175                async_answer_0(icallid, EOK);
     176                break;
     177        /* This might be ugly but async_callback_receive_start makes no
     178         * difference for incorrect call and malloc failure. */
     179        case IPC_M_CONNECT_TO_ME: {
     180                async_sess_t *sess =
     181                    async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
     182                /* Probably ENOMEM error, try again. */
     183                if (sess == NULL) {
     184                        usb_log_warning(
     185                            "Failed to create start console session.\n");
     186                        async_answer_0(icallid, EAGAIN);
     187                        break;
     188                }
    188189                if (kbd_dev->console_sess == NULL) {
    189190                        kbd_dev->console_sess = sess;
    190                         usb_log_debug("default_connection_handler: OK\n");
     191                        usb_log_debug("%s: OK\n", __FUNCTION__);
    191192                        async_answer_0(icallid, EOK);
    192193                } else {
    193                         usb_log_debug("default_connection_handler: "
    194                             "console session already set\n");
     194                        usb_log_error("%s: console session already set\n",
     195                           __FUNCTION__);
    195196                        async_answer_0(icallid, ELIMIT);
    196197                }
    197         } else {
    198                 switch (method) {
    199                 case KBDEV_SET_IND:
    200                         kbd_dev->mods = IPC_GET_ARG1(*icall);
    201                         usb_kbd_set_led(kbd_dev->hid_dev, kbd_dev);
    202                         async_answer_0(icallid, EOK);
    203                         break;
    204                 default:
    205                         usb_log_debug("default_connection_handler: Wrong function.\n");
     198                break;
     199        }
     200        default:
     201                        usb_log_error("%s: Unknown method: %d.\n",
     202                            __FUNCTION__, (int) method);
    206203                        async_answer_0(icallid, EINVAL);
    207204                        break;
    208                 }
    209         }
    210 }
    211 
     205        }
     206
     207}
    212208/*----------------------------------------------------------------------------*/
    213209/* Key processing functions                                                   */
     
    226222 * @param kbd_dev Keyboard device structure.
    227223 */
    228 static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev) 
     224static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev)
    229225{
    230226        if (kbd_dev->output_size == 0) {
     
    274270        }
    275271
    276         usb_log_debug("Output report buffer: %s\n", 
    277             usb_debug_str_buffer(kbd_dev->output_buffer, kbd_dev->output_size, 
     272        usb_log_debug("Output report buffer: %s\n",
     273            usb_debug_str_buffer(kbd_dev->output_buffer, kbd_dev->output_size,
    278274                0));
    279275
    280         usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe,
    281             hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT, 
     276        rc = usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe,
     277            hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT,
    282278            kbd_dev->output_buffer, kbd_dev->output_size);
    283 }
    284 
     279        if (rc != EOK) {
     280                usb_log_warning("Failed to set kbd indicators.\n");
     281        }
     282}
    285283/*----------------------------------------------------------------------------*/
    286284/** Send key event.
     
    291289 * @param key Key code
    292290 */
    293 void usb_kbd_push_ev(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev, int type,
    294     unsigned int key)
     291void usb_kbd_push_ev(usb_kbd_t *kbd_dev, int type, unsigned key)
    295292{
    296293        usb_log_debug2("Sending kbdev event %d/%d to the console\n", type, key);
     
    302299
    303300        async_exch_t *exch = async_exchange_begin(kbd_dev->console_sess);
    304         async_msg_2(exch, KBDEV_EVENT, type, key);
    305         async_exchange_end(exch);
    306 }
    307 
    308 /*----------------------------------------------------------------------------*/
    309 
    310 static inline int usb_kbd_is_lock(unsigned int key_code)
     301        if (exch != NULL) {
     302                async_msg_2(exch, KBDEV_EVENT, type, key);
     303                async_exchange_end(exch);
     304        } else {
     305                usb_log_warning("Failed to send key to console.\n");
     306        }
     307}
     308/*----------------------------------------------------------------------------*/
     309static inline int usb_kbd_is_lock(unsigned int key_code)
    311310{
    312311        return (key_code == KC_NUM_LOCK
     
    314313            || key_code == KC_CAPS_LOCK);
    315314}
    316 
     315/*----------------------------------------------------------------------------*/
    317316static size_t find_in_array_int32(int32_t val, int32_t *arr, size_t arr_size)
    318317{
     
    325324        return (size_t) -1;
    326325}
    327 
    328326/*----------------------------------------------------------------------------*/
    329327/**
     
    342340 * @sa usb_kbd_push_ev(), usb_kbd_repeat_start(), usb_kbd_repeat_stop()
    343341 */
    344 static void usb_kbd_check_key_changes(usb_hid_dev_t *hid_dev, 
     342static void usb_kbd_check_key_changes(usb_hid_dev_t *hid_dev,
    345343    usb_kbd_t *kbd_dev)
    346344{
    347         unsigned int key;
    348         size_t i;
    349345
    350346        /*
     
    356352         * whole input report.
    357353         */
    358         i = find_in_array_int32(ERROR_ROLLOVER, kbd_dev->keys,
     354        size_t i = find_in_array_int32(ERROR_ROLLOVER, kbd_dev->keys,
    359355            kbd_dev->key_count);
    360356        if (i != (size_t) -1) {
    361                 usb_log_debug("Detected phantom state.\n");
     357                usb_log_error("Detected phantom state.\n");
    362358                return;
    363359        }
     
    367363         */
    368364        for (i = 0; i < kbd_dev->key_count; i++) {
    369                 int32_t old_key = kbd_dev->keys_old[i];
     365                const int32_t old_key = kbd_dev->keys_old[i];
    370366                /* Find the old key among currently pressed keys. */
    371                 size_t pos = find_in_array_int32(old_key, kbd_dev->keys,
     367                const size_t pos = find_in_array_int32(old_key, kbd_dev->keys,
    372368                    kbd_dev->key_count);
    373369                /* If the key was not found, we need to signal release. */
    374370                if (pos == (size_t) -1) {
    375                         key = usbhid_parse_scancode(old_key);
     371                        const unsigned key = usbhid_parse_scancode(old_key);
    376372                        if (!usb_kbd_is_lock(key)) {
    377373                                usb_kbd_repeat_stop(kbd_dev, key);
    378374                        }
    379                         usb_kbd_push_ev(hid_dev, kbd_dev, KEY_RELEASE, key);
     375                        usb_kbd_push_ev(kbd_dev, KEY_RELEASE, key);
    380376                        usb_log_debug2("Key released: %u "
    381377                            "(USB code %" PRIu32 ")\n", key, old_key);
     
    387383         */
    388384        for (i = 0; i < kbd_dev->key_count; ++i) {
    389                 int32_t new_key = kbd_dev->keys[i];
     385                const int32_t new_key = kbd_dev->keys[i];
    390386                /* Find the new key among already pressed keys. */
    391                 size_t pos = find_in_array_int32(new_key, kbd_dev->keys_old,
    392                     kbd_dev->key_count);
     387                const size_t pos = find_in_array_int32(new_key,
     388                    kbd_dev->keys_old, kbd_dev->key_count);
    393389                /* If the key was not found, we need to signal press. */
    394390                if (pos == (size_t) -1) {
    395                         key = usbhid_parse_scancode(kbd_dev->keys[i]);
     391                        unsigned key = usbhid_parse_scancode(kbd_dev->keys[i]);
    396392                        if (!usb_kbd_is_lock(key)) {
    397393                                usb_kbd_repeat_start(kbd_dev, key);
    398394                        }
    399                         usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS, key);
     395                        usb_kbd_push_ev(kbd_dev, KEY_PRESS, key);
    400396                        usb_log_debug2("Key pressed: %u "
    401397                            "(USB code %" PRIu32 ")\n", key, new_key);
     
    405401        memcpy(kbd_dev->keys_old, kbd_dev->keys, kbd_dev->key_count * 4);
    406402
     403        // TODO Get rid of this
    407404        char key_buffer[512];
    408405        ddf_dump_buffer(key_buffer, 512,
     
    410407        usb_log_debug2("Stored keys %s.\n", key_buffer);
    411408}
    412 
    413409/*----------------------------------------------------------------------------*/
    414410/* General kbd functions                                                      */
     
    436432
    437433        usb_hid_report_path_t *path = usb_hid_report_path();
    438         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
    439 
    440         usb_hid_report_path_set_report_id (path, hid_dev->report_id);
    441 
    442         // fill in the currently pressed keys
    443 
     434        if (path == NULL) {
     435                usb_log_error("Failed to create hid/kbd report path.\n");
     436                return;
     437        }
     438
     439        int ret =
     440           usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
     441        if (ret != EOK) {
     442                usb_log_error("Failed to append to hid/kbd report path.\n");
     443                return;
     444        }
     445
     446        usb_hid_report_path_set_report_id(path, hid_dev->report_id);
     447
     448        /* Fill in the currently pressed keys. */
    444449        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    445450            &hid_dev->report, NULL, path,
     
    449454
    450455        while (field != NULL) {
    451                 usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n", 
     456                usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n",
    452457                    field, field->value, field->usage);
    453                
     458
    454459                assert(i < kbd_dev->key_count);
    455460
    456                 // save the key usage
     461                /* Save the key usage. */
    457462                if (field->value != 0) {
    458463                        kbd_dev->keys[i] = field->usage;
     
    474479        usb_kbd_check_key_changes(hid_dev, kbd_dev);
    475480}
    476 
    477481/*----------------------------------------------------------------------------*/
    478482/* HID/KBD structure manipulation                                             */
    479483/*----------------------------------------------------------------------------*/
    480 
    481 static void usb_kbd_mark_unusable(usb_kbd_t *kbd_dev)
    482 {
    483         kbd_dev->initialized = USB_KBD_STATUS_TO_DESTROY;
    484 }
    485 
    486 /*----------------------------------------------------------------------------*/
    487 
    488 /**
    489  * Creates a new USB/HID keyboard structure.
    490  *
    491  * The structure returned by this function is not initialized. Use
    492  * usb_kbd_init() to initialize it prior to polling.
    493  *
    494  * @return New uninitialized structure for representing a USB/HID keyboard or
    495  *         NULL if not successful (memory error).
    496  */
    497 static usb_kbd_t *usb_kbd_new(void)
    498 {
    499         usb_kbd_t *kbd_dev =
    500             (usb_kbd_t *)calloc(1, sizeof(usb_kbd_t));
    501 
    502         if (kbd_dev == NULL) {
    503                 usb_log_error("No memory!\n");
    504                 return NULL;
    505         }
    506 
    507         kbd_dev->console_sess = NULL;
    508         kbd_dev->initialized = USB_KBD_STATUS_UNINITIALIZED;
    509 
    510         return kbd_dev;
    511 }
    512 
    513 /*----------------------------------------------------------------------------*/
    514 
    515484static int usb_kbd_create_function(usb_kbd_t *kbd_dev)
    516485{
     
    528497        }
    529498
    530         /*
    531          * Store the initialized HID device and HID ops
    532          * to the DDF function.
    533          */
     499        /* Store the initialized HID device and HID ops
     500         * to the DDF function. */
    534501        fun->ops = &kbd_dev->ops;
    535502        fun->driver_data = kbd_dev;
     
    539506                usb_log_error("Could not bind DDF function: %s.\n",
    540507                    str_error(rc));
    541                 fun->driver_data = NULL; /* We need this later */
     508                fun->driver_data = NULL; /* We did not allocate this. */
    542509                ddf_fun_destroy(fun);
    543510                return rc;
     
    547514            HID_KBD_FUN_NAME, fun->handle);
    548515
    549         usb_log_debug("Adding DDF function to category %s...\n", 
     516        usb_log_debug("Adding DDF function to category %s...\n",
    550517            HID_KBD_CLASS_NAME);
    551518        rc = ddf_fun_add_to_category(fun, HID_KBD_CATEGORY_NAME);
     
    554521                    "Could not add DDF function to category %s: %s.\n",
    555522                    HID_KBD_CLASS_NAME, str_error(rc));
    556                 fun->driver_data = NULL; /* We need this later */
    557                 ddf_fun_destroy(fun);
     523                if (ddf_fun_unbind(fun) == EOK) {
     524                        fun->driver_data = NULL; /* We did not allocate this. */
     525                        ddf_fun_destroy(fun);
     526                } else {
     527                        usb_log_error(
     528                            "Failed to unbind `%s', will not destroy.\n",
     529                            fun->name);
     530                }
    558531                return rc;
    559532        }
     
    562535        return EOK;
    563536}
    564 
    565537/*----------------------------------------------------------------------------*/
    566538/* API functions                                                              */
     
    591563
    592564        if (hid_dev == NULL) {
    593                 usb_log_error("Failed to init keyboard structure: no structure"
    594                     " given.\n");
     565                usb_log_error(
     566                    "Failed to init keyboard structure: no structure given.\n");
    595567                return EINVAL;
    596568        }
    597569
    598         usb_kbd_t *kbd_dev = usb_kbd_new();
     570        usb_kbd_t *kbd_dev = calloc(1, sizeof(usb_kbd_t));
    599571        if (kbd_dev == NULL) {
    600                 usb_log_error("Error while creating USB/HID KBD device "
    601                     "structure.\n");
    602                 return ENOMEM;  // TODO: some other code??
    603         }
     572                usb_log_error("Failed to allocate KBD device structure.\n");
     573                return ENOMEM;
     574        }
     575        /* Default values */
     576        fibril_mutex_initialize(&kbd_dev->repeat_mtx);
     577        kbd_dev->initialized = USB_KBD_STATUS_UNINITIALIZED;
     578        kbd_dev->ops.default_handler = default_connection_handler;
    604579
    605580        /* Store link to HID device */
    606581        kbd_dev->hid_dev = hid_dev;
    607582
    608         /*
    609          * TODO: make more general
    610          */
     583        /* Modifiers and locks */
     584        kbd_dev->mods = DEFAULT_ACTIVE_MODS;
     585
     586        /* Autorepeat */
     587        kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;
     588        kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
     589
     590
     591        // TODO: make more general
    611592        usb_hid_report_path_t *path = usb_hid_report_path();
    612         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
     593        if (path == NULL) {
     594                usb_log_error("Failed to create kbd report path.\n");
     595                usb_kbd_destroy(kbd_dev);
     596                return ENOMEM;
     597        }
     598
     599        int ret =
     600            usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
     601        if (ret != EOK) {
     602                usb_log_error("Failed to append item to kbd report path.\n");
     603                usb_hid_report_path_free(path);
     604                usb_kbd_destroy(kbd_dev);
     605                return ret;
     606        }
    613607
    614608        usb_hid_report_path_set_report_id(path, 0);
    615609
    616         kbd_dev->key_count = usb_hid_report_size(
    617             &hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT);
     610        kbd_dev->key_count =
     611            usb_hid_report_size(&hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT);
     612
    618613        usb_hid_report_path_free(path);
    619614
     
    621616
    622617        kbd_dev->keys = calloc(kbd_dev->key_count, sizeof(int32_t));
    623 
    624618        if (kbd_dev->keys == NULL) {
    625                 usb_log_error("No memory!\n");
    626                 free(kbd_dev);
     619                usb_log_error("Failed to allocate key buffer.\n");
     620                usb_kbd_destroy(kbd_dev);
    627621                return ENOMEM;
    628622        }
    629623
    630         kbd_dev->keys_old =
    631                 (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
    632 
     624        kbd_dev->keys_old = calloc(kbd_dev->key_count, sizeof(int32_t));
    633625        if (kbd_dev->keys_old == NULL) {
    634                 usb_log_error("No memory!\n");
    635                 free(kbd_dev->keys);
    636                 free(kbd_dev);
     626                usb_log_error("Failed to allocate old_key buffer.\n");
     627                usb_kbd_destroy(kbd_dev);
    637628                return ENOMEM;
    638629        }
    639630
    640         /*
    641          * Output report
    642          */
     631        /* Output report */
    643632        kbd_dev->output_size = 0;
    644633        kbd_dev->output_buffer = usb_hid_report_output(&hid_dev->report,
    645634            &kbd_dev->output_size, 0);
    646635        if (kbd_dev->output_buffer == NULL) {
    647                 usb_log_warning("Error creating output report buffer.\n");
    648                 free(kbd_dev->keys);
     636                usb_log_error("Error creating output report buffer.\n");
     637                usb_kbd_destroy(kbd_dev);
    649638                return ENOMEM;
    650639        }
     
    653642
    654643        kbd_dev->led_path = usb_hid_report_path();
    655         usb_hid_report_path_append_item(
     644        if (kbd_dev->led_path == NULL) {
     645                usb_log_error("Failed to create kbd led report path.\n");
     646                usb_kbd_destroy(kbd_dev);
     647                return ENOMEM;
     648        }
     649
     650        ret = usb_hid_report_path_append_item(
    656651            kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
     652        if (ret != EOK) {
     653                usb_log_error("Failed to append to kbd/led report path.\n");
     654                usb_kbd_destroy(kbd_dev);
     655                return ret;
     656        }
    657657
    658658        kbd_dev->led_output_size = usb_hid_report_size(
    659659            &hid_dev->report, 0, USB_HID_REPORT_TYPE_OUTPUT);
    660660
    661         usb_log_debug("Output report size (in items): %zu\n", 
     661        usb_log_debug("Output report size (in items): %zu\n",
    662662            kbd_dev->led_output_size);
    663663
    664         kbd_dev->led_data = (int32_t *)calloc(
    665             kbd_dev->led_output_size, sizeof(int32_t));
    666 
     664        kbd_dev->led_data = calloc(kbd_dev->led_output_size, sizeof(int32_t));
    667665        if (kbd_dev->led_data == NULL) {
    668                 usb_log_warning("Error creating buffer for LED output report."
    669                     "\n");
    670                 free(kbd_dev->keys);
    671                 usb_hid_report_output_free(kbd_dev->output_buffer);
    672                 free(kbd_dev);
     666                usb_log_error("Error creating buffer for LED output report.\n");
     667                usb_kbd_destroy(kbd_dev);
    673668                return ENOMEM;
    674669        }
    675670
    676         /*
    677          * Modifiers and locks
    678          */
    679         kbd_dev->modifiers = 0;
    680         kbd_dev->mods = DEFAULT_ACTIVE_MODS;
    681         kbd_dev->lock_keys = 0;
    682 
    683         /*
    684          * Autorepeat
    685          */
    686         kbd_dev->repeat.key_new = 0;
    687         kbd_dev->repeat.key_repeated = 0;
    688         kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;
    689         kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
    690 
    691         fibril_mutex_initialize(&kbd_dev->repeat_mtx);
    692 
    693         // save the KBD device structure into the HID device structure
     671        /* Set LEDs according to initial setup.
     672         * Set Idle rate */
     673        usb_kbd_set_led(hid_dev, kbd_dev);
     674
     675        usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
     676            hid_dev->usb_dev->interface_no, IDLE_RATE);
     677
     678        /* Save the KBD device structure into the HID device structure. */
    694679        *data = kbd_dev;
    695680
    696         // set handler for incoming calls
    697         kbd_dev->ops.default_handler = default_connection_handler;
    698 
    699         /*
    700          * Set LEDs according to initial setup.
    701          * Set Idle rate
    702          */
    703         usb_kbd_set_led(hid_dev, kbd_dev);
    704 
    705         usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
    706             hid_dev->usb_dev->interface_no, IDLE_RATE);
    707 
    708         /*
    709          * Create new fibril for auto-repeat
    710          */
     681        kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;
     682        usb_log_debug("HID/KBD device structure initialized.\n");
     683
     684        usb_log_debug("Creating KBD function...\n");
     685        ret = usb_kbd_create_function(kbd_dev);
     686        if (ret != EOK) {
     687                usb_kbd_destroy(kbd_dev);
     688                return ret;
     689        }
     690
     691        /* Create new fibril for auto-repeat. */
    711692        fid_t fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev);
    712693        if (fid == 0) {
    713694                usb_log_error("Failed to start fibril for KBD auto-repeat");
     695                usb_kbd_destroy(kbd_dev);
    714696                return ENOMEM;
    715697        }
    716698        fibril_add_ready(fid);
    717699
    718         kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;
    719         usb_log_debug("HID/KBD device structure initialized.\n");
    720 
    721         usb_log_debug("Creating KBD function...\n");
    722         int rc = usb_kbd_create_function(kbd_dev);
    723         if (rc != EOK) {
    724                 usb_kbd_destroy(kbd_dev);
    725                 return rc;
    726         }
    727 
    728700        return EOK;
    729701}
    730 
    731 /*----------------------------------------------------------------------------*/
    732 
     702/*----------------------------------------------------------------------------*/
    733703bool usb_kbd_polling_callback(usb_hid_dev_t *hid_dev, void *data)
    734704{
    735         if (hid_dev == NULL/* || buffer == NULL*/ || data == NULL) {
    736                 // do not continue polling (???)
     705        if (hid_dev == NULL || data == NULL) {
     706                /* This means something serious */
    737707                return false;
    738708        }
    739709
    740         usb_kbd_t *kbd_dev = (usb_kbd_t *)data;
    741         assert(kbd_dev != NULL);
    742 
     710        usb_kbd_t *kbd_dev = data;
    743711        // TODO: add return value from this function
    744712        usb_kbd_process_data(hid_dev, kbd_dev);
     
    746714        return true;
    747715}
    748 
    749 /*----------------------------------------------------------------------------*/
    750 
     716/*----------------------------------------------------------------------------*/
    751717int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev)
    752718{
    753719        return (kbd_dev->initialized == USB_KBD_STATUS_INITIALIZED);
    754720}
    755 
    756 /*----------------------------------------------------------------------------*/
    757 
     721/*----------------------------------------------------------------------------*/
    758722int usb_kbd_is_ready_to_destroy(const usb_kbd_t *kbd_dev)
    759723{
    760724        return (kbd_dev->initialized == USB_KBD_STATUS_TO_DESTROY);
    761725}
    762 
    763726/*----------------------------------------------------------------------------*/
    764727/**
     
    773736        }
    774737
    775         // hangup session to the console
    776         async_hangup(kbd_dev->console_sess);
     738        /* Hangup session to the console. */
     739        if (kbd_dev->console_sess)
     740                async_hangup(kbd_dev->console_sess);
    777741
    778742        //assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
     
    781745        while (fibril_mutex_is_locked(&kbd_dev->repeat_mtx)) {}
    782746
    783         // free all buffers
     747        /* Free all buffers. */
    784748        free(kbd_dev->keys);
    785749        free(kbd_dev->keys_old);
    786750        free(kbd_dev->led_data);
    787751
    788         if (kbd_dev->led_path != NULL) {
    789                 usb_hid_report_path_free(kbd_dev->led_path);
    790         }
    791         if (kbd_dev->output_buffer != NULL) {
    792                 usb_hid_report_output_free(kbd_dev->output_buffer);
    793         }
    794 
    795         if (ddf_fun_unbind(kbd_dev->fun) != EOK) {
    796                 usb_log_warning("Failed to unbind kbd function.\n");
    797         } else {
    798                 usb_log_debug2("%s unbound.\n", kbd_dev->fun->name);
    799                 kbd_dev->fun->driver_data = NULL;
    800                 ddf_fun_destroy(kbd_dev->fun);
    801         }
    802 }
    803 
    804 /*----------------------------------------------------------------------------*/
    805 
     752        usb_hid_report_path_free(kbd_dev->led_path);
     753        usb_hid_report_output_free(kbd_dev->output_buffer);
     754
     755        if (kbd_dev->fun) {
     756                if (ddf_fun_unbind(kbd_dev->fun) != EOK) {
     757                        usb_log_warning("Failed to unbind %s.\n",
     758                            kbd_dev->fun->name);
     759                } else {
     760                        usb_log_debug2("%s unbound.\n", kbd_dev->fun->name);
     761                        kbd_dev->fun->driver_data = NULL;
     762                        ddf_fun_destroy(kbd_dev->fun);
     763                }
     764        }
     765        free(kbd_dev);
     766}
     767/*----------------------------------------------------------------------------*/
    806768void usb_kbd_deinit(usb_hid_dev_t *hid_dev, void *data)
    807769{
    808         if (hid_dev == NULL) {
    809                 return;
    810         }
    811 
    812770        if (data != NULL) {
    813771                usb_kbd_t *kbd_dev = data;
    814772                if (usb_kbd_is_initialized(kbd_dev)) {
    815                         usb_kbd_mark_unusable(kbd_dev);
    816                         /* wait for autorepeat */
     773                        kbd_dev->initialized = USB_KBD_STATUS_TO_DESTROY;
     774                        /* Wait for autorepeat */
    817775                        async_usleep(CHECK_DELAY);
    818                         usb_kbd_destroy(kbd_dev);
    819                 }
    820         }
    821 }
    822 
    823 /*----------------------------------------------------------------------------*/
    824 
     776                }
     777                usb_kbd_destroy(kbd_dev);
     778        }
     779}
     780/*----------------------------------------------------------------------------*/
    825781int usb_kbd_set_boot_protocol(usb_hid_dev_t *hid_dev)
    826782{
     783        assert(hid_dev);
    827784        int rc = usb_hid_parse_report_descriptor(
    828785            &hid_dev->report, USB_KBD_BOOT_REPORT_DESCRIPTOR,
    829             USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE);
     786            sizeof(USB_KBD_BOOT_REPORT_DESCRIPTOR));
    830787
    831788        if (rc != EOK) {
     
    846803        return EOK;
    847804}
    848 
    849805/**
    850806 * @}
Note: See TracChangeset for help on using the changeset viewer.