stowaway.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. * Stowaway keyboard driver for Linux
  3. */
  4. /*
  5. * Copyright (c) 2006 Marek Vasut
  6. *
  7. * Based on Newton keyboard driver for Linux
  8. * by Justin Cormack
  9. */
  10. /*
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  24. *
  25. * Should you need to contact me, the author, you can do so either by
  26. * e-mail - mail your message to <marek.vasut@gmail.com>, or by paper mail:
  27. * Marek Vasut, Liskovecka 559, Frydek-Mistek, 738 01 Czech Republic
  28. */
  29. #include <linux/slab.h>
  30. #include <linux/module.h>
  31. #include <linux/input.h>
  32. #include <linux/init.h>
  33. #include <linux/serio.h>
  34. #define DRIVER_DESC "Stowaway keyboard driver"
  35. MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
  36. MODULE_DESCRIPTION(DRIVER_DESC);
  37. MODULE_LICENSE("GPL");
  38. #define SKBD_KEY_MASK 0x7f
  39. #define SKBD_RELEASE 0x80
  40. static unsigned char skbd_keycode[128] = {
  41. KEY_1, KEY_2, KEY_3, KEY_Z, KEY_4, KEY_5, KEY_6, KEY_7,
  42. 0, KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_GRAVE,
  43. KEY_X, KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_SPACE,
  44. KEY_CAPSLOCK, KEY_TAB, KEY_LEFTCTRL, 0, 0, 0, 0, 0,
  45. 0, 0, 0, KEY_LEFTALT, 0, 0, 0, 0,
  46. 0, 0, 0, 0, KEY_C, KEY_V, KEY_B, KEY_N,
  47. KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE, KEY_HOME, KEY_8, KEY_9, KEY_0, KEY_ESC,
  48. KEY_LEFTBRACE, KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_END, KEY_U, KEY_I, KEY_O, KEY_P,
  49. KEY_APOSTROPHE, KEY_ENTER, KEY_PAGEUP,0, KEY_J, KEY_K, KEY_L, KEY_SEMICOLON,
  50. KEY_SLASH, KEY_UP, KEY_PAGEDOWN, 0,KEY_M, KEY_COMMA, KEY_DOT, KEY_INSERT,
  51. KEY_DELETE, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0,
  52. KEY_LEFTSHIFT, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0,
  53. 0, 0, 0, 0, 0, 0, 0, 0,
  54. 0, 0, 0, 0, 0, 0, 0, 0,
  55. 0, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7,
  56. KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, 0, 0, 0
  57. };
  58. struct skbd {
  59. unsigned char keycode[128];
  60. struct input_dev *dev;
  61. struct serio *serio;
  62. char phys[32];
  63. };
  64. static irqreturn_t skbd_interrupt(struct serio *serio, unsigned char data,
  65. unsigned int flags)
  66. {
  67. struct skbd *skbd = serio_get_drvdata(serio);
  68. struct input_dev *dev = skbd->dev;
  69. if (skbd->keycode[data & SKBD_KEY_MASK]) {
  70. input_report_key(dev, skbd->keycode[data & SKBD_KEY_MASK],
  71. !(data & SKBD_RELEASE));
  72. input_sync(dev);
  73. }
  74. return IRQ_HANDLED;
  75. }
  76. static int skbd_connect(struct serio *serio, struct serio_driver *drv)
  77. {
  78. struct skbd *skbd;
  79. struct input_dev *input_dev;
  80. int err = -ENOMEM;
  81. int i;
  82. skbd = kzalloc(sizeof(struct skbd), GFP_KERNEL);
  83. input_dev = input_allocate_device();
  84. if (!skbd || !input_dev)
  85. goto fail1;
  86. skbd->serio = serio;
  87. skbd->dev = input_dev;
  88. snprintf(skbd->phys, sizeof(skbd->phys), "%s/input0", serio->phys);
  89. memcpy(skbd->keycode, skbd_keycode, sizeof(skbd->keycode));
  90. input_dev->name = "Stowaway Keyboard";
  91. input_dev->phys = skbd->phys;
  92. input_dev->id.bustype = BUS_RS232;
  93. input_dev->id.vendor = SERIO_STOWAWAY;
  94. input_dev->id.product = 0x0001;
  95. input_dev->id.version = 0x0100;
  96. input_dev->cdev.dev = &serio->dev;
  97. input_dev->private = skbd;
  98. input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
  99. input_dev->keycode = skbd->keycode;
  100. input_dev->keycodesize = sizeof(unsigned char);
  101. input_dev->keycodemax = ARRAY_SIZE(skbd_keycode);
  102. for (i = 0; i < ARRAY_SIZE(skbd_keycode); i++)
  103. set_bit(skbd_keycode[i], input_dev->keybit);
  104. clear_bit(0, input_dev->keybit);
  105. serio_set_drvdata(serio, skbd);
  106. err = serio_open(serio, drv);
  107. if (err)
  108. goto fail2;
  109. err = input_register_device(skbd->dev);
  110. if (err)
  111. goto fail3;
  112. return 0;
  113. fail3: serio_close(serio);
  114. fail2: serio_set_drvdata(serio, NULL);
  115. fail1: input_free_device(input_dev);
  116. kfree(skbd);
  117. return err;
  118. }
  119. static void skbd_disconnect(struct serio *serio)
  120. {
  121. struct skbd *skbd = serio_get_drvdata(serio);
  122. serio_close(serio);
  123. serio_set_drvdata(serio, NULL);
  124. input_unregister_device(skbd->dev);
  125. kfree(skbd);
  126. }
  127. static struct serio_device_id skbd_serio_ids[] = {
  128. {
  129. .type = SERIO_RS232,
  130. .proto = SERIO_STOWAWAY,
  131. .id = SERIO_ANY,
  132. .extra = SERIO_ANY,
  133. },
  134. { 0 }
  135. };
  136. MODULE_DEVICE_TABLE(serio, skbd_serio_ids);
  137. static struct serio_driver skbd_drv = {
  138. .driver = {
  139. .name = "stowaway",
  140. },
  141. .description = DRIVER_DESC,
  142. .id_table = skbd_serio_ids,
  143. .interrupt = skbd_interrupt,
  144. .connect = skbd_connect,
  145. .disconnect = skbd_disconnect,
  146. };
  147. static int __init skbd_init(void)
  148. {
  149. return serio_register_driver(&skbd_drv);
  150. }
  151. static void __exit skbd_exit(void)
  152. {
  153. serio_unregister_driver(&skbd_drv);
  154. }
  155. module_init(skbd_init);
  156. module_exit(skbd_exit);