#include <linux/errno.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/input.h> #include <linux/serio.h> #include <linux/init.h> #define DRIVER_DESC "Serial touchpad driver" MODULE_AUTHOR("foobar<foobar@foobar.com>"); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); /** * Per-touchpad data. */ struct sertp { struct input_dev *dev; /**< input device */ struct serio *serio; /**< serio struct */ s32 id; /**< device id */ u8 buf[8]; /**< buffer to receive data */ u8 pre_cnt; /**< received byte pre_cnter */ s8 phys[32]; }; static irqreturn_t sertp_interrupt(struct serio *serio, u8 data, u32 flags, struct pt_regs *regs) { struct sertp *sertp = serio_get_drvdata(serio); printk (KERN_ALERT "sertp_interrupt\n"); sertp_process_data(sertp, data, regs); /* start processing data */ return IRQ_HANDLED; } static void sertp_disconnect(struct serio *serio) { struct sertp *sertp = serio_get_drvdata(serio); printk (KERN_ALERT "sertp_disconnect\n"); input_unregister_device(sertp->dev); serio_close(serio); serio_set_drvdata(serio, NULL); kfree(sertp); } static int sertp_connect(struct serio *serio, struct serio_driver *drv) { struct sertp *sertp; struct input_dev *input_dev; int err; printk (KERN_ALERT "sertp_connect\n"); /* allocate our struct data and input device */ sertp = kzalloc(sizeof(struct sertp), GFP_KERNEL); input_dev = input_allocate_device(); if (!sertp || !input_dev) { err = -ENOMEM; goto fail; } sertp->serio = serio; sertp->id = serio->id.id; sertp->dev = input_dev; snprintf(sertp->phys, sizeof(sertp->phys), "%s/input0", serio->phys); /* Q0 */ input_dev->private = sertp; input_dev->name = "Serial TouchPad"; input_dev->phys = sertp->phys; /* Q1 */ input_dev->id.bustype = BUS_RS232; input_dev->id.vendor = SERIO_ANY; /* Q2 */ input_dev->id.product = sertp->id; input_dev->id.version = 0x0100; input_dev->cdev.dev = &serio->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL) | BIT(REL_HWHEEL); serio_set_drvdata(serio, sertp); err = serio_open(serio, drv); if (err) goto fail; input_register_device(sertp->dev); return 0; fail: serio_set_drvdata(serio, NULL); input_free_device(input_dev); kfree(sertp); return err; } static struct serio_device_id sertp_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_ANY, /* Q3 */ .extra = SERIO_ANY, .id = SERIO_ANY, }, { 0 } }; MODULE_DEVICE_TABLE(serio, sertp_serio_ids); static struct serio_driver sertp_drv = { .driver = { .name = "sertp", }, .description = DRIVER_DESC, .id_table = sertp_serio_ids, .interrupt = sertp_interrupt, .connect = sertp_connect, .disconnect = sertp_disconnect, }; static int __init sertp_init(void) { printk (KERN_ALERT "sertp_init\n"); serio_register_driver(&sertp_drv); return 0; } static void __exit sertp_exit(void) { printk (KERN_ALERT "sertp_exit\n"); serio_unregister_driver(&sertp_drv); } /* Module interfaces */ module_init(sertp_init); module_exit(sertp_exit); |
欢迎光临 Chinaunix (http://bbs.chinaunix.net/) | Powered by Discuz! X3.2 |