button_kbd.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2023 Dzmitry Sankouski <dsankouski@gmail.com>
  4. */
  5. #include <stdlib.h>
  6. #include <common.h>
  7. #include <dm.h>
  8. #include <fdtdec.h>
  9. #include <input.h>
  10. #include <keyboard.h>
  11. #include <button.h>
  12. #include <dm/device-internal.h>
  13. #include <log.h>
  14. #include <asm/io.h>
  15. #include <asm/gpio.h>
  16. #include <linux/delay.h>
  17. #include <linux/input.h>
  18. /**
  19. * struct button_kbd_priv - driver private data
  20. *
  21. * @input: input configuration
  22. * @button_size: number of buttons found
  23. * @old_state: a pointer to old button states array. Used to determine button state change.
  24. */
  25. struct button_kbd_priv {
  26. struct input_config *input;
  27. u32 button_size;
  28. u32 *old_state;
  29. };
  30. static int button_kbd_start(struct udevice *dev)
  31. {
  32. struct button_kbd_priv *priv = dev_get_priv(dev);
  33. int i = 0;
  34. struct udevice *button_gpio_devp;
  35. uclass_foreach_dev_probe(UCLASS_BUTTON, button_gpio_devp) {
  36. struct button_uc_plat *uc_plat = dev_get_uclass_plat(button_gpio_devp);
  37. /* Ignore the top-level button node */
  38. if (!uc_plat->label)
  39. continue;
  40. debug("Found button %s #%d - %s, probing...\n",
  41. uc_plat->label, i, button_gpio_devp->name);
  42. i++;
  43. }
  44. priv->button_size = i;
  45. priv->old_state = calloc(i, sizeof(int));
  46. return 0;
  47. }
  48. int button_read_keys(struct input_config *input)
  49. {
  50. struct button_kbd_priv *priv = dev_get_priv(input->dev);
  51. struct udevice *button_gpio_devp;
  52. struct uclass *uc;
  53. int i = 0;
  54. u32 code, state, state_changed = 0;
  55. uclass_id_foreach_dev(UCLASS_BUTTON, button_gpio_devp, uc) {
  56. struct button_uc_plat *uc_plat = dev_get_uclass_plat(button_gpio_devp);
  57. /* Ignore the top-level button node */
  58. if (!uc_plat->label)
  59. continue;
  60. code = button_get_code(button_gpio_devp);
  61. if (!code)
  62. continue;
  63. state = button_get_state(button_gpio_devp);
  64. state_changed = state != priv->old_state[i];
  65. if (state_changed) {
  66. debug("%s: %d\n", uc_plat->label, code);
  67. priv->old_state[i] = state;
  68. input_add_keycode(input, code, state);
  69. }
  70. i++;
  71. }
  72. return 0;
  73. }
  74. static const struct keyboard_ops button_kbd_ops = {
  75. .start = button_kbd_start,
  76. };
  77. static int button_kbd_probe(struct udevice *dev)
  78. {
  79. struct button_kbd_priv *priv = dev_get_priv(dev);
  80. struct keyboard_priv *uc_priv = dev_get_uclass_priv(dev);
  81. struct stdio_dev *sdev = &uc_priv->sdev;
  82. struct input_config *input = &uc_priv->input;
  83. int ret = 0;
  84. input_init(input, false);
  85. input_add_tables(input, false);
  86. /* Register the device. */
  87. priv->input = input;
  88. input->dev = dev;
  89. input->read_keys = button_read_keys;
  90. strcpy(sdev->name, "button-kbd");
  91. ret = input_stdio_register(sdev);
  92. if (ret) {
  93. debug("%s: input_stdio_register() failed\n", __func__);
  94. return ret;
  95. }
  96. return 0;
  97. }
  98. U_BOOT_DRIVER(button_kbd) = {
  99. .name = "button_kbd",
  100. .id = UCLASS_KEYBOARD,
  101. .ops = &button_kbd_ops,
  102. .priv_auto = sizeof(struct button_kbd_priv),
  103. .probe = button_kbd_probe,
  104. };
  105. U_BOOT_DRVINFO(button_kbd) = {
  106. .name = "button_kbd"
  107. };