keychord.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /*
  2. * drivers/input/misc/keychord.c
  3. *
  4. * Copyright (C) 2008 Google, Inc.
  5. * Author: Mike Lockwood <lockwood@android.com>
  6. *
  7. * This software is licensed under the terms of the GNU General Public
  8. * License version 2, as published by the Free Software Foundation, and
  9. * may be copied, distributed, and modified under those terms.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. */
  17. #include <linux/poll.h>
  18. #include <linux/slab.h>
  19. #include <linux/module.h>
  20. #include <linux/init.h>
  21. #include <linux/spinlock.h>
  22. #include <linux/fs.h>
  23. #include <linux/miscdevice.h>
  24. #include <linux/keychord.h>
  25. #include <linux/sched.h>
  26. #define KEYCHORD_NAME "keychord"
  27. #define BUFFER_SIZE 16
  28. MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
  29. MODULE_DESCRIPTION("Key chord input driver");
  30. MODULE_SUPPORTED_DEVICE("keychord");
  31. MODULE_LICENSE("GPL");
  32. #define NEXT_KEYCHORD(kc) ((struct input_keychord *) \
  33. ((char *)kc + sizeof(struct input_keychord) + \
  34. kc->count * sizeof(kc->keycodes[0])))
  35. struct keychord_device {
  36. struct input_handler input_handler;
  37. int registered;
  38. /* list of keychords to monitor */
  39. struct input_keychord *keychords;
  40. int keychord_count;
  41. /* bitmask of keys contained in our keychords */
  42. unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
  43. /* current state of the keys */
  44. unsigned long keystate[BITS_TO_LONGS(KEY_CNT)];
  45. /* number of keys that are currently pressed */
  46. int key_down;
  47. /* second input_device_id is needed for null termination */
  48. struct input_device_id device_ids[2];
  49. spinlock_t lock;
  50. wait_queue_head_t waitq;
  51. unsigned char head;
  52. unsigned char tail;
  53. __u16 buff[BUFFER_SIZE];
  54. };
  55. static int check_keychord(struct keychord_device *kdev,
  56. struct input_keychord *keychord)
  57. {
  58. int i;
  59. if (keychord->count != kdev->key_down)
  60. return 0;
  61. for (i = 0; i < keychord->count; i++) {
  62. if (!test_bit(keychord->keycodes[i], kdev->keystate))
  63. return 0;
  64. }
  65. /* we have a match */
  66. return 1;
  67. }
  68. static void keychord_event(struct input_handle *handle, unsigned int type,
  69. unsigned int code, int value)
  70. {
  71. struct keychord_device *kdev = handle->private;
  72. struct input_keychord *keychord;
  73. unsigned long flags;
  74. int i, got_chord = 0;
  75. if (type != EV_KEY || code >= KEY_MAX)
  76. return;
  77. spin_lock_irqsave(&kdev->lock, flags);
  78. /* do nothing if key state did not change */
  79. if (!test_bit(code, kdev->keystate) == !value)
  80. goto done;
  81. __change_bit(code, kdev->keystate);
  82. if (value)
  83. kdev->key_down++;
  84. else
  85. kdev->key_down--;
  86. /* don't notify on key up */
  87. if (!value)
  88. goto done;
  89. /* ignore this event if it is not one of the keys we are monitoring */
  90. if (!test_bit(code, kdev->keybit))
  91. goto done;
  92. keychord = kdev->keychords;
  93. if (!keychord)
  94. goto done;
  95. /* check to see if the keyboard state matches any keychords */
  96. for (i = 0; i < kdev->keychord_count; i++) {
  97. if (check_keychord(kdev, keychord)) {
  98. kdev->buff[kdev->head] = keychord->id;
  99. kdev->head = (kdev->head + 1) % BUFFER_SIZE;
  100. got_chord = 1;
  101. break;
  102. }
  103. /* skip to next keychord */
  104. keychord = NEXT_KEYCHORD(keychord);
  105. }
  106. done:
  107. spin_unlock_irqrestore(&kdev->lock, flags);
  108. if (got_chord) {
  109. pr_info("keychord: got keychord id %d. Any tasks: %d\n",
  110. keychord->id,
  111. !list_empty_careful(&kdev->waitq.task_list));
  112. wake_up_interruptible(&kdev->waitq);
  113. }
  114. }
  115. static int keychord_connect(struct input_handler *handler,
  116. struct input_dev *dev,
  117. const struct input_device_id *id)
  118. {
  119. int i, ret;
  120. struct input_handle *handle;
  121. struct keychord_device *kdev =
  122. container_of(handler, struct keychord_device, input_handler);
  123. /*
  124. * ignore this input device if it does not contain any keycodes
  125. * that we are monitoring
  126. */
  127. for (i = 0; i < KEY_MAX; i++) {
  128. if (test_bit(i, kdev->keybit) && test_bit(i, dev->keybit))
  129. break;
  130. }
  131. if (i == KEY_MAX)
  132. return -ENODEV;
  133. handle = kzalloc(sizeof(*handle), GFP_KERNEL);
  134. if (!handle)
  135. return -ENOMEM;
  136. handle->dev = dev;
  137. handle->handler = handler;
  138. handle->name = KEYCHORD_NAME;
  139. handle->private = kdev;
  140. ret = input_register_handle(handle);
  141. if (ret)
  142. goto err_input_register_handle;
  143. ret = input_open_device(handle);
  144. if (ret)
  145. goto err_input_open_device;
  146. pr_info("keychord: using input dev %s for fevent\n", dev->name);
  147. return 0;
  148. err_input_open_device:
  149. input_unregister_handle(handle);
  150. err_input_register_handle:
  151. kfree(handle);
  152. return ret;
  153. }
  154. static void keychord_disconnect(struct input_handle *handle)
  155. {
  156. input_close_device(handle);
  157. input_unregister_handle(handle);
  158. kfree(handle);
  159. }
  160. /*
  161. * keychord_read is used to read keychord events from the driver
  162. */
  163. static ssize_t keychord_read(struct file *file, char __user *buffer,
  164. size_t count, loff_t *ppos)
  165. {
  166. struct keychord_device *kdev = file->private_data;
  167. __u16 id;
  168. int retval;
  169. unsigned long flags;
  170. if (count < sizeof(id))
  171. return -EINVAL;
  172. count = sizeof(id);
  173. if (kdev->head == kdev->tail && (file->f_flags & O_NONBLOCK))
  174. return -EAGAIN;
  175. retval = wait_event_interruptible(kdev->waitq,
  176. kdev->head != kdev->tail);
  177. if (retval)
  178. return retval;
  179. spin_lock_irqsave(&kdev->lock, flags);
  180. /* pop a keychord ID off the queue */
  181. id = kdev->buff[kdev->tail];
  182. kdev->tail = (kdev->tail + 1) % BUFFER_SIZE;
  183. spin_unlock_irqrestore(&kdev->lock, flags);
  184. if (copy_to_user(buffer, &id, count))
  185. return -EFAULT;
  186. return count;
  187. }
  188. /*
  189. * keychord_write is used to configure the driver
  190. */
  191. static ssize_t keychord_write(struct file *file, const char __user *buffer,
  192. size_t count, loff_t *ppos)
  193. {
  194. struct keychord_device *kdev = file->private_data;
  195. struct input_keychord *keychords = 0;
  196. struct input_keychord *keychord, *next, *end;
  197. int ret, i, key;
  198. unsigned long flags;
  199. if (count < sizeof(struct input_keychord))
  200. return -EINVAL;
  201. keychords = kzalloc(count, GFP_KERNEL);
  202. if (!keychords)
  203. return -ENOMEM;
  204. /* read list of keychords from userspace */
  205. if (copy_from_user(keychords, buffer, count)) {
  206. kfree(keychords);
  207. return -EFAULT;
  208. }
  209. /* unregister handler before changing configuration */
  210. if (kdev->registered) {
  211. input_unregister_handler(&kdev->input_handler);
  212. kdev->registered = 0;
  213. }
  214. spin_lock_irqsave(&kdev->lock, flags);
  215. /* clear any existing configuration */
  216. kfree(kdev->keychords);
  217. kdev->keychords = 0;
  218. kdev->keychord_count = 0;
  219. kdev->key_down = 0;
  220. memset(kdev->keybit, 0, sizeof(kdev->keybit));
  221. memset(kdev->keystate, 0, sizeof(kdev->keystate));
  222. kdev->head = kdev->tail = 0;
  223. keychord = keychords;
  224. end = (struct input_keychord *)((char *)keychord + count);
  225. while (keychord < end) {
  226. next = NEXT_KEYCHORD(keychord);
  227. if (keychord->count <= 0 || next > end) {
  228. pr_err("keychord: invalid keycode count %d\n",
  229. keychord->count);
  230. goto err_unlock_return;
  231. }
  232. if (keychord->version != KEYCHORD_VERSION) {
  233. pr_err("keychord: unsupported version %d\n",
  234. keychord->version);
  235. goto err_unlock_return;
  236. }
  237. /* keep track of the keys we are monitoring in keybit */
  238. for (i = 0; i < keychord->count; i++) {
  239. key = keychord->keycodes[i];
  240. if (key < 0 || key >= KEY_CNT) {
  241. pr_err("keychord: keycode %d out of range\n",
  242. key);
  243. goto err_unlock_return;
  244. }
  245. __set_bit(key, kdev->keybit);
  246. }
  247. kdev->keychord_count++;
  248. keychord = next;
  249. }
  250. kdev->keychords = keychords;
  251. spin_unlock_irqrestore(&kdev->lock, flags);
  252. ret = input_register_handler(&kdev->input_handler);
  253. if (ret) {
  254. kfree(keychords);
  255. kdev->keychords = 0;
  256. return ret;
  257. }
  258. kdev->registered = 1;
  259. return count;
  260. err_unlock_return:
  261. spin_unlock_irqrestore(&kdev->lock, flags);
  262. kfree(keychords);
  263. return -EINVAL;
  264. }
  265. static unsigned int keychord_poll(struct file *file, poll_table *wait)
  266. {
  267. struct keychord_device *kdev = file->private_data;
  268. poll_wait(file, &kdev->waitq, wait);
  269. if (kdev->head != kdev->tail)
  270. return POLLIN | POLLRDNORM;
  271. return 0;
  272. }
  273. static int keychord_open(struct inode *inode, struct file *file)
  274. {
  275. struct keychord_device *kdev;
  276. kdev = kzalloc(sizeof(struct keychord_device), GFP_KERNEL);
  277. if (!kdev)
  278. return -ENOMEM;
  279. spin_lock_init(&kdev->lock);
  280. init_waitqueue_head(&kdev->waitq);
  281. kdev->input_handler.event = keychord_event;
  282. kdev->input_handler.connect = keychord_connect;
  283. kdev->input_handler.disconnect = keychord_disconnect;
  284. kdev->input_handler.name = KEYCHORD_NAME;
  285. kdev->input_handler.id_table = kdev->device_ids;
  286. kdev->device_ids[0].flags = INPUT_DEVICE_ID_MATCH_EVBIT;
  287. __set_bit(EV_KEY, kdev->device_ids[0].evbit);
  288. file->private_data = kdev;
  289. return 0;
  290. }
  291. static int keychord_release(struct inode *inode, struct file *file)
  292. {
  293. struct keychord_device *kdev = file->private_data;
  294. if (kdev->registered)
  295. input_unregister_handler(&kdev->input_handler);
  296. kfree(kdev);
  297. return 0;
  298. }
  299. static const struct file_operations keychord_fops = {
  300. .owner = THIS_MODULE,
  301. .open = keychord_open,
  302. .release = keychord_release,
  303. .read = keychord_read,
  304. .write = keychord_write,
  305. .poll = keychord_poll,
  306. };
  307. static struct miscdevice keychord_misc = {
  308. .fops = &keychord_fops,
  309. .name = KEYCHORD_NAME,
  310. .minor = MISC_DYNAMIC_MINOR,
  311. };
  312. static int __init keychord_init(void)
  313. {
  314. return misc_register(&keychord_misc);
  315. }
  316. static void __exit keychord_exit(void)
  317. {
  318. misc_deregister(&keychord_misc);
  319. }
  320. module_init(keychord_init);
  321. module_exit(keychord_exit);