keyreset.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /* drivers/input/keyreset.c
  2. *
  3. * Copyright (C) 2014 Google, Inc.
  4. *
  5. * This software is licensed under the terms of the GNU General Public
  6. * License version 2, as published by the Free Software Foundation, and
  7. * may be copied, distributed, and modified under those terms.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. */
  15. #include <linux/input.h>
  16. #include <linux/keyreset.h>
  17. #include <linux/module.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/reboot.h>
  20. #include <linux/sched.h>
  21. #include <linux/slab.h>
  22. #include <linux/syscalls.h>
  23. #include <linux/keycombo.h>
  24. struct keyreset_state {
  25. int restart_requested;
  26. int (*reset_fn)(void);
  27. struct platform_device *pdev_child;
  28. struct work_struct restart_work;
  29. };
  30. static void do_restart(struct work_struct *unused)
  31. {
  32. sys_sync();
  33. kernel_restart(NULL);
  34. }
  35. static void do_reset_fn(void *priv)
  36. {
  37. struct keyreset_state *state = priv;
  38. if (state->restart_requested)
  39. panic("keyboard reset failed, %d", state->restart_requested);
  40. if (state->reset_fn) {
  41. state->restart_requested = state->reset_fn();
  42. } else {
  43. pr_info("keyboard reset\n");
  44. schedule_work(&state->restart_work);
  45. state->restart_requested = 1;
  46. }
  47. }
  48. static int keyreset_probe(struct platform_device *pdev)
  49. {
  50. int ret = -ENOMEM;
  51. struct keycombo_platform_data *pdata_child;
  52. struct keyreset_platform_data *pdata = pdev->dev.platform_data;
  53. int up_size = 0, down_size = 0, size;
  54. int key, *keyp;
  55. struct keyreset_state *state;
  56. if (!pdata)
  57. return -EINVAL;
  58. state = devm_kzalloc(&pdev->dev, sizeof(*state), GFP_KERNEL);
  59. if (!state)
  60. return -ENOMEM;
  61. state->pdev_child = platform_device_alloc(KEYCOMBO_NAME,
  62. PLATFORM_DEVID_AUTO);
  63. if (!state->pdev_child)
  64. return -ENOMEM;
  65. state->pdev_child->dev.parent = &pdev->dev;
  66. INIT_WORK(&state->restart_work, do_restart);
  67. keyp = pdata->keys_down;
  68. while ((key = *keyp++)) {
  69. if (key >= KEY_MAX)
  70. continue;
  71. down_size++;
  72. }
  73. if (pdata->keys_up) {
  74. keyp = pdata->keys_up;
  75. while ((key = *keyp++)) {
  76. if (key >= KEY_MAX)
  77. continue;
  78. up_size++;
  79. }
  80. }
  81. size = sizeof(struct keycombo_platform_data)
  82. + sizeof(int) * (down_size + 1);
  83. pdata_child = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
  84. if (!pdata_child)
  85. goto error;
  86. memcpy(pdata_child->keys_down, pdata->keys_down,
  87. sizeof(int) * down_size);
  88. if (up_size > 0) {
  89. pdata_child->keys_up = devm_kzalloc(&pdev->dev, up_size + 1,
  90. GFP_KERNEL);
  91. if (!pdata_child->keys_up)
  92. goto error;
  93. memcpy(pdata_child->keys_up, pdata->keys_up,
  94. sizeof(int) * up_size);
  95. if (!pdata_child->keys_up)
  96. goto error;
  97. }
  98. state->reset_fn = pdata->reset_fn;
  99. pdata_child->key_down_fn = do_reset_fn;
  100. pdata_child->priv = state;
  101. pdata_child->key_down_delay = pdata->key_down_delay;
  102. ret = platform_device_add_data(state->pdev_child, pdata_child, size);
  103. if (ret)
  104. goto error;
  105. platform_set_drvdata(pdev, state);
  106. return platform_device_add(state->pdev_child);
  107. error:
  108. platform_device_put(state->pdev_child);
  109. return ret;
  110. }
  111. int keyreset_remove(struct platform_device *pdev)
  112. {
  113. struct keyreset_state *state = platform_get_drvdata(pdev);
  114. platform_device_put(state->pdev_child);
  115. return 0;
  116. }
  117. struct platform_driver keyreset_driver = {
  118. .driver.name = KEYRESET_NAME,
  119. .probe = keyreset_probe,
  120. .remove = keyreset_remove,
  121. };
  122. static int __init keyreset_init(void)
  123. {
  124. return platform_driver_register(&keyreset_driver);
  125. }
  126. static void __exit keyreset_exit(void)
  127. {
  128. return platform_driver_unregister(&keyreset_driver);
  129. }
  130. module_init(keyreset_init);
  131. module_exit(keyreset_exit);