Commit 3e0777b8 authored by Linus Torvalds's avatar Linus Torvalds

Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/dtor/input.git manually

Some manual fixups required due to clashes with the PF_FREEZE cleanups.
parents a94130e0 e5119885
...@@ -1115,7 +1115,7 @@ running once the system is up. ...@@ -1115,7 +1115,7 @@ running once the system is up.
See Documentation/ramdisk.txt. See Documentation/ramdisk.txt.
psmouse.proto= [HW,MOUSE] Highest PS2 mouse protocol extension to psmouse.proto= [HW,MOUSE] Highest PS2 mouse protocol extension to
probe for (bare|imps|exps). probe for (bare|imps|exps|lifebook|any).
psmouse.rate= [HW,MOUSE] Set desired mouse report rate, in reports psmouse.rate= [HW,MOUSE] Set desired mouse report rate, in reports
per second. per second.
psmouse.resetafter= psmouse.resetafter=
......
This diff is collapsed.
...@@ -49,22 +49,8 @@ config GAMEPORT_EMU10K1 ...@@ -49,22 +49,8 @@ config GAMEPORT_EMU10K1
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called emu10k1-gp. module will be called emu10k1-gp.
config GAMEPORT_VORTEX
tristate "Aureal Vortex, Vortex 2 gameport support"
depends on PCI
help
Say Y here if you have an Aureal Vortex 1 or 2 card and want
to use its gameport.
To compile this driver as a module, choose M here: the
module will be called vortex.
config GAMEPORT_FM801 config GAMEPORT_FM801
tristate "ForteMedia FM801 gameport support" tristate "ForteMedia FM801 gameport support"
depends on PCI depends on PCI
config GAMEPORT_CS461X
tristate "Crystal SoundFusion gameport support"
depends on PCI
endif endif
...@@ -5,9 +5,7 @@ ...@@ -5,9 +5,7 @@
# Each configuration option enables a list of files. # Each configuration option enables a list of files.
obj-$(CONFIG_GAMEPORT) += gameport.o obj-$(CONFIG_GAMEPORT) += gameport.o
obj-$(CONFIG_GAMEPORT_CS461X) += cs461x.o
obj-$(CONFIG_GAMEPORT_EMU10K1) += emu10k1-gp.o obj-$(CONFIG_GAMEPORT_EMU10K1) += emu10k1-gp.o
obj-$(CONFIG_GAMEPORT_FM801) += fm801-gp.o obj-$(CONFIG_GAMEPORT_FM801) += fm801-gp.o
obj-$(CONFIG_GAMEPORT_L4) += lightning.o obj-$(CONFIG_GAMEPORT_L4) += lightning.o
obj-$(CONFIG_GAMEPORT_NS558) += ns558.o obj-$(CONFIG_GAMEPORT_NS558) += ns558.o
obj-$(CONFIG_GAMEPORT_VORTEX) += vortex.o
/*
The all defines and part of code (such as cs461x_*) are
contributed from ALSA 0.5.8 sources.
See http://www.alsa-project.org/ for sources
Tested on Linux 686 2.4.0-test9, ALSA 0.5.8a and CS4610
*/
#include <asm/io.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/config.h>
#include <linux/init.h>
#include <linux/gameport.h>
#include <linux/slab.h>
#include <linux/pci.h>
MODULE_AUTHOR("Victor Krapivin");
MODULE_LICENSE("GPL");
/*
These options are experimental
#define CS461X_FULL_MAP
*/
#ifndef PCI_VENDOR_ID_CIRRUS
#define PCI_VENDOR_ID_CIRRUS 0x1013
#endif
#ifndef PCI_DEVICE_ID_CIRRUS_4610
#define PCI_DEVICE_ID_CIRRUS_4610 0x6001
#endif
#ifndef PCI_DEVICE_ID_CIRRUS_4612
#define PCI_DEVICE_ID_CIRRUS_4612 0x6003
#endif
#ifndef PCI_DEVICE_ID_CIRRUS_4615
#define PCI_DEVICE_ID_CIRRUS_4615 0x6004
#endif
/* Registers */
#define BA0_JSPT 0x00000480
#define BA0_JSCTL 0x00000484
#define BA0_JSC1 0x00000488
#define BA0_JSC2 0x0000048C
#define BA0_JSIO 0x000004A0
/* Bits for JSPT */
#define JSPT_CAX 0x00000001
#define JSPT_CAY 0x00000002
#define JSPT_CBX 0x00000004
#define JSPT_CBY 0x00000008
#define JSPT_BA1 0x00000010
#define JSPT_BA2 0x00000020
#define JSPT_BB1 0x00000040
#define JSPT_BB2 0x00000080
/* Bits for JSCTL */
#define JSCTL_SP_MASK 0x00000003
#define JSCTL_SP_SLOW 0x00000000
#define JSCTL_SP_MEDIUM_SLOW 0x00000001
#define JSCTL_SP_MEDIUM_FAST 0x00000002
#define JSCTL_SP_FAST 0x00000003
#define JSCTL_ARE 0x00000004
/* Data register pairs masks */
#define JSC1_Y1V_MASK 0x0000FFFF
#define JSC1_X1V_MASK 0xFFFF0000
#define JSC1_Y1V_SHIFT 0
#define JSC1_X1V_SHIFT 16
#define JSC2_Y2V_MASK 0x0000FFFF
#define JSC2_X2V_MASK 0xFFFF0000
#define JSC2_Y2V_SHIFT 0
#define JSC2_X2V_SHIFT 16
/* JS GPIO */
#define JSIO_DAX 0x00000001
#define JSIO_DAY 0x00000002
#define JSIO_DBX 0x00000004
#define JSIO_DBY 0x00000008
#define JSIO_AXOE 0x00000010
#define JSIO_AYOE 0x00000020
#define JSIO_BXOE 0x00000040
#define JSIO_BYOE 0x00000080
/*
The card initialization code is obfuscated; the module cs461x
need to be loaded after ALSA modules initialized and something
played on the CS 4610 chip (see sources for details of CS4610
initialization code from ALSA)
*/
/* Card specific definitions */
#define CS461X_BA0_SIZE 0x2000
#define CS461X_BA1_DATA0_SIZE 0x3000
#define CS461X_BA1_DATA1_SIZE 0x3800
#define CS461X_BA1_PRG_SIZE 0x7000
#define CS461X_BA1_REG_SIZE 0x0100
#define BA1_SP_DMEM0 0x00000000
#define BA1_SP_DMEM1 0x00010000
#define BA1_SP_PMEM 0x00020000
#define BA1_SP_REG 0x00030000
#define BA1_DWORD_SIZE (13 * 1024 + 512)
#define BA1_MEMORY_COUNT 3
/*
Only one CS461x card is still suppoted; the code requires
redesign to avoid this limitatuion.
*/
static unsigned long ba0_addr;
static unsigned int __iomem *ba0;
#ifdef CS461X_FULL_MAP
static unsigned long ba1_addr;
static union ba1_t {
struct {
unsigned int __iomem *data0;
unsigned int __iomem *data1;
unsigned int __iomem *pmem;
unsigned int __iomem *reg;
} name;
unsigned int __iomem *idx[4];
} ba1;
static void cs461x_poke(unsigned long reg, unsigned int val)
{
writel(val, &ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff]);
}
static unsigned int cs461x_peek(unsigned long reg)
{
return readl(&ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff]);
}
#endif
static void cs461x_pokeBA0(unsigned long reg, unsigned int val)
{
writel(val, &ba0[reg >> 2]);
}
static unsigned int cs461x_peekBA0(unsigned long reg)
{
return readl(&ba0[reg >> 2]);
}
static int cs461x_free(struct pci_dev *pdev)
{
struct gameport *port = pci_get_drvdata(pdev);
if (port)
gameport_unregister_port(port);
if (ba0) iounmap(ba0);
#ifdef CS461X_FULL_MAP
if (ba1.name.data0) iounmap(ba1.name.data0);
if (ba1.name.data1) iounmap(ba1.name.data1);
if (ba1.name.pmem) iounmap(ba1.name.pmem);
if (ba1.name.reg) iounmap(ba1.name.reg);
#endif
return 0;
}
static void cs461x_gameport_trigger(struct gameport *gameport)
{
cs461x_pokeBA0(BA0_JSPT, 0xFF); //outb(gameport->io, 0xFF);
}
static unsigned char cs461x_gameport_read(struct gameport *gameport)
{
return cs461x_peekBA0(BA0_JSPT); //inb(gameport->io);
}
static int cs461x_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
unsigned js1, js2, jst;
js1 = cs461x_peekBA0(BA0_JSC1);
js2 = cs461x_peekBA0(BA0_JSC2);
jst = cs461x_peekBA0(BA0_JSPT);
*buttons = (~jst >> 4) & 0x0F;
axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF;
axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF;
axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF;
axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF;
for(jst=0;jst<4;++jst)
if(axes[jst]==0xFFFF) axes[jst] = -1;
return 0;
}
static int cs461x_gameport_open(struct gameport *gameport, int mode)
{
switch (mode) {
case GAMEPORT_MODE_COOKED:
case GAMEPORT_MODE_RAW:
return 0;
default:
return -1;
}
return 0;
}
static struct pci_device_id cs461x_pci_tbl[] = {
{ PCI_VENDOR_ID_CIRRUS, 0x6001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4610 */
{ PCI_VENDOR_ID_CIRRUS, 0x6003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4612 */
{ PCI_VENDOR_ID_CIRRUS, 0x6005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4615 */
{ 0, }
};
MODULE_DEVICE_TABLE(pci, cs461x_pci_tbl);
static int __devinit cs461x_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
int rc;
struct gameport* port;
rc = pci_enable_device(pdev);
if (rc) {
printk(KERN_ERR "cs461x: Cannot enable PCI gameport (bus %d, devfn %d) error=%d\n",
pdev->bus->number, pdev->devfn, rc);
return rc;
}
ba0_addr = pci_resource_start(pdev, 0);
#ifdef CS461X_FULL_MAP
ba1_addr = pci_resource_start(pdev, 1);
#endif
if (ba0_addr == 0 || ba0_addr == ~0
#ifdef CS461X_FULL_MAP
|| ba1_addr == 0 || ba1_addr == ~0
#endif
) {
printk(KERN_ERR "cs461x: wrong address - ba0 = 0x%lx\n", ba0_addr);
#ifdef CS461X_FULL_MAP
printk(KERN_ERR "cs461x: wrong address - ba1 = 0x%lx\n", ba1_addr);
#endif
cs461x_free(pdev);
return -ENOMEM;
}
ba0 = ioremap(ba0_addr, CS461X_BA0_SIZE);
#ifdef CS461X_FULL_MAP
ba1.name.data0 = ioremap(ba1_addr + BA1_SP_DMEM0, CS461X_BA1_DATA0_SIZE);
ba1.name.data1 = ioremap(ba1_addr + BA1_SP_DMEM1, CS461X_BA1_DATA1_SIZE);
ba1.name.pmem = ioremap(ba1_addr + BA1_SP_PMEM, CS461X_BA1_PRG_SIZE);
ba1.name.reg = ioremap(ba1_addr + BA1_SP_REG, CS461X_BA1_REG_SIZE);
if (ba0 == NULL || ba1.name.data0 == NULL ||
ba1.name.data1 == NULL || ba1.name.pmem == NULL ||
ba1.name.reg == NULL) {
cs461x_free(pdev);
return -ENOMEM;
}
#else
if (ba0 == NULL) {
cs461x_free(pdev);
return -ENOMEM;
}
#endif
if (!(port = gameport_allocate_port())) {
printk(KERN_ERR "cs461x: Memory allocation failed\n");
cs461x_free(pdev);
return -ENOMEM;
}
pci_set_drvdata(pdev, port);
port->open = cs461x_gameport_open;
port->trigger = cs461x_gameport_trigger;
port->read = cs461x_gameport_read;
port->cooked_read = cs461x_gameport_cooked_read;
gameport_set_name(port, "CS416x");
gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev));
port->dev.parent = &pdev->dev;
cs461x_pokeBA0(BA0_JSIO, 0xFF); // ?
cs461x_pokeBA0(BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW);
gameport_register_port(port);
return 0;
}
static void __devexit cs461x_pci_remove(struct pci_dev *pdev)
{
cs461x_free(pdev);
}
static struct pci_driver cs461x_pci_driver = {
.name = "CS461x_gameport",
.id_table = cs461x_pci_tbl,
.probe = cs461x_pci_probe,
.remove = __devexit_p(cs461x_pci_remove),
};
static int __init cs461x_init(void)
{
return pci_register_driver(&cs461x_pci_driver);
}
static void __exit cs461x_exit(void)
{
pci_unregister_driver(&cs461x_pci_driver);
}
module_init(cs461x_init);
module_exit(cs461x_exit);
...@@ -258,18 +258,18 @@ static int __init ns558_init(void) ...@@ -258,18 +258,18 @@ static int __init ns558_init(void)
{ {
int i = 0; int i = 0;
if (pnp_register_driver(&ns558_pnp_driver) >= 0)
pnp_registered = 1;
/* /*
* Probe ISA ports first so that PnP gets to choose free port addresses * Probe ISA ports after PnP, so that PnP ports that are already
* not occupied by the ISA ports. * enabled get detected as PnP. This may be suboptimal in multi-device
* configurations, but saves hassle with simple setups.
*/ */
while (ns558_isa_portlist[i]) while (ns558_isa_portlist[i])
ns558_isa_probe(ns558_isa_portlist[i++]); ns558_isa_probe(ns558_isa_portlist[i++]);
if (pnp_register_driver(&ns558_pnp_driver) >= 0)
pnp_registered = 1;
return (list_empty(&ns558_list) && !pnp_registered) ? -ENODEV : 0; return (list_empty(&ns558_list) && !pnp_registered) ? -ENODEV : 0;
} }
......
/*
* $Id: vortex.c,v 1.5 2002/07/01 15:39:30 vojtech Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik
*
* Based on the work of:
* Raymond Ingles
*/
/*
* Trident 4DWave and Aureal Vortex gameport driver for Linux
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/gameport.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Aureal Vortex and Vortex2 gameport driver");
MODULE_LICENSE("GPL");
#define VORTEX_GCR 0x0c /* Gameport control register */
#define VORTEX_LEG 0x08 /* Legacy port location */
#define VORTEX_AXD 0x10 /* Axes start */
#define VORTEX_DATA_WAIT 20 /* 20 ms */
struct vortex {
struct gameport *gameport;
struct pci_dev *dev;
unsigned char __iomem *base;
unsigned char __iomem *io;
};
static unsigned char vortex_read(struct gameport *gameport)
{
struct vortex *vortex = gameport->port_data;
return readb(vortex->io + VORTEX_LEG);
}
static void vortex_trigger(struct gameport *gameport)
{
struct vortex *vortex = gameport->port_data;
writeb(0xff, vortex->io + VORTEX_LEG);
}
static int vortex_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
struct vortex *vortex = gameport->port_data;
int i;
*buttons = (~readb(vortex->base + VORTEX_LEG) >> 4) & 0xf;
for (i = 0; i < 4; i++) {
axes[i] = readw(vortex->io + VORTEX_AXD + i * sizeof(u32));
if (axes[i] == 0x1fff) axes[i] = -1;
}
return 0;
}
static int vortex_open(struct gameport *gameport, int mode)
{
struct vortex *vortex = gameport->port_data;
switch (mode) {
case GAMEPORT_MODE_COOKED:
writeb(0x40, vortex->io + VORTEX_GCR);
msleep(VORTEX_DATA_WAIT);
return 0;
case GAMEPORT_MODE_RAW:
writeb(0x00, vortex->io + VORTEX_GCR);
return 0;
default:
return -1;
}
return 0;
}
static int __devinit vortex_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct vortex *vortex;
struct gameport *port;
int i;
vortex = kcalloc(1, sizeof(struct vortex), GFP_KERNEL);
port = gameport_allocate_port();
if (!vortex || !port) {
printk(KERN_ERR "vortex: Memory allocation failed.\n");
kfree(vortex);
gameport_free_port(port);
return -ENOMEM;
}
for (i = 0; i < 6; i++)
if (~pci_resource_flags(dev, i) & IORESOURCE_IO)
break;
pci_enable_device(dev);
vortex->dev = dev;
vortex->gameport = port;
vortex->base = ioremap(pci_resource_start(vortex->dev, i),
pci_resource_len(vortex->dev, i));
vortex->io = vortex->base + id->driver_data;
pci_set_drvdata(dev, vortex);
port->port_data = vortex;
port->fuzz = 64;
gameport_set_name(port, "AU88x0");
gameport_set_phys(port, "pci%s/gameport0", pci_name(dev));
port->dev.parent = &dev->dev;
port->read = vortex_read;
port->trigger = vortex_trigger;
port->cooked_read = vortex_cooked_read;
port->open = vortex_open;
gameport_register_port(port);
return 0;
}
static void __devexit vortex_remove(struct pci_dev *dev)
{
struct vortex *vortex = pci_get_drvdata(dev);
gameport_unregister_port(vortex->gameport);
iounmap(vortex->base);
kfree(vortex);
}
static struct pci_device_id vortex_id_table[] = {
{ 0x12eb, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x11000 },
{ 0x12eb, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x28800 },
{ 0 }
};
static struct pci_driver vortex_driver = {
.name = "vortex_gameport",
.id_table = vortex_id_table,
.probe = vortex_probe,
.remove = __devexit_p(vortex_remove),
};
static int __init vortex_init(void)
{
return pci_register_driver(&vortex_driver);
}
static void __exit vortex_exit(void)
{
pci_unregister_driver(&vortex_driver);
}
module_init(vortex_init);
module_exit(vortex_exit);
...@@ -219,10 +219,24 @@ void input_release_device(struct input_handle *handle) ...@@ -219,10 +219,24 @@ void input_release_device(struct input_handle *handle)
int input_open_device(struct input_handle *handle) int input_open_device(struct input_handle *handle)
{ {
struct input_dev *dev = handle->dev;
int err;
err = down_interruptible(&dev->sem);
if (err)
return err;
handle->open++; handle->open++;
if (handle->dev->open)
return handle->dev->open(handle->dev); if (!dev->users++ && dev->open)
return 0; err = dev->open(dev);
if (err)
handle->open--;
up(&dev->sem);
return err;
} }
int input_flush_device(struct input_handle* handle, struct file* file) int input_flush_device(struct input_handle* handle, struct file* file)
...@@ -235,10 +249,17 @@ int input_flush_device(struct input_handle* handle, struct file* file) ...@@ -235,10 +249,17 @@ int input_flush_device(struct input_handle* handle, struct file* file)
void input_close_device(struct input_handle *handle) void input_close_device(struct input_handle *handle)
{ {
struct input_dev *dev = handle->dev;
input_release_device(handle); input_release_device(handle);
if (handle->dev->close)
handle->dev->close(handle->dev); down(&dev->sem);
if (!--dev->users && dev->close)
dev->close(dev);
handle->open--; handle->open--;
up(&dev->sem);
} }
static void input_link_handle(struct input_handle *handle) static void input_link_handle(struct input_handle *handle)
...@@ -415,6 +436,8 @@ void input_register_device(struct input_dev *dev) ...@@ -415,6 +436,8 @@ void input_register_device(struct input_dev *dev)
set_bit(EV_SYN, dev->evbit); set_bit(EV_SYN, dev->evbit);
init_MUTEX(&dev->sem);
/* /*
* If delay and period are pre-set by the driver, then autorepeating * If delay and period are pre-set by the driver, then autorepeating
* is handled by the driver itself and we don't do it in input.c. * is handled by the driver itself and we don't do it in input.c.
...@@ -674,6 +697,8 @@ static int input_handlers_read(char *buf, char **start, off_t pos, int count, in ...@@ -674,6 +697,8 @@ static int input_handlers_read(char *buf, char **start, off_t pos, int count, in
return (count > cnt) ? cnt : count; return (count > cnt) ? cnt : count;
} }
static struct file_operations input_fileops;
static int __init input_proc_init(void) static int __init input_proc_init(void)
{ {
struct proc_dir_entry *entry; struct proc_dir_entry *entry;
...@@ -688,6 +713,8 @@ static int __init input_proc_init(void) ...@@ -688,6 +713,8 @@ static int __init input_proc_init(void)
return -ENOMEM; return -ENOMEM;
} }
entry->owner = THIS_MODULE; entry->owner = THIS_MODULE;
input_fileops = *entry->proc_fops;
entry->proc_fops = &input_fileops;
entry->proc_fops->poll = input_devices_poll; entry->proc_fops->poll = input_devices_poll;
entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL); entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL);
if (entry == NULL) { if (entry == NULL) {
......
...@@ -285,48 +285,33 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait) ...@@ -285,48 +285,33 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait)
(POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR)); (POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR));
} }
static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __user *argp)
{ {
struct joydev_list *list = file->private_data;
struct joydev *joydev = list->joydev;
struct input_dev *dev = joydev->handle.dev; struct input_dev *dev = joydev->handle.dev;
void __user *argp = (void __user *)arg;
int i, j; int i, j;
if (!joydev->exist) return -ENODEV;
switch (cmd) { switch (cmd) {
case JS_SET_CAL: case JS_SET_CAL:
return copy_from_user(&joydev->glue.JS_CORR, argp, return copy_from_user(&joydev->glue.JS_CORR, argp,
sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0; sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0;
case JS_GET_CAL: case JS_GET_CAL:
return copy_to_user(argp, &joydev->glue.JS_CORR, return copy_to_user(argp, &joydev->glue.JS_CORR,
sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0; sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0;
case JS_SET_TIMEOUT: case JS_SET_TIMEOUT:
return get_user(joydev->glue.JS_TIMEOUT, (int __user *) arg); return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp);
case JS_GET_TIMEOUT: case JS_GET_TIMEOUT:
return put_user(joydev->glue.JS_TIMEOUT, (int __user *) arg); return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp);
case JS_SET_TIMELIMIT:
return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg);
case JS_GET_TIMELIMIT:
return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg);
case JS_SET_ALL:
return copy_from_user(&joydev->glue, argp,
sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0;
case JS_GET_ALL:
return copy_to_user(argp, &joydev->glue,
sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0;
case JSIOCGVERSION: case JSIOCGVERSION:
return put_user(JS_VERSION, (__u32 __user *) arg); return put_user(JS_VERSION, (__u32 __user *) argp);
case JSIOCGAXES: case JSIOCGAXES:
return put_user(joydev->nabs, (__u8 __user *) arg); return put_user(joydev->nabs, (__u8 __user *) argp);
case JSIOCGBUTTONS: case JSIOCGBUTTONS:
return put_user(joydev->nkey, (__u8 __user *) arg); return put_user(joydev->nkey, (__u8 __user *) argp);
case JSIOCSCORR: case JSIOCSCORR:
if (copy_from_user(joydev->corr, argp, if (copy_from_user(joydev->corr, argp,
sizeof(struct js_corr) * joydev->nabs)) sizeof(joydev->corr[0]) * joydev->nabs))
return -EFAULT; return -EFAULT;
for (i = 0; i < joydev->nabs; i++) { for (i = 0; i < joydev->nabs; i++) {
j = joydev->abspam[i]; j = joydev->abspam[i];
...@@ -335,7 +320,7 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd ...@@ -335,7 +320,7 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
return 0; return 0;
case JSIOCGCORR: case JSIOCGCORR:
return copy_to_user(argp, joydev->corr, return copy_to_user(argp, joydev->corr,
sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0; sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0;
case JSIOCSAXMAP: case JSIOCSAXMAP:
if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1))) if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1)))
return -EFAULT; return -EFAULT;
...@@ -371,6 +356,84 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd ...@@ -371,6 +356,84 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
return -EINVAL; return -EINVAL;
} }
#ifdef CONFIG_COMPAT
static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct joydev_list *list = file->private_data;
struct joydev *joydev = list->joydev;
void __user *argp = (void __user *)arg;
s32 tmp32;
struct JS_DATA_SAVE_TYPE_32 ds32;
int err;
if (!joydev->exist) return -ENODEV;
switch(cmd) {
case JS_SET_TIMELIMIT:
err = get_user(tmp32, (s32 __user *) arg);
if (err == 0)
joydev->glue.JS_TIMELIMIT = tmp32;
break;
case JS_GET_TIMELIMIT:
tmp32 = joydev->glue.JS_TIMELIMIT;
err = put_user(tmp32, (s32 __user *) arg);
break;
case JS_SET_ALL:
err = copy_from_user(&ds32, argp,
sizeof(ds32)) ? -EFAULT : 0;
if (err == 0) {
joydev->glue.JS_TIMEOUT = ds32.JS_TIMEOUT;
joydev->glue.BUSY = ds32.BUSY;
joydev->glue.JS_EXPIRETIME = ds32.JS_EXPIRETIME;
joydev->glue.JS_TIMELIMIT = ds32.JS_TIMELIMIT;
joydev->glue.JS_SAVE = ds32.JS_SAVE;
joydev->glue.JS_CORR = ds32.JS_CORR;
}
break;
case JS_GET_ALL:
ds32.JS_TIMEOUT = joydev->glue.JS_TIMEOUT;
ds32.BUSY = joydev->glue.BUSY;
ds32.JS_EXPIRETIME = joydev->glue.JS_EXPIRETIME;
ds32.JS_TIMELIMIT = joydev->glue.JS_TIMELIMIT;
ds32.JS_SAVE = joydev->glue.JS_SAVE;
ds32.JS_CORR = joydev->glue.JS_CORR;
err = copy_to_user(argp, &ds32,
sizeof(ds32)) ? -EFAULT : 0;
break;
default:
err = joydev_ioctl_common(joydev, cmd, argp);
}
return err;
}
#endif /* CONFIG_COMPAT */
static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
struct joydev_list *list = file->private_data;
struct joydev *joydev = list->joydev;
void __user *argp = (void __user *)arg;
if (!joydev->exist) return -ENODEV;
switch(cmd) {
case JS_SET_TIMELIMIT:
return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg);
case JS_GET_TIMELIMIT:
return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg);
case JS_SET_ALL:
return copy_from_user(&joydev->glue, argp,
sizeof(joydev->glue)) ? -EFAULT : 0;
case JS_GET_ALL:
return copy_to_user(argp, &joydev->glue,
sizeof(joydev->glue)) ? -EFAULT : 0;
default:
return joydev_ioctl_common(joydev, cmd, argp);
}
}
static struct file_operations joydev_fops = { static struct file_operations joydev_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.read = joydev_read, .read = joydev_read,
...@@ -379,6 +442,9 @@ static struct file_operations joydev_fops = { ...@@ -379,6 +442,9 @@ static struct file_operations joydev_fops = {
.open = joydev_open, .open = joydev_open,
.release = joydev_release, .release = joydev_release,
.ioctl = joydev_ioctl, .ioctl = joydev_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = joydev_compat_ioctl,
#endif
.fasync = joydev_fasync, .fasync = joydev_fasync,
}; };
......
...@@ -185,7 +185,7 @@ static void a3d_poll(struct gameport *gameport) ...@@ -185,7 +185,7 @@ static void a3d_poll(struct gameport *gameport)
a3d->reads++; a3d->reads++;
if (a3d_read_packet(a3d->gameport, a3d->length, data) != a3d->length || if (a3d_read_packet(a3d->gameport, a3d->length, data) != a3d->length ||
data[0] != a3d->mode || a3d_csum(data, a3d->length)) data[0] != a3d->mode || a3d_csum(data, a3d->length))
a3d->bads++; a3d->bads++;
else else
a3d_read(a3d, data); a3d_read(a3d, data);
} }
......
...@@ -82,7 +82,7 @@ static char adi_cm2_abs[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ }; ...@@ -82,7 +82,7 @@ static char adi_cm2_abs[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
static char adi_wmf_abs[] = { ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y }; static char adi_wmf_abs[] = { ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y };
static short adi_wmgpe_key[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT }; static short adi_wmgpe_key[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT };
static short adi_wmi_key[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_EXTRA }; static short adi_wmi_key[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_EXTRA };
static short adi_wmed3d_key[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2 }; static short adi_wmed3d_key[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2 };
static short adi_cm2_key[] = { BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 }; static short adi_cm2_key[] = { BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 };
...@@ -183,7 +183,7 @@ static void adi_move_bits(struct adi_port *port, int length) ...@@ -183,7 +183,7 @@ static void adi_move_bits(struct adi_port *port, int length)
int i; int i;
struct adi *adi = port->adi; struct adi *adi = port->adi;
adi[0].idx = adi[1].idx = 0; adi[0].idx = adi[1].idx = 0;
if (adi[0].ret <= 0 || adi[1].ret <= 0) return; if (adi[0].ret <= 0 || adi[1].ret <= 0) return;
if (adi[0].data[0] & 0x20 || ~adi[1].data[0] & 0x20) return; if (adi[0].data[0] & 0x20 || ~adi[1].data[0] & 0x20) return;
......
...@@ -51,7 +51,8 @@ MODULE_PARM_DESC(map, "Map of attached joysticks in form of <a>,<b> (default is ...@@ -51,7 +51,8 @@ MODULE_PARM_DESC(map, "Map of attached joysticks in form of <a>,<b> (default is
__obsolete_setup("amijoy="); __obsolete_setup("amijoy=");
static int amijoy_used[2] = { 0, 0 }; static int amijoy_used;
static DECLARE_MUTEX(amijoy_sem);
static struct input_dev amijoy_dev[2]; static struct input_dev amijoy_dev[2];
static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" }; static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" };
...@@ -84,26 +85,30 @@ static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp) ...@@ -84,26 +85,30 @@ static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp)
static int amijoy_open(struct input_dev *dev) static int amijoy_open(struct input_dev *dev)
{ {
int *used = dev->private; int err;
if ((*used)++) err = down_interruptible(&amijoy_sem);
return 0; if (err)
return err;
if (request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", amijoy_interrupt)) { if (!amijoy_used && request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", amijoy_interrupt)) {
(*used)--;
printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB); printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB);
return -EBUSY; err = -EBUSY;
goto out;
} }
return 0; amijoy_used++;
out:
up(&amijoy_sem);
return err;
} }
static void amijoy_close(struct input_dev *dev) static void amijoy_close(struct input_dev *dev)
{ {
int *used = dev->private; down(&amijoysem);
if (!--amijoy_used)
if (!--(*used))
free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt); free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt);
up(&amijoy_sem);
} }
static int __init amijoy_init(void) static int __init amijoy_init(void)
...@@ -138,8 +143,6 @@ static int __init amijoy_init(void) ...@@ -138,8 +143,6 @@ static int __init amijoy_init(void)
amijoy_dev[i].id.product = 0x0003; amijoy_dev[i].id.product = 0x0003;
amijoy_dev[i].id.version = 0x0100; amijoy_dev[i].id.version = 0x0100;
amijoy_dev[i].private = amijoy_used + i;
input_register_device(amijoy_dev + i); input_register_device(amijoy_dev + i);
printk(KERN_INFO "input: %s at joy%ddat\n", amijoy_name, i); printk(KERN_INFO "input: %s at joy%ddat\n", amijoy_name, i);
} }
......
...@@ -87,7 +87,7 @@ __obsolete_setup("db9_3="); ...@@ -87,7 +87,7 @@ __obsolete_setup("db9_3=");
#define DB9_NORMAL 0x0a #define DB9_NORMAL 0x0a
#define DB9_NOSELECT 0x08 #define DB9_NOSELECT 0x08
#define DB9_MAX_DEVICES 2 #define DB9_MAX_DEVICES 2
#define DB9_GENESIS6_DELAY 14 #define DB9_GENESIS6_DELAY 14
#define DB9_REFRESH_TIME HZ/100 #define DB9_REFRESH_TIME HZ/100
...@@ -98,6 +98,7 @@ struct db9 { ...@@ -98,6 +98,7 @@ struct db9 {
struct pardevice *pd; struct pardevice *pd;
int mode; int mode;
int used; int used;
struct semaphore sem;
char phys[2][32]; char phys[2][32];
}; };
...@@ -503,6 +504,11 @@ static int db9_open(struct input_dev *dev) ...@@ -503,6 +504,11 @@ static int db9_open(struct input_dev *dev)
{ {
struct db9 *db9 = dev->private; struct db9 *db9 = dev->private;
struct parport *port = db9->pd->port; struct parport *port = db9->pd->port;
int err;
err = down_interruptible(&db9->sem);
if (err)
return err;
if (!db9->used++) { if (!db9->used++) {
parport_claim(db9->pd); parport_claim(db9->pd);
...@@ -514,6 +520,7 @@ static int db9_open(struct input_dev *dev) ...@@ -514,6 +520,7 @@ static int db9_open(struct input_dev *dev)
mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME); mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME);
} }
up(&db9->sem);
return 0; return 0;
} }
...@@ -522,12 +529,14 @@ static void db9_close(struct input_dev *dev) ...@@ -522,12 +529,14 @@ static void db9_close(struct input_dev *dev)
struct db9 *db9 = dev->private; struct db9 *db9 = dev->private;
struct parport *port = db9->pd->port; struct parport *port = db9->pd->port;
down(&db9->sem);
if (!--db9->used) { if (!--db9->used) {
del_timer(&db9->timer); del_timer_sync(&db9->timer);
parport_write_control(port, 0x00); parport_write_control(port, 0x00);
parport_data_forward(port); parport_data_forward(port);
parport_release(db9->pd); parport_release(db9->pd);
} }
up(&db9->sem);
} }
static struct db9 __init *db9_probe(int *config, int nargs) static struct db9 __init *db9_probe(int *config, int nargs)
...@@ -563,12 +572,12 @@ static struct db9 __init *db9_probe(int *config, int nargs) ...@@ -563,12 +572,12 @@ static struct db9 __init *db9_probe(int *config, int nargs)
} }
} }
if (!(db9 = kmalloc(sizeof(struct db9), GFP_KERNEL))) { if (!(db9 = kcalloc(1, sizeof(struct db9), GFP_KERNEL))) {
parport_put_port(pp); parport_put_port(pp);
return NULL; return NULL;
} }
memset(db9, 0, sizeof(struct db9));
init_MUTEX(&db9->sem);
db9->mode = config[1]; db9->mode = config[1];
init_timer(&db9->timer); init_timer(&db9->timer);
db9->timer.data = (long) db9; db9->timer.data = (long) db9;
......
/* /*
* NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux
* *
* Copyright (c) 1999-2004 Vojtech Pavlik <vojtech@suse.cz> * Copyright (c) 1999-2004 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (c) 2004 Peter Nelson <rufus-kernel@hackish.org> * Copyright (c) 2004 Peter Nelson <rufus-kernel@hackish.org>
* *
* Based on the work of: * Based on the work of:
* Andree Borrmann John Dahlstrom * Andree Borrmann John Dahlstrom
* David Kuder Nathan Hand * David Kuder Nathan Hand
*/ */
/* /*
...@@ -81,6 +81,7 @@ struct gc { ...@@ -81,6 +81,7 @@ struct gc {
struct timer_list timer; struct timer_list timer;
unsigned char pads[GC_MAX + 1]; unsigned char pads[GC_MAX + 1];
int used; int used;
struct semaphore sem;
char phys[5][32]; char phys[5][32];
}; };
...@@ -433,7 +434,7 @@ static void gc_timer(unsigned long private) ...@@ -433,7 +434,7 @@ static void gc_timer(unsigned long private)
gc_psx_read_packet(gc, data_psx, data); gc_psx_read_packet(gc, data_psx, data);
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++) {
switch (data[i]) { switch (data[i]) {
case GC_PSX_RUMBLE: case GC_PSX_RUMBLE:
...@@ -503,22 +504,33 @@ static void gc_timer(unsigned long private) ...@@ -503,22 +504,33 @@ static void gc_timer(unsigned long private)
static int gc_open(struct input_dev *dev) static int gc_open(struct input_dev *dev)
{ {
struct gc *gc = dev->private; struct gc *gc = dev->private;
int err;
err = down_interruptible(&gc->sem);
if (err)
return err;
if (!gc->used++) { if (!gc->used++) {
parport_claim(gc->pd); parport_claim(gc->pd);
parport_write_control(gc->pd->port, 0x04); parport_write_control(gc->pd->port, 0x04);
mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
} }
up(&gc->sem);
return 0; return 0;
} }
static void gc_close(struct input_dev *dev) static void gc_close(struct input_dev *dev)
{ {
struct gc *gc = dev->private; struct gc *gc = dev->private;
down(&gc->sem);
if (!--gc->used) { if (!--gc->used) {
del_timer(&gc->timer); del_timer_sync(&gc->timer);
parport_write_control(gc->pd->port, 0x00); parport_write_control(gc->pd->port, 0x00);
parport_release(gc->pd); parport_release(gc->pd);
} }
up(&gc->sem);
} }
static struct gc __init *gc_probe(int *config, int nargs) static struct gc __init *gc_probe(int *config, int nargs)
...@@ -542,11 +554,12 @@ static struct gc __init *gc_probe(int *config, int nargs) ...@@ -542,11 +554,12 @@ static struct gc __init *gc_probe(int *config, int nargs)
return NULL; return NULL;
} }
if (!(gc = kmalloc(sizeof(struct gc), GFP_KERNEL))) { if (!(gc = kcalloc(1, sizeof(struct gc), GFP_KERNEL))) {
parport_put_port(pp); parport_put_port(pp);
return NULL; return NULL;
} }
memset(gc, 0, sizeof(struct gc));
init_MUTEX(&gc->sem);
gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
......
...@@ -329,7 +329,7 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv) ...@@ -329,7 +329,7 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
for (i = 0; i < gf2k_axes[gf2k->id]; i++) { for (i = 0; i < gf2k_axes[gf2k->id]; i++) {
gf2k->dev.absmax[gf2k_abs[i]] = (i < 2) ? gf2k->dev.abs[gf2k_abs[i]] * 2 - 32 : gf2k->dev.absmax[gf2k_abs[i]] = (i < 2) ? gf2k->dev.abs[gf2k_abs[i]] * 2 - 32 :
gf2k->dev.abs[gf2k_abs[0]] + gf2k->dev.abs[gf2k_abs[1]] - 32; gf2k->dev.abs[gf2k_abs[0]] + gf2k->dev.abs[gf2k_abs[1]] - 32;
gf2k->dev.absmin[gf2k_abs[i]] = 32; gf2k->dev.absmin[gf2k_abs[i]] = 32;
gf2k->dev.absfuzz[gf2k_abs[i]] = 8; gf2k->dev.absfuzz[gf2k_abs[i]] = 8;
gf2k->dev.absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0; gf2k->dev.absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0;
......
...@@ -171,7 +171,7 @@ static int mp_io(struct gameport* gameport, int sendflags, int sendcode, u32 *pa ...@@ -171,7 +171,7 @@ static int mp_io(struct gameport* gameport, int sendflags, int sendcode, u32 *pa
*packet = 0; *packet = 0;
raw_data = gameport_read(gameport); raw_data = gameport_read(gameport);
if (raw_data & 1) if (raw_data & 1)
return IO_RETRY; return IO_RETRY;
for (i = 0; i < 64; i++) { for (i = 0; i < 64; i++) {
raw_data = gameport_read(gameport); raw_data = gameport_read(gameport);
......
...@@ -78,6 +78,7 @@ static struct iforce_device iforce_device[] = { ...@@ -78,6 +78,7 @@ static struct iforce_device iforce_device[] = {
{ 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //? { 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //? { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //? { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //?
{ 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce } { 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce }
}; };
......
...@@ -229,6 +229,7 @@ static struct usb_device_id iforce_usb_ids [] = { ...@@ -229,6 +229,7 @@ static struct usb_device_id iforce_usb_ids [] = {
{ USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */ { USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */
{ USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */ { USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */
{ USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */ { USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */
{ USB_DEVICE(0x06f8, 0xa302) }, /* Guillemot Jet Leader 3D */
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
......
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
* Copyright (c) 1999-2001 Vojtech Pavlik * Copyright (c) 1999-2001 Vojtech Pavlik
* *
* Based on the work of: * Based on the work of:
* David Thompson * David Thompson
* Joseph Krahn * Joseph Krahn
*/ */
/* /*
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Copyright (c) 1999-2001 Vojtech Pavlik * Copyright (c) 1999-2001 Vojtech Pavlik
* *
* Based on the work of: * Based on the work of:
* David Thompson * David Thompson
*/ */
/* /*
......
...@@ -79,7 +79,7 @@ static short tmdc_btn_pad[TMDC_BTN] = ...@@ -79,7 +79,7 @@ static short tmdc_btn_pad[TMDC_BTN] =
{ BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_START, BTN_SELECT, BTN_TL, BTN_TR }; { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_START, BTN_SELECT, BTN_TL, BTN_TR };
static short tmdc_btn_joy[TMDC_BTN] = static short tmdc_btn_joy[TMDC_BTN] =
{ BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_THUMB2, BTN_PINKIE, { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_THUMB2, BTN_PINKIE,
BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z }; BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z };
static short tmdc_btn_fm[TMDC_BTN] = static short tmdc_btn_fm[TMDC_BTN] =
{ BTN_TRIGGER, BTN_C, BTN_B, BTN_A, BTN_THUMB, BTN_X, BTN_Y, BTN_Z, BTN_TOP, BTN_TOP2 }; { BTN_TRIGGER, BTN_C, BTN_B, BTN_A, BTN_THUMB, BTN_X, BTN_Y, BTN_Z, BTN_TOP, BTN_TOP2 };
static short tmdc_btn_at[TMDC_BTN] = static short tmdc_btn_at[TMDC_BTN] =
......
...@@ -84,6 +84,7 @@ static struct tgfx { ...@@ -84,6 +84,7 @@ static struct tgfx {
char phys[7][32]; char phys[7][32];
int sticks; int sticks;
int used; int used;
struct semaphore sem;
} *tgfx_base[3]; } *tgfx_base[3];
/* /*
...@@ -99,7 +100,7 @@ static void tgfx_timer(unsigned long private) ...@@ -99,7 +100,7 @@ static void tgfx_timer(unsigned long private)
for (i = 0; i < 7; i++) for (i = 0; i < 7; i++)
if (tgfx->sticks & (1 << i)) { if (tgfx->sticks & (1 << i)) {
dev = tgfx->dev + i; dev = tgfx->dev + i;
parport_write_data(tgfx->pd->port, ~(1 << i)); parport_write_data(tgfx->pd->port, ~(1 << i));
data1 = parport_read_status(tgfx->pd->port) ^ 0x7f; data1 = parport_read_status(tgfx->pd->port) ^ 0x7f;
...@@ -122,23 +123,34 @@ static void tgfx_timer(unsigned long private) ...@@ -122,23 +123,34 @@ static void tgfx_timer(unsigned long private)
static int tgfx_open(struct input_dev *dev) static int tgfx_open(struct input_dev *dev)
{ {
struct tgfx *tgfx = dev->private; struct tgfx *tgfx = dev->private;
if (!tgfx->used++) { int err;
err = down_interruptible(&tgfx->sem);
if (err)
return err;
if (!tgfx->used++) {
parport_claim(tgfx->pd); parport_claim(tgfx->pd);
parport_write_control(tgfx->pd->port, 0x04); parport_write_control(tgfx->pd->port, 0x04);
mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME); mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME);
} }
return 0;
up(&tgfx->sem);
return 0;
} }
static void tgfx_close(struct input_dev *dev) static void tgfx_close(struct input_dev *dev)
{ {
struct tgfx *tgfx = dev->private; struct tgfx *tgfx = dev->private;
if (!--tgfx->used) {
del_timer(&tgfx->timer); down(&tgfx->sem);
if (!--tgfx->used) {
del_timer_sync(&tgfx->timer);
parport_write_control(tgfx->pd->port, 0x00); parport_write_control(tgfx->pd->port, 0x00);
parport_release(tgfx->pd); parport_release(tgfx->pd);
} }
up(&tgfx->sem);
} }
/* /*
...@@ -166,11 +178,12 @@ static struct tgfx __init *tgfx_probe(int *config, int nargs) ...@@ -166,11 +178,12 @@ static struct tgfx __init *tgfx_probe(int *config, int nargs)
return NULL; return NULL;
} }
if (!(tgfx = kmalloc(sizeof(struct tgfx), GFP_KERNEL))) { if (!(tgfx = kcalloc(1, sizeof(struct tgfx), GFP_KERNEL))) {
parport_put_port(pp); parport_put_port(pp);
return NULL; return NULL;
} }
memset(tgfx, 0, sizeof(struct tgfx));
init_MUTEX(&tgfx->sem);
tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
......
...@@ -227,7 +227,7 @@ static ssize_t atkbd_do_set_##_name(struct device *d, struct device_attribute *a ...@@ -227,7 +227,7 @@ static ssize_t atkbd_do_set_##_name(struct device *d, struct device_attribute *a
{ \ { \
return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name); \ return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name); \
} \ } \
static struct device_attribute atkbd_attr_##_name = \ static struct device_attribute atkbd_attr_##_name = \
__ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name); __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name);
ATKBD_DEFINE_ATTR(extra); ATKBD_DEFINE_ATTR(extra);
...@@ -388,7 +388,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, ...@@ -388,7 +388,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
value = atkbd->release ? 0 : value = atkbd->release ? 0 :
(1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key))); (1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key)));
switch (value) { /* Workaround Toshiba laptop multiple keypress */ switch (value) { /* Workaround Toshiba laptop multiple keypress */
case 0: case 0:
atkbd->last = 0; atkbd->last = 0;
break; break;
...@@ -894,7 +894,7 @@ static int atkbd_reconnect(struct serio *serio) ...@@ -894,7 +894,7 @@ static int atkbd_reconnect(struct serio *serio)
if (atkbd->write) { if (atkbd->write) {
param[0] = (test_bit(LED_SCROLLL, atkbd->dev.led) ? 1 : 0) param[0] = (test_bit(LED_SCROLLL, atkbd->dev.led) ? 1 : 0)
| (test_bit(LED_NUML, atkbd->dev.led) ? 2 : 0) | (test_bit(LED_NUML, atkbd->dev.led) ? 2 : 0)
| (test_bit(LED_CAPSL, atkbd->dev.led) ? 4 : 0); | (test_bit(LED_CAPSL, atkbd->dev.led) ? 4 : 0);
if (atkbd_probe(atkbd)) if (atkbd_probe(atkbd))
return -1; return -1;
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#define CORGI_KEY_CALENDER KEY_F1 #define CORGI_KEY_CALENDER KEY_F1
#define CORGI_KEY_ADDRESS KEY_F2 #define CORGI_KEY_ADDRESS KEY_F2
#define CORGI_KEY_FN KEY_F3 #define CORGI_KEY_FN KEY_F3
#define CORGI_KEY_CANCEL KEY_F4
#define CORGI_KEY_OFF KEY_SUSPEND #define CORGI_KEY_OFF KEY_SUSPEND
#define CORGI_KEY_EXOK KEY_F5 #define CORGI_KEY_EXOK KEY_F5
#define CORGI_KEY_EXCANCEL KEY_F6 #define CORGI_KEY_EXCANCEL KEY_F6
...@@ -46,6 +47,7 @@ ...@@ -46,6 +47,7 @@
#define CORGI_KEY_EXJOGUP KEY_F8 #define CORGI_KEY_EXJOGUP KEY_F8
#define CORGI_KEY_JAP1 KEY_LEFTCTRL #define CORGI_KEY_JAP1 KEY_LEFTCTRL
#define CORGI_KEY_JAP2 KEY_LEFTALT #define CORGI_KEY_JAP2 KEY_LEFTALT
#define CORGI_KEY_MAIL KEY_F10
#define CORGI_KEY_OK KEY_F11 #define CORGI_KEY_OK KEY_F11
#define CORGI_KEY_MENU KEY_F12 #define CORGI_KEY_MENU KEY_F12
#define CORGI_HINGE_0 KEY_KP0 #define CORGI_HINGE_0 KEY_KP0
...@@ -59,8 +61,8 @@ static unsigned char corgikbd_keycode[NR_SCANCODES] = { ...@@ -59,8 +61,8 @@ static unsigned char corgikbd_keycode[NR_SCANCODES] = {
KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */
CORGI_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ CORGI_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */
CORGI_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, /* 65-80 */ CORGI_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, /* 65-80 */
KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */ CORGI_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */
KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */ KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, CORGI_KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */
CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */ CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */
CORGI_HINGE_0, CORGI_HINGE_1, CORGI_HINGE_2 /* 125-127 */ CORGI_HINGE_0, CORGI_HINGE_1, CORGI_HINGE_2 /* 125-127 */
}; };
......
...@@ -15,10 +15,10 @@ ...@@ -15,10 +15,10 @@
* information given below, I will _not_ be liable! * information given below, I will _not_ be liable!
* *
* RJ10 pinout: To DE9: Or DB25: * RJ10 pinout: To DE9: Or DB25:
* 1 - RxD <----> Pin 3 (TxD) <-> Pin 2 (TxD) * 1 - RxD <----> Pin 3 (TxD) <-> Pin 2 (TxD)
* 2 - GND <----> Pin 5 (GND) <-> Pin 7 (GND) * 2 - GND <----> Pin 5 (GND) <-> Pin 7 (GND)
* 4 - TxD <----> Pin 2 (RxD) <-> Pin 3 (RxD) * 4 - TxD <----> Pin 2 (RxD) <-> Pin 3 (RxD)
* 3 - +12V (from HDD drive connector), DON'T connect to DE9 or DB25!!! * 3 - +12V (from HDD drive connector), DON'T connect to DE9 or DB25!!!
* *
* Pin numbers for DE9 and DB25 are noted on the plug (quite small:). For * Pin numbers for DE9 and DB25 are noted on the plug (quite small:). For
* RJ10, it's like this: * RJ10, it's like this:
......
...@@ -42,7 +42,7 @@ MODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>"); ...@@ -42,7 +42,7 @@ MODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>");
MODULE_DESCRIPTION("LoCoMo keyboard driver"); MODULE_DESCRIPTION("LoCoMo keyboard driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#define LOCOMOKBD_NUMKEYS 128 #define LOCOMOKBD_NUMKEYS 128
#define KEY_ACTIVITY KEY_F16 #define KEY_ACTIVITY KEY_F16
#define KEY_CONTACT KEY_F18 #define KEY_CONTACT KEY_F18
...@@ -61,7 +61,7 @@ static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = { ...@@ -61,7 +61,7 @@ static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = {
KEY_G, KEY_F, KEY_X, KEY_S, 0, 0, 0, 0, 0, 0, /* 90 - 99 */ KEY_G, KEY_F, KEY_X, KEY_S, 0, 0, 0, 0, 0, 0, /* 90 - 99 */
0, 0, KEY_DOT, 0, KEY_COMMA, KEY_N, KEY_B, KEY_C, KEY_Z, KEY_A, /* 100 - 109 */ 0, 0, KEY_DOT, 0, KEY_COMMA, KEY_N, KEY_B, KEY_C, KEY_Z, KEY_A, /* 100 - 109 */
KEY_LEFTSHIFT, KEY_TAB, KEY_LEFTCTRL, 0, 0, 0, 0, 0, 0, 0, /* 110 - 119 */ KEY_LEFTSHIFT, KEY_TAB, KEY_LEFTCTRL, 0, 0, 0, 0, 0, 0, 0, /* 110 - 119 */
KEY_M, KEY_SPACE, KEY_V, KEY_APOSTROPHE, KEY_SLASH, 0, 0, 0 /* 120 - 128 */ KEY_M, KEY_SPACE, KEY_V, KEY_APOSTROPHE, KEY_SLASH, 0, 0, 0 /* 120 - 128 */
}; };
#define KB_ROWS 16 #define KB_ROWS 16
...@@ -82,7 +82,7 @@ struct locomokbd { ...@@ -82,7 +82,7 @@ struct locomokbd {
struct locomo_dev *ldev; struct locomo_dev *ldev;
unsigned long base; unsigned long base;
spinlock_t lock; spinlock_t lock;
struct timer_list timer; struct timer_list timer;
}; };
...@@ -95,7 +95,7 @@ static inline void locomokbd_charge_all(unsigned long membase) ...@@ -95,7 +95,7 @@ static inline void locomokbd_charge_all(unsigned long membase)
static inline void locomokbd_activate_all(unsigned long membase) static inline void locomokbd_activate_all(unsigned long membase)
{ {
unsigned long r; unsigned long r;
locomo_writel(0, membase + LOCOMO_KSC); locomo_writel(0, membase + LOCOMO_KSC);
r = locomo_readl(membase + LOCOMO_KIC); r = locomo_readl(membase + LOCOMO_KIC);
r &= 0xFEFF; r &= 0xFEFF;
...@@ -127,7 +127,7 @@ static inline void locomokbd_reset_col(unsigned long membase, int col) ...@@ -127,7 +127,7 @@ static inline void locomokbd_reset_col(unsigned long membase, int col)
*/ */
/* Scan the hardware keyboard and push any changes up through the input layer */ /* Scan the hardware keyboard and push any changes up through the input layer */
static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *regs) static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *regs)
{ {
unsigned int row, col, rowd, scancode; unsigned int row, col, rowd, scancode;
unsigned long flags; unsigned long flags;
...@@ -138,7 +138,7 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs * ...@@ -138,7 +138,7 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *
if (regs) if (regs)
input_regs(&locomokbd->input, regs); input_regs(&locomokbd->input, regs);
locomokbd_charge_all(membase); locomokbd_charge_all(membase);
num_pressed = 0; num_pressed = 0;
...@@ -146,9 +146,9 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs * ...@@ -146,9 +146,9 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *
locomokbd_activate_col(membase, col); locomokbd_activate_col(membase, col);
udelay(KB_DELAY); udelay(KB_DELAY);
rowd = ~locomo_readl(membase + LOCOMO_KIB); rowd = ~locomo_readl(membase + LOCOMO_KIB);
for (row = 0; row < KB_ROWS; row++ ) { for (row = 0; row < KB_ROWS; row++) {
scancode = SCANCODE(col, row); scancode = SCANCODE(col, row);
if (rowd & KB_ROWMASK(row)) { if (rowd & KB_ROWMASK(row)) {
num_pressed += 1; num_pressed += 1;
...@@ -170,7 +170,7 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs * ...@@ -170,7 +170,7 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *
spin_unlock_irqrestore(&locomokbd->lock, flags); spin_unlock_irqrestore(&locomokbd->lock, flags);
} }
/* /*
* LoCoMo keyboard interrupt handler. * LoCoMo keyboard interrupt handler.
*/ */
static irqreturn_t locomokbd_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t locomokbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
...@@ -205,8 +205,8 @@ static int locomokbd_probe(struct locomo_dev *dev) ...@@ -205,8 +205,8 @@ static int locomokbd_probe(struct locomo_dev *dev)
memset(locomokbd, 0, sizeof(struct locomokbd)); memset(locomokbd, 0, sizeof(struct locomokbd));
/* try and claim memory region */ /* try and claim memory region */
if (!request_mem_region((unsigned long) dev->mapbase, if (!request_mem_region((unsigned long) dev->mapbase,
dev->length, dev->length,
LOCOMO_DRIVER_NAME(dev))) { LOCOMO_DRIVER_NAME(dev))) {
ret = -EBUSY; ret = -EBUSY;
printk(KERN_ERR "locomokbd: Can't acquire access to io memory for keyboard\n"); printk(KERN_ERR "locomokbd: Can't acquire access to io memory for keyboard\n");
...@@ -225,7 +225,7 @@ static int locomokbd_probe(struct locomo_dev *dev) ...@@ -225,7 +225,7 @@ static int locomokbd_probe(struct locomo_dev *dev)
locomokbd->timer.data = (unsigned long) locomokbd; locomokbd->timer.data = (unsigned long) locomokbd;
locomokbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); locomokbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
init_input_dev(&locomokbd->input); init_input_dev(&locomokbd->input);
locomokbd->input.keycode = locomokbd->keycode; locomokbd->input.keycode = locomokbd->keycode;
locomokbd->input.keycodesize = sizeof(unsigned char); locomokbd->input.keycodesize = sizeof(unsigned char);
...@@ -271,11 +271,11 @@ static int locomokbd_probe(struct locomo_dev *dev) ...@@ -271,11 +271,11 @@ static int locomokbd_probe(struct locomo_dev *dev)
static int locomokbd_remove(struct locomo_dev *dev) static int locomokbd_remove(struct locomo_dev *dev)
{ {
struct locomokbd *locomokbd = locomo_get_drvdata(dev); struct locomokbd *locomokbd = locomo_get_drvdata(dev);
free_irq(dev->irq[0], locomokbd); free_irq(dev->irq[0], locomokbd);
del_timer_sync(&locomokbd->timer); del_timer_sync(&locomokbd->timer);
input_unregister_device(&locomokbd->input); input_unregister_device(&locomokbd->input);
locomo_set_drvdata(dev, NULL); locomo_set_drvdata(dev, NULL);
......
/* /*
* $Id: maple_keyb.c,v 1.4 2004/03/22 01:18:15 lethal Exp $ * $Id: maple_keyb.c,v 1.4 2004/03/22 01:18:15 lethal Exp $
* SEGA Dreamcast keyboard driver * SEGA Dreamcast keyboard driver
* Based on drivers/usb/usbkbd.c * Based on drivers/usb/usbkbd.c
*/ */
...@@ -40,7 +40,6 @@ struct dc_kbd { ...@@ -40,7 +40,6 @@ struct dc_kbd {
struct input_dev dev; struct input_dev dev;
unsigned char new[8]; unsigned char new[8];
unsigned char old[8]; unsigned char old[8];
int open;
}; };
...@@ -95,22 +94,6 @@ static void dc_kbd_callback(struct mapleq *mq) ...@@ -95,22 +94,6 @@ static void dc_kbd_callback(struct mapleq *mq)
} }
} }
static int dc_kbd_open(struct input_dev *dev)
{
struct dc_kbd *kbd = dev->private;
kbd->open++;
return 0;
}
static void dc_kbd_close(struct input_dev *dev)
{
struct dc_kbd *kbd = dev->private;
kbd->open--;
}
static int dc_kbd_connect(struct maple_device *dev) static int dc_kbd_connect(struct maple_device *dev)
{ {
int i; int i;
...@@ -133,9 +116,6 @@ static int dc_kbd_connect(struct maple_device *dev) ...@@ -133,9 +116,6 @@ static int dc_kbd_connect(struct maple_device *dev)
clear_bit(0, kbd->dev.keybit); clear_bit(0, kbd->dev.keybit);
kbd->dev.private = kbd; kbd->dev.private = kbd;
kbd->dev.open = dc_kbd_open;
kbd->dev.close = dc_kbd_close;
kbd->dev.event = NULL;
kbd->dev.name = dev->product_name; kbd->dev.name = dev->product_name;
kbd->dev.id.bustype = BUS_MAPLE; kbd->dev.id.bustype = BUS_MAPLE;
......
...@@ -298,9 +298,11 @@ static int uinput_alloc_device(struct file *file, const char __user *buffer, siz ...@@ -298,9 +298,11 @@ static int uinput_alloc_device(struct file *file, const char __user *buffer, siz
/* check if absmin/absmax/absfuzz/absflat are filled as /* check if absmin/absmax/absfuzz/absflat are filled as
* told in Documentation/input/input-programming.txt */ * told in Documentation/input/input-programming.txt */
if (test_bit(EV_ABS, dev->evbit)) { if (test_bit(EV_ABS, dev->evbit)) {
retval = uinput_validate_absbits(dev); int err = uinput_validate_absbits(dev);
if (retval < 0) if (err < 0) {
retval = err;
kfree(dev->name); kfree(dev->name);
}
} }
exit: exit:
......
...@@ -15,4 +15,4 @@ obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o ...@@ -15,4 +15,4 @@ obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o
obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o
psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o
...@@ -30,10 +30,11 @@ ...@@ -30,10 +30,11 @@
#define ALPS_DUALPOINT 0x01 #define ALPS_DUALPOINT 0x01
#define ALPS_WHEEL 0x02 #define ALPS_WHEEL 0x02
#define ALPS_FW_BK 0x04 #define ALPS_FW_BK_1 0x04
#define ALPS_4BTN 0x08 #define ALPS_4BTN 0x08
#define ALPS_OLDPROTO 0x10 #define ALPS_OLDPROTO 0x10
#define ALPS_PASS 0x20 #define ALPS_PASS 0x20
#define ALPS_FW_BK_2 0x40
static struct alps_model_info alps_model_data[] = { 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 */
...@@ -43,11 +44,11 @@ static struct alps_model_info alps_model_data[] = { ...@@ -43,11 +44,11 @@ static struct alps_model_info alps_model_data[] = {
{ { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, { { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
{ { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, 0 }, { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, 0 },
{ { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ { { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */
{ { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK }, /* NEC Versa L320 */ { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */
{ { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 },
{ { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */ { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */
{ { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
{ { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */
{ { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */
{ { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },
{ { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */
...@@ -61,11 +62,11 @@ static struct alps_model_info alps_model_data[] = { ...@@ -61,11 +62,11 @@ static struct alps_model_info alps_model_data[] = {
/* /*
* ALPS abolute Mode - new format * ALPS abolute Mode - new format
* *
* byte 0: 1 ? ? ? 1 ? ? ? * byte 0: 1 ? ? ? 1 ? ? ?
* byte 1: 0 x6 x5 x4 x3 x2 x1 x0 * byte 1: 0 x6 x5 x4 x3 x2 x1 x0
* byte 2: 0 x10 x9 x8 x7 ? fin ges * byte 2: 0 x10 x9 x8 x7 ? fin ges
* byte 3: 0 y9 y8 y7 1 M R L * byte 3: 0 y9 y8 y7 1 M R L
* byte 4: 0 y6 y5 y4 y3 y2 y1 y0 * byte 4: 0 y6 y5 y4 y3 y2 y1 y0
* byte 5: 0 z6 z5 z4 z3 z2 z1 z0 * byte 5: 0 z6 z5 z4 z3 z2 z1 z0
* *
...@@ -81,11 +82,12 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs) ...@@ -81,11 +82,12 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
struct input_dev *dev = &psmouse->dev; struct input_dev *dev = &psmouse->dev;
struct input_dev *dev2 = &priv->dev2; struct input_dev *dev2 = &priv->dev2;
int x, y, z, ges, fin, left, right, middle; int x, y, z, ges, fin, left, right, middle;
int back = 0, forward = 0;
input_regs(dev, regs); input_regs(dev, regs);
if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */ if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */
input_report_key(dev2, BTN_LEFT, packet[0] & 1); input_report_key(dev2, BTN_LEFT, packet[0] & 1);
input_report_key(dev2, BTN_RIGHT, packet[0] & 2); input_report_key(dev2, BTN_RIGHT, packet[0] & 2);
input_report_key(dev2, BTN_MIDDLE, packet[0] & 4); input_report_key(dev2, BTN_MIDDLE, packet[0] & 4);
input_report_rel(dev2, REL_X, input_report_rel(dev2, REL_X,
...@@ -112,6 +114,18 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs) ...@@ -112,6 +114,18 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
z = packet[5]; z = packet[5];
} }
if (priv->i->flags & ALPS_FW_BK_1) {
back = packet[2] & 4;
forward = packet[0] & 0x10;
}
if (priv->i->flags & ALPS_FW_BK_2) {
back = packet[3] & 4;
forward = packet[2] & 4;
if ((middle = forward && back))
forward = back = 0;
}
ges = packet[2] & 1; ges = packet[2] & 1;
fin = packet[2] & 2; fin = packet[2] & 2;
...@@ -155,13 +169,12 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs) ...@@ -155,13 +169,12 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
input_report_abs(dev, ABS_PRESSURE, z); input_report_abs(dev, ABS_PRESSURE, z);
input_report_key(dev, BTN_TOOL_FINGER, z > 0); input_report_key(dev, BTN_TOOL_FINGER, z > 0);
if (priv->i->flags & ALPS_WHEEL) if (priv->i->flags & ALPS_WHEEL)
input_report_rel(dev, REL_WHEEL, ((packet[0] >> 4) & 0x07) | ((packet[2] >> 2) & 0x08)); input_report_rel(dev, REL_WHEEL, ((packet[0] >> 4) & 0x07) | ((packet[2] >> 2) & 0x08));
if (priv->i->flags & ALPS_FW_BK) { if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
input_report_key(dev, BTN_FORWARD, packet[0] & 0x10); input_report_key(dev, BTN_FORWARD, forward);
input_report_key(dev, BTN_BACK, packet[2] & 0x04); input_report_key(dev, BTN_BACK, back);
} }
input_sync(dev); input_sync(dev);
...@@ -257,7 +270,6 @@ static struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *vers ...@@ -257,7 +270,6 @@ static struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *vers
static int alps_passthrough_mode(struct psmouse *psmouse, int enable) static int alps_passthrough_mode(struct psmouse *psmouse, int enable)
{ {
struct ps2dev *ps2dev = &psmouse->ps2dev; struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char param[3];
int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11;
if (ps2_command(ps2dev, NULL, cmd) || if (ps2_command(ps2dev, NULL, cmd) ||
...@@ -267,7 +279,7 @@ static int alps_passthrough_mode(struct psmouse *psmouse, int enable) ...@@ -267,7 +279,7 @@ static int alps_passthrough_mode(struct psmouse *psmouse, int enable)
return -1; return -1;
/* we may get 3 more bytes, just ignore them */ /* we may get 3 more bytes, just ignore them */
ps2_command(ps2dev, param, 0x0300); ps2_drain(ps2dev, 3, 100);
return 0; return 0;
} }
...@@ -425,7 +437,7 @@ int alps_init(struct psmouse *psmouse) ...@@ -425,7 +437,7 @@ int alps_init(struct psmouse *psmouse)
psmouse->dev.relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL); psmouse->dev.relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL);
} }
if (priv->i->flags & ALPS_FW_BK) { if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD); psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD);
psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK); psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK);
} }
...@@ -436,8 +448,8 @@ int alps_init(struct psmouse *psmouse) ...@@ -436,8 +448,8 @@ int alps_init(struct psmouse *psmouse)
priv->dev2.id.bustype = BUS_I8042; priv->dev2.id.bustype = BUS_I8042;
priv->dev2.id.vendor = 0x0002; priv->dev2.id.vendor = 0x0002;
priv->dev2.id.product = PSMOUSE_ALPS; priv->dev2.id.product = PSMOUSE_ALPS;
priv->dev2.id.version = 0x0000; priv->dev2.id.version = 0x0000;
priv->dev2.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); priv->dev2.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
priv->dev2.relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y); priv->dev2.relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y);
priv->dev2.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); priv->dev2.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
...@@ -461,17 +473,15 @@ int alps_init(struct psmouse *psmouse) ...@@ -461,17 +473,15 @@ int alps_init(struct psmouse *psmouse)
int alps_detect(struct psmouse *psmouse, int set_properties) int alps_detect(struct psmouse *psmouse, int set_properties)
{ {
int version; int version;
struct alps_model_info *model; struct alps_model_info *model;
if (!(model = alps_get_model(psmouse, &version))) if (!(model = alps_get_model(psmouse, &version)))
return -1; return -1;
if (set_properties) { if (set_properties) {
psmouse->vendor = "ALPS"; psmouse->vendor = "ALPS";
if (model->flags & ALPS_DUALPOINT) psmouse->name = model->flags & ALPS_DUALPOINT ?
psmouse->name = "DualPoint TouchPad"; "DualPoint TouchPad" : "GlidePoint";
else
psmouse->name = "GlidePoint";
psmouse->model = version; psmouse->model = version;
} }
return 0; return 0;
......
...@@ -33,7 +33,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); ...@@ -33,7 +33,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Amiga mouse driver"); MODULE_DESCRIPTION("Amiga mouse driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static int amimouse_used = 0;
static int amimouse_lastx, amimouse_lasty; static int amimouse_lastx, amimouse_lasty;
static struct input_dev amimouse_dev; static struct input_dev amimouse_dev;
...@@ -81,16 +80,12 @@ static int amimouse_open(struct input_dev *dev) ...@@ -81,16 +80,12 @@ static int amimouse_open(struct input_dev *dev)
{ {
unsigned short joy0dat; unsigned short joy0dat;
if (amimouse_used++)
return 0;
joy0dat = custom.joy0dat; joy0dat = custom.joy0dat;
amimouse_lastx = joy0dat & 0xff; amimouse_lastx = joy0dat & 0xff;
amimouse_lasty = joy0dat >> 8; amimouse_lasty = joy0dat >> 8;
if (request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse", amimouse_interrupt)) { if (request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse", amimouse_interrupt)) {
amimouse_used--;
printk(KERN_ERR "amimouse.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB); printk(KERN_ERR "amimouse.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB);
return -EBUSY; return -EBUSY;
} }
...@@ -100,8 +95,7 @@ static int amimouse_open(struct input_dev *dev) ...@@ -100,8 +95,7 @@ static int amimouse_open(struct input_dev *dev)
static void amimouse_close(struct input_dev *dev) static void amimouse_close(struct input_dev *dev)
{ {
if (!--amimouse_used) free_irq(IRQ_AMIGA_VERTB, amimouse_interrupt);
free_irq(IRQ_AMIGA_VERTB, amimouse_interrupt);
} }
static int __init amimouse_init(void) static int __init amimouse_init(void)
......
...@@ -17,18 +17,18 @@ ...@@ -17,18 +17,18 @@
/* /*
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
* Should you need to contact me, the author, you can do so either by * Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
...@@ -87,29 +87,23 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)"); ...@@ -87,29 +87,23 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)");
__obsolete_setup("inport_irq="); __obsolete_setup("inport_irq=");
static int inport_used;
static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int inport_open(struct input_dev *dev) static int inport_open(struct input_dev *dev)
{ {
if (!inport_used++) { if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL))
if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL)) return -EBUSY;
return -EBUSY; outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
}
return 0; return 0;
} }
static void inport_close(struct input_dev *dev) static void inport_close(struct input_dev *dev)
{ {
if (!--inport_used) { outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
outb(INPORT_MODE_BASE, INPORT_DATA_PORT); free_irq(inport_irq, NULL);
free_irq(inport_irq, NULL);
}
} }
static struct input_dev inport_dev = { static struct input_dev inport_dev = {
...@@ -120,11 +114,11 @@ static struct input_dev inport_dev = { ...@@ -120,11 +114,11 @@ static struct input_dev inport_dev = {
.close = inport_close, .close = inport_close,
.name = INPORT_NAME, .name = INPORT_NAME,
.phys = "isa023c/input0", .phys = "isa023c/input0",
.id = { .id = {
.bustype = BUS_ISA, .bustype = BUS_ISA,
.vendor = INPORT_VENDOR, .vendor = INPORT_VENDOR,
.product = 0x0001, .product = 0x0001,
.version = 0x0100, .version = 0x0100,
}, },
}; };
......
/*
* Fujitsu B-series Lifebook PS/2 TouchScreen driver
*
* Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (c) 2005 Kenan Esau <kenan.esau@conan.de>
*
* TouchScreen detection, absolute mode setting and packet layout is taken from
* Harald Hoyer's description of the device.
*
* 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 <linux/input.h>
#include <linux/serio.h>
#include <linux/libps2.h>
#include <linux/dmi.h>
#include "psmouse.h"
#include "lifebook.h"
static struct dmi_system_id lifebook_dmi_table[] = {
{
.ident = "Lifebook B",
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"),
},
},
{ }
};
static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
{
unsigned char *packet = psmouse->packet;
struct input_dev *dev = &psmouse->dev;
if (psmouse->pktcnt != 3)
return PSMOUSE_GOOD_DATA;
input_regs(dev, regs);
/* calculate X and Y */
if ((packet[0] & 0x08) == 0x00) {
input_report_abs(dev, ABS_X,
(packet[1] | ((packet[0] & 0x30) << 4)));
input_report_abs(dev, ABS_Y,
1024 - (packet[2] | ((packet[0] & 0xC0) << 2)));
} else {
input_report_rel(dev, REL_X,
((packet[0] & 0x10) ? packet[1] - 256 : packet[1]));
input_report_rel(dev, REL_Y,
-(int)((packet[0] & 0x20) ? packet[2] - 256 : packet[2]));
}
input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
input_report_key(dev, BTN_TOUCH, packet[0] & 0x04);
input_sync(dev);
return PSMOUSE_FULL_PACKET;
}
static int lifebook_absolute_mode(struct psmouse *psmouse)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char param;
if (psmouse_reset(psmouse))
return -1;
/*
Enable absolute output -- ps2_command fails always but if
you leave this call out the touchsreen will never send
absolute coordinates
*/
param = 0x07;
ps2_command(ps2dev, &param, PSMOUSE_CMD_SETRES);
return 0;
}
static void lifebook_set_resolution(struct psmouse *psmouse, unsigned int resolution)
{
unsigned char params[] = { 0, 1, 2, 2, 3 };
if (resolution == 0 || resolution > 400)
resolution = 400;
ps2_command(&psmouse->ps2dev, &params[resolution / 100], PSMOUSE_CMD_SETRES);
psmouse->resolution = 50 << params[resolution / 100];
}
static void lifebook_disconnect(struct psmouse *psmouse)
{
psmouse_reset(psmouse);
}
int lifebook_detect(struct psmouse *psmouse, int set_properties)
{
if (!dmi_check_system(lifebook_dmi_table))
return -1;
if (set_properties) {
psmouse->vendor = "Fujitsu";
psmouse->name = "Lifebook TouchScreen";
}
return 0;
}
int lifebook_init(struct psmouse *psmouse)
{
if (lifebook_absolute_mode(psmouse))
return -1;
psmouse->dev.evbit[0] = BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
psmouse->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
psmouse->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
input_set_abs_params(&psmouse->dev, ABS_X, 0, 1024, 0, 0);
input_set_abs_params(&psmouse->dev, ABS_Y, 0, 1024, 0, 0);
psmouse->protocol_handler = lifebook_process_byte;
psmouse->set_resolution = lifebook_set_resolution;
psmouse->disconnect = lifebook_disconnect;
psmouse->reconnect = lifebook_absolute_mode;
psmouse->pktsize = 3;
return 0;
}
/*
* Fujitsu B-series Lifebook PS/2 TouchScreen driver
*
* Copyright (c) 2005 Vojtech Pavlik
*
* 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.
*/
#ifndef _LIFEBOOK_H
#define _LIFEBOOK_H
int lifebook_detect(struct psmouse *psmouse, int set_properties);
int lifebook_init(struct psmouse *psmouse);
#endif
...@@ -18,18 +18,18 @@ ...@@ -18,18 +18,18 @@
/* /*
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
* Should you need to contact me, the author, you can do so either by * Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
...@@ -77,16 +77,11 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)"); ...@@ -77,16 +77,11 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)");
__obsolete_setup("logibm_irq="); __obsolete_setup("logibm_irq=");
static int logibm_used = 0;
static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int logibm_open(struct input_dev *dev) static int logibm_open(struct input_dev *dev)
{ {
if (logibm_used++)
return 0;
if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) { if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) {
logibm_used--;
printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq); printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq);
return -EBUSY; return -EBUSY;
} }
...@@ -96,8 +91,6 @@ static int logibm_open(struct input_dev *dev) ...@@ -96,8 +91,6 @@ static int logibm_open(struct input_dev *dev)
static void logibm_close(struct input_dev *dev) static void logibm_close(struct input_dev *dev)
{ {
if (--logibm_used)
return;
outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT); outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
free_irq(logibm_irq, NULL); free_irq(logibm_irq, NULL);
} }
...@@ -167,7 +160,7 @@ static int __init logibm_init(void) ...@@ -167,7 +160,7 @@ static int __init logibm_init(void)
outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT); outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
input_register_device(&logibm_dev); input_register_device(&logibm_dev);
printk(KERN_INFO "input: Logitech bus mouse at %#x irq %d\n", LOGIBM_BASE, logibm_irq); printk(KERN_INFO "input: Logitech bus mouse at %#x irq %d\n", LOGIBM_BASE, logibm_irq);
return 0; return 0;
......
/* /*
* $Id: maplemouse.c,v 1.2 2004/03/22 01:18:15 lethal Exp $ * $Id: maplemouse.c,v 1.2 2004/03/22 01:18:15 lethal Exp $
* SEGA Dreamcast mouse driver * SEGA Dreamcast mouse driver
* Based on drivers/usb/usbmouse.c * Based on drivers/usb/usbmouse.c
*/ */
...@@ -15,80 +15,51 @@ ...@@ -15,80 +15,51 @@
MODULE_AUTHOR("YAEGASHI Takeshi <t@keshi.org>"); MODULE_AUTHOR("YAEGASHI Takeshi <t@keshi.org>");
MODULE_DESCRIPTION("SEGA Dreamcast mouse driver"); MODULE_DESCRIPTION("SEGA Dreamcast mouse driver");
struct dc_mouse {
struct input_dev dev;
int open;
};
static void dc_mouse_callback(struct mapleq *mq) static void dc_mouse_callback(struct mapleq *mq)
{ {
int buttons, relx, rely, relz; int buttons, relx, rely, relz;
struct maple_device *mapledev = mq->dev; struct maple_device *mapledev = mq->dev;
struct dc_mouse *mouse = mapledev->private_data; struct input_dev *dev = mapledev->private_data;
struct input_dev *dev = &mouse->dev;
unsigned char *res = mq->recvbuf; unsigned char *res = mq->recvbuf;
buttons = ~res[8]; buttons = ~res[8];
relx=*(unsigned short *)(res+12)-512; relx = *(unsigned short *)(res + 12) - 512;
rely=*(unsigned short *)(res+14)-512; rely = *(unsigned short *)(res + 14) - 512;
relz=*(unsigned short *)(res+16)-512; relz = *(unsigned short *)(res + 16) - 512;
input_report_key(dev, BTN_LEFT, buttons&4); input_report_key(dev, BTN_LEFT, buttons & 4);
input_report_key(dev, BTN_MIDDLE, buttons&9); input_report_key(dev, BTN_MIDDLE, buttons & 9);
input_report_key(dev, BTN_RIGHT, buttons&2); input_report_key(dev, BTN_RIGHT, buttons & 2);
input_report_rel(dev, REL_X, relx); input_report_rel(dev, REL_X, relx);
input_report_rel(dev, REL_Y, rely); input_report_rel(dev, REL_Y, rely);
input_report_rel(dev, REL_WHEEL, relz); input_report_rel(dev, REL_WHEEL, relz);
input_sync(dev); input_sync(dev);
} }
static int dc_mouse_open(struct input_dev *dev)
{
struct dc_mouse *mouse = dev->private;
mouse->open++;
return 0;
}
static void dc_mouse_close(struct input_dev *dev)
{
struct dc_mouse *mouse = dev->private;
mouse->open--;
}
static int dc_mouse_connect(struct maple_device *dev) static int dc_mouse_connect(struct maple_device *dev)
{ {
unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]); unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
struct dc_mouse *mouse; struct input_dev *input_dev;
if (!(mouse = kmalloc(sizeof(struct dc_mouse), GFP_KERNEL))) if (!(input_dev = kmalloc(sizeof(struct input_dev), GFP_KERNEL)))
return -1; return -1;
memset(mouse, 0, sizeof(struct dc_mouse));
dev->private_data = mouse;
mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); dev->private_data = input_dev;
mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
init_input_dev(&mouse->dev); memset(input_dev, 0, sizeof(struct dc_mouse));
init_input_dev(input_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);
mouse->dev.private = mouse; input_dev->name = dev->product_name;
mouse->dev.open = dc_mouse_open; input_dev->id.bustype = BUS_MAPLE;
mouse->dev.close = dc_mouse_close;
mouse->dev.event = NULL;
mouse->dev.name = dev->product_name; input_register_device(input_dev);
mouse->dev.id.bustype = BUS_MAPLE;
input_register_device(&mouse->dev);
maple_getcond_callback(dev, dc_mouse_callback, 1, MAPLE_FUNC_MOUSE); maple_getcond_callback(dev, dc_mouse_callback, 1, MAPLE_FUNC_MOUSE);
printk(KERN_INFO "input: mouse(0x%lx): %s\n", data, mouse->dev.name); printk(KERN_INFO "input: mouse(0x%lx): %s\n", data, input_dev->name);
return 0; return 0;
} }
...@@ -96,10 +67,10 @@ static int dc_mouse_connect(struct maple_device *dev) ...@@ -96,10 +67,10 @@ static int dc_mouse_connect(struct maple_device *dev)
static void dc_mouse_disconnect(struct maple_device *dev) static void dc_mouse_disconnect(struct maple_device *dev)
{ {
struct dc_mouse *mouse = dev->private_data; struct input_dev *input_dev = dev->private_data;
input_unregister_device(&mouse->dev); input_unregister_device(input_dev);
kfree(mouse); kfree(input_dev);
} }
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Copyright (c) 2000-2001 Vojtech Pavlik * Copyright (c) 2000-2001 Vojtech Pavlik
* *
* Based on the work of: * Based on the work of:
* Alan Cox Robin O'Leary * Alan Cox Robin O'Leary
*/ */
/* /*
...@@ -56,7 +56,6 @@ static int pc110pad_io = 0x15e0; ...@@ -56,7 +56,6 @@ 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_data[3];
static int pc110pad_count; static int pc110pad_count;
static int pc110pad_used;
static char *pc110pad_name = "IBM PC110 TouchPad"; static char *pc110pad_name = "IBM PC110 TouchPad";
static char *pc110pad_phys = "isa15e0/input0"; static char *pc110pad_phys = "isa15e0/input0";
...@@ -74,7 +73,7 @@ static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs) ...@@ -74,7 +73,7 @@ static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs)
if (pc110pad_count < 3) if (pc110pad_count < 3)
return IRQ_HANDLED; return IRQ_HANDLED;
input_regs(&pc110pad_dev, regs); input_regs(&pc110pad_dev, regs);
input_report_key(&pc110pad_dev, BTN_TOUCH, input_report_key(&pc110pad_dev, BTN_TOUCH,
pc110pad_data[0] & 0x01); pc110pad_data[0] & 0x01);
...@@ -90,15 +89,11 @@ static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs) ...@@ -90,15 +89,11 @@ static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs)
static void pc110pad_close(struct input_dev *dev) 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) 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,NULL);
pc110pad_interrupt(0,NULL,NULL); pc110pad_interrupt(0,NULL,NULL);
...@@ -145,7 +140,7 @@ static int __init pc110pad_init(void) ...@@ -145,7 +140,7 @@ static int __init pc110pad_init(void)
pc110pad_dev.absmax[ABS_X] = 0x1ff; pc110pad_dev.absmax[ABS_X] = 0x1ff;
pc110pad_dev.absmax[ABS_Y] = 0x0ff; pc110pad_dev.absmax[ABS_Y] = 0x0ff;
pc110pad_dev.open = pc110pad_open; pc110pad_dev.open = pc110pad_open;
pc110pad_dev.close = pc110pad_close; pc110pad_dev.close = pc110pad_close;
...@@ -156,17 +151,17 @@ static int __init pc110pad_init(void) ...@@ -156,17 +151,17 @@ static int __init pc110pad_init(void)
pc110pad_dev.id.product = 0x0001; pc110pad_dev.id.product = 0x0001;
pc110pad_dev.id.version = 0x0100; pc110pad_dev.id.version = 0x0100;
input_register_device(&pc110pad_dev); input_register_device(&pc110pad_dev);
printk(KERN_INFO "input: %s at %#x irq %d\n", printk(KERN_INFO "input: %s at %#x irq %d\n",
pc110pad_name, pc110pad_io, pc110pad_irq); pc110pad_name, pc110pad_io, pc110pad_irq);
return 0; return 0;
} }
static void __exit pc110pad_exit(void) static void __exit pc110pad_exit(void)
{ {
input_unregister_device(&pc110pad_dev); input_unregister_device(&pc110pad_dev);
outb(PC110PAD_OFF, pc110pad_io + 2); outb(PC110PAD_OFF, pc110pad_io + 2);
......
This diff is collapsed.
...@@ -77,6 +77,8 @@ enum psmouse_type { ...@@ -77,6 +77,8 @@ enum psmouse_type {
PSMOUSE_IMEX, PSMOUSE_IMEX,
PSMOUSE_SYNAPTICS, PSMOUSE_SYNAPTICS,
PSMOUSE_ALPS, PSMOUSE_ALPS,
PSMOUSE_LIFEBOOK,
PSMOUSE_AUTO /* This one should always be last */
}; };
int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command); int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command);
...@@ -99,7 +101,7 @@ static ssize_t psmouse_do_set_##_name(struct device *d, struct device_attribute ...@@ -99,7 +101,7 @@ static ssize_t psmouse_do_set_##_name(struct device *d, struct device_attribute
{ \ { \
return psmouse_attr_set_helper(d, b, s, psmouse_attr_set_##_name); \ return psmouse_attr_set_helper(d, b, s, psmouse_attr_set_##_name); \
} \ } \
static struct device_attribute psmouse_attr_##_name = \ static struct device_attribute psmouse_attr_##_name = \
__ATTR(_name, S_IWUSR | S_IRUGO, \ __ATTR(_name, S_IWUSR | S_IRUGO, \
psmouse_do_show_##_name, psmouse_do_set_##_name); psmouse_do_show_##_name, psmouse_do_set_##_name);
......
...@@ -59,7 +59,7 @@ static irqreturn_t rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs) ...@@ -59,7 +59,7 @@ static irqreturn_t rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs)
b = (short) (__raw_readl(0xe0310000) ^ 0x70); b = (short) (__raw_readl(0xe0310000) ^ 0x70);
dx = x - rpcmouse_lastx; dx = x - rpcmouse_lastx;
dy = y - rpcmouse_lasty; dy = y - rpcmouse_lasty;
rpcmouse_lastx = x; rpcmouse_lastx = x;
rpcmouse_lasty = y; rpcmouse_lasty = y;
......
/* /*
* Driver for DEC VSXXX-AA mouse (hockey-puck mouse, ball or two rollers) * Driver for DEC VSXXX-AA mouse (hockey-puck mouse, ball or two rollers)
* DEC VSXXX-GA mouse (rectangular mouse, with ball) * DEC VSXXX-GA mouse (rectangular mouse, with ball)
* DEC VSXXX-AB tablet (digitizer with hair cross or stylus) * DEC VSXXX-AB tablet (digitizer with hair cross or stylus)
* *
* Copyright (C) 2003-2004 by Jan-Benedict Glaw <jbglaw@lug-owl.de> * Copyright (C) 2003-2004 by Jan-Benedict Glaw <jbglaw@lug-owl.de>
* *
......
...@@ -220,6 +220,7 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h ...@@ -220,6 +220,7 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h
struct mousedev_list *list; struct mousedev_list *list;
struct mousedev_motion *p; struct mousedev_motion *p;
unsigned long flags; unsigned long flags;
int wake_readers = 0;
list_for_each_entry(list, &mousedev->list, node) { list_for_each_entry(list, &mousedev->list, node) {
spin_lock_irqsave(&list->packet_lock, flags); spin_lock_irqsave(&list->packet_lock, flags);
...@@ -255,11 +256,14 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h ...@@ -255,11 +256,14 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h
spin_unlock_irqrestore(&list->packet_lock, flags); spin_unlock_irqrestore(&list->packet_lock, flags);
if (list->ready) if (list->ready) {
kill_fasync(&list->fasync, SIGIO, POLL_IN); kill_fasync(&list->fasync, SIGIO, POLL_IN);
wake_readers = 1;
}
} }
wake_up_interruptible(&mousedev->wait); if (wake_readers)
wake_up_interruptible(&mousedev->wait);
} }
static void mousedev_touchpad_touch(struct mousedev *mousedev, int value) static void mousedev_touchpad_touch(struct mousedev *mousedev, int value)
......
...@@ -29,6 +29,7 @@ MODULE_LICENSE("GPL"); ...@@ -29,6 +29,7 @@ MODULE_LICENSE("GPL");
EXPORT_SYMBOL(ps2_init); EXPORT_SYMBOL(ps2_init);
EXPORT_SYMBOL(ps2_sendbyte); EXPORT_SYMBOL(ps2_sendbyte);
EXPORT_SYMBOL(ps2_drain);
EXPORT_SYMBOL(ps2_command); EXPORT_SYMBOL(ps2_command);
EXPORT_SYMBOL(ps2_schedule_command); EXPORT_SYMBOL(ps2_schedule_command);
EXPORT_SYMBOL(ps2_handle_ack); EXPORT_SYMBOL(ps2_handle_ack);
...@@ -45,11 +46,11 @@ struct ps2work { ...@@ -45,11 +46,11 @@ struct ps2work {
/* /*
* ps2_sendbyte() sends a byte to the mouse, and waits for acknowledge. * ps2_sendbyte() sends a byte to the device and waits for acknowledge.
* It doesn't handle retransmission, though it could - because when there would * It doesn't handle retransmission, though it could - because if there
* be need for retransmissions, the mouse has to be replaced anyway. * is a need for retransmissions device has to be replaced anyway.
* *
* ps2_sendbyte() can only be called from a process context * ps2_sendbyte() can only be called from a process context.
*/ */
int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout) int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout)
...@@ -71,6 +72,91 @@ int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout) ...@@ -71,6 +72,91 @@ int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout)
return -ps2dev->nak; return -ps2dev->nak;
} }
/*
* ps2_drain() waits for device to transmit requested number of bytes
* and discards them.
*/
void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout)
{
if (maxbytes > sizeof(ps2dev->cmdbuf)) {
WARN_ON(1);
maxbytes = sizeof(ps2dev->cmdbuf);
}
down(&ps2dev->cmd_sem);
serio_pause_rx(ps2dev->serio);
ps2dev->flags = PS2_FLAG_CMD;
ps2dev->cmdcnt = maxbytes;
serio_continue_rx(ps2dev->serio);
wait_event_timeout(ps2dev->wait,
!(ps2dev->flags & PS2_FLAG_CMD),
msecs_to_jiffies(timeout));
up(&ps2dev->cmd_sem);
}
/*
* ps2_is_keyboard_id() checks received ID byte against the list of
* known keyboard IDs.
*/
static inline int ps2_is_keyboard_id(char id_byte)
{
static char keyboard_ids[] = {
0xab, /* Regular keyboards */
0xac, /* NCD Sun keyboard */
0x2b, /* Trust keyboard, translated */
0x5d, /* Trust keyboard */
0x60, /* NMB SGI keyboard, translated */
0x47, /* NMB SGI keyboard */
};
return memchr(keyboard_ids, id_byte, sizeof(keyboard_ids)) != NULL;
}
/*
* ps2_adjust_timeout() is called after receiving 1st byte of command
* response and tries to reduce remaining timeout to speed up command
* completion.
*/
static int ps2_adjust_timeout(struct ps2dev *ps2dev, int command, int timeout)
{
switch (command) {
case PS2_CMD_RESET_BAT:
/*
* Device has sent the first response byte after
* reset command, reset is thus done, so we can
* shorten the timeout.
* The next byte will come soon (keyboard) or not
* at all (mouse).
*/
if (timeout > msecs_to_jiffies(100))
timeout = msecs_to_jiffies(100);
break;
case PS2_CMD_GETID:
/*
* If device behind the port is not a keyboard there
* won't be 2nd byte of ID response.
*/
if (!ps2_is_keyboard_id(ps2dev->cmdbuf[1])) {
serio_pause_rx(ps2dev->serio);
ps2dev->flags = ps2dev->cmdcnt = 0;
serio_continue_rx(ps2dev->serio);
timeout = 0;
}
break;
default:
break;
}
return timeout;
}
/* /*
* ps2_command() sends a command and its parameters to the mouse, * ps2_command() sends a command and its parameters to the mouse,
* then waits for the response and puts it in the param array. * then waits for the response and puts it in the param array.
...@@ -86,6 +172,11 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) ...@@ -86,6 +172,11 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
int rc = -1; int rc = -1;
int i; int i;
if (receive > sizeof(ps2dev->cmdbuf)) {
WARN_ON(1);
return -1;
}
down(&ps2dev->cmd_sem); down(&ps2dev->cmd_sem);
serio_pause_rx(ps2dev->serio); serio_pause_rx(ps2dev->serio);
...@@ -101,10 +192,9 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) ...@@ -101,10 +192,9 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
* ACKing the reset command, and so it can take a long * ACKing the reset command, and so it can take a long
* time before the ACK arrrives. * time before the ACK arrrives.
*/ */
if (command & 0xff) if (ps2_sendbyte(ps2dev, command & 0xff,
if (ps2_sendbyte(ps2dev, command & 0xff, command == PS2_CMD_RESET_BAT ? 1000 : 200))
command == PS2_CMD_RESET_BAT ? 1000 : 200)) goto out;
goto out;
for (i = 0; i < send; i++) for (i = 0; i < send; i++)
if (ps2_sendbyte(ps2dev, param[i], 200)) if (ps2_sendbyte(ps2dev, param[i], 200))
...@@ -120,33 +210,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) ...@@ -120,33 +210,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
if (ps2dev->cmdcnt && timeout > 0) { if (ps2dev->cmdcnt && timeout > 0) {
if (command == PS2_CMD_RESET_BAT && timeout > msecs_to_jiffies(100)) { timeout = ps2_adjust_timeout(ps2dev, command, timeout);
/*
* Device has sent the first response byte
* after a reset command, reset is thus done,
* shorten the timeout. The next byte will come
* soon (keyboard) or not at all (mouse).
*/
timeout = msecs_to_jiffies(100);
}
if (command == PS2_CMD_GETID &&
ps2dev->cmdbuf[receive - 1] != 0xab && /* Regular keyboards */
ps2dev->cmdbuf[receive - 1] != 0xac && /* NCD Sun keyboard */
ps2dev->cmdbuf[receive - 1] != 0x2b && /* Trust keyboard, translated */
ps2dev->cmdbuf[receive - 1] != 0x5d && /* Trust keyboard */
ps2dev->cmdbuf[receive - 1] != 0x60 && /* NMB SGI keyboard, translated */
ps2dev->cmdbuf[receive - 1] != 0x47) { /* NMB SGI keyboard */
/*
* Device behind the port is not a keyboard
* so we don't need to wait for the 2nd byte
* of ID response.
*/
serio_pause_rx(ps2dev->serio);
ps2dev->flags = ps2dev->cmdcnt = 0;
serio_continue_rx(ps2dev->serio);
}
wait_event_timeout(ps2dev->wait, wait_event_timeout(ps2dev->wait,
!(ps2dev->flags & PS2_FLAG_CMD), timeout); !(ps2dev->flags & PS2_FLAG_CMD), timeout);
} }
...@@ -160,7 +224,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) ...@@ -160,7 +224,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
rc = 0; rc = 0;
out: out:
serio_pause_rx(ps2dev->serio); serio_pause_rx(ps2dev->serio);
ps2dev->flags = 0; ps2dev->flags = 0;
serio_continue_rx(ps2dev->serio); serio_continue_rx(ps2dev->serio);
......
...@@ -226,7 +226,7 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) ...@@ -226,7 +226,7 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv)
input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0); input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0);
input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 255, 0, 0); input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 255, 0, 0);
break; break;
case 1: /* 6-byte protocol */ case 1: /* 6-byte protocol */
input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 15, 0, 0); input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 15, 0, 0);
......
This diff is collapsed.
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
* found in Gateway AOL Connected Touchpad computers. * found in Gateway AOL Connected Touchpad computers.
* *
* Documentation for ICS MK712 can be found at: * Documentation for ICS MK712 can be found at:
* http://www.icst.com/pdf/mk712.pdf * http://www.icst.com/pdf/mk712.pdf
*/ */
/* /*
...@@ -77,7 +77,6 @@ MODULE_PARM_DESC(irq, "IRQ of MK712 touchscreen controller"); ...@@ -77,7 +77,6 @@ MODULE_PARM_DESC(irq, "IRQ of MK712 touchscreen controller");
#define MK712_READ_ONE_POINT 0x20 #define MK712_READ_ONE_POINT 0x20
#define MK712_POWERUP 0x40 #define MK712_POWERUP 0x40
static int mk712_used = 0;
static struct input_dev mk712_dev; static struct input_dev mk712_dev;
static DEFINE_SPINLOCK(mk712_lock); static DEFINE_SPINLOCK(mk712_lock);
...@@ -130,17 +129,14 @@ static int mk712_open(struct input_dev *dev) ...@@ -130,17 +129,14 @@ static int mk712_open(struct input_dev *dev)
spin_lock_irqsave(&mk712_lock, flags); spin_lock_irqsave(&mk712_lock, flags);
if (!mk712_used++) { outb(0, mk712_io + MK712_CONTROL); /* Reset */
outb(0, mk712_io + MK712_CONTROL); /* Reset */ outb(MK712_ENABLE_INT | MK712_INT_ON_CONVERSION_COMPLETE |
MK712_INT_ON_CHANGE_IN_TOUCH_STATUS |
MK712_ENABLE_PERIODIC_CONVERSIONS |
MK712_POWERUP, mk712_io + MK712_CONTROL);
outb(MK712_ENABLE_INT | MK712_INT_ON_CONVERSION_COMPLETE | outb(10, mk712_io + MK712_RATE); /* 187 points per second */
MK712_INT_ON_CHANGE_IN_TOUCH_STATUS |
MK712_ENABLE_PERIODIC_CONVERSIONS |
MK712_POWERUP, mk712_io + MK712_CONTROL);
outb(10, mk712_io + MK712_RATE); /* 187 points per second */
}
spin_unlock_irqrestore(&mk712_lock, flags); spin_unlock_irqrestore(&mk712_lock, flags);
...@@ -153,8 +149,7 @@ static void mk712_close(struct input_dev *dev) ...@@ -153,8 +149,7 @@ static void mk712_close(struct input_dev *dev)
spin_lock_irqsave(&mk712_lock, flags); spin_lock_irqsave(&mk712_lock, flags);
if (!--mk712_used) outb(0, mk712_io + MK712_CONTROL);
outb(0, mk712_io + MK712_CONTROL);
spin_unlock_irqrestore(&mk712_lock, flags); spin_unlock_irqrestore(&mk712_lock, flags);
} }
......
...@@ -31,6 +31,7 @@ obj-$(CONFIG_USB_MOUSE) += input/ ...@@ -31,6 +31,7 @@ obj-$(CONFIG_USB_MOUSE) += input/
obj-$(CONFIG_USB_MTOUCH) += input/ obj-$(CONFIG_USB_MTOUCH) += input/
obj-$(CONFIG_USB_POWERMATE) += input/ obj-$(CONFIG_USB_POWERMATE) += input/
obj-$(CONFIG_USB_WACOM) += input/ obj-$(CONFIG_USB_WACOM) += input/
obj-$(CONFIG_USB_ACECAD) += input/
obj-$(CONFIG_USB_XPAD) += input/ obj-$(CONFIG_USB_XPAD) += input/
obj-$(CONFIG_USB_DABUSB) += media/ obj-$(CONFIG_USB_DABUSB) += media/
......
...@@ -151,6 +151,18 @@ config USB_WACOM ...@@ -151,6 +151,18 @@ config USB_WACOM
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called wacom. module will be called wacom.
config USB_ACECAD
tristate "Acecad Flair tablet support"
depends on USB && INPUT
help
Say Y here if you want to use the USB version of the Acecad Flair
tablet. Make sure to say Y to "Mouse support"
(CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
(CONFIG_INPUT_EVDEV) as well.
To compile this driver as a module, choose M here: the
module will be called acecad.
config USB_KBTAB config USB_KBTAB
tristate "KB Gear JamStudio tablet support" tristate "KB Gear JamStudio tablet support"
depends on USB && INPUT depends on USB && INPUT
...@@ -190,6 +202,18 @@ config USB_MTOUCH ...@@ -190,6 +202,18 @@ config USB_MTOUCH
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called mtouchusb. module will be called mtouchusb.
config USB_ITMTOUCH
tristate "ITM Touch USB Touchscreen Driver"
depends on USB && INPUT
---help---
Say Y here if you want to use a ITM Touch USB
Touchscreen controller.
This touchscreen is used in LG 1510SF monitors.
To compile this driver as a module, choose M here: the
module will be called itmtouch.
config USB_EGALAX config USB_EGALAX
tristate "eGalax TouchKit USB Touchscreen Driver" tristate "eGalax TouchKit USB Touchscreen Driver"
depends on USB && INPUT depends on USB && INPUT
......
...@@ -33,7 +33,9 @@ obj-$(CONFIG_USB_KBD) += usbkbd.o ...@@ -33,7 +33,9 @@ obj-$(CONFIG_USB_KBD) += usbkbd.o
obj-$(CONFIG_USB_KBTAB) += kbtab.o obj-$(CONFIG_USB_KBTAB) += kbtab.o
obj-$(CONFIG_USB_MOUSE) += usbmouse.o obj-$(CONFIG_USB_MOUSE) += usbmouse.o
obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o
obj-$(CONFIG_USB_ITMTOUCH) += itmtouch.o
obj-$(CONFIG_USB_EGALAX) += touchkitusb.o obj-$(CONFIG_USB_EGALAX) += touchkitusb.o
obj-$(CONFIG_USB_POWERMATE) += powermate.o obj-$(CONFIG_USB_POWERMATE) += powermate.o
obj-$(CONFIG_USB_WACOM) += wacom.o obj-$(CONFIG_USB_WACOM) += wacom.o
obj-$(CONFIG_USB_ACECAD) += acecad.o
obj-$(CONFIG_USB_XPAD) += xpad.o obj-$(CONFIG_USB_XPAD) += xpad.o
/*
* Copyright (c) 2001-2005 Edouard TISSERANT <edouard.tisserant@wanadoo.fr>
* Copyright (c) 2004-2005 Stephane VOLTZ <svoltz@numericable.fr>
*
* USB Acecad "Acecad Flair" tablet support
*
* Changelog:
* v3.2 - Added sysfs support
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb.h>
/*
* Version Information
*/
#define DRIVER_VERSION "v3.2"
#define DRIVER_DESC "USB Acecad Flair tablet driver"
#define DRIVER_LICENSE "GPL"
#define DRIVER_AUTHOR "Edouard TISSERANT <edouard.tisserant@wanadoo.fr>"
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE(DRIVER_LICENSE);
#define USB_VENDOR_ID_ACECAD 0x0460
#define USB_DEVICE_ID_FLAIR 0x0004
#define USB_DEVICE_ID_302 0x0008
struct usb_acecad {
char name[128];
char phys[64];
struct usb_device *usbdev;
struct input_dev dev;
struct urb *irq;
signed char *data;
dma_addr_t data_dma;
};
static void usb_acecad_irq(struct urb *urb, struct pt_regs *regs)
{
struct usb_acecad *acecad = urb->context;
unsigned char *data = acecad->data;
struct input_dev *dev = &acecad->dev;
int prox, status;
switch (urb->status) {
case 0:
/* success */
break;
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
return;
default:
dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
goto resubmit;
}
prox = (data[0] & 0x04) >> 2;
input_report_key(dev, BTN_TOOL_PEN, prox);
if (prox) {
int x = data[1] | (data[2] << 8);
int y = data[3] | (data[4] << 8);
/*Pressure should compute the same way for flair and 302*/
int pressure = data[5] | ((int)data[6] << 8);
int touch = data[0] & 0x01;
int stylus = (data[0] & 0x10) >> 4;
int stylus2 = (data[0] & 0x20) >> 5;
input_report_abs(dev, ABS_X, x);
input_report_abs(dev, ABS_Y, y);
input_report_abs(dev, ABS_PRESSURE, pressure);
input_report_key(dev, BTN_TOUCH, touch);
input_report_key(dev, BTN_STYLUS, stylus);
input_report_key(dev, BTN_STYLUS2, stylus2);
}
/* event termination */
input_sync(dev);
resubmit:
status = usb_submit_urb (urb, GFP_ATOMIC);
if (status)
err ("can't resubmit intr, %s-%s/input0, status %d",
acecad->usbdev->bus->bus_name, acecad->usbdev->devpath, status);
}
static int usb_acecad_open(struct input_dev *dev)
{
struct usb_acecad *acecad = dev->private;
acecad->irq->dev = acecad->usbdev;
if (usb_submit_urb(acecad->irq, GFP_KERNEL))
return -EIO;
return 0;
}
static void usb_acecad_close(struct input_dev *dev)
{
struct usb_acecad *acecad = dev->private;
usb_kill_urb(acecad->irq);
}
static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_host_interface *interface = intf->cur_altsetting;
struct usb_endpoint_descriptor *endpoint;
struct usb_acecad *acecad;
int pipe, maxp;
char path[64];
if (interface->desc.bNumEndpoints != 1)
return -ENODEV;
endpoint = &interface->endpoint[0].desc;
if (!(endpoint->bEndpointAddress & 0x80))
return -ENODEV;
if ((endpoint->bmAttributes & 3) != 3)
return -ENODEV;
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
acecad = kcalloc(1, sizeof(struct usb_acecad), GFP_KERNEL);
if (!acecad)
return -ENOMEM;
acecad->data = usb_buffer_alloc(dev, 8, SLAB_KERNEL, &acecad->data_dma);
if (!acecad->data)
goto fail1;
acecad->irq = usb_alloc_urb(0, GFP_KERNEL);
if (!acecad->irq)
goto fail2;
if (dev->manufacturer)
strlcpy(acecad->name, dev->manufacturer, sizeof(acecad->name));
if (dev->product) {
if (dev->manufacturer)
strlcat(acecad->name, " ", sizeof(acecad->name));
strlcat(acecad->name, dev->product, sizeof(acecad->name));
}
usb_make_path(dev, path, sizeof(path));
snprintf(acecad->phys, sizeof(acecad->phys), "%s/input0", path);
acecad->usbdev = dev;
acecad->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
acecad->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
acecad->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
acecad->dev.keybit[LONG(BTN_DIGI)] = BIT(BTN_TOOL_PEN) |BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2);
switch (id->driver_info) {
case 0:
acecad->dev.absmax[ABS_X] = 5000;
acecad->dev.absmax[ABS_Y] = 3750;
acecad->dev.absmax[ABS_PRESSURE] = 512;
if (!strlen(acecad->name))
snprintf(acecad->name, sizeof(acecad->name),
"USB Acecad Flair Tablet %04x:%04x",
dev->descriptor.idVendor, dev->descriptor.idProduct);
break;
case 1:
acecad->dev.absmax[ABS_X] = 3000;
acecad->dev.absmax[ABS_Y] = 2250;
acecad->dev.absmax[ABS_PRESSURE] = 1024;
if (!strlen(acecad->name))
snprintf(acecad->name, sizeof(acecad->name),
"USB Acecad 302 Tablet %04x:%04x",
dev->descriptor.idVendor, dev->descriptor.idProduct);
break;
}
acecad->dev.absfuzz[ABS_X] = 4;
acecad->dev.absfuzz[ABS_Y] = 4;
acecad->dev.private = acecad;
acecad->dev.open = usb_acecad_open;
acecad->dev.close = usb_acecad_close;
acecad->dev.name = acecad->name;
acecad->dev.phys = acecad->phys;
acecad->dev.id.bustype = BUS_USB;
acecad->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor);
acecad->dev.id.product = le16_to_cpu(dev->descriptor.idProduct);
acecad->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice);
acecad->dev.dev = &intf->dev;
usb_fill_int_urb(acecad->irq, dev, pipe,
acecad->data, maxp > 8 ? 8 : maxp,
usb_acecad_irq, acecad, endpoint->bInterval);
acecad->irq->transfer_dma = acecad->data_dma;
acecad->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
input_register_device(&acecad->dev);
printk(KERN_INFO "input: %s with packet size %d on %s\n",
acecad->name, maxp, path);
usb_set_intfdata(intf, acecad);
return 0;
fail2: usb_buffer_free(dev, 8, acecad->data, acecad->data_dma);
fail1: kfree(acecad);
return -ENOMEM;
}
static void usb_acecad_disconnect(struct usb_interface *intf)
{
struct usb_acecad *acecad = usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL);
if (acecad) {
usb_kill_urb(acecad->irq);
input_unregister_device(&acecad->dev);
usb_free_urb(acecad->irq);
usb_buffer_free(interface_to_usbdev(intf), 10, acecad->data, acecad->data_dma);
kfree(acecad);
}
}
static struct usb_device_id usb_acecad_id_table [] = {
{ USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_FLAIR), .driver_info = 0 },
{ USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_302), .driver_info = 1 },
{ }
};
MODULE_DEVICE_TABLE(usb, usb_acecad_id_table);
static struct usb_driver usb_acecad_driver = {
.owner = THIS_MODULE,
.name = "usb_acecad",
.probe = usb_acecad_probe,
.disconnect = usb_acecad_disconnect,
.id_table = usb_acecad_id_table,
};
static int __init usb_acecad_init(void)
{
int result = usb_register(&usb_acecad_driver);
if (result == 0)
info(DRIVER_VERSION ":" DRIVER_DESC);
return result;
}
static void __exit usb_acecad_exit(void)
{
usb_deregister(&usb_acecad_driver);
}
module_init(usb_acecad_init);
module_exit(usb_acecad_exit);
/* /*
* Native support for the Aiptek HyperPen USB Tablets * Native support for the Aiptek HyperPen USB Tablets
* (4000U/5000U/6000U/8000U/12000U) * (4000U/5000U/6000U/8000U/12000U)
* *
* Copyright (c) 2001 Chris Atenasio <chris@crud.net> * Copyright (c) 2001 Chris Atenasio <chris@crud.net>
* Copyright (c) 2002-2004 Bryan W. Headley <bwheadley@earthlink.net> * Copyright (c) 2002-2004 Bryan W. Headley <bwheadley@earthlink.net>
* *
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
* - Added support for the sysfs interface, deprecating the * - Added support for the sysfs interface, deprecating the
* procfs interface for 2.5.x kernel. Also added support for * procfs interface for 2.5.x kernel. Also added support for
* Wheel command. Bryan W. Headley July-15-2003. * Wheel command. Bryan W. Headley July-15-2003.
* v1.2 - Reworked jitter timer as a kernel thread. * v1.2 - Reworked jitter timer as a kernel thread.
* Bryan W. Headley November-28-2003/Jan-10-2004. * Bryan W. Headley November-28-2003/Jan-10-2004.
* v1.3 - Repaired issue of kernel thread going nuts on single-processor * v1.3 - Repaired issue of kernel thread going nuts on single-processor
* machines, introduced programmableDelay as a command line * machines, introduced programmableDelay as a command line
...@@ -49,10 +49,10 @@ ...@@ -49,10 +49,10 @@
* NOTE: * NOTE:
* This kernel driver is augmented by the "Aiptek" XFree86 input * This kernel driver is augmented by the "Aiptek" XFree86 input
* driver for your X server, as well as the Gaiptek GUI Front-end * driver for your X server, as well as the Gaiptek GUI Front-end
* "Tablet Manager". * "Tablet Manager".
* These three products are highly interactive with one another, * These three products are highly interactive with one another,
* so therefore it's easier to document them all as one subsystem. * so therefore it's easier to document them all as one subsystem.
* Please visit the project's "home page", located at, * Please visit the project's "home page", located at,
* http://aiptektablet.sourceforge.net. * http://aiptektablet.sourceforge.net.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -156,7 +156,7 @@ ...@@ -156,7 +156,7 @@
* Command/Data Description Return Bytes Return Value * Command/Data Description Return Bytes Return Value
* 0x10/0x00 SwitchToMouse 0 * 0x10/0x00 SwitchToMouse 0
* 0x10/0x01 SwitchToTablet 0 * 0x10/0x01 SwitchToTablet 0
* 0x18/0x04 SetResolution 0 * 0x18/0x04 SetResolution 0
* 0x12/0xFF AutoGainOn 0 * 0x12/0xFF AutoGainOn 0
* 0x17/0x00 FilterOn 0 * 0x17/0x00 FilterOn 0
* 0x01/0x00 GetXExtension 2 MaxX * 0x01/0x00 GetXExtension 2 MaxX
...@@ -247,7 +247,7 @@ ...@@ -247,7 +247,7 @@
#define AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE 2 #define AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE 2
#define AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED 3 #define AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED 3
/* Time to wait (in ms) to help mask hand jittering /* Time to wait (in ms) to help mask hand jittering
* when pressing the stylus buttons. * when pressing the stylus buttons.
*/ */
#define AIPTEK_JITTER_DELAY_DEFAULT 50 #define AIPTEK_JITTER_DELAY_DEFAULT 50
...@@ -324,7 +324,6 @@ struct aiptek { ...@@ -324,7 +324,6 @@ struct aiptek {
struct aiptek_settings curSetting; /* tablet's current programmable */ struct aiptek_settings curSetting; /* tablet's current programmable */
struct aiptek_settings newSetting; /* ... and new param settings */ struct aiptek_settings newSetting; /* ... and new param settings */
unsigned int ifnum; /* interface number for IO */ unsigned int ifnum; /* interface number for IO */
int openCount; /* module use counter */
int diagnostic; /* tablet diagnostic codes */ int diagnostic; /* tablet diagnostic codes */
unsigned long eventCount; /* event count */ unsigned long eventCount; /* event count */
int inDelay; /* jitter: in jitter delay? */ int inDelay; /* jitter: in jitter delay? */
...@@ -791,7 +790,7 @@ static void aiptek_irq(struct urb *urb, struct pt_regs *regs) ...@@ -791,7 +790,7 @@ static void aiptek_irq(struct urb *urb, struct pt_regs *regs)
* specific Aiptek model numbers, because there has been overlaps, * specific Aiptek model numbers, because there has been overlaps,
* use, and reuse of id's in existing models. Certain models have * use, and reuse of id's in existing models. Certain models have
* been known to use more than one ID, indicative perhaps of * been known to use more than one ID, indicative perhaps of
* manufacturing revisions. In any event, we consider these * manufacturing revisions. In any event, we consider these
* IDs to not be model-specific nor unique. * IDs to not be model-specific nor unique.
*/ */
static const struct usb_device_id aiptek_ids[] = { static const struct usb_device_id aiptek_ids[] = {
...@@ -814,15 +813,9 @@ static int aiptek_open(struct input_dev *inputdev) ...@@ -814,15 +813,9 @@ static int aiptek_open(struct input_dev *inputdev)
{ {
struct aiptek *aiptek = inputdev->private; struct aiptek *aiptek = inputdev->private;
if (aiptek->openCount++ > 0) {
return 0;
}
aiptek->urb->dev = aiptek->usbdev; aiptek->urb->dev = aiptek->usbdev;
if (usb_submit_urb(aiptek->urb, GFP_KERNEL) != 0) { if (usb_submit_urb(aiptek->urb, GFP_KERNEL) != 0)
aiptek->openCount--;
return -EIO; return -EIO;
}
return 0; return 0;
} }
...@@ -834,13 +827,11 @@ static void aiptek_close(struct input_dev *inputdev) ...@@ -834,13 +827,11 @@ static void aiptek_close(struct input_dev *inputdev)
{ {
struct aiptek *aiptek = inputdev->private; struct aiptek *aiptek = inputdev->private;
if (--aiptek->openCount == 0) { usb_kill_urb(aiptek->urb);
usb_kill_urb(aiptek->urb);
}
} }
/*********************************************************************** /***********************************************************************
* aiptek_set_report and aiptek_get_report() are borrowed from Linux 2.4.x, * aiptek_set_report and aiptek_get_report() are borrowed from Linux 2.4.x,
* where they were known as usb_set_report and usb_get_report. * where they were known as usb_set_report and usb_get_report.
*/ */
static int static int
...@@ -2252,7 +2243,6 @@ static void aiptek_disconnect(struct usb_interface *intf) ...@@ -2252,7 +2243,6 @@ static void aiptek_disconnect(struct usb_interface *intf)
AIPTEK_PACKET_LENGTH, AIPTEK_PACKET_LENGTH,
aiptek->data, aiptek->data_dma); aiptek->data, aiptek->data_dma);
kfree(aiptek); kfree(aiptek);
aiptek = NULL;
} }
} }
......
This diff is collapsed.
...@@ -232,7 +232,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign ...@@ -232,7 +232,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
report->size += parser->global.report_size * parser->global.report_count; report->size += parser->global.report_size * parser->global.report_count;
if (!parser->local.usage_index) /* Ignore padding fields */ if (!parser->local.usage_index) /* Ignore padding fields */
return 0; return 0;
usages = max_t(int, parser->local.usage_index, parser->global.report_count); usages = max_t(int, parser->local.usage_index, parser->global.report_count);
...@@ -765,7 +765,7 @@ static __inline__ __u32 s32ton(__s32 value, unsigned n) ...@@ -765,7 +765,7 @@ static __inline__ __u32 s32ton(__s32 value, unsigned n)
static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
{ {
report += (offset >> 5) << 2; offset &= 31; report += (offset >> 5) << 2; offset &= 31;
return (le64_to_cpu(get_unaligned((__le64*)report)) >> offset) & ((1 << n) - 1); return (le64_to_cpu(get_unaligned((__le64*)report)) >> offset) & ((1ULL << n) - 1);
} }
static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
...@@ -1233,6 +1233,13 @@ int hid_wait_io(struct hid_device *hid) ...@@ -1233,6 +1233,13 @@ int hid_wait_io(struct hid_device *hid)
return 0; return 0;
} }
static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle)
{
return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (idle << 8) | report,
ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT);
}
static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
unsigned char type, void *buf, int size) unsigned char type, void *buf, int size)
{ {
...@@ -1301,10 +1308,6 @@ void hid_init_reports(struct hid_device *hid) ...@@ -1301,10 +1308,6 @@ void hid_init_reports(struct hid_device *hid)
if (err) if (err)
warn("timeout initializing reports\n"); warn("timeout initializing reports\n");
usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0),
HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0,
hid->ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT);
} }
#define USB_VENDOR_ID_WACOM 0x056a #define USB_VENDOR_ID_WACOM 0x056a
...@@ -1318,6 +1321,10 @@ void hid_init_reports(struct hid_device *hid) ...@@ -1318,6 +1321,10 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_WACOM_INTUOS3 0x00B0 #define USB_DEVICE_ID_WACOM_INTUOS3 0x00B0
#define USB_DEVICE_ID_WACOM_CINTIQ 0x003F #define USB_DEVICE_ID_WACOM_CINTIQ 0x003F
#define USB_VENDOR_ID_ACECAD 0x0460
#define USB_DEVICE_ID_ACECAD_FLAIR 0x0004
#define USB_DEVICE_ID_ACECAD_302 0x0008
#define USB_VENDOR_ID_KBGEAR 0x084e #define USB_VENDOR_ID_KBGEAR 0x084e
#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001
...@@ -1502,6 +1509,9 @@ static struct hid_blacklist { ...@@ -1502,6 +1509,9 @@ static struct hid_blacklist {
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
...@@ -1590,6 +1600,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) ...@@ -1590,6 +1600,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
return NULL; return NULL;
} }
hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0);
if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) { if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) {
dbg("reading report descriptor failed"); dbg("reading report descriptor failed");
kfree(rdesc); kfree(rdesc);
...@@ -1635,7 +1647,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) ...@@ -1635,7 +1647,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
/* Change the polling interval of mice. */ /* Change the polling interval of mice. */
if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0)
interval = hid_mousepoll_interval; interval = hid_mousepoll_interval;
if (endpoint->bEndpointAddress & USB_DIR_IN) { if (endpoint->bEndpointAddress & USB_DIR_IN) {
if (hid->urbin) if (hid->urbin)
continue; continue;
......
...@@ -67,7 +67,7 @@ static const struct hid_usage_entry hid_usage_table[] = { ...@@ -67,7 +67,7 @@ static const struct hid_usage_entry hid_usage_table[] = {
{0, 0x44, "Vbry"}, {0, 0x44, "Vbry"},
{0, 0x45, "Vbrz"}, {0, 0x45, "Vbrz"},
{0, 0x46, "Vno"}, {0, 0x46, "Vno"},
{0, 0x80, "SystemControl"}, {0, 0x80, "SystemControl"},
{0, 0x81, "SystemPowerDown"}, {0, 0x81, "SystemPowerDown"},
{0, 0x82, "SystemSleep"}, {0, 0x82, "SystemSleep"},
{0, 0x83, "SystemWakeUp"}, {0, 0x83, "SystemWakeUp"},
...@@ -347,7 +347,7 @@ __inline__ static void tab(int n) { ...@@ -347,7 +347,7 @@ __inline__ static void tab(int n) {
static void hid_dump_field(struct hid_field *field, int n) { static void hid_dump_field(struct hid_field *field, int n) {
int j; int j;
if (field->physical) { if (field->physical) {
tab(n); tab(n);
printk("Physical("); printk("Physical(");
...@@ -408,7 +408,7 @@ static void hid_dump_field(struct hid_field *field, int n) { ...@@ -408,7 +408,7 @@ static void hid_dump_field(struct hid_field *field, int n) {
printk("%s", units[sys][i]); printk("%s", units[sys][i]);
if(nibble != 1) { if(nibble != 1) {
/* This is a _signed_ nibble(!) */ /* This is a _signed_ nibble(!) */
int val = nibble & 0x7; int val = nibble & 0x7;
if(nibble & 0x08) if(nibble & 0x08)
val = -((0x7 & ~val) +1); val = -((0x7 & ~val) +1);
...@@ -443,7 +443,7 @@ static void __attribute__((unused)) hid_dump_device(struct hid_device *device) { ...@@ -443,7 +443,7 @@ static void __attribute__((unused)) hid_dump_device(struct hid_device *device) {
struct list_head *list; struct list_head *list;
unsigned i,k; unsigned i,k;
static char *table[] = {"INPUT", "OUTPUT", "FEATURE"}; static char *table[] = {"INPUT", "OUTPUT", "FEATURE"};
for (i = 0; i < HID_REPORT_TYPES; i++) { for (i = 0; i < HID_REPORT_TYPES; i++) {
report_enum = device->report_enum + i; report_enum = device->report_enum + i;
list = report_enum->report_list.next; list = report_enum->report_list.next;
...@@ -664,8 +664,8 @@ static char *keys[KEY_MAX + 1] = { ...@@ -664,8 +664,8 @@ static char *keys[KEY_MAX + 1] = {
static char *relatives[REL_MAX + 1] = { static char *relatives[REL_MAX + 1] = {
[REL_X] = "X", [REL_Y] = "Y", [REL_X] = "X", [REL_Y] = "Y",
[REL_Z] = "Z", [REL_HWHEEL] = "HWheel", [REL_Z] = "Z", [REL_HWHEEL] = "HWheel",
[REL_DIAL] = "Dial", [REL_WHEEL] = "Wheel", [REL_DIAL] = "Dial", [REL_WHEEL] = "Wheel",
[REL_MISC] = "Misc", [REL_MISC] = "Misc",
}; };
static char *absolutes[ABS_MAX + 1] = { static char *absolutes[ABS_MAX + 1] = {
...@@ -690,9 +690,9 @@ static char *misc[MSC_MAX + 1] = { ...@@ -690,9 +690,9 @@ static char *misc[MSC_MAX + 1] = {
}; };
static char *leds[LED_MAX + 1] = { static char *leds[LED_MAX + 1] = {
[LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock", [LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock",
[LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose", [LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose",
[LED_KANA] = "Kana", [LED_SLEEP] = "Sleep", [LED_KANA] = "Kana", [LED_SLEEP] = "Sleep",
[LED_SUSPEND] = "Suspend", [LED_MUTE] = "Mute", [LED_SUSPEND] = "Suspend", [LED_MUTE] = "Mute",
[LED_MISC] = "Misc", [LED_MISC] = "Misc",
}; };
......
...@@ -164,7 +164,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel ...@@ -164,7 +164,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case HID_GD_X: case HID_GD_Y: case HID_GD_Z: case HID_GD_X: case HID_GD_Y: case HID_GD_Z:
case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ: case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ:
case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL: case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL:
if (field->flags & HID_MAIN_ITEM_RELATIVE) if (field->flags & HID_MAIN_ITEM_RELATIVE)
map_rel(usage->hid & 0xf); map_rel(usage->hid & 0xf);
else else
map_abs(usage->hid & 0xf); map_abs(usage->hid & 0xf);
...@@ -297,7 +297,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel ...@@ -297,7 +297,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case HID_UP_MSVENDOR: case HID_UP_MSVENDOR:
goto ignore; goto ignore;
case HID_UP_PID: case HID_UP_PID:
set_bit(EV_FF, input->evbit); set_bit(EV_FF, input->evbit);
...@@ -349,7 +349,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel ...@@ -349,7 +349,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
goto ignore; goto ignore;
if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) && if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) &&
(usage->type == EV_REL) && (usage->code == REL_WHEEL)) (usage->type == EV_REL) && (usage->code == REL_WHEEL))
set_bit(REL_HWHEEL, bit); set_bit(REL_HWHEEL, bit);
if (((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005)) if (((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005))
...@@ -365,11 +365,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel ...@@ -365,11 +365,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
a = field->logical_minimum = 0; a = field->logical_minimum = 0;
b = field->logical_maximum = 255; b = field->logical_maximum = 255;
} }
if (field->application == HID_GD_GAMEPAD || field->application == HID_GD_JOYSTICK) if (field->application == HID_GD_GAMEPAD || field->application == HID_GD_JOYSTICK)
input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4); input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4);
else input_set_abs_params(input, usage->code, a, b, 0, 0); else input_set_abs_params(input, usage->code, a, b, 0, 0);
} }
if (usage->hat_min < usage->hat_max || usage->hat_dir) { if (usage->hat_min < usage->hat_max || usage->hat_dir) {
...@@ -420,7 +420,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct ...@@ -420,7 +420,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
return; return;
} }
if (usage->hat_min < usage->hat_max || usage->hat_dir) { if (usage->hat_min < usage->hat_max || usage->hat_dir) {
int hat_dir = usage->hat_dir; int hat_dir = usage->hat_dir;
if (!hat_dir) if (!hat_dir)
hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1; hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1;
...@@ -551,7 +551,7 @@ int hidinput_connect(struct hid_device *hid) ...@@ -551,7 +551,7 @@ int hidinput_connect(struct hid_device *hid)
for (i = 0; i < hid->maxcollection; i++) for (i = 0; i < hid->maxcollection; i++)
if (hid->collection[i].type == HID_COLLECTION_APPLICATION || if (hid->collection[i].type == HID_COLLECTION_APPLICATION ||
hid->collection[i].type == HID_COLLECTION_PHYSICAL) hid->collection[i].type == HID_COLLECTION_PHYSICAL)
if (IS_INPUT_APPLICATION(hid->collection[i].usage)) if (IS_INPUT_APPLICATION(hid->collection[i].usage))
break; break;
if (i == hid->maxcollection) if (i == hid->maxcollection)
...@@ -592,7 +592,7 @@ int hidinput_connect(struct hid_device *hid) ...@@ -592,7 +592,7 @@ int hidinput_connect(struct hid_device *hid)
for (j = 0; j < report->field[i]->maxusage; j++) for (j = 0; j < report->field[i]->maxusage; j++)
hidinput_configure_usage(hidinput, report->field[i], hidinput_configure_usage(hidinput, report->field[i],
report->field[i]->usage + j); report->field[i]->usage + j);
if (hid->quirks & HID_QUIRK_MULTI_INPUT) { if (hid->quirks & HID_QUIRK_MULTI_INPUT) {
/* This will leave hidinput NULL, so that it /* This will leave hidinput NULL, so that it
* allocates another one if we have more inputs on * allocates another one if we have more inputs on
......
...@@ -94,7 +94,7 @@ struct lgff_device { ...@@ -94,7 +94,7 @@ struct lgff_device {
isn't really necessary */ isn't really necessary */
unsigned long flags[1]; /* Contains various information about the unsigned long flags[1]; /* Contains various information about the
state of the driver for this device */ state of the driver for this device */
struct timer_list timer; struct timer_list timer;
}; };
...@@ -234,7 +234,7 @@ static struct hid_report* hid_lgff_duplicate_report(struct hid_report* report) ...@@ -234,7 +234,7 @@ static struct hid_report* hid_lgff_duplicate_report(struct hid_report* report)
kfree(ret); kfree(ret);
return NULL; return NULL;
} }
memset(ret->field[0]->value, 0, sizeof(s32[8])); memset(ret->field[0]->value, 0, sizeof(s32[8]));
return ret; return ret;
} }
...@@ -295,11 +295,11 @@ static int hid_lgff_event(struct hid_device *hid, struct input_dev* input, ...@@ -295,11 +295,11 @@ static int hid_lgff_event(struct hid_device *hid, struct input_dev* input,
unsigned long flags; unsigned long flags;
if (type != EV_FF) return -EINVAL; if (type != EV_FF) return -EINVAL;
if (!LGFF_CHECK_OWNERSHIP(code, lgff)) return -EACCES; if (!LGFF_CHECK_OWNERSHIP(code, lgff)) return -EACCES;
if (value < 0) return -EINVAL; if (value < 0) return -EINVAL;
spin_lock_irqsave(&lgff->lock, flags); spin_lock_irqsave(&lgff->lock, flags);
if (value > 0) { if (value > 0) {
if (test_bit(EFFECT_STARTED, effect->flags)) { if (test_bit(EFFECT_STARTED, effect->flags)) {
spin_unlock_irqrestore(&lgff->lock, flags); spin_unlock_irqrestore(&lgff->lock, flags);
...@@ -345,7 +345,7 @@ static int hid_lgff_flush(struct input_dev *dev, struct file *file) ...@@ -345,7 +345,7 @@ static int hid_lgff_flush(struct input_dev *dev, struct file *file)
and perform ioctls on the same fd all at the same time */ and perform ioctls on the same fd all at the same time */
if ( current->pid == lgff->effects[i].owner if ( current->pid == lgff->effects[i].owner
&& test_bit(EFFECT_USED, lgff->effects[i].flags)) { && test_bit(EFFECT_USED, lgff->effects[i].flags)) {
if (hid_lgff_erase(dev, i)) if (hid_lgff_erase(dev, i))
warn("erase effect %d failed", i); warn("erase effect %d failed", i);
} }
...@@ -378,7 +378,7 @@ static int hid_lgff_upload_effect(struct input_dev* input, ...@@ -378,7 +378,7 @@ static int hid_lgff_upload_effect(struct input_dev* input,
struct lgff_effect new; struct lgff_effect new;
int id; int id;
unsigned long flags; unsigned long flags;
dbg("ioctl rumble"); dbg("ioctl rumble");
if (!test_bit(effect->type, input->ffbit)) return -EINVAL; if (!test_bit(effect->type, input->ffbit)) return -EINVAL;
...@@ -441,7 +441,7 @@ static void hid_lgff_timer(unsigned long timer_data) ...@@ -441,7 +441,7 @@ static void hid_lgff_timer(unsigned long timer_data)
spin_lock_irqsave(&lgff->lock, flags); spin_lock_irqsave(&lgff->lock, flags);
for (i=0; i<LGFF_EFFECTS; ++i) { for (i=0; i<LGFF_EFFECTS; ++i) {
struct lgff_effect* effect = lgff->effects +i; struct lgff_effect* effect = lgff->effects +i;
if (test_bit(EFFECT_PLAYING, effect->flags)) { if (test_bit(EFFECT_PLAYING, effect->flags)) {
...@@ -491,7 +491,7 @@ static void hid_lgff_timer(unsigned long timer_data) ...@@ -491,7 +491,7 @@ static void hid_lgff_timer(unsigned long timer_data)
set_bit(EFFECT_PLAYING, lgff->effects[i].flags); set_bit(EFFECT_PLAYING, lgff->effects[i].flags);
} }
} }
} }
#define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff #define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff
...@@ -524,5 +524,5 @@ static void hid_lgff_timer(unsigned long timer_data) ...@@ -524,5 +524,5 @@ static void hid_lgff_timer(unsigned long timer_data)
add_timer(&lgff->timer); add_timer(&lgff->timer);
} }
spin_unlock_irqrestore(&lgff->lock, flags); spin_unlock_irqrestore(&lgff->lock, flags);
} }
...@@ -118,7 +118,7 @@ struct hid_item { ...@@ -118,7 +118,7 @@ struct hid_item {
#define HID_MAIN_ITEM_CONSTANT 0x001 #define HID_MAIN_ITEM_CONSTANT 0x001
#define HID_MAIN_ITEM_VARIABLE 0x002 #define HID_MAIN_ITEM_VARIABLE 0x002
#define HID_MAIN_ITEM_RELATIVE 0x004 #define HID_MAIN_ITEM_RELATIVE 0x004
#define HID_MAIN_ITEM_WRAP 0x008 #define HID_MAIN_ITEM_WRAP 0x008
#define HID_MAIN_ITEM_NONLINEAR 0x010 #define HID_MAIN_ITEM_NONLINEAR 0x010
#define HID_MAIN_ITEM_NO_PREFERRED 0x020 #define HID_MAIN_ITEM_NO_PREFERRED 0x020
#define HID_MAIN_ITEM_NULL_STATE 0x040 #define HID_MAIN_ITEM_NULL_STATE 0x040
...@@ -172,14 +172,14 @@ struct hid_item { ...@@ -172,14 +172,14 @@ struct hid_item {
#define HID_USAGE_PAGE 0xffff0000 #define HID_USAGE_PAGE 0xffff0000
#define HID_UP_UNDEFINED 0x00000000 #define HID_UP_UNDEFINED 0x00000000
#define HID_UP_GENDESK 0x00010000 #define HID_UP_GENDESK 0x00010000
#define HID_UP_KEYBOARD 0x00070000 #define HID_UP_KEYBOARD 0x00070000
#define HID_UP_LED 0x00080000 #define HID_UP_LED 0x00080000
#define HID_UP_BUTTON 0x00090000 #define HID_UP_BUTTON 0x00090000
#define HID_UP_ORDINAL 0x000a0000 #define HID_UP_ORDINAL 0x000a0000
#define HID_UP_CONSUMER 0x000c0000 #define HID_UP_CONSUMER 0x000c0000
#define HID_UP_DIGITIZER 0x000d0000 #define HID_UP_DIGITIZER 0x000d0000
#define HID_UP_PID 0x000f0000 #define HID_UP_PID 0x000f0000
#define HID_UP_HPVENDOR 0xff7f0000 #define HID_UP_HPVENDOR 0xff7f0000
#define HID_UP_MSVENDOR 0xff000000 #define HID_UP_MSVENDOR 0xff000000
...@@ -406,7 +406,7 @@ struct hid_device { /* device report descriptor */ ...@@ -406,7 +406,7 @@ struct hid_device { /* device report descriptor */
dma_addr_t outbuf_dma; /* Output buffer dma */ dma_addr_t outbuf_dma; /* Output buffer dma */
spinlock_t outlock; /* Output fifo spinlock */ spinlock_t outlock; /* Output fifo spinlock */
unsigned claimed; /* Claimed by hidinput, hiddev? */ unsigned claimed; /* Claimed by hidinput, hiddev? */
unsigned quirks; /* Various quirks the device can pull on us */ unsigned quirks; /* Various quirks the device can pull on us */
struct list_head inputs; /* The list of inputs */ struct list_head inputs; /* The list of inputs */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -859,6 +859,10 @@ struct input_dev { ...@@ -859,6 +859,10 @@ struct input_dev {
int (*erase_effect)(struct input_dev *dev, int effect_id); int (*erase_effect)(struct input_dev *dev, int effect_id);
struct input_handle *grab; struct input_handle *grab;
struct semaphore sem; /* serializes open and close operations */
unsigned int users;
struct device *dev; struct device *dev;
struct list_head h_list; struct list_head h_list;
......
This diff is collapsed.
...@@ -41,6 +41,7 @@ struct ps2dev { ...@@ -41,6 +41,7 @@ struct ps2dev {
void ps2_init(struct ps2dev *ps2dev, struct serio *serio); void ps2_init(struct ps2dev *ps2dev, struct serio *serio);
int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout); int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout);
void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout);
int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command); int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command);
int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int command); int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int command);
int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data); int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data);
......
This diff is collapsed.
...@@ -52,7 +52,7 @@ config SOUND_CMPCI_MIDI ...@@ -52,7 +52,7 @@ config SOUND_CMPCI_MIDI
config SOUND_CMPCI_JOYSTICK config SOUND_CMPCI_JOYSTICK
bool "Enable joystick" bool "Enable joystick"
depends on SOUND_CMPCI && X86 depends on SOUND_CMPCI && X86 && (GAMEPORT=y || SOUND_CMPCI=GAMEPORT)
help help
Say Y here in order to enable the joystick port on a sound card using Say Y here in order to enable the joystick port on a sound card using
the CMI8338 or the CMI8738 chipset. You need to config the the CMI8338 or the CMI8738 chipset. You need to config the
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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