Index: linux-2.6.22-source/drivers/input/serio/cokbd.c =================================================================== --- /dev/null +++ linux-2.6.22-source/drivers/input/serio/cokbd.c @@ -0,0 +1,133 @@ +/* + * Cooperative Linux virtual keyboard controller driver + * + * Copyright (c) 1999-2002 Dan Aloni + */ + +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +MODULE_AUTHOR("Dan Aloni "); +MODULE_DESCRIPTION("Cooperative Linux virtual keyboard controller driver"); +MODULE_LICENSE("GPL"); + +/* + * Names. + */ + +#define COKBD_PHYS_DESC "cokbd" + +static struct serio cokbd_port; + +static irqreturn_t cokbdio_interrupt(int irq, void *dev_id); + +/* + * cokbd_write() sends a byte out through the keyboard interface. + */ + +#define ATKBD_CMD_GETID 0x02f2 + +static int cokbd_write(struct serio *port, unsigned char c) +{ + return 0; +} + +/* + * cokbd_open() is called when a port is open by the higher layer. + * It allocates the interrupt and enables in in the chip. + */ + +static int cokbd_open(struct serio *port) +{ + if (request_irq(KEYBOARD_IRQ, cokbdio_interrupt, 0, "cokbd", NULL)) { + printk(KERN_ERR "cobkd.c: Can't get irq %d for %s, unregistering the port.\n", KEYBOARD_IRQ, "KBD"); + serio_unregister_port(port); + return -1; + } + + return 0; +} + +static void cokbd_close(struct serio *port) +{ + printk(KERN_INFO "cokbd closed\n"); + + free_irq(KEYBOARD_IRQ, NULL); +} + +/* + * Structures for registering the devices in the serio.c module. + */ + +static struct serio cokbd_port = +{ + .id.type = SERIO_8042_XL, + .write = cokbd_write, + .open = cokbd_open, + .close = cokbd_close, + .name = "cokbd port", + .phys = COKBD_PHYS_DESC, +}; + +/* + * cokbdio_interrupt() is the most important function in this driver - + * it handles the interrupts from keyboard, and sends incoming bytes + * to the upper layers. + */ + +static irqreturn_t cokbdio_interrupt(int irq, void *dev_id) +{ + co_message_node_t *node_message; + while (co_get_message(&node_message, CO_DEVICE_KEYBOARD)) { + co_linux_message_t *message = (co_linux_message_t *)&node_message->msg.data; + co_scan_code_t *sc = (co_scan_code_t *)message->data; + unsigned long scancode = sc->code; + + switch (sc->mode) + { + case CO_KBD_SCANCODE_RAW: + serio_interrupt(&cokbd_port, scancode, 0); + break; + + case CO_KBD_SCANCODE_ASCII: + keyboard_inject_utf8(scancode); + break; + } + co_free_message(node_message); + } + + return IRQ_HANDLED; +} + +int __init cokbdio_init(void) +{ + serio_register_port(&cokbd_port); + + printk(KERN_INFO "serio: cokbd at irq %d\n", KEYBOARD_IRQ); + + return 0; +} + +void __exit cokbdio_exit(void) +{ + serio_unregister_port(&cokbd_port); +} + +module_init(cokbdio_init); +module_exit(cokbdio_exit);