X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Finput%2Fmouse%2Fpc110pad.c;h=f155c1fea04e3bd2e3181106886782011f3d64e7;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=526a11e70bbf51e419d9ade2148a30313c982560;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c index 526a11e70..f155c1fea 100644 --- a/drivers/input/mouse/pc110pad.c +++ b/drivers/input/mouse/pc110pad.c @@ -4,7 +4,7 @@ * Copyright (c) 2000-2001 Vojtech Pavlik * * Based on the work of: - * Alan Cox Robin O'Leary + * Alan Cox Robin O'Leary */ /* @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -52,15 +53,11 @@ MODULE_LICENSE("GPL"); static int pc110pad_irq = 10; static int pc110pad_io = 0x15e0; -static struct input_dev pc110pad_dev; +static struct input_dev *pc110pad_dev; static int pc110pad_data[3]; static int pc110pad_count; -static int pc110pad_used; -static char *pc110pad_name = "IBM PC110 TouchPad"; -static char *pc110pad_phys = "isa15e0/input0"; - -static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs) +static irqreturn_t pc110pad_interrupt(int irq, void *ptr) { int value = inb_p(pc110pad_io); int handshake = inb_p(pc110pad_io + 2); @@ -73,15 +70,14 @@ static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs) if (pc110pad_count < 3) return IRQ_HANDLED; - - input_regs(&pc110pad_dev, regs); - input_report_key(&pc110pad_dev, BTN_TOUCH, + + input_report_key(pc110pad_dev, BTN_TOUCH, pc110pad_data[0] & 0x01); - input_report_abs(&pc110pad_dev, ABS_X, + input_report_abs(pc110pad_dev, ABS_X, pc110pad_data[1] | ((pc110pad_data[0] << 3) & 0x80) | ((pc110pad_data[0] << 1) & 0x100)); - input_report_abs(&pc110pad_dev, ABS_Y, + input_report_abs(pc110pad_dev, ABS_Y, pc110pad_data[2] | ((pc110pad_data[0] << 4) & 0x80)); - input_sync(&pc110pad_dev); + input_sync(pc110pad_dev); pc110pad_count = 0; return IRQ_HANDLED; @@ -89,73 +85,96 @@ static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs) static void pc110pad_close(struct input_dev *dev) { - if (!--pc110pad_used) - outb(PC110PAD_OFF, pc110pad_io + 2); + outb(PC110PAD_OFF, pc110pad_io + 2); } static int pc110pad_open(struct input_dev *dev) { - if (pc110pad_used++) - return 0; - - pc110pad_interrupt(0,NULL,NULL); - pc110pad_interrupt(0,NULL,NULL); - pc110pad_interrupt(0,NULL,NULL); + pc110pad_interrupt(0, NULL); + pc110pad_interrupt(0, NULL); + pc110pad_interrupt(0, NULL); outb(PC110PAD_ON, pc110pad_io + 2); pc110pad_count = 0; return 0; } +/* + * We try to avoid enabling the hardware if it's not + * there, but we don't know how to test. But we do know + * that the PC110 is not a PCI system. So if we find any + * PCI devices in the machine, we don't have a PC110. + */ static int __init pc110pad_init(void) { - if (request_region(pc110pad_io, 4, "pc110pad")) - { - printk(KERN_ERR "pc110pad: I/O area %#x-%#x in use.\n", pc110pad_io, pc110pad_io + 4); + struct pci_dev *dev; + int err; + + dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); + if (dev) { + pci_dev_put(dev); + return -ENOENT; + } + + if (!request_region(pc110pad_io, 4, "pc110pad")) { + printk(KERN_ERR "pc110pad: I/O area %#x-%#x in use.\n", + pc110pad_io, pc110pad_io + 4); return -EBUSY; } outb(PC110PAD_OFF, pc110pad_io + 2); - if (request_irq(pc110pad_irq, pc110pad_interrupt, 0, "pc110pad", NULL)) - { - release_region(pc110pad_io, 4); + if (request_irq(pc110pad_irq, pc110pad_interrupt, 0, "pc110pad", NULL)) { printk(KERN_ERR "pc110pad: Unable to get irq %d.\n", pc110pad_irq); - return -EBUSY; + err = -EBUSY; + goto err_release_region; } - pc110pad_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - pc110pad_dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y); - pc110pad_dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); + pc110pad_dev = input_allocate_device(); + if (!pc110pad_dev) { + printk(KERN_ERR "pc110pad: Not enough memory.\n"); + err = -ENOMEM; + goto err_free_irq; + } + + pc110pad_dev->name = "IBM PC110 TouchPad"; + pc110pad_dev->phys = "isa15e0/input0"; + pc110pad_dev->id.bustype = BUS_ISA; + pc110pad_dev->id.vendor = 0x0003; + pc110pad_dev->id.product = 0x0001; + pc110pad_dev->id.version = 0x0100; + + pc110pad_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + pc110pad_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y); + pc110pad_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); - pc110pad_dev.absmax[ABS_X] = 0x1ff; - pc110pad_dev.absmax[ABS_Y] = 0x0ff; - - pc110pad_dev.open = pc110pad_open; - pc110pad_dev.close = pc110pad_close; + pc110pad_dev->absmax[ABS_X] = 0x1ff; + pc110pad_dev->absmax[ABS_Y] = 0x0ff; - pc110pad_dev.name = pc110pad_name; - pc110pad_dev.phys = pc110pad_phys; - pc110pad_dev.id.bustype = BUS_ISA; - pc110pad_dev.id.vendor = 0x0003; - pc110pad_dev.id.product = 0x0001; - pc110pad_dev.id.version = 0x0100; + pc110pad_dev->open = pc110pad_open; + pc110pad_dev->close = pc110pad_close; - input_register_device(&pc110pad_dev); + err = input_register_device(pc110pad_dev); + if (err) + goto err_free_dev; - printk(KERN_INFO "input: %s at %#x irq %d\n", - pc110pad_name, pc110pad_io, pc110pad_irq); - return 0; + + err_free_dev: + input_free_device(pc110pad_dev); + err_free_irq: + free_irq(pc110pad_irq, NULL); + err_release_region: + release_region(pc110pad_io, 4); + + return err; } - + static void __exit pc110pad_exit(void) { - input_unregister_device(&pc110pad_dev); - outb(PC110PAD_OFF, pc110pad_io + 2); - free_irq(pc110pad_irq, NULL); + input_unregister_device(pc110pad_dev); release_region(pc110pad_io, 4); }