Commit b9abaa3f authored by Linus Torvalds's avatar Linus Torvalds
parents 8995b161 736ce432
...@@ -3,7 +3,7 @@ Apple Touchpad Driver (appletouch) ...@@ -3,7 +3,7 @@ Apple Touchpad Driver (appletouch)
Copyright (C) 2005 Stelian Pop <stelian@popies.net> Copyright (C) 2005 Stelian Pop <stelian@popies.net>
appletouch is a Linux kernel driver for the USB touchpad found on post appletouch is a Linux kernel driver for the USB touchpad found on post
February 2005 Apple Alu Powerbooks. February 2005 and October 2005 Apple Aluminium Powerbooks.
This driver is derived from Johannes Berg's appletrackpad driver[1], but it has This driver is derived from Johannes Berg's appletrackpad driver[1], but it has
been improved in some areas: been improved in some areas:
...@@ -13,7 +13,8 @@ been improved in some areas: ...@@ -13,7 +13,8 @@ been improved in some areas:
Credits go to Johannes Berg for reverse-engineering the touchpad protocol, Credits go to Johannes Berg for reverse-engineering the touchpad protocol,
Frank Arnold for further improvements, and Alex Harper for some additional Frank Arnold for further improvements, and Alex Harper for some additional
information about the inner workings of the touchpad sensors. information about the inner workings of the touchpad sensors. Michael
Hanselmann added support for the October 2005 models.
Usage: Usage:
------ ------
......
This diff is collapsed.
...@@ -52,5 +52,12 @@ config GAMEPORT_EMU10K1 ...@@ -52,5 +52,12 @@ config GAMEPORT_EMU10K1
config GAMEPORT_FM801 config GAMEPORT_FM801
tristate "ForteMedia FM801 gameport support" tristate "ForteMedia FM801 gameport support"
depends on PCI depends on PCI
help
Say Y here if you have ForteMedia FM801 PCI audio controller
(Abit AU10, Genius Sound Maker, HP Workstation zx2000,
and others), and want to use its gameport.
To compile this driver as a module, choose M here: the
module will be called fm801-gp.
endif endif
...@@ -321,7 +321,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, ...@@ -321,7 +321,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
switch (code) { switch (code) {
case ATKBD_RET_BAT: case ATKBD_RET_BAT:
atkbd->enabled = 0; atkbd->enabled = 0;
serio_rescan(atkbd->ps2dev.serio); serio_reconnect(atkbd->ps2dev.serio);
goto out; goto out;
case ATKBD_RET_EMUL0: case ATKBD_RET_EMUL0:
atkbd->emul = 1; atkbd->emul = 1;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/platform_device.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -24,7 +25,7 @@ MODULE_AUTHOR("Richard Zidlicky <rz@linux-m68k.org>"); ...@@ -24,7 +25,7 @@ MODULE_AUTHOR("Richard Zidlicky <rz@linux-m68k.org>");
MODULE_DESCRIPTION("m68k beeper driver"); MODULE_DESCRIPTION("m68k beeper driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static struct input_dev *m68kspkr_dev; static struct platform_device *m68kspkr_platform_device;
static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{ {
...@@ -47,36 +48,103 @@ static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int ...@@ -47,36 +48,103 @@ static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int
return 0; return 0;
} }
static int __devinit m68kspkr_probe(struct platform_device *dev)
{
struct input_dev *input_dev;
int err;
input_dev = input_allocate_device();
if (!input_dev)
return -ENOMEM;
input_dev->name = "m68k beeper";
input_dev->phys = "m68k/generic";
input_dev->id.bustype = BUS_HOST;
input_dev->id.vendor = 0x001f;
input_dev->id.product = 0x0001;
input_dev->id.version = 0x0100;
input_dev->cdev.dev = &dev->dev;
input_dev->evbit[0] = BIT(EV_SND);
input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
input_dev->event = m68kspkr_event;
err = input_register_device(input_dev);
if (err) {
input_free_device(input_dev);
return err;
}
platform_set_drvdata(dev, input_dev);
return 0;
}
static int __devexit m68kspkr_remove(struct platform_device *dev)
{
struct input_dev *input_dev = platform_get_drvdata(dev);
input_unregister_device(input_dev);
platform_set_drvdata(dev, NULL);
/* turn off the speaker */
m68kspkr_event(NULL, EV_SND, SND_BELL, 0);
return 0;
}
static void m68kspkr_shutdown(struct platform_device *dev)
{
/* turn off the speaker */
m68kspkr_event(NULL, EV_SND, SND_BELL, 0);
}
static struct platform_driver m68kspkr_platform_driver = {
.driver = {
.name = "m68kspkr",
.owner = THIS_MODULE,
},
.probe = m68kspkr_probe,
.remove = __devexit_p(m68kspkr_remove),
.shutdown = m68kspkr_shutdown,
};
static int __init m68kspkr_init(void) static int __init m68kspkr_init(void)
{ {
if (!mach_beep) { int err;
if (!mach_beep) {
printk(KERN_INFO "m68kspkr: no lowlevel beep support\n"); printk(KERN_INFO "m68kspkr: no lowlevel beep support\n");
return -ENODEV; return -ENODEV;
} }
m68kspkr_dev = input_allocate_device(); err = platform_driver_register(&m68kspkr_platform_driver);
if (!m68kspkr_dev) if (err)
return -ENOMEM; return err;
m68kspkr_dev->name = "m68k beeper";
m68kspkr_dev->phys = "m68k/generic";
m68kspkr_dev->id.bustype = BUS_HOST;
m68kspkr_dev->id.vendor = 0x001f;
m68kspkr_dev->id.product = 0x0001;
m68kspkr_dev->id.version = 0x0100;
m68kspkr_dev->evbit[0] = BIT(EV_SND); m68kspkr_platform_device = platform_device_alloc("m68kspkr", -1);
m68kspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); if (!m68kspkr_platform_device) {
m68kspkr_dev->event = m68kspkr_event; err = -ENOMEM;
goto err_unregister_driver;
}
input_register_device(m68kspkr_dev); err = platform_device_add(m68kspkr_platform_device);
if (err)
goto err_free_device;
return 0; return 0;
err_free_device:
platform_device_put(m68kspkr_platform_device);
err_unregister_driver:
platform_driver_unregister(&m68kspkr_platform_driver);
return err;
} }
static void __exit m68kspkr_exit(void) static void __exit m68kspkr_exit(void)
{ {
input_unregister_device(m68kspkr_dev); platform_device_unregister(m68kspkr_platform_device);
platform_driver_unregister(&m68kspkr_platform_driver);
} }
module_init(m68kspkr_init); module_init(m68kspkr_init);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/platform_device.h>
#include <asm/8253pit.h> #include <asm/8253pit.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -23,8 +24,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); ...@@ -23,8 +24,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("PC Speaker beeper driver"); MODULE_DESCRIPTION("PC Speaker beeper driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static struct input_dev *pcspkr_dev; static struct platform_device *pcspkr_platform_device;
static DEFINE_SPINLOCK(i8253_beep_lock); static DEFINE_SPINLOCK(i8253_beep_lock);
static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
...@@ -64,8 +64,11 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c ...@@ -64,8 +64,11 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c
return 0; return 0;
} }
static int __init pcspkr_init(void) static int __devinit pcspkr_probe(struct platform_device *dev)
{ {
struct input_dev *pcspkr_dev;
int err;
pcspkr_dev = input_allocate_device(); pcspkr_dev = input_allocate_device();
if (!pcspkr_dev) if (!pcspkr_dev)
return -ENOMEM; return -ENOMEM;
...@@ -76,22 +79,93 @@ static int __init pcspkr_init(void) ...@@ -76,22 +79,93 @@ static int __init pcspkr_init(void)
pcspkr_dev->id.vendor = 0x001f; pcspkr_dev->id.vendor = 0x001f;
pcspkr_dev->id.product = 0x0001; pcspkr_dev->id.product = 0x0001;
pcspkr_dev->id.version = 0x0100; pcspkr_dev->id.version = 0x0100;
pcspkr_dev->cdev.dev = &dev->dev;
pcspkr_dev->evbit[0] = BIT(EV_SND); pcspkr_dev->evbit[0] = BIT(EV_SND);
pcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); pcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
pcspkr_dev->event = pcspkr_event; pcspkr_dev->event = pcspkr_event;
input_register_device(pcspkr_dev); err = input_register_device(pcspkr_dev);
if (err) {
input_free_device(pcspkr_dev);
return err;
}
platform_set_drvdata(dev, pcspkr_dev);
return 0; return 0;
} }
static void __exit pcspkr_exit(void) static int __devexit pcspkr_remove(struct platform_device *dev)
{
struct input_dev *pcspkr_dev = platform_get_drvdata(dev);
input_unregister_device(pcspkr_dev);
platform_set_drvdata(dev, NULL);
/* turn off the speaker */
pcspkr_event(NULL, EV_SND, SND_BELL, 0);
return 0;
}
static int pcspkr_suspend(struct platform_device *dev, pm_message_t state)
{
pcspkr_event(NULL, EV_SND, SND_BELL, 0);
return 0;
}
static void pcspkr_shutdown(struct platform_device *dev)
{ {
input_unregister_device(pcspkr_dev);
/* turn off the speaker */ /* turn off the speaker */
pcspkr_event(NULL, EV_SND, SND_BELL, 0); pcspkr_event(NULL, EV_SND, SND_BELL, 0);
} }
static struct platform_driver pcspkr_platform_driver = {
.driver = {
.name = "pcspkr",
.owner = THIS_MODULE,
},
.probe = pcspkr_probe,
.remove = __devexit_p(pcspkr_remove),
.suspend = pcspkr_suspend,
.shutdown = pcspkr_shutdown,
};
static int __init pcspkr_init(void)
{
int err;
err = platform_driver_register(&pcspkr_platform_driver);
if (err)
return err;
pcspkr_platform_device = platform_device_alloc("pcspkr", -1);
if (!pcspkr_platform_device) {
err = -ENOMEM;
goto err_unregister_driver;
}
err = platform_device_add(pcspkr_platform_device);
if (err)
goto err_free_device;
return 0;
err_free_device:
platform_device_put(pcspkr_platform_device);
err_unregister_driver:
platform_driver_unregister(&pcspkr_platform_driver);
return err;
}
static void __exit pcspkr_exit(void)
{
platform_device_unregister(pcspkr_platform_device);
platform_driver_unregister(&pcspkr_platform_driver);
}
module_init(pcspkr_init); module_init(pcspkr_init);
module_exit(pcspkr_exit); module_exit(pcspkr_exit);
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/platform_device.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/ebus.h> #include <asm/ebus.h>
...@@ -20,22 +21,10 @@ MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); ...@@ -20,22 +21,10 @@ MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
MODULE_DESCRIPTION("Sparc Speaker beeper driver"); MODULE_DESCRIPTION("Sparc Speaker beeper driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
const char *beep_name;
static unsigned long beep_iobase; static unsigned long beep_iobase;
static struct input_dev *sparcspkr_dev; static int (*beep_event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
static DEFINE_SPINLOCK(beep_lock);
DEFINE_SPINLOCK(beep_lock);
static void __init init_sparcspkr_struct(void)
{
sparcspkr_dev->evbit[0] = BIT(EV_SND);
sparcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
sparcspkr_dev->phys = "sparc/input0";
sparcspkr_dev->id.bustype = BUS_ISA;
sparcspkr_dev->id.vendor = 0x001f;
sparcspkr_dev->id.product = 0x0001;
sparcspkr_dev->id.version = 0x0100;
}
static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{ {
...@@ -59,39 +48,16 @@ static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned in ...@@ -59,39 +48,16 @@ static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned in
/* EBUS speaker only has on/off state, the frequency does not /* EBUS speaker only has on/off state, the frequency does not
* appear to be programmable. * appear to be programmable.
*/ */
if (count) { if (beep_iobase & 0x2UL)
if (beep_iobase & 0x2UL) outb(!!count, beep_iobase);
outb(1, beep_iobase); else
else outl(!!count, beep_iobase);
outl(1, beep_iobase);
} else {
if (beep_iobase & 0x2UL)
outb(0, beep_iobase);
else
outl(0, beep_iobase);
}
spin_unlock_irqrestore(&beep_lock, flags); spin_unlock_irqrestore(&beep_lock, flags);
return 0; return 0;
} }
static int __init init_ebus_beep(struct linux_ebus_device *edev)
{
beep_iobase = edev->resource[0].start;
sparcspkr_dev = input_allocate_device();
if (!sparcspkr_dev)
return -ENOMEM;
sparcspkr_dev->name = "Sparc EBUS Speaker";
sparcspkr_dev->event = ebus_spkr_event;
input_register_device(sparcspkr_dev);
return 0;
}
#ifdef CONFIG_SPARC64 #ifdef CONFIG_SPARC64
static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{ {
...@@ -129,30 +95,103 @@ static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int ...@@ -129,30 +95,103 @@ static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int
return 0; return 0;
} }
#endif
static int __init init_isa_beep(struct sparc_isa_device *isa_dev) static int __devinit sparcspkr_probe(struct platform_device *dev)
{ {
beep_iobase = isa_dev->resource.start; struct input_dev *input_dev;
int error;
sparcspkr_dev = input_allocate_device(); input_dev = input_allocate_device();
if (!sparcspkr_dev) if (!input_dev)
return -ENOMEM; return -ENOMEM;
init_sparcspkr_struct(); input_dev->name = beep_name;
input_dev->phys = "sparc/input0";
input_dev->id.bustype = BUS_ISA;
input_dev->id.vendor = 0x001f;
input_dev->id.product = 0x0001;
input_dev->id.version = 0x0100;
input_dev->cdev.dev = &dev->dev;
sparcspkr_dev->name = "Sparc ISA Speaker"; input_dev->evbit[0] = BIT(EV_SND);
sparcspkr_dev->event = isa_spkr_event; input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
input_register_device(sparcspkr_dev); input_dev->event = beep_event;
error = input_register_device(input_dev);
if (error) {
input_free_device(input_dev);
return error;
}
platform_set_drvdata(dev, input_dev);
return 0; return 0;
} }
#endif
static int __devexit sparcspkr_remove(struct platform_device *dev)
{
struct input_dev *input_dev = platform_get_drvdata(dev);
input_unregister_device(input_dev);
platform_set_drvdata(dev, NULL);
/* turn off the speaker */
beep_event(NULL, EV_SND, SND_BELL, 0);
return 0;
}
static void sparcspkr_shutdown(struct platform_device *dev)
{
/* turn off the speaker */
beep_event(NULL, EV_SND, SND_BELL, 0);
}
static struct platform_driver sparcspkr_platform_driver = {
.driver = {
.name = "sparcspkr",
.owner = THIS_MODULE,
},
.probe = sparcspkr_probe,
.remove = __devexit_p(sparcspkr_remove),
.shutdown = sparcspkr_shutdown,
};
static struct platform_device *sparcspkr_platform_device;
static int __init sparcspkr_drv_init(void)
{
int error;
error = platform_driver_register(&sparcspkr_platform_driver);
if (error)
return error;
sparcspkr_platform_device = platform_device_alloc("sparcspkr", -1);
if (!sparcspkr_platform_device) {
error = -ENOMEM;
goto err_unregister_driver;
}
error = platform_device_add(sparcspkr_platform_device);
if (error)
goto err_free_device;
return 0;
err_free_device:
platform_device_put(sparcspkr_platform_device);
err_unregister_driver:
platform_driver_unregister(&sparcspkr_platform_driver);
return error;
}
static int __init sparcspkr_init(void) static int __init sparcspkr_init(void)
{ {
struct linux_ebus *ebus; struct linux_ebus *ebus;
struct linux_ebus_device *edev = NULL; struct linux_ebus_device *edev;
#ifdef CONFIG_SPARC64 #ifdef CONFIG_SPARC64
struct sparc_isa_bridge *isa_br; struct sparc_isa_bridge *isa_br;
struct sparc_isa_device *isa_dev; struct sparc_isa_device *isa_dev;
...@@ -160,8 +199,12 @@ static int __init sparcspkr_init(void) ...@@ -160,8 +199,12 @@ static int __init sparcspkr_init(void)
for_each_ebus(ebus) { for_each_ebus(ebus) {
for_each_ebusdev(edev, ebus) { for_each_ebusdev(edev, ebus) {
if (!strcmp(edev->prom_name, "beep")) if (!strcmp(edev->prom_name, "beep")) {
return init_ebus_beep(edev); beep_name = "Sparc EBUS Speaker";
beep_event = ebus_spkr_event;
beep_iobase = edev->resource[0].start;
return sparcspkr_drv_init();
}
} }
} }
#ifdef CONFIG_SPARC64 #ifdef CONFIG_SPARC64
...@@ -170,8 +213,12 @@ static int __init sparcspkr_init(void) ...@@ -170,8 +213,12 @@ static int __init sparcspkr_init(void)
/* A hack, the beep device's base lives in /* A hack, the beep device's base lives in
* the DMA isa node. * the DMA isa node.
*/ */
if (!strcmp(isa_dev->prom_name, "dma")) if (!strcmp(isa_dev->prom_name, "dma")) {
return init_isa_beep(isa_dev); beep_name = "Sparc ISA Speaker";
beep_event = isa_spkr_event,
beep_iobase = isa_dev->resource.start;
return sparcspkr_drv_init();
}
} }
} }
#endif #endif
...@@ -181,7 +228,8 @@ static int __init sparcspkr_init(void) ...@@ -181,7 +228,8 @@ static int __init sparcspkr_init(void)
static void __exit sparcspkr_exit(void) static void __exit sparcspkr_exit(void)
{ {
input_unregister_device(sparcspkr_dev); platform_device_unregister(sparcspkr_platform_device);
platform_driver_unregister(&sparcspkr_platform_driver);
} }
module_init(sparcspkr_init); module_init(sparcspkr_init);
......
...@@ -174,7 +174,7 @@ static u16 bios_pop_queue(void) ...@@ -174,7 +174,7 @@ static u16 bios_pop_queue(void)
return regs.eax; return regs.eax;
} }
static void __init bios_attach(void) static void __devinit bios_attach(void)
{ {
struct regs regs; struct regs regs;
...@@ -194,7 +194,7 @@ static void bios_detach(void) ...@@ -194,7 +194,7 @@ static void bios_detach(void)
call_bios(&regs); call_bios(&regs);
} }
static u8 __init bios_get_cmos_address(void) static u8 __devinit bios_get_cmos_address(void)
{ {
struct regs regs; struct regs regs;
...@@ -206,7 +206,7 @@ static u8 __init bios_get_cmos_address(void) ...@@ -206,7 +206,7 @@ static u8 __init bios_get_cmos_address(void)
return regs.ecx; return regs.ecx;
} }
static u16 __init bios_get_default_setting(u8 subsys) static u16 __devinit bios_get_default_setting(u8 subsys)
{ {
struct regs regs; struct regs regs;
...@@ -296,6 +296,16 @@ static struct key_entry keymap_acer_aspire_1500[] = { ...@@ -296,6 +296,16 @@ static struct key_entry keymap_acer_aspire_1500[] = {
{ KE_END, 0 } { KE_END, 0 }
}; };
static struct key_entry keymap_acer_travelmate_240[] = {
{ KE_KEY, 0x31, KEY_MAIL },
{ KE_KEY, 0x36, KEY_WWW },
{ KE_KEY, 0x11, KEY_PROG1 },
{ KE_KEY, 0x12, KEY_PROG2 },
{ KE_BLUETOOTH, 0x44, 0 },
{ KE_WIFI, 0x30, 0 },
{ KE_END, 0 }
};
/* /*
* If your machine is not here (which is currently rather likely), please send * If your machine is not here (which is currently rather likely), please send
* a list of buttons and their key codes (reported when loading this module * a list of buttons and their key codes (reported when loading this module
...@@ -320,6 +330,15 @@ static struct dmi_system_id dmi_ids[] = { ...@@ -320,6 +330,15 @@ static struct dmi_system_id dmi_ids[] = {
}, },
.driver_data = keymap_acer_aspire_1500 .driver_data = keymap_acer_aspire_1500
}, },
{
.callback = dmi_matched,
.ident = "Acer TravelMate 240",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 240"),
},
.driver_data = keymap_acer_travelmate_240
},
{ NULL, } { NULL, }
}; };
...@@ -348,7 +367,7 @@ static int __init select_keymap(void) ...@@ -348,7 +367,7 @@ static int __init select_keymap(void)
static struct input_dev *input_dev; static struct input_dev *input_dev;
static int __init setup_input_dev(void) static int __devinit setup_input_dev(void)
{ {
const struct key_entry *key; const struct key_entry *key;
int error; int error;
...@@ -447,6 +466,52 @@ static void poll_bios(unsigned long discard) ...@@ -447,6 +466,52 @@ static void poll_bios(unsigned long discard)
mod_timer(&poll_timer, jiffies + HZ / POLL_FREQUENCY); mod_timer(&poll_timer, jiffies + HZ / POLL_FREQUENCY);
} }
static int __devinit wistron_probe(struct platform_device *dev)
{
int err = setup_input_dev();
if (err)
return err;
bios_attach();
cmos_address = bios_get_cmos_address();
if (have_wifi) {
u16 wifi = bios_get_default_setting(WIFI);
if (wifi & 1)
wifi_enabled = (wifi & 2) ? 1 : 0;
else
have_wifi = 0;
if (have_wifi)
bios_set_state(WIFI, wifi_enabled);
}
if (have_bluetooth) {
u16 bt = bios_get_default_setting(BLUETOOTH);
if (bt & 1)
bluetooth_enabled = (bt & 2) ? 1 : 0;
else
have_bluetooth = 0;
if (have_bluetooth)
bios_set_state(BLUETOOTH, bluetooth_enabled);
}
poll_bios(1); /* Flush stale event queue and arm timer */
return 0;
}
static int __devexit wistron_remove(struct platform_device *dev)
{
del_timer_sync(&poll_timer);
input_unregister_device(input_dev);
bios_detach();
return 0;
}
#ifdef CONFIG_PM
static int wistron_suspend(struct platform_device *dev, pm_message_t state) static int wistron_suspend(struct platform_device *dev, pm_message_t state)
{ {
del_timer_sync(&poll_timer); del_timer_sync(&poll_timer);
...@@ -472,13 +537,20 @@ static int wistron_resume(struct platform_device *dev) ...@@ -472,13 +537,20 @@ static int wistron_resume(struct platform_device *dev)
return 0; return 0;
} }
#else
#define wistron_suspend NULL
#define wistron_resume NULL
#endif
static struct platform_driver wistron_driver = { static struct platform_driver wistron_driver = {
.suspend = wistron_suspend,
.resume = wistron_resume,
.driver = { .driver = {
.name = "wistron-bios", .name = "wistron-bios",
.owner = THIS_MODULE,
}, },
.probe = wistron_probe,
.remove = __devexit_p(wistron_remove),
.suspend = wistron_suspend,
.resume = wistron_resume,
}; };
static int __init wb_module_init(void) static int __init wb_module_init(void)
...@@ -493,55 +565,27 @@ static int __init wb_module_init(void) ...@@ -493,55 +565,27 @@ static int __init wb_module_init(void)
if (err) if (err)
return err; return err;
bios_attach();
cmos_address = bios_get_cmos_address();
err = platform_driver_register(&wistron_driver); err = platform_driver_register(&wistron_driver);
if (err) if (err)
goto err_detach_bios; goto err_unmap_bios;
wistron_device = platform_device_register_simple("wistron-bios", -1, NULL, 0); wistron_device = platform_device_alloc("wistron-bios", -1);
if (IS_ERR(wistron_device)) { if (!wistron_device) {
err = PTR_ERR(wistron_device); err = -ENOMEM;
goto err_unregister_driver; goto err_unregister_driver;
} }
if (have_wifi) { err = platform_device_add(wistron_device);
u16 wifi = bios_get_default_setting(WIFI);
if (wifi & 1)
wifi_enabled = (wifi & 2) ? 1 : 0;
else
have_wifi = 0;
if (have_wifi)
bios_set_state(WIFI, wifi_enabled);
}
if (have_bluetooth) {
u16 bt = bios_get_default_setting(BLUETOOTH);
if (bt & 1)
bluetooth_enabled = (bt & 2) ? 1 : 0;
else
have_bluetooth = 0;
if (have_bluetooth)
bios_set_state(BLUETOOTH, bluetooth_enabled);
}
err = setup_input_dev();
if (err) if (err)
goto err_unregister_device; goto err_free_device;
poll_bios(1); /* Flush stale event queue and arm timer */
return 0; return 0;
err_unregister_device: err_free_device:
platform_device_unregister(wistron_device); platform_device_put(wistron_device);
err_unregister_driver: err_unregister_driver:
platform_driver_unregister(&wistron_driver); platform_driver_unregister(&wistron_driver);
err_detach_bios: err_unmap_bios:
bios_detach();
unmap_bios(); unmap_bios();
return err; return err;
...@@ -549,11 +593,8 @@ static int __init wb_module_init(void) ...@@ -549,11 +593,8 @@ static int __init wb_module_init(void)
static void __exit wb_module_exit(void) static void __exit wb_module_exit(void)
{ {
del_timer_sync(&poll_timer);
input_unregister_device(input_dev);
platform_device_unregister(wistron_device); platform_device_unregister(wistron_device);
platform_driver_unregister(&wistron_driver); platform_driver_unregister(&wistron_driver);
bios_detach();
unmap_bios(); unmap_bios();
} }
......
...@@ -40,6 +40,7 @@ static struct alps_model_info alps_model_data[] = { ...@@ -40,6 +40,7 @@ static struct alps_model_info alps_model_data[] = {
{ { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */
{ { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, { { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
{ { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, { { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
{ { 0x60, 0x03, 0xc8 }, 0xf8, 0xf8, 0 }, /* HP ze1115 */
{ { 0x63, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, { { 0x63, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
{ { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, { { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
{ { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */
......
...@@ -27,6 +27,13 @@ static struct dmi_system_id lifebook_dmi_table[] = { ...@@ -27,6 +27,13 @@ static struct dmi_system_id lifebook_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"), DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"),
}, },
}, },
{
.ident = "Lifebook B142",
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"),
},
},
{ } { }
}; };
......
...@@ -226,7 +226,9 @@ static struct ps2pp_info *get_model_info(unsigned char model) ...@@ -226,7 +226,9 @@ static struct ps2pp_info *get_model_info(unsigned char model)
{ 80, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL }, { 80, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL },
{ 81, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, { 81, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 83, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, { 83, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 85, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 86, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, { 86, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 87, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 88, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, { 88, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 96, 0, 0 }, { 96, 0, 0 },
{ 97, PS2PP_KIND_TP3, PS2PP_WHEEL | PS2PP_HWHEEL }, { 97, PS2PP_KIND_TP3, PS2PP_WHEEL | PS2PP_HWHEEL },
......
...@@ -527,11 +527,15 @@ static int psmouse_extensions(struct psmouse *psmouse, ...@@ -527,11 +527,15 @@ static int psmouse_extensions(struct psmouse *psmouse,
if (max_proto > PSMOUSE_IMEX && ps2pp_init(psmouse, set_properties) == 0) if (max_proto > PSMOUSE_IMEX && ps2pp_init(psmouse, set_properties) == 0)
return PSMOUSE_PS2PP; return PSMOUSE_PS2PP;
if (max_proto > PSMOUSE_IMEX && trackpoint_detect(psmouse, set_properties) == 0)
return PSMOUSE_TRACKPOINT;
/* /*
* Reset to defaults in case the device got confused by extended * Reset to defaults in case the device got confused by extended
* protocol probes. * protocol probes. Note that we do full reset becuase some mice
* put themselves to sleep when see PSMOUSE_RESET_DIS.
*/ */
ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); psmouse_reset(psmouse);
if (max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse, set_properties) == 0) if (max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse, set_properties) == 0)
return PSMOUSE_IMEX; return PSMOUSE_IMEX;
...@@ -539,12 +543,6 @@ static int psmouse_extensions(struct psmouse *psmouse, ...@@ -539,12 +543,6 @@ static int psmouse_extensions(struct psmouse *psmouse,
if (max_proto >= PSMOUSE_IMPS && intellimouse_detect(psmouse, set_properties) == 0) if (max_proto >= PSMOUSE_IMPS && intellimouse_detect(psmouse, set_properties) == 0)
return PSMOUSE_IMPS; return PSMOUSE_IMPS;
/*
* Try to initialize the IBM TrackPoint
*/
if (max_proto > PSMOUSE_IMEX && trackpoint_detect(psmouse, set_properties) == 0)
return PSMOUSE_TRACKPOINT;
/* /*
* Okay, all failed, we have a standard mouse here. The number of the buttons * Okay, all failed, we have a standard mouse here. The number of the buttons
* is still a question, though. We assume 3. * is still a question, though. We assume 3.
...@@ -559,7 +557,6 @@ static int psmouse_extensions(struct psmouse *psmouse, ...@@ -559,7 +557,6 @@ static int psmouse_extensions(struct psmouse *psmouse,
* extensions. * extensions.
*/ */
psmouse_reset(psmouse); psmouse_reset(psmouse);
ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
} }
return PSMOUSE_PS2; return PSMOUSE_PS2;
......
...@@ -40,15 +40,15 @@ MODULE_LICENSE("GPL"); ...@@ -40,15 +40,15 @@ MODULE_LICENSE("GPL");
#endif #endif
static int xres = CONFIG_INPUT_MOUSEDEV_SCREEN_X; static int xres = CONFIG_INPUT_MOUSEDEV_SCREEN_X;
module_param(xres, uint, 0); module_param(xres, uint, 0644);
MODULE_PARM_DESC(xres, "Horizontal screen resolution"); MODULE_PARM_DESC(xres, "Horizontal screen resolution");
static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y; static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y;
module_param(yres, uint, 0); module_param(yres, uint, 0644);
MODULE_PARM_DESC(yres, "Vertical screen resolution"); MODULE_PARM_DESC(yres, "Vertical screen resolution");
static unsigned tap_time = 200; static unsigned tap_time = 200;
module_param(tap_time, uint, 0); module_param(tap_time, uint, 0644);
MODULE_PARM_DESC(tap_time, "Tap time for touchpads in absolute mode (msecs)"); MODULE_PARM_DESC(tap_time, "Tap time for touchpads in absolute mode (msecs)");
struct mousedev_hw_data { struct mousedev_hw_data {
...@@ -155,7 +155,7 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, ...@@ -155,7 +155,7 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev,
switch (code) { switch (code) {
case ABS_X: case ABS_X:
size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
if (size == 0) size = xres; if (size == 0) size = xres ? : 1;
if (value > dev->absmax[ABS_X]) value = dev->absmax[ABS_X]; if (value > dev->absmax[ABS_X]) value = dev->absmax[ABS_X];
if (value < dev->absmin[ABS_X]) value = dev->absmin[ABS_X]; if (value < dev->absmin[ABS_X]) value = dev->absmin[ABS_X];
mousedev->packet.x = ((value - dev->absmin[ABS_X]) * xres) / size; mousedev->packet.x = ((value - dev->absmin[ABS_X]) * xres) / size;
...@@ -164,7 +164,7 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, ...@@ -164,7 +164,7 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev,
case ABS_Y: case ABS_Y:
size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y]; size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y];
if (size == 0) size = yres; if (size == 0) size = yres ? : 1;
if (value > dev->absmax[ABS_Y]) value = dev->absmax[ABS_Y]; if (value > dev->absmax[ABS_Y]) value = dev->absmax[ABS_Y];
if (value < dev->absmin[ABS_Y]) value = dev->absmin[ABS_Y]; if (value < dev->absmin[ABS_Y]) value = dev->absmin[ABS_Y];
mousedev->packet.y = yres - ((value - dev->absmin[ABS_Y]) * yres) / size; mousedev->packet.y = yres - ((value - dev->absmin[ABS_Y]) * yres) / size;
......
...@@ -154,7 +154,7 @@ static int ct82c710_write(struct serio *port, unsigned char c) ...@@ -154,7 +154,7 @@ static int ct82c710_write(struct serio *port, unsigned char c)
* See if we can find a 82C710 device. Read mouse address. * See if we can find a 82C710 device. Read mouse address.
*/ */
static int __init ct82c710_probe(void) static int __init ct82c710_detect(void)
{ {
outb_p(0x55, 0x2fa); /* Any value except 9, ff or 36 */ outb_p(0x55, 0x2fa); /* Any value except 9, ff or 36 */
outb_p(0xaa, 0x3fa); /* Inverse of 55 */ outb_p(0xaa, 0x3fa); /* Inverse of 55 */
...@@ -163,7 +163,7 @@ static int __init ct82c710_probe(void) ...@@ -163,7 +163,7 @@ static int __init ct82c710_probe(void)
outb_p(0x1b, 0x2fa); /* Inverse of e4 */ outb_p(0x1b, 0x2fa); /* Inverse of e4 */
outb_p(0x0f, 0x390); /* Write index */ outb_p(0x0f, 0x390); /* Write index */
if (inb_p(0x391) != 0xe4) /* Config address found? */ if (inb_p(0x391) != 0xe4) /* Config address found? */
return -1; /* No: no 82C710 here */ return -ENODEV; /* No: no 82C710 here */
outb_p(0x0d, 0x390); /* Write index */ outb_p(0x0d, 0x390); /* Write index */
ct82c710_iores.start = inb_p(0x391) << 2; /* Get mouse I/O address */ ct82c710_iores.start = inb_p(0x391) << 2; /* Get mouse I/O address */
...@@ -175,51 +175,88 @@ static int __init ct82c710_probe(void) ...@@ -175,51 +175,88 @@ static int __init ct82c710_probe(void)
return 0; return 0;
} }
static struct serio * __init ct82c710_allocate_port(void) static int __devinit ct82c710_probe(struct platform_device *dev)
{ {
struct serio *serio; ct82c710_port = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!ct82c710_port)
serio = kmalloc(sizeof(struct serio), GFP_KERNEL); return -ENOMEM;
if (serio) {
memset(serio, 0, sizeof(struct serio)); ct82c710_port->id.type = SERIO_8042;
serio->id.type = SERIO_8042; ct82c710_port->dev.parent = &dev->dev;
serio->open = ct82c710_open; ct82c710_port->open = ct82c710_open;
serio->close = ct82c710_close; ct82c710_port->close = ct82c710_close;
serio->write = ct82c710_write; ct82c710_port->write = ct82c710_write;
serio->dev.parent = &ct82c710_device->dev; strlcpy(ct82c710_port->name, "C&T 82c710 mouse port",
strlcpy(serio->name, "C&T 82c710 mouse port", sizeof(serio->name)); sizeof(ct82c710_port->name));
snprintf(serio->phys, sizeof(serio->phys), "isa%04lx/serio0", CT82C710_DATA); snprintf(ct82c710_port->phys, sizeof(ct82c710_port->phys),
} "isa%04lx/serio0", CT82C710_DATA);
serio_register_port(ct82c710_port);
return 0;
}
static int __devexit ct82c710_remove(struct platform_device *dev)
{
serio_unregister_port(ct82c710_port);
return serio; return 0;
} }
static struct platform_driver ct82c710_driver = {
.driver = {
.name = "ct82c710",
.owner = THIS_MODULE,
},
.probe = ct82c710_probe,
.remove = __devexit_p(ct82c710_remove),
};
static int __init ct82c710_init(void) static int __init ct82c710_init(void)
{ {
if (ct82c710_probe()) int error;
return -ENODEV;
ct82c710_device = platform_device_register_simple("ct82c710", -1, &ct82c710_iores, 1); error = ct82c710_detect();
if (IS_ERR(ct82c710_device)) if (error)
return PTR_ERR(ct82c710_device); return error;
if (!(ct82c710_port = ct82c710_allocate_port())) { error = platform_driver_register(&ct82c710_driver);
platform_device_unregister(ct82c710_device); if (error)
return -ENOMEM; return error;
ct82c710_device = platform_device_alloc("ct82c710", -1);
if (!ct82c710_device) {
error = -ENOMEM;
goto err_unregister_driver;
} }
error = platform_device_add_resources(ct82c710_device, &ct82c710_iores, 1);
if (error)
goto err_free_device;
error = platform_device_add(ct82c710_device);
if (error)
goto err_free_device;
serio_register_port(ct82c710_port); serio_register_port(ct82c710_port);
printk(KERN_INFO "serio: C&T 82c710 mouse port at %#lx irq %d\n", printk(KERN_INFO "serio: C&T 82c710 mouse port at %#lx irq %d\n",
CT82C710_DATA, CT82C710_IRQ); CT82C710_DATA, CT82C710_IRQ);
return 0; return 0;
err_free_device:
platform_device_put(ct82c710_device);
err_unregister_driver:
platform_driver_unregister(&ct82c710_driver);
return error;
} }
static void __exit ct82c710_exit(void) static void __exit ct82c710_exit(void)
{ {
serio_unregister_port(ct82c710_port);
platform_device_unregister(ct82c710_device); platform_device_unregister(ct82c710_device);
platform_driver_unregister(&ct82c710_driver);
} }
module_init(ct82c710_init); module_init(ct82c710_init);
......
...@@ -84,6 +84,14 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { ...@@ -84,6 +84,14 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
DMI_MATCH(DMI_PRODUCT_VERSION, "DL760"), DMI_MATCH(DMI_PRODUCT_VERSION, "DL760"),
}, },
}, },
{
.ident = "OQO Model 01",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "OQO"),
DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"),
DMI_MATCH(DMI_PRODUCT_VERSION, "00"),
},
},
{ } { }
}; };
...@@ -158,6 +166,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { ...@@ -158,6 +166,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Sentia"), DMI_MATCH(DMI_PRODUCT_NAME, "Sentia"),
}, },
}, },
{
.ident = "Sharp Actius MM20",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "SHARP"),
DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"),
},
},
{ } { }
}; };
......
...@@ -572,7 +572,7 @@ static int i8042_enable_mux_ports(void) ...@@ -572,7 +572,7 @@ static int i8042_enable_mux_ports(void)
* LCS/Telegraphics. * LCS/Telegraphics.
*/ */
static int __init i8042_check_mux(void) static int __devinit i8042_check_mux(void)
{ {
unsigned char mux_version; unsigned char mux_version;
...@@ -600,7 +600,7 @@ static int __init i8042_check_mux(void) ...@@ -600,7 +600,7 @@ static int __init i8042_check_mux(void)
* the presence of an AUX interface. * the presence of an AUX interface.
*/ */
static int __init i8042_check_aux(void) static int __devinit i8042_check_aux(void)
{ {
unsigned char param; unsigned char param;
static int i8042_check_aux_cookie; static int i8042_check_aux_cookie;
...@@ -678,7 +678,7 @@ static int __init i8042_check_aux(void) ...@@ -678,7 +678,7 @@ static int __init i8042_check_aux(void)
* registers it, and reports to the user. * registers it, and reports to the user.
*/ */
static int __init i8042_port_register(struct i8042_port *port) static int __devinit i8042_port_register(struct i8042_port *port)
{ {
i8042_ctr &= ~port->disable; i8042_ctr &= ~port->disable;
...@@ -956,7 +956,6 @@ static int i8042_resume(struct platform_device *dev) ...@@ -956,7 +956,6 @@ static int i8042_resume(struct platform_device *dev)
panic_blink = i8042_panic_blink; panic_blink = i8042_panic_blink;
return 0; return 0;
} }
/* /*
...@@ -969,16 +968,7 @@ static void i8042_shutdown(struct platform_device *dev) ...@@ -969,16 +968,7 @@ static void i8042_shutdown(struct platform_device *dev)
i8042_controller_cleanup(); i8042_controller_cleanup();
} }
static struct platform_driver i8042_driver = { static int __devinit i8042_create_kbd_port(void)
.suspend = i8042_suspend,
.resume = i8042_resume,
.shutdown = i8042_shutdown,
.driver = {
.name = "i8042",
},
};
static int __init i8042_create_kbd_port(void)
{ {
struct serio *serio; struct serio *serio;
struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO];
...@@ -1003,7 +993,7 @@ static int __init i8042_create_kbd_port(void) ...@@ -1003,7 +993,7 @@ static int __init i8042_create_kbd_port(void)
return i8042_port_register(port); return i8042_port_register(port);
} }
static int __init i8042_create_aux_port(void) static int __devinit i8042_create_aux_port(void)
{ {
struct serio *serio; struct serio *serio;
struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO]; struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO];
...@@ -1028,7 +1018,7 @@ static int __init i8042_create_aux_port(void) ...@@ -1028,7 +1018,7 @@ static int __init i8042_create_aux_port(void)
return i8042_port_register(port); return i8042_port_register(port);
} }
static int __init i8042_create_mux_port(int index) static int __devinit i8042_create_mux_port(int index)
{ {
struct serio *serio; struct serio *serio;
struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index]; struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index];
...@@ -1057,37 +1047,16 @@ static int __init i8042_create_mux_port(int index) ...@@ -1057,37 +1047,16 @@ static int __init i8042_create_mux_port(int index)
return i8042_port_register(port); return i8042_port_register(port);
} }
static int __init i8042_init(void) static int __devinit i8042_probe(struct platform_device *dev)
{ {
int i, have_ports = 0; int i, have_ports = 0;
int err; int err;
dbg_init();
init_timer(&i8042_timer); init_timer(&i8042_timer);
i8042_timer.function = i8042_timer_func; i8042_timer.function = i8042_timer_func;
err = i8042_platform_init(); if (i8042_controller_init())
if (err) return -ENODEV;
return err;
i8042_ports[I8042_AUX_PORT_NO].irq = I8042_AUX_IRQ;
i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ;
if (i8042_controller_init()) {
err = -ENODEV;
goto err_platform_exit;
}
err = platform_driver_register(&i8042_driver);
if (err)
goto err_controller_cleanup;
i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0);
if (IS_ERR(i8042_platform_device)) {
err = PTR_ERR(i8042_platform_device);
goto err_unregister_driver;
}
if (!i8042_noaux && !i8042_check_aux()) { if (!i8042_noaux && !i8042_check_aux()) {
if (!i8042_nomux && !i8042_check_mux()) { if (!i8042_nomux && !i8042_check_mux()) {
...@@ -1113,30 +1082,23 @@ static int __init i8042_init(void) ...@@ -1113,30 +1082,23 @@ static int __init i8042_init(void)
if (!have_ports) { if (!have_ports) {
err = -ENODEV; err = -ENODEV;
goto err_unregister_device; goto err_controller_cleanup;
} }
mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
return 0; return 0;
err_unregister_ports: err_unregister_ports:
for (i = 0; i < I8042_NUM_PORTS; i++) for (i = 0; i < I8042_NUM_PORTS; i++)
if (i8042_ports[i].serio) if (i8042_ports[i].serio)
serio_unregister_port(i8042_ports[i].serio); serio_unregister_port(i8042_ports[i].serio);
err_unregister_device:
platform_device_unregister(i8042_platform_device);
err_unregister_driver:
platform_driver_unregister(&i8042_driver);
err_controller_cleanup: err_controller_cleanup:
i8042_controller_cleanup(); i8042_controller_cleanup();
err_platform_exit:
i8042_platform_exit();
return err; return err;
} }
static void __exit i8042_exit(void) static int __devexit i8042_remove(struct platform_device *dev)
{ {
int i; int i;
...@@ -1148,6 +1110,62 @@ static void __exit i8042_exit(void) ...@@ -1148,6 +1110,62 @@ static void __exit i8042_exit(void)
del_timer_sync(&i8042_timer); del_timer_sync(&i8042_timer);
return 0;
}
static struct platform_driver i8042_driver = {
.driver = {
.name = "i8042",
.owner = THIS_MODULE,
},
.probe = i8042_probe,
.remove = __devexit_p(i8042_remove),
.suspend = i8042_suspend,
.resume = i8042_resume,
.shutdown = i8042_shutdown,
};
static int __init i8042_init(void)
{
int err;
dbg_init();
err = i8042_platform_init();
if (err)
return err;
i8042_ports[I8042_AUX_PORT_NO].irq = I8042_AUX_IRQ;
i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ;
err = platform_driver_register(&i8042_driver);
if (err)
goto err_platform_exit;
i8042_platform_device = platform_device_alloc("i8042", -1);
if (!i8042_platform_device) {
err = -ENOMEM;
goto err_unregister_driver;
}
err = platform_device_add(i8042_platform_device);
if (err)
goto err_free_device;
return 0;
err_free_device:
platform_device_put(i8042_platform_device);
err_unregister_driver:
platform_driver_unregister(&i8042_driver);
err_platform_exit:
i8042_platform_exit();
return err;
}
static void __exit i8042_exit(void)
{
platform_device_unregister(i8042_platform_device); platform_device_unregister(i8042_platform_device);
platform_driver_unregister(&i8042_driver); platform_driver_unregister(&i8042_driver);
......
...@@ -118,13 +118,12 @@ static void maceps2_close(struct serio *dev) ...@@ -118,13 +118,12 @@ static void maceps2_close(struct serio *dev)
} }
static struct serio * __init maceps2_allocate_port(int idx) static struct serio * __devinit maceps2_allocate_port(int idx)
{ {
struct serio *serio; struct serio *serio;
serio = kmalloc(sizeof(struct serio), GFP_KERNEL); serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) { if (serio) {
memset(serio, 0, sizeof(struct serio));
serio->id.type = SERIO_8042; serio->id.type = SERIO_8042;
serio->write = maceps2_write; serio->write = maceps2_write;
serio->open = maceps2_open; serio->open = maceps2_open;
...@@ -138,24 +137,13 @@ static struct serio * __init maceps2_allocate_port(int idx) ...@@ -138,24 +137,13 @@ static struct serio * __init maceps2_allocate_port(int idx)
return serio; return serio;
} }
static int __devinit maceps2_probe(struct platform_device *dev)
static int __init maceps2_init(void)
{ {
maceps2_device = platform_device_register_simple("maceps2", -1, NULL, 0);
if (IS_ERR(maceps2_device))
return PTR_ERR(maceps2_device);
port_data[0].port = &mace->perif.ps2.keyb;
port_data[0].irq = MACEISA_KEYB_IRQ;
port_data[1].port = &mace->perif.ps2.mouse;
port_data[1].irq = MACEISA_MOUSE_IRQ;
maceps2_port[0] = maceps2_allocate_port(0); maceps2_port[0] = maceps2_allocate_port(0);
maceps2_port[1] = maceps2_allocate_port(1); maceps2_port[1] = maceps2_allocate_port(1);
if (!maceps2_port[0] || !maceps2_port[1]) { if (!maceps2_port[0] || !maceps2_port[1]) {
kfree(maceps2_port[0]); kfree(maceps2_port[0]);
kfree(maceps2_port[1]); kfree(maceps2_port[1]);
platform_device_unregister(maceps2_device);
return -ENOMEM; return -ENOMEM;
} }
...@@ -165,11 +153,59 @@ static int __init maceps2_init(void) ...@@ -165,11 +153,59 @@ static int __init maceps2_init(void)
return 0; return 0;
} }
static void __exit maceps2_exit(void) static int __devexit maceps2_remove(struct platform_device *dev)
{ {
serio_unregister_port(maceps2_port[0]); serio_unregister_port(maceps2_port[0]);
serio_unregister_port(maceps2_port[1]); serio_unregister_port(maceps2_port[1]);
return 0;
}
static struct platform_driver maceps2_driver = {
.driver = {
.name = "maceps2",
.owner = THIS_MODULE,
},
.probe = maceps2_probe,
.remove = __devexit_p(maceps2_remove),
};
static int __init maceps2_init(void)
{
int error;
error = platform_driver_register(&maceps2_driver);
if (error)
return error;
maceps2_device = platform_device_alloc("maceps2", -1);
if (!maceps2_device) {
error = -ENOMEM;
goto err_unregister_driver;
}
port_data[0].port = &mace->perif.ps2.keyb;
port_data[0].irq = MACEISA_KEYB_IRQ;
port_data[1].port = &mace->perif.ps2.mouse;
port_data[1].irq = MACEISA_MOUSE_IRQ;
error = platform_device_add(maceps2_device);
if (error)
goto err_free_device;
return 0;
err_free_device:
platform_device_put(maceps2_device);
err_unregister_driver:
platform_driver_unregister(&maceps2_driver);
return error;
}
static void __exit maceps2_exit(void)
{
platform_device_unregister(maceps2_device); platform_device_unregister(maceps2_device);
platform_driver_unregister(&maceps2_driver);
} }
module_init(maceps2_init); module_init(maceps2_init);
......
...@@ -75,13 +75,13 @@ static irqreturn_t q40kbd_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -75,13 +75,13 @@ static irqreturn_t q40kbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static void q40kbd_flush(void) static void q40kbd_flush(void)
{ {
int maxread = 100; int maxread = 100;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&q40kbd_lock, flags); spin_lock_irqsave(&q40kbd_lock, flags);
while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG))) while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)))
master_inb(KEYCODE_REG); master_inb(KEYCODE_REG);
spin_unlock_irqrestore(&q40kbd_lock, flags); spin_unlock_irqrestore(&q40kbd_lock, flags);
} }
...@@ -97,14 +97,14 @@ static int q40kbd_open(struct serio *port) ...@@ -97,14 +97,14 @@ static int q40kbd_open(struct serio *port)
if (request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, "q40kbd", NULL)) { if (request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, "q40kbd", NULL)) {
printk(KERN_ERR "q40kbd.c: Can't get irq %d.\n", Q40_IRQ_KEYBOARD); printk(KERN_ERR "q40kbd.c: Can't get irq %d.\n", Q40_IRQ_KEYBOARD);
return -1; return -EBUSY;
} }
/* off we go */ /* off we go */
master_outb(-1, KEYBOARD_UNLOCK_REG); master_outb(-1, KEYBOARD_UNLOCK_REG);
master_outb(1, KEY_IRQ_ENABLE_REG); master_outb(1, KEY_IRQ_ENABLE_REG);
return 0; return 0;
} }
static void q40kbd_close(struct serio *port) static void q40kbd_close(struct serio *port)
...@@ -116,48 +116,73 @@ static void q40kbd_close(struct serio *port) ...@@ -116,48 +116,73 @@ static void q40kbd_close(struct serio *port)
q40kbd_flush(); q40kbd_flush();
} }
static struct serio * __init q40kbd_allocate_port(void) static int __devinit q40kbd_probe(struct platform_device *dev)
{ {
struct serio *serio; q40kbd_port = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!q40kbd_port)
serio = kmalloc(sizeof(struct serio), GFP_KERNEL); return -ENOMEM;
if (serio) {
memset(serio, 0, sizeof(struct serio)); q40kbd_port->id.type = SERIO_8042;
serio->id.type = SERIO_8042; q40kbd_port->open = q40kbd_open;
serio->open = q40kbd_open; q40kbd_port->close = q40kbd_close;
serio->close = q40kbd_close; q40kbd_port->dev.parent = &dev->dev;
serio->dev.parent = &q40kbd_device->dev; strlcpy(q40kbd_port->name, "Q40 Kbd Port", sizeof(q40kbd_port->name));
strlcpy(serio->name, "Q40 Kbd Port", sizeof(serio->name)); strlcpy(q40kbd_port->phys, "Q40", sizeof(q40kbd_port->phys));
strlcpy(serio->phys, "Q40", sizeof(serio->phys));
} serio_register_port(q40kbd_port);
printk(KERN_INFO "serio: Q40 kbd registered\n");
return serio; return 0;
} }
static int __devexit q40kbd_remove(struct platform_device *dev)
{
serio_unregister_port(q40kbd_port);
return 0;
}
static struct platform_driver q40kbd_driver = {
.driver = {
.name = "q40kbd",
.owner = THIS_MODULE,
},
.probe = q40kbd_probe,
.remove = __devexit_p(q40kbd_remove),
};
static int __init q40kbd_init(void) static int __init q40kbd_init(void)
{ {
int error;
if (!MACH_IS_Q40) if (!MACH_IS_Q40)
return -EIO; return -EIO;
q40kbd_device = platform_device_register_simple("q40kbd", -1, NULL, 0); error = platform_driver_register(&q40kbd_driver);
if (IS_ERR(q40kbd_device)) if (error)
return PTR_ERR(q40kbd_device); return error;
if (!(q40kbd_port = q40kbd_allocate_port())) { q40kbd_device = platform_device_alloc("q40kbd", -1);
platform_device_unregister(q40kbd_device); if (!q40kbd_device)
return -ENOMEM; goto err_unregister_driver;
}
serio_register_port(q40kbd_port); error = platform_device_add(q40kbd_device);
printk(KERN_INFO "serio: Q40 kbd registered\n"); if (error)
goto err_free_device;
return 0; return 0;
err_free_device:
platform_device_put(q40kbd_device);
err_unregister_driver:
platform_driver_unregister(&q40kbd_driver);
return error;
} }
static void __exit q40kbd_exit(void) static void __exit q40kbd_exit(void)
{ {
serio_unregister_port(q40kbd_port);
platform_device_unregister(q40kbd_device); platform_device_unregister(q40kbd_device);
platform_driver_unregister(&q40kbd_driver);
} }
module_init(q40kbd_init); module_init(q40kbd_init);
......
...@@ -141,8 +141,8 @@ struct reverse_heartbeat { ...@@ -141,8 +141,8 @@ struct reverse_heartbeat {
}; };
struct ibmasm_remote { struct ibmasm_remote {
struct input_dev keybd_dev; struct input_dev *keybd_dev;
struct input_dev mouse_dev; struct input_dev *mouse_dev;
}; };
struct service_processor { struct service_processor {
...@@ -157,7 +157,7 @@ struct service_processor { ...@@ -157,7 +157,7 @@ struct service_processor {
char dirname[IBMASM_NAME_SIZE]; char dirname[IBMASM_NAME_SIZE];
char devname[IBMASM_NAME_SIZE]; char devname[IBMASM_NAME_SIZE];
unsigned int number; unsigned int number;
struct ibmasm_remote *remote; struct ibmasm_remote remote;
int serial_line; int serial_line;
struct device *dev; struct device *dev;
}; };
......
...@@ -203,9 +203,9 @@ void ibmasm_handle_mouse_interrupt(struct service_processor *sp, ...@@ -203,9 +203,9 @@ void ibmasm_handle_mouse_interrupt(struct service_processor *sp,
print_input(&input); print_input(&input);
if (input.type == INPUT_TYPE_MOUSE) { if (input.type == INPUT_TYPE_MOUSE) {
send_mouse_event(&sp->remote->mouse_dev, regs, &input); send_mouse_event(sp->remote.mouse_dev, regs, &input);
} else if (input.type == INPUT_TYPE_KEYBOARD) { } else if (input.type == INPUT_TYPE_KEYBOARD) {
send_keyboard_event(&sp->remote->keybd_dev, regs, &input); send_keyboard_event(sp->remote.keybd_dev, regs, &input);
} else } else
break; break;
...@@ -217,56 +217,70 @@ void ibmasm_handle_mouse_interrupt(struct service_processor *sp, ...@@ -217,56 +217,70 @@ void ibmasm_handle_mouse_interrupt(struct service_processor *sp,
int ibmasm_init_remote_input_dev(struct service_processor *sp) int ibmasm_init_remote_input_dev(struct service_processor *sp)
{ {
/* set up the mouse input device */ /* set up the mouse input device */
struct ibmasm_remote *remote; struct input_dev *mouse_dev, *keybd_dev;
struct pci_dev *pdev = to_pci_dev(sp->dev); struct pci_dev *pdev = to_pci_dev(sp->dev);
int error = -ENOMEM;
int i; int i;
sp->remote = remote = kmalloc(sizeof(*remote), GFP_KERNEL); sp->remote.mouse_dev = mouse_dev = input_allocate_device();
if (!remote) sp->remote.keybd_dev = keybd_dev = input_allocate_device();
return -ENOMEM;
memset(remote, 0, sizeof(*remote)); if (!mouse_dev || !keybd_dev)
goto err_free_devices;
remote->mouse_dev.private = remote; mouse_dev->id.bustype = BUS_PCI;
init_input_dev(&remote->mouse_dev); mouse_dev->id.vendor = pdev->vendor;
remote->mouse_dev.id.vendor = pdev->vendor; mouse_dev->id.product = pdev->device;
remote->mouse_dev.id.product = pdev->device; mouse_dev->id.version = 1;
remote->mouse_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); mouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
remote->mouse_dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | mouse_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) |
BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
set_bit(BTN_TOUCH, remote->mouse_dev.keybit); set_bit(BTN_TOUCH, mouse_dev->keybit);
remote->mouse_dev.name = remote_mouse_name; mouse_dev->name = remote_mouse_name;
input_set_abs_params(&remote->mouse_dev, ABS_X, 0, xmax, 0, 0); input_set_abs_params(mouse_dev, ABS_X, 0, xmax, 0, 0);
input_set_abs_params(&remote->mouse_dev, ABS_Y, 0, ymax, 0, 0); input_set_abs_params(mouse_dev, ABS_Y, 0, ymax, 0, 0);
remote->keybd_dev.private = remote; mouse_dev->id.bustype = BUS_PCI;
init_input_dev(&remote->keybd_dev); keybd_dev->id.vendor = pdev->vendor;
remote->keybd_dev.id.vendor = pdev->vendor; keybd_dev->id.product = pdev->device;
remote->keybd_dev.id.product = pdev->device; mouse_dev->id.version = 2;
remote->keybd_dev.evbit[0] = BIT(EV_KEY); keybd_dev->evbit[0] = BIT(EV_KEY);
remote->keybd_dev.name = remote_keybd_name; keybd_dev->name = remote_keybd_name;
for (i=0; i<XLATE_SIZE; i++) { for (i = 0; i < XLATE_SIZE; i++) {
if (xlate_high[i]) if (xlate_high[i])
set_bit(xlate_high[i], remote->keybd_dev.keybit); set_bit(xlate_high[i], keybd_dev->keybit);
if (xlate[i]) if (xlate[i])
set_bit(xlate[i], remote->keybd_dev.keybit); set_bit(xlate[i], keybd_dev->keybit);
} }
input_register_device(&remote->mouse_dev); error = input_register_device(mouse_dev);
input_register_device(&remote->keybd_dev); if (error)
goto err_free_devices;
error = input_register_device(keybd_dev);
if (error)
goto err_unregister_mouse_dev;
enable_mouse_interrupts(sp); enable_mouse_interrupts(sp);
printk(KERN_INFO "ibmasm remote responding to events on RSA card %d\n", sp->number); printk(KERN_INFO "ibmasm remote responding to events on RSA card %d\n", sp->number);
return 0; return 0;
err_unregister_mouse_dev:
input_unregister_device(mouse_dev);
err_free_devices:
input_free_device(mouse_dev);
input_free_device(keybd_dev);
return error;
} }
void ibmasm_free_remote_input_dev(struct service_processor *sp) void ibmasm_free_remote_input_dev(struct service_processor *sp)
{ {
disable_mouse_interrupts(sp); disable_mouse_interrupts(sp);
input_unregister_device(&sp->remote->keybd_dev); input_unregister_device(sp->remote.mouse_dev);
input_unregister_device(&sp->remote->mouse_dev); input_unregister_device(sp->remote.keybd_dev);
kfree(sp->remote);
} }
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* Copyright (C) 2005 Stelian Pop (stelian@popies.net) * Copyright (C) 2005 Stelian Pop (stelian@popies.net)
* Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de) * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de)
* Copyright (C) 2005 Peter Osterlund (petero2@telia.com) * Copyright (C) 2005 Peter Osterlund (petero2@telia.com)
* Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch)
* *
* Thanks to Alex Harper <basilisk@foobox.net> for his inputs. * Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
* *
...@@ -38,6 +39,11 @@ ...@@ -38,6 +39,11 @@
/* Apple has powerbooks which have the keyboard with different Product IDs */ /* Apple has powerbooks which have the keyboard with different Product IDs */
#define APPLE_VENDOR_ID 0x05AC #define APPLE_VENDOR_ID 0x05AC
/* These names come from Info.plist in AppleUSBTrackpad.kext */
#define GEYSER_ANSI_PRODUCT_ID 0x0214
#define GEYSER_ISO_PRODUCT_ID 0x0215
#define GEYSER_JIS_PRODUCT_ID 0x0216
#define ATP_DEVICE(prod) \ #define ATP_DEVICE(prod) \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
USB_DEVICE_ID_MATCH_INT_CLASS | \ USB_DEVICE_ID_MATCH_INT_CLASS | \
...@@ -53,13 +59,17 @@ static struct usb_device_id atp_table [] = { ...@@ -53,13 +59,17 @@ static struct usb_device_id atp_table [] = {
{ ATP_DEVICE(0x020F) }, { ATP_DEVICE(0x020F) },
{ ATP_DEVICE(0x030A) }, { ATP_DEVICE(0x030A) },
{ ATP_DEVICE(0x030B) }, { ATP_DEVICE(0x030B) },
{ } /* Terminating entry */
/* PowerBooks Oct 2005 */
{ ATP_DEVICE(GEYSER_ANSI_PRODUCT_ID) },
{ ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) },
{ ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) },
/* Terminating entry */
{ }
}; };
MODULE_DEVICE_TABLE (usb, atp_table); MODULE_DEVICE_TABLE (usb, atp_table);
/* size of a USB urb transfer */
#define ATP_DATASIZE 81
/* /*
* number of sensors. Note that only 16 instead of 26 X (horizontal) * number of sensors. Note that only 16 instead of 26 X (horizontal)
* sensors exist on 12" and 15" PowerBooks. All models have 16 Y * sensors exist on 12" and 15" PowerBooks. All models have 16 Y
...@@ -108,6 +118,8 @@ struct atp { ...@@ -108,6 +118,8 @@ struct atp {
signed char xy_old[ATP_XSENSORS + ATP_YSENSORS]; signed char xy_old[ATP_XSENSORS + ATP_YSENSORS];
/* accumulated sensors */ /* accumulated sensors */
int xy_acc[ATP_XSENSORS + ATP_YSENSORS]; int xy_acc[ATP_XSENSORS + ATP_YSENSORS];
int overflowwarn; /* overflow warning printed? */
int datalen; /* size of an USB urb transfer */
}; };
#define dbg_dump(msg, tab) \ #define dbg_dump(msg, tab) \
...@@ -124,7 +136,7 @@ struct atp { ...@@ -124,7 +136,7 @@ struct atp {
if (debug) printk(format, ##a); \ if (debug) printk(format, ##a); \
} while (0) } while (0)
MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold"); MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann");
MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver"); MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -132,6 +144,16 @@ static int debug = 1; ...@@ -132,6 +144,16 @@ static int debug = 1;
module_param(debug, int, 0644); module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Activate debugging output"); MODULE_PARM_DESC(debug, "Activate debugging output");
/* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */
static inline int atp_is_geyser_2(struct atp *dev)
{
int16_t productId = le16_to_cpu(dev->udev->descriptor.idProduct);
return (productId == GEYSER_ANSI_PRODUCT_ID) ||
(productId == GEYSER_ISO_PRODUCT_ID) ||
(productId == GEYSER_JIS_PRODUCT_ID);
}
static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
int *z, int *fingers) int *z, int *fingers)
{ {
...@@ -168,13 +190,20 @@ static inline void atp_report_fingers(struct input_dev *input, int fingers) ...@@ -168,13 +190,20 @@ static inline void atp_report_fingers(struct input_dev *input, int fingers)
static void atp_complete(struct urb* urb, struct pt_regs* regs) static void atp_complete(struct urb* urb, struct pt_regs* regs)
{ {
int x, y, x_z, y_z, x_f, y_f; int x, y, x_z, y_z, x_f, y_f;
int retval, i; int retval, i, j;
struct atp *dev = urb->context; struct atp *dev = urb->context;
switch (urb->status) { switch (urb->status) {
case 0: case 0:
/* success */ /* success */
break; break;
case -EOVERFLOW:
if(!dev->overflowwarn) {
printk("appletouch: OVERFLOW with data "
"length %d, actual length is %d\n",
dev->datalen, dev->urb->actual_length);
dev->overflowwarn = 1;
}
case -ECONNRESET: case -ECONNRESET:
case -ENOENT: case -ENOENT:
case -ESHUTDOWN: case -ESHUTDOWN:
...@@ -189,23 +218,45 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs) ...@@ -189,23 +218,45 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs)
} }
/* drop incomplete datasets */ /* drop incomplete datasets */
if (dev->urb->actual_length != ATP_DATASIZE) { if (dev->urb->actual_length != dev->datalen) {
dprintk("appletouch: incomplete data package.\n"); dprintk("appletouch: incomplete data package.\n");
goto exit; goto exit;
} }
/* reorder the sensors values */ /* reorder the sensors values */
for (i = 0; i < 8; i++) { if (atp_is_geyser_2(dev)) {
/* X values */ memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
dev->xy_cur[i ] = dev->data[5 * i + 2];
dev->xy_cur[i + 8] = dev->data[5 * i + 4]; /*
dev->xy_cur[i + 16] = dev->data[5 * i + 42]; * The values are laid out like this:
if (i < 2) * Y1, Y2, -, Y3, Y4, -, ..., X1, X2, -, X3, X4, -, ...
dev->xy_cur[i + 24] = dev->data[5 * i + 44]; * '-' is an unused value.
*/
/* Y values */
dev->xy_cur[i + 26] = dev->data[5 * i + 1]; /* read X values */
dev->xy_cur[i + 34] = dev->data[5 * i + 3]; for (i = 0, j = 19; i < 20; i += 2, j += 3) {
dev->xy_cur[i] = dev->data[j];
dev->xy_cur[i + 1] = dev->data[j + 1];
}
/* read Y values */
for (i = 0, j = 1; i < 9; i += 2, j += 3) {
dev->xy_cur[ATP_XSENSORS + i] = dev->data[j];
dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 1];
}
} else {
for (i = 0; i < 8; i++) {
/* X values */
dev->xy_cur[i ] = dev->data[5 * i + 2];
dev->xy_cur[i + 8] = dev->data[5 * i + 4];
dev->xy_cur[i + 16] = dev->data[5 * i + 42];
if (i < 2)
dev->xy_cur[i + 24] = dev->data[5 * i + 44];
/* Y values */
dev->xy_cur[i + 26] = dev->data[5 * i + 1];
dev->xy_cur[i + 34] = dev->data[5 * i + 3];
}
} }
dbg_dump("sample", dev->xy_cur); dbg_dump("sample", dev->xy_cur);
...@@ -216,16 +267,24 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs) ...@@ -216,16 +267,24 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs)
dev->x_old = dev->y_old = -1; dev->x_old = dev->y_old = -1;
memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
/* 17" Powerbooks have 10 extra X sensors */ /* 17" Powerbooks have extra X sensors */
for (i = 16; i < ATP_XSENSORS; i++) for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) {
if (dev->xy_cur[i]) { if (!dev->xy_cur[i]) continue;
printk("appletouch: 17\" model detected.\n");
printk("appletouch: 17\" model detected.\n");
if(atp_is_geyser_2(dev))
input_set_abs_params(dev->input, ABS_X, 0,
(20 - 1) *
ATP_XFACT - 1,
ATP_FUZZ, 0);
else
input_set_abs_params(dev->input, ABS_X, 0, input_set_abs_params(dev->input, ABS_X, 0,
(ATP_XSENSORS - 1) * (ATP_XSENSORS - 1) *
ATP_XFACT - 1, ATP_XFACT - 1,
ATP_FUZZ, 0); ATP_FUZZ, 0);
break;
} break;
}
goto exit; goto exit;
} }
...@@ -282,7 +341,8 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs) ...@@ -282,7 +341,8 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs)
memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
} }
input_report_key(dev->input, BTN_LEFT, !!dev->data[80]); input_report_key(dev->input, BTN_LEFT,
!!dev->data[dev->datalen - 1]);
input_sync(dev->input); input_sync(dev->input);
...@@ -353,6 +413,8 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id ...@@ -353,6 +413,8 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
dev->udev = udev; dev->udev = udev;
dev->input = input_dev; dev->input = input_dev;
dev->overflowwarn = 0;
dev->datalen = (atp_is_geyser_2(dev)?64:81);
dev->urb = usb_alloc_urb(0, GFP_KERNEL); dev->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->urb) { if (!dev->urb) {
...@@ -360,7 +422,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id ...@@ -360,7 +422,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
goto err_free_devs; goto err_free_devs;
} }
dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL, dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL,
&dev->urb->transfer_dma); &dev->urb->transfer_dma);
if (!dev->data) { if (!dev->data) {
retval = -ENOMEM; retval = -ENOMEM;
...@@ -369,7 +431,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id ...@@ -369,7 +431,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
usb_fill_int_urb(dev->urb, udev, usb_fill_int_urb(dev->urb, udev,
usb_rcvintpipe(udev, int_in_endpointAddr), usb_rcvintpipe(udev, int_in_endpointAddr),
dev->data, ATP_DATASIZE, atp_complete, dev, 1); dev->data, dev->datalen, atp_complete, dev, 1);
usb_make_path(udev, dev->phys, sizeof(dev->phys)); usb_make_path(udev, dev->phys, sizeof(dev->phys));
strlcat(dev->phys, "/input0", sizeof(dev->phys)); strlcat(dev->phys, "/input0", sizeof(dev->phys));
...@@ -385,14 +447,25 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id ...@@ -385,14 +447,25 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
set_bit(EV_ABS, input_dev->evbit); set_bit(EV_ABS, input_dev->evbit);
/* if (atp_is_geyser_2(dev)) {
* 12" and 15" Powerbooks only have 16 x sensors, /*
* 17" models are detected later. * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected
*/ * later.
input_set_abs_params(input_dev, ABS_X, 0, */
(16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0); input_set_abs_params(input_dev, ABS_X, 0,
input_set_abs_params(input_dev, ABS_Y, 0, ((15 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0);
(ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0); input_set_abs_params(input_dev, ABS_Y, 0,
((9 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0);
} else {
/*
* 12" and 15" Powerbooks only have 16 x sensors,
* 17" models are detected later.
*/
input_set_abs_params(input_dev, ABS_X, 0,
(16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
input_set_abs_params(input_dev, ABS_Y, 0,
(ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
}
input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0); input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
set_bit(EV_KEY, input_dev->evbit); set_bit(EV_KEY, input_dev->evbit);
...@@ -427,7 +500,7 @@ static void atp_disconnect(struct usb_interface *iface) ...@@ -427,7 +500,7 @@ static void atp_disconnect(struct usb_interface *iface)
usb_kill_urb(dev->urb); usb_kill_urb(dev->urb);
input_unregister_device(dev->input); input_unregister_device(dev->input);
usb_free_urb(dev->urb); usb_free_urb(dev->urb);
usb_buffer_free(dev->udev, ATP_DATASIZE, usb_buffer_free(dev->udev, dev->datalen,
dev->data, dev->urb->transfer_dma); dev->data, dev->urb->transfer_dma);
kfree(dev); kfree(dev);
} }
......
...@@ -681,6 +681,21 @@ static char *keys[KEY_MAX + 1] = { ...@@ -681,6 +681,21 @@ static char *keys[KEY_MAX + 1] = {
[KEY_SEND] = "Send", [KEY_REPLY] = "Reply", [KEY_SEND] = "Send", [KEY_REPLY] = "Reply",
[KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save", [KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save",
[KEY_DOCUMENTS] = "Documents", [KEY_DOCUMENTS] = "Documents",
[KEY_FN] = "Fn", [KEY_FN_ESC] = "Fn+ESC",
[KEY_FN_1] = "Fn+1", [KEY_FN_2] = "Fn+2",
[KEY_FN_B] = "Fn+B", [KEY_FN_D] = "Fn+D",
[KEY_FN_E] = "Fn+E", [KEY_FN_F] = "Fn+F",
[KEY_FN_S] = "Fn+S",
[KEY_FN_F1] = "Fn+F1", [KEY_FN_F2] = "Fn+F2",
[KEY_FN_F3] = "Fn+F3", [KEY_FN_F4] = "Fn+F4",
[KEY_FN_F5] = "Fn+F5", [KEY_FN_F6] = "Fn+F6",
[KEY_FN_F7] = "Fn+F7", [KEY_FN_F8] = "Fn+F8",
[KEY_FN_F9] = "Fn+F9", [KEY_FN_F10] = "Fn+F10",
[KEY_FN_F11] = "Fn+F11", [KEY_FN_F12] = "Fn+F12",
[KEY_KBDILLUMTOGGLE] = "KbdIlluminationToggle",
[KEY_KBDILLUMDOWN] = "KbdIlluminationDown",
[KEY_KBDILLUMUP] = "KbdIlluminationUp",
[KEY_SWITCHVIDEOMODE] = "SwitchVideoMode",
}; };
static char *relatives[REL_MAX + 1] = { static char *relatives[REL_MAX + 1] = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment