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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Generic linux-input device driver for axis-bearing devices
  3.  *
  4.  * Copyright (c) 2001 Brian S. Julin
  5.  * All rights reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions, and the following disclaimer,
  12.  *    without modification.
  13.  * 2. The name of the author may not be used to endorse or promote products
  14.  *    derived from this software without specific prior written permission.
  15.  *
  16.  * Alternatively, this software may be distributed under the terms of the
  17.  * GNU General Public License ("GPL").
  18.  *
  19.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  20.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22.  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  23.  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  25.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  28.  *
  29.  * References:
  30.  * HP-HIL Technical Reference Manual.  Hewlett Packard Product No. 45918A
  31.  *
  32.  */
  33. #include <linux/hil.h>
  34. #include <linux/input.h>
  35. #include <linux/serio.h>
  36. #include <linux/kernel.h>
  37. #include <linux/module.h>
  38. #include <linux/init.h>
  39. #include <linux/slab.h>
  40. #define PREFIX "HIL PTR: "
  41. #define HIL_GENERIC_NAME "generic HIL pointer device"
  42. MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
  43. MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver");
  44. MODULE_LICENSE("Dual BSD/GPL");
  45. #define TABLET_SIMULATES_MOUSE /* allow tablet to be used as mouse */
  46. #undef  TABLET_AUTOADJUST /* auto-adjust valid tablet ranges */
  47. #define HIL_PTR_MAX_LENGTH 16
  48. struct hil_ptr {
  49. struct input_dev dev;
  50. struct serio *serio;
  51. /* Input buffer and index for packets from HIL bus. */
  52. hil_packet data[HIL_PTR_MAX_LENGTH];
  53. int idx4; /* four counts per packet */
  54. /* Raw device info records from HIL bus, see hil.h for fields. */
  55. char idd[HIL_PTR_MAX_LENGTH]; /* DID byte and IDD record */
  56. char rsc[HIL_PTR_MAX_LENGTH]; /* RSC record */
  57. char exd[HIL_PTR_MAX_LENGTH]; /* EXD record */
  58. char rnm[HIL_PTR_MAX_LENGTH + 1]; /* RNM record + NULL term. */
  59. /* Extra device details not contained in struct input_dev. */
  60. unsigned int nbtn, naxes;
  61. unsigned int btnmap[7];
  62. /* Something to sleep around with. */
  63. struct semaphore sem;
  64. };
  65. /* Process a complete packet after transfer from the HIL */
  66. static void hil_ptr_process_record(struct hil_ptr *ptr)
  67. {
  68. struct input_dev *dev = &ptr->dev;
  69. hil_packet *data = ptr->data;
  70. hil_packet p;
  71. int idx, i, cnt, laxis;
  72. int ax16, absdev;
  73. idx = ptr->idx4/4;
  74. p = data[idx - 1];
  75. if ((p & ~HIL_CMDCT_POL) == 
  76.     (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report;
  77. if ((p & ~HIL_CMDCT_RPL) == 
  78.     (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report;
  79. /* Not a poll response.  See if we are loading config records. */
  80. switch (p & HIL_PKT_DATA_MASK) {
  81. case HIL_CMD_IDD:
  82. for (i = 0; i < idx; i++)
  83. ptr->idd[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
  84. for (; i < HIL_PTR_MAX_LENGTH; i++)
  85. ptr->idd[i] = 0;
  86. break;
  87. case HIL_CMD_RSC:
  88. for (i = 0; i < idx; i++)
  89. ptr->rsc[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
  90. for (; i < HIL_PTR_MAX_LENGTH; i++)
  91. ptr->rsc[i] = 0;
  92. break;
  93. case HIL_CMD_EXD:
  94. for (i = 0; i < idx; i++)
  95. ptr->exd[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
  96. for (; i < HIL_PTR_MAX_LENGTH; i++)
  97. ptr->exd[i] = 0;
  98. break;
  99. case HIL_CMD_RNM:
  100. for (i = 0; i < idx; i++)
  101. ptr->rnm[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
  102. for (; i < HIL_PTR_MAX_LENGTH + 1; i++)
  103. ptr->rnm[i] = '';
  104. break;
  105. default:
  106. /* These occur when device isn't present */
  107. if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break; 
  108. /* Anything else we'd like to know about. */
  109. printk(KERN_WARNING PREFIX "Device sent unknown record %xn", p);
  110. break;
  111. }
  112. goto out;
  113.  report:
  114. if ((p & HIL_CMDCT_POL) != idx - 1) {
  115. printk(KERN_WARNING PREFIX "Malformed poll packet %x (idx = %i)n", p, idx);
  116. goto out;
  117. }
  118. i = (ptr->data[0] & HIL_POL_AXIS_ALT) ? 3 : 0;
  119. laxis = ptr->data[0] & HIL_POL_NUM_AXES_MASK;
  120. laxis += i;
  121. ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */
  122. absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS; 
  123. for (cnt = 1; i < laxis; i++) {
  124. unsigned int lo,hi,val;
  125. lo = ptr->data[cnt++] & HIL_PKT_DATA_MASK;
  126. hi = ax16 ? (ptr->data[cnt++] & HIL_PKT_DATA_MASK) : 0;
  127. if (absdev) {
  128. val = lo + (hi<<8);
  129. #ifdef TABLET_AUTOADJUST
  130. if (val < ptr->dev.absmin[ABS_X + i])
  131. ptr->dev.absmin[ABS_X + i] = val;
  132. if (val > ptr->dev.absmax[ABS_X + i])
  133. ptr->dev.absmax[ABS_X + i] = val;
  134. #endif
  135. if (i%3) val = ptr->dev.absmax[ABS_X + i] - val;
  136. input_report_abs(dev, ABS_X + i, val);
  137. } else {
  138. val = (int) (((int8_t)lo) | ((int8_t)hi<<8));
  139. if (i%3) val *= -1;
  140. input_report_rel(dev, REL_X + i, val);
  141. }
  142. }
  143. while (cnt < idx - 1) {
  144. unsigned int btn;
  145. int up;
  146. btn = ptr->data[cnt++];
  147. up = btn & 1;
  148. btn &= 0xfe;
  149. if (btn == 0x8e) {
  150. continue; /* TODO: proximity == touch? */
  151. }
  152. else if ((btn > 0x8c) || (btn < 0x80)) continue;
  153. btn = (btn - 0x80) >> 1;
  154. btn = ptr->btnmap[btn];
  155. input_report_key(dev, btn, !up);
  156. }
  157.  out:
  158. ptr->idx4 = 0;
  159. up(&ptr->sem);
  160. }
  161. static void hil_ptr_process_err(struct hil_ptr *ptr) {
  162. printk(KERN_WARNING PREFIX "errored HIL packetn");
  163. ptr->idx4 = 0;
  164. up(&ptr->sem);
  165. return;
  166. }
  167. static void hil_ptr_interrupt(struct serio *serio, 
  168.       unsigned char data, 
  169.       unsigned int flags)
  170. {
  171. struct hil_ptr *ptr;
  172. hil_packet packet;
  173. int idx;
  174. ptr = (struct hil_ptr *)serio->private;
  175. if (ptr == NULL) {
  176. BUG();
  177. return;
  178. }
  179. if (ptr->idx4 >= (HIL_PTR_MAX_LENGTH * sizeof(hil_packet))) {
  180. hil_ptr_process_err(ptr);
  181. return;
  182. }
  183. idx = ptr->idx4/4;
  184. if (!(ptr->idx4 % 4)) ptr->data[idx] = 0;
  185. packet = ptr->data[idx];
  186. packet |= ((hil_packet)data) << ((3 - (ptr->idx4 % 4)) * 8);
  187. ptr->data[idx] = packet;
  188. /* Records of N 4-byte hil_packets must terminate with a command. */
  189. if ((++(ptr->idx4)) % 4) return;
  190. if ((packet & 0xffff0000) != HIL_ERR_INT) {
  191. hil_ptr_process_err(ptr);
  192. return;
  193. }
  194. if (packet & HIL_PKT_CMD) 
  195. hil_ptr_process_record(ptr);
  196. }
  197. static void hil_ptr_disconnect(struct serio *serio)
  198. {
  199. struct hil_ptr *ptr;
  200. ptr = (struct hil_ptr *)serio->private;
  201. if (ptr == NULL) {
  202. BUG();
  203. return;
  204. }
  205. input_unregister_device(&ptr->dev);
  206. serio_close(serio);
  207. kfree(ptr);
  208. }
  209. static void hil_ptr_connect(struct serio *serio, struct serio_dev *dev)
  210. {
  211. struct hil_ptr *ptr;
  212. char *txt;
  213. unsigned int i, naxsets, btntype;
  214. uint8_t did, *idd;
  215. if (serio->type != (SERIO_HIL_MLC | SERIO_HIL)) return;
  216. if (!(ptr = kmalloc(sizeof(struct hil_ptr), GFP_KERNEL))) return;
  217. memset(ptr, 0, sizeof(struct hil_ptr));
  218. if (serio_open(serio, dev)) goto bail0;
  219. serio->private = ptr;
  220. ptr->serio = serio;
  221. ptr->dev.private = ptr;
  222. init_MUTEX_LOCKED(&(ptr->sem));
  223. /* Get device info.  MLC driver supplies devid/status/etc. */
  224. serio->write(serio, 0);
  225. serio->write(serio, 0);
  226. serio->write(serio, HIL_PKT_CMD >> 8);
  227. serio->write(serio, HIL_CMD_IDD);
  228. down(&(ptr->sem));
  229. serio->write(serio, 0);
  230. serio->write(serio, 0);
  231. serio->write(serio, HIL_PKT_CMD >> 8);
  232. serio->write(serio, HIL_CMD_RSC);
  233. down(&(ptr->sem));
  234. serio->write(serio, 0);
  235. serio->write(serio, 0);
  236. serio->write(serio, HIL_PKT_CMD >> 8);
  237. serio->write(serio, HIL_CMD_RNM);
  238. down(&(ptr->sem));
  239. serio->write(serio, 0);
  240. serio->write(serio, 0);
  241. serio->write(serio, HIL_PKT_CMD >> 8);
  242. serio->write(serio, HIL_CMD_EXD);
  243. down(&(ptr->sem));
  244. up(&(ptr->sem));
  245. did = ptr->idd[0];
  246. idd = ptr->idd + 1;
  247. txt = "unknown";
  248. if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) {
  249. ptr->dev.evbit[0] = BIT(EV_REL);
  250. txt = "relative";
  251. }
  252. if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_ABS) {
  253. ptr->dev.evbit[0] = BIT(EV_ABS);
  254. txt = "absolute";
  255. }
  256. if (!ptr->dev.evbit[0]) {
  257. goto bail1;
  258. }
  259. ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd);
  260. if (ptr->nbtn) ptr->dev.evbit[0] |= BIT(EV_KEY);
  261. naxsets = HIL_IDD_NUM_AXSETS(*idd);
  262. ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd);
  263. printk(KERN_INFO PREFIX "HIL pointer device found (did: 0x%02x, axis: %s)n",
  264. did, txt);
  265. printk(KERN_INFO PREFIX "HIL pointer has %i buttons and %i sets of %i axesn",
  266. ptr->nbtn, naxsets, ptr->naxes);
  267. btntype = BTN_MISC;
  268. if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET)
  269. #ifdef TABLET_SIMULATES_MOUSE
  270. btntype = BTN_TOUCH;
  271. #else
  272. btntype = BTN_DIGI;
  273. #endif
  274. if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN)
  275. btntype = BTN_TOUCH;
  276. if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE)
  277. btntype = BTN_MOUSE;
  278. for (i = 0; i < ptr->nbtn; i++) {
  279. set_bit(btntype | i, ptr->dev.keybit);
  280. ptr->btnmap[i] = btntype | i;
  281. }
  282. if (btntype == BTN_MOUSE) {
  283. /* Swap buttons 2 and 3 */
  284. ptr->btnmap[1] = BTN_MIDDLE;
  285. ptr->btnmap[2] = BTN_RIGHT;
  286. }
  287. if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) {
  288. for (i = 0; i < ptr->naxes; i++) {
  289. set_bit(REL_X + i, ptr->dev.relbit);
  290. }
  291. for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) {
  292. set_bit(REL_X + i, ptr->dev.relbit);
  293. }
  294. } else {
  295. for (i = 0; i < ptr->naxes; i++) {
  296.    set_bit(ABS_X + i, ptr->dev.absbit);
  297. ptr->dev.absmin[ABS_X + i] = 0;
  298. ptr->dev.absmax[ABS_X + i] = 
  299. HIL_IDD_AXIS_MAX((ptr->idd + 1), i);
  300. }
  301. for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) {
  302. set_bit(ABS_X + i, ptr->dev.absbit);
  303. ptr->dev.absmin[ABS_X + i] = 0;
  304. ptr->dev.absmax[ABS_X + i] = 
  305. HIL_IDD_AXIS_MAX((ptr->idd + 1), (i - 3));
  306. }
  307. #ifdef TABLET_AUTOADJUST
  308. for (i = 0; i < ABS_MAX; i++) {
  309. int diff = ptr->dev.absmax[ABS_X + i] / 10;
  310. ptr->dev.absmin[ABS_X + i] += diff;
  311. ptr->dev.absmax[ABS_X + i] -= diff;
  312. }
  313. #endif
  314. }
  315. ptr->dev.name = strlen(ptr->rnm) ? ptr->rnm : HIL_GENERIC_NAME;
  316. ptr->dev.idbus = BUS_HIL;
  317. ptr->dev.idvendor = SERIO_HIL;
  318. ptr->dev.idproduct = 0x0001; /* TODO: get from ptr->rsc */
  319. ptr->dev.idversion = 0x0100; /* TODO: get from ptr->rsc */
  320. input_register_device(&ptr->dev);
  321. printk(KERN_INFO "input%d: %s on hil%dn",
  322. ptr->dev.number, 
  323. (btntype == BTN_MOUSE) ? "HIL mouse":"HIL tablet or touchpad",
  324. 0);
  325. return;
  326.  bail1:
  327. serio_close(serio);
  328.  bail0:
  329. kfree(ptr);
  330. return;
  331. }
  332. struct serio_dev hil_ptr_serio_dev = {
  333. connect: hil_ptr_connect,
  334. disconnect: hil_ptr_disconnect,
  335. interrupt: hil_ptr_interrupt
  336. };
  337. static int __init hil_ptr_init(void)
  338. {
  339. serio_register_device(&hil_ptr_serio_dev);
  340.         return 0;
  341. }
  342.                 
  343. static void __exit hil_ptr_exit(void)
  344. {
  345. serio_unregister_device(&hil_ptr_serio_dev);
  346. }
  347.                         
  348. module_init(hil_ptr_init);
  349. module_exit(hil_ptr_exit);