Ignore:
File:
1 edited

Legend:

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

    r350274a r56fd7cf  
    3434 * USB HID keyboard device structure and API.
    3535 */
     36
     37/* XXX Fix this */
     38#define _DDF_DATA_IMPLANT
    3639
    3740#include <errno.h>
     
    100103
    101104const char *HID_KBD_FUN_NAME = "keyboard";
    102 const char *HID_KBD_CATEGORY = "keyboard";
     105const char *HID_KBD_CATEGORY_NAME = "keyboard";
    103106
    104107static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev);
     
    476479}
    477480
     481/* HID/KBD structure manipulation                                             */
     482
     483static int usb_kbd_create_function(usb_kbd_t *kbd_dev)
     484{
     485        assert(kbd_dev != NULL);
     486        assert(kbd_dev->hid_dev != NULL);
     487        assert(kbd_dev->hid_dev->usb_dev != NULL);
     488
     489        /* Create the exposed function. */
     490        usb_log_debug("Creating DDF function %s...\n", HID_KBD_FUN_NAME);
     491        ddf_fun_t *fun = ddf_fun_create(kbd_dev->hid_dev->usb_dev->ddf_dev,
     492            fun_exposed, HID_KBD_FUN_NAME);
     493        if (fun == NULL) {
     494                usb_log_error("Could not create DDF function node.\n");
     495                return ENOMEM;
     496        }
     497
     498        /* Store the initialized HID device and HID ops
     499         * to the DDF function. */
     500        ddf_fun_set_ops(fun, &kbdops);
     501        ddf_fun_data_implant(fun, kbd_dev);
     502
     503        int rc = ddf_fun_bind(fun);
     504        if (rc != EOK) {
     505                usb_log_error("Could not bind DDF function: %s.\n",
     506                    str_error(rc));
     507                ddf_fun_destroy(fun);
     508                return rc;
     509        }
     510
     511        usb_log_debug("%s function created. Handle: %" PRIun "\n",
     512            HID_KBD_FUN_NAME, ddf_fun_get_handle(fun));
     513
     514        usb_log_debug("Adding DDF function to category %s...\n",
     515            HID_KBD_CLASS_NAME);
     516        rc = ddf_fun_add_to_category(fun, HID_KBD_CATEGORY_NAME);
     517        if (rc != EOK) {
     518                usb_log_error(
     519                    "Could not add DDF function to category %s: %s.\n",
     520                    HID_KBD_CLASS_NAME, str_error(rc));
     521                if (ddf_fun_unbind(fun) == EOK) {
     522                        ddf_fun_destroy(fun);
     523                } else {
     524                        usb_log_error(
     525                            "Failed to unbind `%s', will not destroy.\n",
     526                            ddf_fun_get_name(fun));
     527                }
     528                return rc;
     529        }
     530        kbd_dev->fun = fun;
     531
     532        return EOK;
     533}
     534
    478535/* API functions                                                              */
    479536
     
    500557int usb_kbd_init(usb_hid_dev_t *hid_dev, void **data)
    501558{
    502         ddf_fun_t *fun = NULL;
    503         usb_kbd_t *kbd_dev = NULL;
    504         usb_hid_report_path_t *path = NULL;
    505         bool bound = false;
    506         fid_t fid = 0;
    507         int rc;
    508 
    509559        usb_log_debug("Initializing HID/KBD structure...\n");
    510560
     
    512562                usb_log_error(
    513563                    "Failed to init keyboard structure: no structure given.\n");
    514                 rc = EINVAL;
    515                 goto error;
    516         }
    517 
    518         /* Create the exposed function. */
    519         usb_log_debug("Creating DDF function %s...\n", HID_KBD_FUN_NAME);
    520         fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    521             HID_KBD_FUN_NAME);
    522         if (fun == NULL) {
    523                 usb_log_error("Could not create DDF function node.\n");
    524                 rc = ENOMEM;
    525                 goto error;
    526         }
    527 
    528         /* Store the initialized HID device and HID ops
    529          * to the DDF function. */
    530         ddf_fun_set_ops(fun, &kbdops);
    531 
    532         kbd_dev = ddf_fun_data_alloc(fun, sizeof(usb_kbd_t));
     564                return EINVAL;
     565        }
     566
     567        usb_kbd_t *kbd_dev = calloc(1, sizeof(usb_kbd_t));
    533568        if (kbd_dev == NULL) {
    534569                usb_log_error("Failed to allocate KBD device structure.\n");
    535                 rc = ENOMEM;
    536                 goto error;
    537         }
    538 
    539         kbd_dev->fun = fun;
    540 
     570                return ENOMEM;
     571        }
    541572        /* Default values */
    542573        fibril_mutex_initialize(&kbd_dev->repeat_mtx);
     
    553584        kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
    554585
     586
    555587        // TODO: make more general
    556         path = usb_hid_report_path();
     588        usb_hid_report_path_t *path = usb_hid_report_path();
    557589        if (path == NULL) {
    558590                usb_log_error("Failed to create kbd report path.\n");
    559                 rc = ENOMEM;
    560                 goto error;
    561         }
    562 
    563         rc = usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
    564         if (rc != EOK) {
     591                usb_kbd_destroy(kbd_dev);
     592                return ENOMEM;
     593        }
     594
     595        int ret =
     596            usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
     597        if (ret != EOK) {
    565598                usb_log_error("Failed to append item to kbd report path.\n");
    566                 goto error;
     599                usb_hid_report_path_free(path);
     600                usb_kbd_destroy(kbd_dev);
     601                return ret;
    567602        }
    568603
     
    573608
    574609        usb_hid_report_path_free(path);
    575         path = NULL;
    576610
    577611        usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count);
     
    580614        if (kbd_dev->keys == NULL) {
    581615                usb_log_error("Failed to allocate key buffer.\n");
    582                 rc = ENOMEM;
    583                 goto error;
     616                usb_kbd_destroy(kbd_dev);
     617                return ENOMEM;
    584618        }
    585619
     
    587621        if (kbd_dev->keys_old == NULL) {
    588622                usb_log_error("Failed to allocate old_key buffer.\n");
    589                 rc = ENOMEM;
    590                 goto error;
     623                usb_kbd_destroy(kbd_dev);
     624                return ENOMEM;
    591625        }
    592626
     
    597631        if (kbd_dev->output_buffer == NULL) {
    598632                usb_log_error("Error creating output report buffer.\n");
    599                 rc = ENOMEM;
    600                 goto error;
     633                usb_kbd_destroy(kbd_dev);
     634                return ENOMEM;
    601635        }
    602636
     
    606640        if (kbd_dev->led_path == NULL) {
    607641                usb_log_error("Failed to create kbd led report path.\n");
    608                 rc = ENOMEM;
    609                 goto error;
    610         }
    611 
    612         rc = usb_hid_report_path_append_item(
     642                usb_kbd_destroy(kbd_dev);
     643                return ENOMEM;
     644        }
     645
     646        ret = usb_hid_report_path_append_item(
    613647            kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
    614         if (rc != EOK) {
     648        if (ret != EOK) {
    615649                usb_log_error("Failed to append to kbd/led report path.\n");
    616                 goto error;
     650                usb_kbd_destroy(kbd_dev);
     651                return ret;
    617652        }
    618653
     
    626661        if (kbd_dev->led_data == NULL) {
    627662                usb_log_error("Error creating buffer for LED output report.\n");
    628                 rc = ENOMEM;
    629                 goto error;
     663                usb_kbd_destroy(kbd_dev);
     664                return ENOMEM;
    630665        }
    631666
     
    637672            hid_dev->usb_dev->interface_no, IDLE_RATE);
    638673
     674        /* Save the KBD device structure into the HID device structure. */
     675        *data = kbd_dev;
     676
     677        kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;
     678        usb_log_debug("HID/KBD device structure initialized.\n");
     679
     680        usb_log_debug("Creating KBD function...\n");
     681        ret = usb_kbd_create_function(kbd_dev);
     682        if (ret != EOK) {
     683                usb_kbd_destroy(kbd_dev);
     684                return ret;
     685        }
     686
    639687        /* Create new fibril for auto-repeat. */
    640         fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev);
     688        fid_t fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev);
    641689        if (fid == 0) {
    642690                usb_log_error("Failed to start fibril for KBD auto-repeat");
    643                 rc = ENOMEM;
    644                 goto error;
    645         }
    646 
    647         kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;
    648         usb_log_debug("HID/KBD device structure initialized.\n");
    649 
    650         rc = ddf_fun_bind(fun);
    651         if (rc != EOK) {
    652                 usb_log_error("Could not bind DDF function: %s.\n",
    653                     str_error(rc));
    654                 goto error;
    655         }
    656 
    657         bound = true;
    658 
    659         usb_log_debug("%s function created. Handle: %" PRIun "\n",
    660             HID_KBD_FUN_NAME, ddf_fun_get_handle(fun));
    661 
    662         usb_log_debug("Adding DDF function to category %s...\n",
    663             HID_KBD_CATEGORY);
    664         rc = ddf_fun_add_to_category(fun, HID_KBD_CATEGORY);
    665         if (rc != EOK) {
    666                 usb_log_error(
    667                     "Could not add DDF function to category %s: %s.\n",
    668                     HID_KBD_CATEGORY, str_error(rc));
    669                 goto error;
    670         }
    671 
     691                usb_kbd_destroy(kbd_dev);
     692                return ENOMEM;
     693        }
    672694        fibril_add_ready(fid);
    673695
    674         /* Save the KBD device structure into the HID device structure. */
    675         *data = kbd_dev;
    676 
    677696        return EOK;
    678 error:
    679         if (bound)
    680                 ddf_fun_unbind(fun);
    681         if (fid != 0)
    682                 fibril_destroy(fid);
    683         if (kbd_dev != NULL) {
    684                 free(kbd_dev->led_data);
    685                 if (kbd_dev->led_path != NULL)
    686                         usb_hid_report_path_free(kbd_dev->led_path);
    687                 if (kbd_dev->output_buffer != NULL)
    688                         usb_hid_report_output_free(kbd_dev->output_buffer);
    689                 free(kbd_dev->keys_old);
    690                 free(kbd_dev->keys);
    691         }
    692         if (path != NULL)
    693                 usb_hid_report_path_free(path);
    694         if (fun != NULL)
    695                 ddf_fun_destroy(fun);
    696         return rc;
    697697}
    698698
     
    749749        usb_hid_report_output_free(kbd_dev->output_buffer);
    750750
    751         ddf_fun_unbind(kbd_dev->fun);
    752         ddf_fun_destroy(kbd_dev->fun);
     751        if (kbd_dev->fun) {
     752                if (ddf_fun_unbind(kbd_dev->fun) != EOK) {
     753                        usb_log_warning("Failed to unbind %s.\n",
     754                            ddf_fun_get_name(kbd_dev->fun));
     755                } else {
     756                        usb_log_debug2("%s unbound.\n",
     757                            ddf_fun_get_name(kbd_dev->fun));
     758                        ddf_fun_destroy(kbd_dev->fun);
     759                }
     760        }
    753761}
    754762
Note: See TracChangeset for help on using the changeset viewer.