Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.16 606 lines 14 kB view raw
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 36#include <linux/config.h> 37 38/* 39 * NOTE: 40 * 41 * This driver has only been tested with the Consumer IR 42 * port of the ITE 8172 system controller. 43 * 44 * You do not need this driver if you are using the ps/2 or 45 * USB adapter that the keyboard ships with. You only need 46 * this driver if your board has a IR port and the keyboard 47 * data is being sent directly to the IR. In that case, 48 * you also need some low-level IR support. See it8172_cir.c. 49 * 50 */ 51 52#ifdef CONFIG_QTRONIX_KEYBOARD 53 54#include <linux/module.h> 55#include <linux/types.h> 56#include <linux/pci.h> 57#include <linux/kernel.h> 58 59#include <asm/it8172/it8172.h> 60#include <asm/it8172/it8172_int.h> 61#include <asm/it8172/it8172_cir.h> 62 63#include <linux/spinlock.h> 64#include <linux/sched.h> 65#include <linux/interrupt.h> 66#include <linux/tty.h> 67#include <linux/mm.h> 68#include <linux/signal.h> 69#include <linux/init.h> 70#include <linux/kbd_ll.h> 71#include <linux/delay.h> 72#include <linux/poll.h> 73#include <linux/miscdevice.h> 74#include <linux/slab.h> 75#include <linux/kbd_kern.h> 76#include <linux/smp_lock.h> 77#include <asm/io.h> 78#include <linux/pc_keyb.h> 79 80#include <asm/keyboard.h> 81#include <linux/bitops.h> 82#include <asm/uaccess.h> 83#include <asm/irq.h> 84#include <asm/system.h> 85 86#define leading1 0 87#define leading2 0xF 88 89#define KBD_CIR_PORT 0 90#define AUX_RECONNECT 170 /* scancode when ps2 device is plugged (back) in */ 91 92static int data_index; 93struct cir_port *cir; 94static unsigned char kbdbytes[5]; 95static unsigned char cir_data[32]; /* we only need 16 chars */ 96 97static void kbd_int_handler(int irq, void *dev_id, struct pt_regs *regs); 98static int handle_data(unsigned char *p_data); 99static inline void handle_mouse_event(unsigned char scancode); 100static inline void handle_keyboard_event(unsigned char scancode, int down); 101static int __init psaux_init(void); 102 103static struct aux_queue *queue; /* Mouse data buffer. */ 104static int aux_count = 0; 105 106/* 107 * Keys accessed through the 'Fn' key 108 * The Fn key does not produce a key-up sequence. So, the first 109 * time the user presses it, it will be key-down event. The key 110 * stays down until the user presses it again. 111 */ 112#define NUM_FN_KEYS 56 113static unsigned char fn_keys[NUM_FN_KEYS] = { 114 0,0,0,0,0,0,0,0, /* 0 7 */ 115 8,9,10,93,0,0,0,0, /* 8 15 */ 116 0,0,0,0,0,0,0,5, /* 16 23 */ 117 6,7,91,0,0,0,0,0, /* 24 31 */ 118 0,0,0,0,0,2,3,4, /* 32 39 */ 119 92,0,0,0,0,0,0,0, /* 40 47 */ 120 0,0,0,0,11,0,94,95 /* 48 55 */ 121 122}; 123 124void __init init_qtronix_990P_kbd(void) 125{ 126 int retval; 127 128 cir = (struct cir_port *)kmalloc(sizeof(struct cir_port), GFP_KERNEL); 129 if (!cir) { 130 printk("Unable to initialize Qtronix keyboard\n"); 131 return; 132 } 133 134 /* 135 * revisit 136 * this should be programmable, somehow by the, by the user. 137 */ 138 cir->port = KBD_CIR_PORT; 139 cir->baud_rate = 0x1d; 140 cir->rdwos = 0; 141 cir->rxdcr = 0x3; 142 cir->hcfs = 0; 143 cir->fifo_tl = 0; 144 cir->cfq = 0x1d; 145 cir_port_init(cir); 146 147 retval = request_irq(IT8172_CIR0_IRQ, kbd_int_handler, 148 (unsigned long )(SA_INTERRUPT|SA_SHIRQ), 149 (const char *)"Qtronix IR Keyboard", (void *)cir); 150 151 if (retval) { 152 printk("unable to allocate cir %d irq %d\n", 153 cir->port, IT8172_CIR0_IRQ); 154 } 155#ifdef CONFIG_PSMOUSE 156 psaux_init(); 157#endif 158} 159 160static inline unsigned char BitReverse(unsigned short key) 161{ 162 unsigned char rkey = 0; 163 rkey |= (key & 0x1) << 7; 164 rkey |= (key & 0x2) << 5; 165 rkey |= (key & 0x4) << 3; 166 rkey |= (key & 0x8) << 1; 167 rkey |= (key & 0x10) >> 1; 168 rkey |= (key & 0x20) >> 3; 169 rkey |= (key & 0x40) >> 5; 170 rkey |= (key & 0x80) >> 7; 171 return rkey; 172 173} 174 175 176static inline u_int8_t UpperByte(u_int8_t data) 177{ 178 return (data >> 4); 179} 180 181 182static inline u_int8_t LowerByte(u_int8_t data) 183{ 184 return (data & 0xF); 185} 186 187 188int CheckSumOk(u_int8_t byte1, u_int8_t byte2, 189 u_int8_t byte3, u_int8_t byte4, u_int8_t byte5) 190{ 191 u_int8_t CheckSum; 192 193 CheckSum = (byte1 & 0x0F) + byte2 + byte3 + byte4 + byte5; 194 if ( LowerByte(UpperByte(CheckSum) + LowerByte(CheckSum)) != UpperByte(byte1) ) 195 return 0; 196 else 197 return 1; 198} 199 200 201static void kbd_int_handler(int irq, void *dev_id, struct pt_regs *regs) 202{ 203 struct cir_port *cir; 204 int j; 205 unsigned char int_status; 206 207 cir = (struct cir_port *)dev_id; 208 int_status = get_int_status(cir); 209 if (int_status & 0x4) { 210 clear_fifo(cir); 211 return; 212 } 213 214 while (cir_get_rx_count(cir)) { 215 216 cir_data[data_index] = cir_read_data(cir); 217 218 if (data_index == 0) {/* expecting first byte */ 219 if (cir_data[data_index] != leading1) { 220 //printk("!leading byte %x\n", cir_data[data_index]); 221 set_rx_active(cir); 222 clear_fifo(cir); 223 continue; 224 } 225 } 226 if (data_index == 1) { 227 if ((cir_data[data_index] & 0xf) != leading2) { 228 set_rx_active(cir); 229 data_index = 0; /* start over */ 230 clear_fifo(cir); 231 continue; 232 } 233 } 234 235 if ( (cir_data[data_index] == 0xff)) { /* last byte */ 236 //printk("data_index %d\n", data_index); 237 set_rx_active(cir); 238#if 0 239 for (j=0; j<=data_index; j++) { 240 printk("rx_data %d: %x\n", j, cir_data[j]); 241 } 242#endif 243 data_index = 0; 244 handle_data(cir_data); 245 return; 246 } 247 else if (data_index>16) { 248 set_rx_active(cir); 249#if 0 250 printk("warning: data_index %d\n", data_index); 251 for (j=0; j<=data_index; j++) { 252 printk("rx_data %d: %x\n", j, cir_data[j]); 253 } 254#endif 255 data_index = 0; 256 clear_fifo(cir); 257 return; 258 } 259 data_index++; 260 } 261} 262 263 264#define NUM_KBD_BYTES 5 265static int handle_data(unsigned char *p_data) 266{ 267 u_int32_t bit_bucket; 268 u_int32_t i, j; 269 u_int32_t got_bits, next_byte; 270 int down = 0; 271 272 /* Reorganize the bit stream */ 273 for (i=0; i<16; i++) 274 p_data[i] = BitReverse(~p_data[i]); 275 276 /* 277 * We've already previously checked that p_data[0] 278 * is equal to leading1 and that (p_data[1] & 0xf) 279 * is equal to leading2. These twelve bits are the 280 * leader code. We can now throw them away (the 12 281 * bits) and continue parsing the stream. 282 */ 283 bit_bucket = p_data[1] << 12; 284 got_bits = 4; 285 next_byte = 2; 286 287 /* 288 * Process four bits at a time 289 */ 290 for (i=0; i<NUM_KBD_BYTES; i++) { 291 292 kbdbytes[i]=0; 293 294 for (j=0; j<8; j++) /* 8 bits per byte */ 295 { 296 if (got_bits < 4) { 297 bit_bucket |= (p_data[next_byte++] << (8 - got_bits)); 298 got_bits += 8; 299 } 300 301 if ((bit_bucket & 0xF000) == 0x8000) { 302 /* Convert 1000b to 1 */ 303 kbdbytes[i] = 0x80 | (kbdbytes[i] >> 1); 304 got_bits -= 4; 305 bit_bucket = bit_bucket << 4; 306 } 307 else if ((bit_bucket & 0xC000) == 0x8000) { 308 /* Convert 10b to 0 */ 309 kbdbytes[i] = kbdbytes[i] >> 1; 310 got_bits -= 2; 311 bit_bucket = bit_bucket << 2; 312 } 313 else { 314 /* bad serial stream */ 315 return 1; 316 } 317 318 if (next_byte > 16) { 319 //printk("error: too many bytes\n"); 320 return 1; 321 } 322 } 323 } 324 325 326 if (!CheckSumOk(kbdbytes[0], kbdbytes[1], 327 kbdbytes[2], kbdbytes[3], kbdbytes[4])) { 328 //printk("checksum failed\n"); 329 return 1; 330 } 331 332 if (kbdbytes[1] & 0x08) { 333 //printk("m: %x %x %x\n", kbdbytes[1], kbdbytes[2], kbdbytes[3]); 334 handle_mouse_event(kbdbytes[1]); 335 handle_mouse_event(kbdbytes[2]); 336 handle_mouse_event(kbdbytes[3]); 337 } 338 else { 339 if (kbdbytes[2] == 0) down = 1; 340#if 0 341 if (down) 342 printk("down %d\n", kbdbytes[3]); 343 else 344 printk("up %d\n", kbdbytes[3]); 345#endif 346 handle_keyboard_event(kbdbytes[3], down); 347 } 348 return 0; 349} 350 351 352DEFINE_SPINLOCK(kbd_controller_lock); 353static unsigned char handle_kbd_event(void); 354 355 356int kbd_setkeycode(unsigned int scancode, unsigned int keycode) 357{ 358 printk("kbd_setkeycode scancode %x keycode %x\n", scancode, keycode); 359 return 0; 360} 361 362int kbd_getkeycode(unsigned int scancode) 363{ 364 return scancode; 365} 366 367 368int kbd_translate(unsigned char scancode, unsigned char *keycode, 369 char raw_mode) 370{ 371 static int prev_scancode = 0; 372 373 if (scancode == 0x00 || scancode == 0xff) { 374 prev_scancode = 0; 375 return 0; 376 } 377 378 /* todo */ 379 if (!prev_scancode && scancode == 160) { /* Fn key down */ 380 //printk("Fn key down\n"); 381 prev_scancode = 160; 382 return 0; 383 } 384 else if (prev_scancode && scancode == 160) { /* Fn key up */ 385 //printk("Fn key up\n"); 386 prev_scancode = 0; 387 return 0; 388 } 389 390 /* todo */ 391 if (prev_scancode == 160) { 392 if (scancode <= NUM_FN_KEYS) { 393 *keycode = fn_keys[scancode]; 394 //printk("fn keycode %d\n", *keycode); 395 } 396 else 397 return 0; 398 } 399 else if (scancode <= 127) { 400 *keycode = scancode; 401 } 402 else 403 return 0; 404 405 406 return 1; 407} 408 409char kbd_unexpected_up(unsigned char keycode) 410{ 411 //printk("kbd_unexpected_up\n"); 412 return 0; 413} 414 415static unsigned char kbd_exists = 1; 416 417static inline void handle_keyboard_event(unsigned char scancode, int down) 418{ 419 kbd_exists = 1; 420 handle_scancode(scancode, down); 421 tasklet_schedule(&keyboard_tasklet); 422} 423 424 425void kbd_leds(unsigned char leds) 426{ 427} 428 429/* dummy */ 430void kbd_init_hw(void) 431{ 432} 433 434 435 436static inline void handle_mouse_event(unsigned char scancode) 437{ 438 if(scancode == AUX_RECONNECT){ 439 queue->head = queue->tail = 0; /* Flush input queue */ 440 // __aux_write_ack(AUX_ENABLE_DEV); /* ping the mouse :) */ 441 return; 442 } 443 444 if (aux_count) { 445 int head = queue->head; 446 447 queue->buf[head] = scancode; 448 head = (head + 1) & (AUX_BUF_SIZE-1); 449 if (head != queue->tail) { 450 queue->head = head; 451 kill_fasync(&queue->fasync, SIGIO, POLL_IN); 452 wake_up_interruptible(&queue->proc_list); 453 } 454 } 455} 456 457static unsigned char get_from_queue(void) 458{ 459 unsigned char result; 460 unsigned long flags; 461 462 spin_lock_irqsave(&kbd_controller_lock, flags); 463 result = queue->buf[queue->tail]; 464 queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1); 465 spin_unlock_irqrestore(&kbd_controller_lock, flags); 466 return result; 467} 468 469 470static inline int queue_empty(void) 471{ 472 return queue->head == queue->tail; 473} 474 475static int fasync_aux(int fd, struct file *filp, int on) 476{ 477 int retval; 478 479 //printk("fasync_aux\n"); 480 retval = fasync_helper(fd, filp, on, &queue->fasync); 481 if (retval < 0) 482 return retval; 483 return 0; 484} 485 486 487/* 488 * Random magic cookie for the aux device 489 */ 490#define AUX_DEV ((void *)queue) 491 492static int release_aux(struct inode * inode, struct file * file) 493{ 494 fasync_aux(-1, file, 0); 495 aux_count--; 496 return 0; 497} 498 499static int open_aux(struct inode * inode, struct file * file) 500{ 501 if (aux_count++) { 502 return 0; 503 } 504 queue->head = queue->tail = 0; /* Flush input queue */ 505 return 0; 506} 507 508/* 509 * Put bytes from input queue to buffer. 510 */ 511 512static ssize_t read_aux(struct file * file, char * buffer, 513 size_t count, loff_t *ppos) 514{ 515 DECLARE_WAITQUEUE(wait, current); 516 ssize_t i = count; 517 unsigned char c; 518 519 if (queue_empty()) { 520 if (file->f_flags & O_NONBLOCK) 521 return -EAGAIN; 522 add_wait_queue(&queue->proc_list, &wait); 523repeat: 524 set_current_state(TASK_INTERRUPTIBLE); 525 if (queue_empty() && !signal_pending(current)) { 526 schedule(); 527 goto repeat; 528 } 529 current->state = TASK_RUNNING; 530 remove_wait_queue(&queue->proc_list, &wait); 531 } 532 while (i > 0 && !queue_empty()) { 533 c = get_from_queue(); 534 put_user(c, buffer++); 535 i--; 536 } 537 if (count-i) { 538 struct inode *inode = file->f_dentry->d_inode; 539 inode->i_atime = current_fs_time(inode->i_sb); 540 return count-i; 541 } 542 if (signal_pending(current)) 543 return -ERESTARTSYS; 544 return 0; 545} 546 547/* 548 * Write to the aux device. 549 */ 550 551static ssize_t write_aux(struct file * file, const char * buffer, 552 size_t count, loff_t *ppos) 553{ 554 /* 555 * The ITE boards this was tested on did not have the 556 * transmit wires connected. 557 */ 558 return count; 559} 560 561static unsigned int aux_poll(struct file *file, poll_table * wait) 562{ 563 poll_wait(file, &queue->proc_list, wait); 564 if (!queue_empty()) 565 return POLLIN | POLLRDNORM; 566 return 0; 567} 568 569struct file_operations psaux_fops = { 570 .read = read_aux, 571 .write = write_aux, 572 .poll = aux_poll, 573 .open = open_aux, 574 .release = release_aux, 575 .fasync = fasync_aux, 576}; 577 578/* 579 * Initialize driver. 580 */ 581static struct miscdevice psaux_mouse = { 582 PSMOUSE_MINOR, "psaux", &psaux_fops 583}; 584 585static int __init psaux_init(void) 586{ 587 int retval; 588 589 retval = misc_register(&psaux_mouse); 590 if(retval < 0) 591 return retval; 592 593 queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL); 594 if (!queue) { 595 misc_deregister(&psaux_mouse); 596 return -ENOMEM; 597 } 598 599 memset(queue, 0, sizeof(*queue)); 600 queue->head = queue->tail = 0; 601 init_waitqueue_head(&queue->proc_list); 602 603 return 0; 604} 605module_init(init_qtronix_990P_kbd); 606#endif