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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *
  3.  * BRIEF MODULE DESCRIPTION
  4.  * Qtronix 990P infrared keyboard driver.
  5.  *
  6.  *
  7.  * Copyright 2001 MontaVista Software Inc.
  8.  * Author: MontaVista Software, Inc.
  9.  *          ppopov@mvista.com or source@mvista.com
  10.  *
  11.  *
  12.  *  The bottom portion of this driver was take from 
  13.  *  pc_keyb.c  Please see that file for copyrights.
  14.  *
  15.  *  This program is free software; you can redistribute  it and/or modify it
  16.  *  under  the terms of  the GNU General  Public License as published by the
  17.  *  Free Software Foundation;  either version 2 of the  License, or (at your
  18.  *  option) any later version.
  19.  *
  20.  *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
  21.  *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
  22.  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
  23.  *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
  24.  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  25.  *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
  26.  *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  27.  *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
  28.  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  29.  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30.  *
  31.  *  You should have received a copy of the  GNU General Public License along
  32.  *  with this program; if not, write  to the Free Software Foundation, Inc.,
  33.  *  675 Mass Ave, Cambridge, MA 02139, USA.
  34.  */
  35. #include <linux/config.h>
  36. /* 
  37.  * NOTE:  
  38.  *
  39.  * This driver has only been tested with the Consumer IR
  40.  * port of the ITE 8172 system controller.
  41.  *
  42.  * You do not need this driver if you are using the ps/2 or
  43.  * USB adapter that the keyboard ships with.  You only need 
  44.  * this driver if your board has a IR port and the keyboard
  45.  * data is being sent directly to the IR.  In that case,
  46.  * you also need some low-level IR support. See it8172_cir.c.
  47.  *
  48.  */
  49. #ifdef CONFIG_QTRONIX_KEYBOARD
  50. #include <linux/module.h>
  51. #include <linux/types.h>
  52. #include <linux/pci.h>
  53. #include <linux/kernel.h>
  54. #include <asm/it8172/it8172.h>
  55. #include <asm/it8172/it8172_int.h>
  56. #include <asm/it8172/it8172_cir.h>
  57. #include <linux/spinlock.h>
  58. #include <linux/sched.h>
  59. #include <linux/interrupt.h>
  60. #include <linux/tty.h>
  61. #include <linux/mm.h>
  62. #include <linux/signal.h>
  63. #include <linux/init.h>
  64. #include <linux/kbd_ll.h>
  65. #include <linux/delay.h>
  66. #include <linux/random.h>
  67. #include <linux/poll.h>
  68. #include <linux/miscdevice.h>
  69. #include <linux/slab.h>
  70. #include <linux/kbd_kern.h>
  71. #include <linux/smp_lock.h>
  72. #include <asm/io.h>
  73. #include <linux/pc_keyb.h>
  74. #include <asm/keyboard.h>
  75. #include <asm/bitops.h>
  76. #include <asm/uaccess.h>
  77. #include <asm/irq.h>
  78. #include <asm/system.h>
  79. #define leading1 0
  80. #define leading2 0xF
  81. #define KBD_CIR_PORT 0
  82. #define AUX_RECONNECT 170 /* scancode when ps2 device is plugged (back) in */
  83. static int data_index;
  84. struct cir_port *cir;
  85. static unsigned char kbdbytes[5];
  86. static unsigned char cir_data[32]; /* we only need 16 chars */
  87. static void kbd_int_handler(int irq, void *dev_id, struct pt_regs *regs);
  88. static int handle_data(unsigned char *p_data);
  89. static inline void handle_mouse_event(unsigned char scancode);
  90. static inline void handle_keyboard_event(unsigned char scancode, int down);
  91. static int __init psaux_init(void);
  92. static struct aux_queue *queue; /* Mouse data buffer. */
  93. static int aux_count = 0;
  94. /*
  95.  * Keys accessed through the 'Fn' key
  96.  * The Fn key does not produce a key-up sequence. So, the first
  97.  * time the user presses it, it will be key-down event. The key
  98.  * stays down until the user presses it again.
  99.  */
  100. #define NUM_FN_KEYS 56
  101. static unsigned char fn_keys[NUM_FN_KEYS] = {
  102. 0,0,0,0,0,0,0,0,        /* 0 7   */
  103. 8,9,10,93,0,0,0,0,      /* 8 15  */
  104. 0,0,0,0,0,0,0,5,        /* 16 23 */
  105. 6,7,91,0,0,0,0,0,       /* 24 31 */
  106. 0,0,0,0,0,2,3,4,        /* 32 39 */
  107. 92,0,0,0,0,0,0,0,       /* 40 47 */
  108. 0,0,0,0,11,0,94,95        /* 48 55 */
  109. };
  110. void __init init_qtronix_990P_kbd(void)
  111. {
  112. int retval;
  113. cir = (struct cir_port *)kmalloc(sizeof(struct cir_port), GFP_KERNEL);
  114. if (!cir) {
  115. printk("Unable to initialize Qtronix keyboardn");
  116. return;
  117. }
  118. /* 
  119.  * revisit
  120.  * this should be programmable, somehow by the, by the user.
  121.  */
  122. cir->port = KBD_CIR_PORT;
  123. cir->baud_rate = 0x1d;
  124. cir->rdwos = 0;
  125. cir->rxdcr = 0x3;
  126. cir->hcfs = 0;
  127. cir->fifo_tl = 0;
  128. cir->cfq = 0x1d;
  129. cir_port_init(cir);
  130. retval = request_irq(IT8172_CIR0_IRQ, kbd_int_handler, 
  131. (unsigned long )(SA_INTERRUPT|SA_SHIRQ), 
  132. (const char *)"Qtronix IR Keyboard", (void *)cir);
  133. if (retval) {
  134. printk("unable to allocate cir %d irq %dn", 
  135. cir->port, IT8172_CIR0_IRQ);
  136. }
  137. #ifdef CONFIG_PSMOUSE
  138. psaux_init();
  139. #endif
  140. }
  141. static inline unsigned char BitReverse(unsigned short key)
  142. {
  143. unsigned char rkey = 0;
  144. rkey |= (key & 0x1) << 7;
  145. rkey |= (key & 0x2) << 5;
  146. rkey |= (key & 0x4) << 3;
  147. rkey |= (key & 0x8) << 1;
  148. rkey |= (key & 0x10) >> 1;
  149. rkey |= (key & 0x20) >> 3;
  150. rkey |= (key & 0x40) >> 5;
  151. rkey |= (key & 0x80) >> 7;
  152. return rkey;
  153. }
  154. static inline u_int8_t UpperByte(u_int8_t data)
  155. {
  156. return (data >> 4);
  157. }
  158. static inline u_int8_t LowerByte(u_int8_t data)
  159. {
  160. return (data & 0xF);
  161. }
  162. int CheckSumOk(u_int8_t byte1, u_int8_t byte2, 
  163. u_int8_t byte3, u_int8_t byte4, u_int8_t byte5)
  164. {
  165. u_int8_t CheckSum;
  166. CheckSum = (byte1 & 0x0F) + byte2 + byte3 + byte4 + byte5;
  167. if ( LowerByte(UpperByte(CheckSum) + LowerByte(CheckSum)) != UpperByte(byte1) )
  168. return 0;
  169. else
  170. return 1;
  171. }
  172. static void kbd_int_handler(int irq, void *dev_id, struct pt_regs *regs)
  173. {
  174. struct cir_port *cir;
  175. int j;
  176. unsigned char int_status;
  177. cir = (struct cir_port *)dev_id;
  178. int_status = get_int_status(cir);;
  179. if (int_status & 0x4) {
  180. clear_fifo(cir);
  181. return;
  182. }
  183. while (cir_get_rx_count(cir)) {
  184. cir_data[data_index] = cir_read_data(cir);
  185. if (data_index == 0) {/* expecting first byte */
  186. if (cir_data[data_index] != leading1) {
  187. //printk("!leading byte %xn", cir_data[data_index]);
  188. set_rx_active(cir);
  189. clear_fifo(cir);
  190. continue;
  191. }
  192. }
  193. if (data_index == 1) {
  194. if ((cir_data[data_index] & 0xf) != leading2) {
  195. set_rx_active(cir);
  196. data_index = 0; /* start over */
  197. clear_fifo(cir);
  198. continue;
  199. }
  200. }
  201. if ( (cir_data[data_index] == 0xff)) { /* last byte */
  202. //printk("data_index %dn", data_index);
  203. set_rx_active(cir);
  204. #if 0
  205. for (j=0; j<=data_index; j++) {
  206. printk("rx_data %d:  %xn", j, cir_data[j]);
  207. }
  208. #endif
  209. data_index = 0;
  210. handle_data(cir_data);
  211. return;
  212. }
  213. else if (data_index>16) {
  214. set_rx_active(cir);
  215. #if 0
  216. printk("warning: data_index %dn", data_index);
  217. for (j=0; j<=data_index; j++) {
  218. printk("rx_data %d:  %xn", j, cir_data[j]);
  219. }
  220. #endif
  221. data_index = 0;
  222. clear_fifo(cir);
  223. return;
  224. }
  225. data_index++;
  226. }
  227. }
  228. #define NUM_KBD_BYTES 5
  229. static int handle_data(unsigned char *p_data)
  230. {
  231. u_int32_t bit_bucket;
  232. u_int32_t i, j;
  233. u_int32_t got_bits, next_byte;
  234. int down = 0;
  235. /* Reorganize the bit stream */
  236. for (i=0; i<16; i++)
  237. p_data[i] = BitReverse(~p_data[i]);
  238. /* 
  239.  * We've already previously checked that p_data[0]
  240.  * is equal to leading1 and that (p_data[1] & 0xf)
  241.  * is equal to leading2. These twelve bits are the
  242.  * leader code.  We can now throw them away (the 12
  243.  * bits) and continue parsing the stream.
  244.  */
  245. bit_bucket = p_data[1] << 12;
  246. got_bits = 4;
  247. next_byte = 2;
  248. /* 
  249.  * Process four bits at a time
  250.  */
  251. for (i=0; i<NUM_KBD_BYTES; i++) {
  252. kbdbytes[i]=0;
  253. for (j=0; j<8; j++) /* 8 bits per byte */
  254. {
  255. if (got_bits < 4) {
  256. bit_bucket |= (p_data[next_byte++] << (8 - got_bits));
  257. got_bits += 8;
  258. }
  259. if ((bit_bucket & 0xF000) == 0x8000) { 
  260. /* Convert 1000b to 1 */
  261. kbdbytes[i] = 0x80 | (kbdbytes[i] >> 1);
  262. got_bits -= 4;
  263. bit_bucket = bit_bucket << 4;
  264. }
  265. else if ((bit_bucket & 0xC000) == 0x8000) {
  266. /* Convert 10b to 0 */
  267. kbdbytes[i] =  kbdbytes[i] >> 1;
  268. got_bits -= 2;
  269. bit_bucket = bit_bucket << 2;
  270. }
  271. else {
  272. /* bad serial stream */
  273. return 1;
  274. }
  275. if (next_byte > 16) {
  276. //printk("error: too many bytesn");
  277. return 1;
  278. }
  279. }
  280. }
  281. if (!CheckSumOk(kbdbytes[0], kbdbytes[1], 
  282. kbdbytes[2], kbdbytes[3], kbdbytes[4])) {
  283. //printk("checksum failedn");
  284. return 1;
  285. }
  286. if (kbdbytes[1] & 0x08) {
  287. //printk("m: %x %x %xn", kbdbytes[1], kbdbytes[2], kbdbytes[3]);
  288. handle_mouse_event(kbdbytes[1]);
  289. handle_mouse_event(kbdbytes[2]);
  290. handle_mouse_event(kbdbytes[3]);
  291. }
  292. else {
  293. if (kbdbytes[2] == 0) down = 1;
  294. #if 0
  295. if (down)
  296. printk("down %dn", kbdbytes[3]);
  297. else
  298. printk("up %dn", kbdbytes[3]);
  299. #endif
  300. handle_keyboard_event(kbdbytes[3], down);
  301. }
  302. return 0;
  303. }
  304. spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
  305. static unsigned char handle_kbd_event(void);
  306. int kbd_setkeycode(unsigned int scancode, unsigned int keycode)
  307. {
  308. printk("kbd_setkeycode scancode %x keycode %xn", scancode, keycode);
  309. return 0;
  310. }
  311. int kbd_getkeycode(unsigned int scancode)
  312. {
  313. return scancode;
  314. }
  315. int kbd_translate(unsigned char scancode, unsigned char *keycode,
  316.     char raw_mode)
  317. {
  318. static int prev_scancode = 0;
  319. if (scancode == 0x00 || scancode == 0xff) {
  320. prev_scancode = 0;
  321. return 0;
  322. }
  323. /* todo */
  324. if (!prev_scancode && scancode == 160) { /* Fn key down */
  325. //printk("Fn key downn");
  326. prev_scancode = 160;
  327. return 0;
  328. }
  329. else if (prev_scancode && scancode == 160) { /* Fn key up */
  330. //printk("Fn key upn");
  331. prev_scancode = 0;
  332. return 0;
  333. }
  334. /* todo */
  335. if (prev_scancode == 160) {
  336. if (scancode <= NUM_FN_KEYS) {
  337. *keycode = fn_keys[scancode];
  338. //printk("fn keycode %dn", *keycode);
  339. }
  340. else
  341. return 0;
  342. else if (scancode <= 127) {
  343. *keycode = scancode;
  344. }
  345. else
  346. return 0;
  347.   return 1;
  348. }
  349. char kbd_unexpected_up(unsigned char keycode)
  350. {
  351. //printk("kbd_unexpected_upn");
  352. return 0;
  353. }
  354. static unsigned char kbd_exists = 1;
  355. static inline void handle_keyboard_event(unsigned char scancode, int down)
  356. {
  357. kbd_exists = 1;
  358. handle_scancode(scancode, down);
  359. tasklet_schedule(&keyboard_tasklet);
  360. }
  361. void kbd_leds(unsigned char leds)
  362. {
  363. }
  364. /* dummy */
  365. void kbd_init_hw(void)
  366. {
  367. }
  368. static inline void handle_mouse_event(unsigned char scancode)
  369. {
  370. if(scancode == AUX_RECONNECT){
  371. queue->head = queue->tail = 0;  /* Flush input queue */
  372. // __aux_write_ack(AUX_ENABLE_DEV);  /* ping the mouse :) */
  373. return;
  374. }
  375. add_mouse_randomness(scancode);
  376. if (aux_count) {
  377. int head = queue->head;
  378. queue->buf[head] = scancode;
  379. head = (head + 1) & (AUX_BUF_SIZE-1);
  380. if (head != queue->tail) {
  381. queue->head = head;
  382. kill_fasync(&queue->fasync, SIGIO, POLL_IN);
  383. wake_up_interruptible(&queue->proc_list);
  384. }
  385. }
  386. }
  387. static unsigned char get_from_queue(void)
  388. {
  389. unsigned char result;
  390. unsigned long flags;
  391. spin_lock_irqsave(&kbd_controller_lock, flags);
  392. result = queue->buf[queue->tail];
  393. queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
  394. spin_unlock_irqrestore(&kbd_controller_lock, flags);
  395. return result;
  396. }
  397. static inline int queue_empty(void)
  398. {
  399. return queue->head == queue->tail;
  400. }
  401. static int fasync_aux(int fd, struct file *filp, int on)
  402. {
  403. int retval;
  404. //printk("fasync_auxn");
  405. retval = fasync_helper(fd, filp, on, &queue->fasync);
  406. if (retval < 0)
  407. return retval;
  408. return 0;
  409. }
  410. /*
  411.  * Random magic cookie for the aux device
  412.  */
  413. #define AUX_DEV ((void *)queue)
  414. static int release_aux(struct inode * inode, struct file * file)
  415. {
  416. lock_kernel();
  417. fasync_aux(-1, file, 0);
  418. aux_count--;
  419. unlock_kernel();
  420. return 0;
  421. }
  422. static int open_aux(struct inode * inode, struct file * file)
  423. {
  424. if (aux_count++) {
  425. return 0;
  426. }
  427. queue->head = queue->tail = 0; /* Flush input queue */
  428. return 0;
  429. }
  430. /*
  431.  * Put bytes from input queue to buffer.
  432.  */
  433. static ssize_t read_aux(struct file * file, char * buffer,
  434. size_t count, loff_t *ppos)
  435. {
  436. DECLARE_WAITQUEUE(wait, current);
  437. ssize_t i = count;
  438. unsigned char c;
  439. if (queue_empty()) {
  440. if (file->f_flags & O_NONBLOCK)
  441. return -EAGAIN;
  442. add_wait_queue(&queue->proc_list, &wait);
  443. repeat:
  444. set_current_state(TASK_INTERRUPTIBLE);
  445. if (queue_empty() && !signal_pending(current)) {
  446. schedule();
  447. goto repeat;
  448. }
  449. current->state = TASK_RUNNING;
  450. remove_wait_queue(&queue->proc_list, &wait);
  451. }
  452. while (i > 0 && !queue_empty()) {
  453. c = get_from_queue();
  454. put_user(c, buffer++);
  455. i--;
  456. }
  457. if (count-i) {
  458. file->f_dentry->d_inode->i_atime = CURRENT_TIME;
  459. return count-i;
  460. }
  461. if (signal_pending(current))
  462. return -ERESTARTSYS;
  463. return 0;
  464. }
  465. /*
  466.  * Write to the aux device.
  467.  */
  468. static ssize_t write_aux(struct file * file, const char * buffer,
  469.  size_t count, loff_t *ppos)
  470. {
  471. /*
  472.  * The ITE boards this was tested on did not have the
  473.  * transmit wires connected.
  474.  */
  475. return count;
  476. }
  477. static unsigned int aux_poll(struct file *file, poll_table * wait)
  478. {
  479. poll_wait(file, &queue->proc_list, wait);
  480. if (!queue_empty())
  481. return POLLIN | POLLRDNORM;
  482. return 0;
  483. }
  484. struct file_operations psaux_fops = {
  485. read: read_aux,
  486. write: write_aux,
  487. poll: aux_poll,
  488. open: open_aux,
  489. release: release_aux,
  490. fasync: fasync_aux,
  491. };
  492. /*
  493.  * Initialize driver.
  494.  */
  495. static struct miscdevice psaux_mouse = {
  496. PSMOUSE_MINOR, "psaux", &psaux_fops
  497. };
  498. static int __init psaux_init(void)
  499. {
  500. misc_register(&psaux_mouse);
  501. queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
  502. memset(queue, 0, sizeof(*queue));
  503. queue->head = queue->tail = 0;
  504. init_waitqueue_head(&queue->proc_list);
  505. return 0;
  506. }
  507. module_init(init_qtronix_990P_kbd);
  508. #endif