magellan.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:5k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: magellan.c,v 1.8 2000/05/31 13:17:12 vojtech Exp $
  3.  *
  4.  *  Copyright (c) 1999-2000 Vojtech Pavlik
  5.  *
  6.  *  Sponsored by SuSE
  7.  */
  8. /*
  9.  * Magellan and Space Mouse 6dof controller driver for Linux
  10.  */
  11. /*
  12.  * This program is free software; you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License as published by
  14.  * the Free Software Foundation; either version 2 of the License, or 
  15.  * (at your option) any later version.
  16.  * 
  17.  * This program is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  * GNU General Public License for more details.
  21.  * 
  22.  * You should have received a copy of the GNU General Public License
  23.  * along with this program; if not, write to the Free Software
  24.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  25.  * 
  26.  *  Should you need to contact me, the author, you can do so either by
  27.  * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
  28.  * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
  29.  */
  30. #include <linux/kernel.h>
  31. #include <linux/module.h>
  32. #include <linux/slab.h>
  33. #include <linux/input.h>
  34. #include <linux/serio.h>
  35. #include <linux/init.h>
  36. /*
  37.  * Definitions & global arrays.
  38.  */
  39. #define MAGELLAN_MAX_LENGTH 32
  40. static int magellan_buttons[] = { BTN_0, BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8};
  41. static int magellan_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ};
  42. static char *magellan_name = "LogiCad3D Magellan";
  43. /*
  44.  * Per-Magellan data.
  45.  */
  46. struct magellan {
  47. struct input_dev dev;
  48. int idx;
  49. unsigned char data[MAGELLAN_MAX_LENGTH];
  50. };
  51. /*
  52.  * magellan_crunch_nibbles() verifies that the bytes sent from the Magellan
  53.  * have correct upper nibbles for the lower ones, if not, the packet will
  54.  * be thrown away. It also strips these upper halves to simplify further
  55.  * processing.
  56.  */
  57. static int magellan_crunch_nibbles(unsigned char *data, int count)
  58. {
  59. static unsigned char nibbles[16] = "0AB3D56GH9:K<MN?";
  60. do {
  61. if (data[count] == nibbles[data[count] & 0xf])
  62. data[count] = data[count] & 0xf;
  63. else
  64. return -1;
  65. } while (--count);
  66. return 0;
  67. }
  68. static void magellan_process_packet(struct magellan* magellan)
  69. {
  70. struct input_dev *dev = &magellan->dev;
  71. unsigned char *data = magellan->data;
  72. int i, t;
  73. if (!magellan->idx) return;
  74. switch (magellan->data[0]) {
  75. case 'd': /* Axis data */
  76. if (magellan->idx != 25) return;
  77. if (magellan_crunch_nibbles(data, 24)) return;
  78. for (i = 0; i < 6; i++)
  79. input_report_abs(dev, magellan_axes[i],
  80. (data[(i << 2) + 1] << 12 | data[(i << 2) + 2] << 8 |
  81.  data[(i << 2) + 3] <<  4 | data[(i << 2) + 4]) - 32768);
  82. break;
  83. case 'k': /* Button data */
  84. if (magellan->idx != 4) return;
  85. if (magellan_crunch_nibbles(data, 3)) return;
  86. t = (data[1] << 1) | (data[2] << 5) | data[3];
  87. for (i = 0; i < 9; i++) input_report_key(dev, magellan_buttons[i], (t >> i) & 1);
  88. break;
  89. }
  90. }
  91. static void magellan_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
  92. {
  93. struct magellan* magellan = serio->private;
  94. if (data == 'r') {
  95. magellan_process_packet(magellan);
  96. magellan->idx = 0;
  97. } else {
  98. if (magellan->idx < MAGELLAN_MAX_LENGTH)
  99. magellan->data[magellan->idx++] = data;
  100. }
  101. /*
  102.  * magellan_disconnect() is the opposite of magellan_connect()
  103.  */
  104. static void magellan_disconnect(struct serio *serio)
  105. {
  106. struct magellan* magellan = serio->private;
  107. input_unregister_device(&magellan->dev);
  108. serio_close(serio);
  109. kfree(magellan);
  110. }
  111. /*
  112.  * magellan_connect() is the routine that is called when someone adds a
  113.  * new serio device. It looks for the Magellan, and if found, registers
  114.  * it as an input device.
  115.  */
  116. static void magellan_connect(struct serio *serio, struct serio_dev *dev)
  117. {
  118. struct magellan *magellan;
  119. int i, t;
  120. if (serio->type != (SERIO_RS232 | SERIO_MAGELLAN))
  121. return;
  122. if (!(magellan = kmalloc(sizeof(struct magellan), GFP_KERNEL)))
  123. return;
  124. memset(magellan, 0, sizeof(struct magellan));
  125. magellan->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
  126. for (i = 0; i < 9; i++)
  127. set_bit(magellan_buttons[i], &magellan->dev.keybit);
  128. for (i = 0; i < 6; i++) {
  129. t = magellan_axes[i];
  130. set_bit(t, magellan->dev.absbit);
  131. magellan->dev.absmin[t] = -360;
  132. magellan->dev.absmax[t] =  360;
  133. }
  134. magellan->dev.private = magellan;
  135. magellan->dev.name = magellan_name;
  136. magellan->dev.idbus = BUS_RS232;
  137. magellan->dev.idvendor = SERIO_MAGELLAN;
  138. magellan->dev.idproduct = 0x0001;
  139. magellan->dev.idversion = 0x0100;
  140. serio->private = magellan;
  141. if (serio_open(serio, dev)) {
  142. kfree(magellan);
  143. return;
  144. }
  145. input_register_device(&magellan->dev);
  146. printk(KERN_INFO "input%d: %s on serio%dn", magellan->dev.number, magellan_name, serio->number);
  147. }
  148. /*
  149.  * The serio device structure.
  150.  */
  151. static struct serio_dev magellan_dev = {
  152. interrupt: magellan_interrupt,
  153. connect: magellan_connect,
  154. disconnect: magellan_disconnect,
  155. };
  156. /*
  157.  * The functions for inserting/removing us as a module.
  158.  */
  159. int __init magellan_init(void)
  160. {
  161. serio_register_device(&magellan_dev);
  162. return 0;
  163. }
  164. void __exit magellan_exit(void)
  165. {
  166. serio_unregister_device(&magellan_dev);
  167. }
  168. module_init(magellan_init);
  169. module_exit(magellan_exit);
  170. MODULE_LICENSE("GPL");