Ignore:
Timestamp:
2016-07-22T08:24:47Z (8 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f76d2c2
Parents:
5b18137 (diff), 8351f9a4 (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 from lp:~jan.vesely/helenos/usb

File:
1 edited

Legend:

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

    r5b18137 rb4b534ac  
    100100
    101101const char *HID_KBD_FUN_NAME = "keyboard";
    102 const char *HID_KBD_CATEGORY = "keyboard";
     102const char *HID_KBD_CATEGORY_NAME = "keyboard";
    103103
    104104static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev);
     
    261261
    262262        if (rc != EOK) {
    263                 usb_log_warning("Error translating LED output to output report"
    264                     ".\n");
     263                usb_log_warning("Could not translate LED output to output"
     264                    "report.\n");
    265265                return;
    266266        }
     
    270270                0));
    271271
    272         rc = usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe,
    273             hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT,
     272        rc = usbhid_req_set_report(
     273            usb_device_get_default_pipe(hid_dev->usb_dev),
     274            usb_device_get_iface_number(hid_dev->usb_dev),
     275            USB_HID_REPORT_TYPE_OUTPUT,
    274276            kbd_dev->output_buffer, kbd_dev->output_size);
    275277        if (rc != EOK) {
     
    476478}
    477479
    478 /* API functions                                                              */
    479 
    480 /**
    481  * Initialization of the USB/HID keyboard structure.
    482  *
    483  * This functions initializes required structures from the device's descriptors.
    484  *
    485  * During initialization, the keyboard is switched into boot protocol, the idle
    486  * rate is set to 0 (infinity), resulting in the keyboard only reporting event
    487  * when a key is pressed or released. Finally, the LED lights are turned on
    488  * according to the default setup of lock keys.
    489  *
    490  * @note By default, the keyboards is initialized with Num Lock turned on and
    491  *       other locks turned off.
    492  *
    493  * @param kbd_dev Keyboard device structure to be initialized.
    494  * @param dev DDF device structure of the keyboard.
    495  *
    496  * @retval EOK if successful.
    497  * @retval EINVAL if some parameter is not given.
    498  * @return Other value inherited from function usbhid_dev_init().
    499  */
    500 int usb_kbd_init(usb_hid_dev_t *hid_dev, void **data)
    501 {
    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 
    509         usb_log_debug("Initializing HID/KBD structure...\n");
    510 
    511         if (hid_dev == NULL) {
    512                 usb_log_error(
    513                     "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));
    533         if (kbd_dev == NULL) {
    534                 usb_log_error("Failed to allocate KBD device structure.\n");
    535                 rc = ENOMEM;
    536                 goto error;
    537         }
    538 
    539         kbd_dev->fun = fun;
     480/* HID/KBD structure manipulation                                             */
     481
     482static int kbd_dev_init(usb_kbd_t *kbd_dev, usb_hid_dev_t *hid_dev)
     483{
     484        assert(kbd_dev);
     485        assert(hid_dev);
    540486
    541487        /* Default values */
     
    554500
    555501        // TODO: make more general
    556         path = usb_hid_report_path();
     502        usb_hid_report_path_t *path = usb_hid_report_path();
    557503        if (path == NULL) {
    558504                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) {
     505                usb_kbd_destroy(kbd_dev);
     506                return ENOMEM;
     507        }
     508
     509        int ret =
     510            usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
     511        if (ret != EOK) {
    565512                usb_log_error("Failed to append item to kbd report path.\n");
    566                 goto error;
     513                usb_hid_report_path_free(path);
     514                usb_kbd_destroy(kbd_dev);
     515                return ret;
    567516        }
    568517
     
    573522
    574523        usb_hid_report_path_free(path);
    575         path = NULL;
    576524
    577525        usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count);
     
    580528        if (kbd_dev->keys == NULL) {
    581529                usb_log_error("Failed to allocate key buffer.\n");
    582                 rc = ENOMEM;
    583                 goto error;
     530                usb_kbd_destroy(kbd_dev);
     531                return ENOMEM;
    584532        }
    585533
     
    587535        if (kbd_dev->keys_old == NULL) {
    588536                usb_log_error("Failed to allocate old_key buffer.\n");
    589                 rc = ENOMEM;
    590                 goto error;
     537                usb_kbd_destroy(kbd_dev);
     538                return ENOMEM;
    591539        }
    592540
     
    597545        if (kbd_dev->output_buffer == NULL) {
    598546                usb_log_error("Error creating output report buffer.\n");
    599                 rc = ENOMEM;
    600                 goto error;
     547                usb_kbd_destroy(kbd_dev);
     548                return ENOMEM;
    601549        }
    602550
     
    606554        if (kbd_dev->led_path == NULL) {
    607555                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(
     556                usb_kbd_destroy(kbd_dev);
     557                return ENOMEM;
     558        }
     559
     560        ret = usb_hid_report_path_append_item(
    613561            kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
    614         if (rc != EOK) {
     562        if (ret != EOK) {
    615563                usb_log_error("Failed to append to kbd/led report path.\n");
    616                 goto error;
     564                usb_kbd_destroy(kbd_dev);
     565                return ret;
    617566        }
    618567
     
    626575        if (kbd_dev->led_data == NULL) {
    627576                usb_log_error("Error creating buffer for LED output report.\n");
    628                 rc = ENOMEM;
    629                 goto error;
     577                usb_kbd_destroy(kbd_dev);
     578                return ENOMEM;
    630579        }
    631580
     
    634583        usb_kbd_set_led(hid_dev, kbd_dev);
    635584
    636         usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
    637             hid_dev->usb_dev->interface_no, IDLE_RATE);
     585        usbhid_req_set_idle(usb_device_get_default_pipe(hid_dev->usb_dev),
     586            usb_device_get_iface_number(hid_dev->usb_dev), IDLE_RATE);
     587
     588
     589        kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;
     590        usb_log_debug("HID/KBD device structure initialized.\n");
     591
     592        return EOK;
     593}
     594
     595
     596/* API functions                                                              */
     597
     598/**
     599 * Initialization of the USB/HID keyboard structure.
     600 *
     601 * This functions initializes required structures from the device's descriptors.
     602 *
     603 * During initialization, the keyboard is switched into boot protocol, the idle
     604 * rate is set to 0 (infinity), resulting in the keyboard only reporting event
     605 * when a key is pressed or released. Finally, the LED lights are turned on
     606 * according to the default setup of lock keys.
     607 *
     608 * @note By default, the keyboards is initialized with Num Lock turned on and
     609 *       other locks turned off.
     610 *
     611 * @param kbd_dev Keyboard device structure to be initialized.
     612 * @param dev DDF device structure of the keyboard.
     613 *
     614 * @retval EOK if successful.
     615 * @retval EINVAL if some parameter is not given.
     616 * @return Other value inherited from function usbhid_dev_init().
     617 */
     618int usb_kbd_init(usb_hid_dev_t *hid_dev, void **data)
     619{
     620        usb_log_debug("Initializing HID/KBD structure...\n");
     621
     622        if (hid_dev == NULL) {
     623                usb_log_error(
     624                    "Failed to init keyboard structure: no structure given.\n");
     625                return EINVAL;
     626        }
     627
     628        /* Create the exposed function. */
     629        usb_log_debug("Creating DDF function %s...\n", HID_KBD_FUN_NAME);
     630        ddf_fun_t *fun = usb_device_ddf_fun_create(hid_dev->usb_dev,
     631            fun_exposed, HID_KBD_FUN_NAME);
     632        if (fun == NULL) {
     633                usb_log_error("Could not create DDF function node.\n");
     634                return ENOMEM;
     635        }
     636
     637        usb_kbd_t *kbd_dev = ddf_fun_data_alloc(fun, sizeof(usb_kbd_t));
     638        if (kbd_dev == NULL) {
     639                usb_log_error("Failed to allocate KBD device structure.\n");
     640                ddf_fun_destroy(fun);
     641                return ENOMEM;
     642        }
     643
     644        int ret = kbd_dev_init(kbd_dev, hid_dev);
     645        if (ret != EOK) {
     646                usb_log_error("Failed to initialize KBD device  structure.\n");
     647                ddf_fun_destroy(fun);
     648                return ret;
     649        }
     650
     651        /* Store the initialized HID device and HID ops
     652         * to the DDF function. */
     653        ddf_fun_set_ops(fun, &kbdops);
     654
     655        ret = ddf_fun_bind(fun);
     656        if (ret != EOK) {
     657                usb_log_error("Could not bind DDF function: %s.\n",
     658                    str_error(ret));
     659                usb_kbd_destroy(kbd_dev);
     660                ddf_fun_destroy(fun);
     661                return ret;
     662        }
     663
     664        usb_log_debug("%s function created. Handle: %" PRIun "\n",
     665            HID_KBD_FUN_NAME, ddf_fun_get_handle(fun));
     666
     667        usb_log_debug("Adding DDF function to category %s...\n",
     668            HID_KBD_CATEGORY_NAME);
     669        ret = ddf_fun_add_to_category(fun, HID_KBD_CATEGORY_NAME);
     670        if (ret != EOK) {
     671                usb_log_error(
     672                    "Could not add DDF function to category %s: %s.\n",
     673                    HID_KBD_CATEGORY_NAME, str_error(ret));
     674                usb_kbd_destroy(kbd_dev);
     675                if (ddf_fun_unbind(fun) == EOK) {
     676                        ddf_fun_destroy(fun);
     677                } else {
     678                        usb_log_error(
     679                            "Failed to unbind `%s', will not destroy.\n",
     680                            ddf_fun_get_name(fun));
     681                }
     682                return ret;
     683        }
    638684
    639685        /* Create new fibril for auto-repeat. */
    640         fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev);
     686        fid_t fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev);
    641687        if (fid == 0) {
    642688                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 
     689                usb_kbd_destroy(kbd_dev);
     690                return ENOMEM;
     691        }
    672692        fibril_add_ready(fid);
    673 
     693        kbd_dev->fun = fun;
    674694        /* Save the KBD device structure into the HID device structure. */
    675695        *data = kbd_dev;
    676696
    677697        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;
    697698}
    698699
     
    749750        usb_hid_report_output_free(kbd_dev->output_buffer);
    750751
    751         ddf_fun_unbind(kbd_dev->fun);
    752         ddf_fun_destroy(kbd_dev->fun);
     752        if (kbd_dev->fun) {
     753                if (ddf_fun_unbind(kbd_dev->fun) != EOK) {
     754                        usb_log_warning("Failed to unbind %s.\n",
     755                            ddf_fun_get_name(kbd_dev->fun));
     756                } else {
     757                        usb_log_debug2("%s unbound.\n",
     758                            ddf_fun_get_name(kbd_dev->fun));
     759                        ddf_fun_destroy(kbd_dev->fun);
     760                }
     761        }
    753762}
    754763
     
    779788        }
    780789
    781         rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe,
    782             hid_dev->usb_dev->interface_no, USB_HID_PROTOCOL_BOOT);
     790        rc = usbhid_req_set_protocol(
     791            usb_device_get_default_pipe(hid_dev->usb_dev),
     792            usb_device_get_iface_number(hid_dev->usb_dev),
     793            USB_HID_PROTOCOL_BOOT);
    783794
    784795        if (rc != EOK) {
Note: See TracChangeset for help on using the changeset viewer.