ia64/linux-2.6.18-xen.hg

annotate drivers/char/qtronix.c @ 0:831230e53067

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