cros.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. *
  4. * Copyright (C) 2012 Google Inc.
  5. * Copyright (C) 2016 Free Software Foundation, Inc.
  6. *
  7. * This is based on depthcharge code.
  8. *
  9. * GRUB is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation, either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * GRUB is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  21. */
  22. #include <grub/ps2.h>
  23. #include <grub/fdtbus.h>
  24. #include <grub/err.h>
  25. #include <grub/machine/kernel.h>
  26. #include <grub/misc.h>
  27. #include <grub/term.h>
  28. #include <grub/time.h>
  29. #include <grub/fdtbus.h>
  30. #include <grub/arm/cros_ec.h>
  31. static struct grub_ps2_state ps2_state;
  32. struct grub_cros_ec_keyscan old_scan;
  33. static const struct grub_fdtbus_dev *cros_ec;
  34. static grub_uint8_t map_code[GRUB_CROS_EC_KEYSCAN_COLS][GRUB_CROS_EC_KEYSCAN_ROWS];
  35. static grub_uint8_t e0_translate[16] =
  36. {
  37. 0x1c, 0x1d, 0x35, 0x00,
  38. 0x38, 0x00, 0x47, 0x48,
  39. 0x49, 0x4b, 0x4d, 0x4f,
  40. 0x50, 0x51, 0x52, 0x53,
  41. };
  42. /* If there is a character pending, return it;
  43. otherwise return GRUB_TERM_NO_KEY. */
  44. static int
  45. grub_cros_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused)))
  46. {
  47. struct grub_cros_ec_keyscan scan;
  48. int i, j;
  49. if (grub_cros_ec_scan_keyboard (cros_ec, &scan) < 0)
  50. return GRUB_TERM_NO_KEY;
  51. for (i = 0; i < GRUB_CROS_EC_KEYSCAN_COLS; i++)
  52. if (scan.data[i] ^ old_scan.data[i])
  53. for (j = 0; j < GRUB_CROS_EC_KEYSCAN_ROWS; j++)
  54. if ((scan.data[i] ^ old_scan.data[i]) & (1 << j))
  55. {
  56. grub_uint8_t code = map_code[i][j];
  57. int ret;
  58. grub_uint8_t brk = 0;
  59. if (!(scan.data[i] & (1 << j)))
  60. brk = 0x80;
  61. grub_dprintf ("cros_keyboard", "key <%d, %d> code %x\n", i, j, code);
  62. if (code < 0x60)
  63. ret = grub_ps2_process_incoming_byte (&ps2_state, code | brk);
  64. else if (code >= 0x60 && code < 0x70 && e0_translate[code - 0x60])
  65. {
  66. grub_ps2_process_incoming_byte (&ps2_state, 0xe0);
  67. ret = grub_ps2_process_incoming_byte (&ps2_state, e0_translate[code - 0x60] | brk);
  68. }
  69. else
  70. ret = GRUB_TERM_NO_KEY;
  71. old_scan.data[i] ^= (1 << j);
  72. if (ret != GRUB_TERM_NO_KEY)
  73. return ret;
  74. }
  75. return GRUB_TERM_NO_KEY;
  76. }
  77. static struct grub_term_input grub_cros_keyboard_term =
  78. {
  79. .name = "cros_keyboard",
  80. .getkey = grub_cros_keyboard_getkey
  81. };
  82. static grub_err_t
  83. cros_attach (const struct grub_fdtbus_dev *dev)
  84. {
  85. grub_size_t keymap_size, i;
  86. const grub_uint8_t *keymap = grub_fdtbus_get_prop (dev, "linux,keymap", &keymap_size);
  87. if (!dev->parent || !grub_cros_ec_validate (dev->parent))
  88. return GRUB_ERR_IO;
  89. if (keymap)
  90. {
  91. for (i = 0; i + 3 < keymap_size; i += 4)
  92. if (keymap[i+1] < GRUB_CROS_EC_KEYSCAN_COLS && keymap[i] < GRUB_CROS_EC_KEYSCAN_ROWS
  93. && keymap[i+2] == 0 && keymap[i+3] < 0x80)
  94. map_code[keymap[i+1]][keymap[i]] = keymap[i+3];
  95. }
  96. cros_ec = dev->parent;
  97. ps2_state.current_set = 1;
  98. ps2_state.at_keyboard_status = 0;
  99. grub_term_register_input ("cros_keyboard", &grub_cros_keyboard_term);
  100. return GRUB_ERR_NONE;
  101. }
  102. static struct grub_fdtbus_driver cros =
  103. {
  104. .compatible = "google,cros-ec-keyb",
  105. .attach = cros_attach
  106. };
  107. void
  108. grub_cros_init (void)
  109. {
  110. grub_fdtbus_register (&cros);
  111. }