stowaway.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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/serio.h>
  33. #define DRIVER_DESC "Stowaway keyboard driver"
  34. MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
  35. MODULE_DESCRIPTION(DRIVER_DESC);
  36. MODULE_LICENSE("GPL");
  37. #define SKBD_KEY_MASK 0x7f
  38. #define SKBD_RELEASE 0x80
  39. static unsigned char skbd_keycode[128] = {
  40. KEY_1, KEY_2, KEY_3, KEY_Z, KEY_4, KEY_5, KEY_6, KEY_7,
  41. 0, KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_GRAVE,
  42. KEY_X, KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_SPACE,
  43. KEY_CAPSLOCK, KEY_TAB, KEY_LEFTCTRL, 0, 0, 0, 0, 0,
  44. 0, 0, 0, KEY_LEFTALT, 0, 0, 0, 0,
  45. 0, 0, 0, 0, KEY_C, KEY_V, KEY_B, KEY_N,
  46. KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE, KEY_HOME, KEY_8, KEY_9, KEY_0, KEY_ESC,
  47. KEY_LEFTBRACE, KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_END, KEY_U, KEY_I, KEY_O, KEY_P,
  48. KEY_APOSTROPHE, KEY_ENTER, KEY_PAGEUP,0, KEY_J, KEY_K, KEY_L, KEY_SEMICOLON,
  49. KEY_SLASH, KEY_UP, KEY_PAGEDOWN, 0,KEY_M, KEY_COMMA, KEY_DOT, KEY_INSERT,
  50. KEY_DELETE, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0,
  51. KEY_LEFTSHIFT, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0,
  52. 0, 0, 0, 0, 0, 0, 0, 0,
  53. 0, 0, 0, 0, 0, 0, 0, 0,
  54. 0, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7,
  55. KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, 0, 0, 0
  56. };
  57. struct skbd {
  58. unsigned char keycode[128];
  59. struct input_dev *dev;
  60. struct serio *serio;
  61. char phys[32];
  62. };
  63. static irqreturn_t skbd_interrupt(struct serio *serio, unsigned char data,
  64. unsigned int flags)
  65. {
  66. struct skbd *skbd = serio_get_drvdata(serio);
  67. struct input_dev *dev = skbd->dev;
  68. if (skbd->keycode[data & SKBD_KEY_MASK]) {
  69. input_report_key(dev, skbd->keycode[data & SKBD_KEY_MASK],
  70. !(data & SKBD_RELEASE));
  71. input_sync(dev);
  72. }
  73. return IRQ_HANDLED;
  74. }
  75. static int skbd_connect(struct serio *serio, struct serio_driver *drv)
  76. {
  77. struct skbd *skbd;
  78. struct input_dev *input_dev;
  79. int err = -ENOMEM;
  80. int i;
  81. skbd = kzalloc(sizeof(struct skbd), GFP_KERNEL);
  82. input_dev = input_allocate_device();
  83. if (!skbd || !input_dev)
  84. goto fail1;
  85. skbd->serio = serio;
  86. skbd->dev = input_dev;
  87. snprintf(skbd->phys, sizeof(skbd->phys), "%s/input0", serio->phys);
  88. memcpy(skbd->keycode, skbd_keycode, sizeof(skbd->keycode));
  89. input_dev->name = "Stowaway Keyboard";
  90. input_dev->phys = skbd->phys;
  91. input_dev->id.bustype = BUS_RS232;
  92. input_dev->id.vendor = SERIO_STOWAWAY;
  93. input_dev->id.product = 0x0001;
  94. input_dev->id.version = 0x0100;
  95. input_dev->dev.parent = &serio->dev;
  96. input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
  97. input_dev->keycode = skbd->keycode;
  98. input_dev->keycodesize = sizeof(unsigned char);
  99. input_dev->keycodemax = ARRAY_SIZE(skbd_keycode);
  100. for (i = 0; i < ARRAY_SIZE(skbd_keycode); i++)
  101. set_bit(skbd_keycode[i], input_dev->keybit);
  102. clear_bit(0, input_dev->keybit);
  103. serio_set_drvdata(serio, skbd);
  104. err = serio_open(serio, drv);
  105. if (err)
  106. goto fail2;
  107. err = input_register_device(skbd->dev);
  108. if (err)
  109. goto fail3;
  110. return 0;
  111. fail3: serio_close(serio);
  112. fail2: serio_set_drvdata(serio, NULL);
  113. fail1: input_free_device(input_dev);
  114. kfree(skbd);
  115. return err;
  116. }
  117. static void skbd_disconnect(struct serio *serio)
  118. {
  119. struct skbd *skbd = serio_get_drvdata(serio);
  120. serio_close(serio);
  121. serio_set_drvdata(serio, NULL);
  122. input_unregister_device(skbd->dev);
  123. kfree(skbd);
  124. }
  125. static struct serio_device_id skbd_serio_ids[] = {
  126. {
  127. .type = SERIO_RS232,
  128. .proto = SERIO_STOWAWAY,
  129. .id = SERIO_ANY,
  130. .extra = SERIO_ANY,
  131. },
  132. { 0 }
  133. };
  134. MODULE_DEVICE_TABLE(serio, skbd_serio_ids);
  135. static struct serio_driver skbd_drv = {
  136. .driver = {
  137. .name = "stowaway",
  138. },
  139. .description = DRIVER_DESC,
  140. .id_table = skbd_serio_ids,
  141. .interrupt = skbd_interrupt,
  142. .connect = skbd_connect,
  143. .disconnect = skbd_disconnect,
  144. };
  145. module_serio_driver(skbd_drv);