stowaway.c 4.5 KB

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