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.
See Documentation/ramdisk.txt.
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
per second.
psmouse.resetafter=
......
......@@ -21,6 +21,7 @@
#include <linux/smp_lock.h>
#include <linux/device.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/compat.h>
struct evdev {
int exist;
......@@ -145,6 +146,41 @@ static int evdev_open(struct inode * inode, struct file * file)
return 0;
}
#ifdef CONFIG_COMPAT
struct input_event_compat {
struct compat_timeval time;
__u16 type;
__u16 code;
__s32 value;
};
#ifdef CONFIG_X86_64
# define COMPAT_TEST test_thread_flag(TIF_IA32)
#elif defined(CONFIG_IA64)
# define COMPAT_TEST IS_IA32_PROCESS(ia64_task_regs(current))
#elif defined(CONFIG_ARCH_S390)
# define COMPAT_TEST test_thread_flag(TIF_31BIT)
#else
# define COMPAT_TEST test_thread_flag(TIF_32BIT)
#endif
static ssize_t evdev_write_compat(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
{
struct evdev_list *list = file->private_data;
struct input_event_compat event;
int retval = 0;
while (retval < count) {
if (copy_from_user(&event, buffer + retval, sizeof(struct input_event_compat)))
return -EFAULT;
input_event(list->evdev->handle.dev, event.type, event.code, event.value);
retval += sizeof(struct input_event_compat);
}
return retval;
}
#endif
static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
{
struct evdev_list *list = file->private_data;
......@@ -153,6 +189,11 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_
if (!list->evdev->exist) return -ENODEV;
#ifdef CONFIG_COMPAT
if (COMPAT_TEST)
return evdev_write_compat(file, buffer, count, ppos);
#endif
while (retval < count) {
if (copy_from_user(&event, buffer + retval, sizeof(struct input_event)))
......@@ -164,11 +205,56 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_
return retval;
}
#ifdef CONFIG_COMPAT
static ssize_t evdev_read_compat(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
{
struct evdev_list *list = file->private_data;
int retval;
if (count < sizeof(struct input_event_compat))
return -EINVAL;
if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK))
return -EAGAIN;
retval = wait_event_interruptible(list->evdev->wait,
list->head != list->tail || (!list->evdev->exist));
if (retval)
return retval;
if (!list->evdev->exist)
return -ENODEV;
while (list->head != list->tail && retval + sizeof(struct input_event_compat) <= count) {
struct input_event *event = (struct input_event *) list->buffer + list->tail;
struct input_event_compat event_compat;
event_compat.time.tv_sec = event->time.tv_sec;
event_compat.time.tv_usec = event->time.tv_usec;
event_compat.type = event->type;
event_compat.code = event->code;
event_compat.value = event->value;
if (copy_to_user(buffer + retval, &event_compat,
sizeof(struct input_event_compat))) return -EFAULT;
list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
retval += sizeof(struct input_event_compat);
}
return retval;
}
#endif
static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
{
struct evdev_list *list = file->private_data;
int retval;
#ifdef CONFIG_COMPAT
if (COMPAT_TEST)
return evdev_read_compat(file, buffer, count, ppos);
#endif
if (count < sizeof(struct input_event))
return -EINVAL;
......@@ -203,7 +289,7 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait)
(list->evdev->exist ? 0 : (POLLHUP | POLLERR));
}
static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct evdev_list *list = file->private_data;
struct evdev *evdev = list->evdev;
......@@ -285,9 +371,11 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
default:
if (_IOC_TYPE(cmd) != 'E' || _IOC_DIR(cmd) != _IOC_READ)
if (_IOC_TYPE(cmd) != 'E')
return -EINVAL;
if (_IOC_DIR(cmd) == _IOC_READ) {
if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) {
long *bits;
......@@ -370,6 +458,160 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
return 0;
}
}
if (_IOC_DIR(cmd) == _IOC_WRITE) {
if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
int t = _IOC_NR(cmd) & ABS_MAX;
if (copy_from_user(&abs, p, sizeof(struct input_absinfo)))
return -EFAULT;
dev->abs[t] = abs.value;
dev->absmin[t] = abs.minimum;
dev->absmax[t] = abs.maximum;
dev->absfuzz[t] = abs.fuzz;
dev->absflat[t] = abs.flat;
return 0;
}
}
}
return -EINVAL;
}
#ifdef CONFIG_COMPAT
#define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8)
#define NBITS_COMPAT(x) ((((x)-1)/BITS_PER_LONG_COMPAT)+1)
#define OFF_COMPAT(x) ((x)%BITS_PER_LONG_COMPAT)
#define BIT_COMPAT(x) (1UL<<OFF_COMPAT(x))
#define LONG_COMPAT(x) ((x)/BITS_PER_LONG_COMPAT)
#define test_bit_compat(bit, array) ((array[LONG_COMPAT(bit)] >> OFF_COMPAT(bit)) & 1)
#ifdef __BIG_ENDIAN
#define bit_to_user(bit, max) \
do { \
int i; \
int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \
if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \
for (i = 0; i < len / sizeof(compat_long_t); i++) \
if (copy_to_user((compat_long_t*) p + i, \
(compat_long_t*) (bit) + i + 1 - ((i % 2) << 1), \
sizeof(compat_long_t))) \
return -EFAULT; \
return len; \
} while (0)
#else
#define bit_to_user(bit, max) \
do { \
int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \
if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \
return copy_to_user(p, (bit), len) ? -EFAULT : len; \
} while (0)
#endif
static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
{
struct evdev_list *list = file->private_data;
struct evdev *evdev = list->evdev;
struct input_dev *dev = evdev->handle.dev;
struct input_absinfo abs;
void __user *p = compat_ptr(arg);
if (!evdev->exist) return -ENODEV;
switch (cmd) {
case EVIOCGVERSION:
case EVIOCGID:
case EVIOCGKEYCODE:
case EVIOCSKEYCODE:
case EVIOCSFF:
case EVIOCRMFF:
case EVIOCGEFFECTS:
case EVIOCGRAB:
return evdev_ioctl(file, cmd, (unsigned long) p);
default:
if (_IOC_TYPE(cmd) != 'E')
return -EINVAL;
if (_IOC_DIR(cmd) == _IOC_READ) {
if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) {
long *bits;
int max;
switch (_IOC_NR(cmd) & EV_MAX) {
case 0: bits = dev->evbit; max = EV_MAX; break;
case EV_KEY: bits = dev->keybit; max = KEY_MAX; break;
case EV_REL: bits = dev->relbit; max = REL_MAX; break;
case EV_ABS: bits = dev->absbit; max = ABS_MAX; break;
case EV_MSC: bits = dev->mscbit; max = MSC_MAX; break;
case EV_LED: bits = dev->ledbit; max = LED_MAX; break;
case EV_SND: bits = dev->sndbit; max = SND_MAX; break;
case EV_FF: bits = dev->ffbit; max = FF_MAX; break;
default: return -EINVAL;
}
bit_to_user(bits, max);
}
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
bit_to_user(dev->key, KEY_MAX);
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
bit_to_user(dev->led, LED_MAX);
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
bit_to_user(dev->snd, SND_MAX);
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
int len;
if (!dev->name) return -ENOENT;
len = strlen(dev->name) + 1;
if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
return copy_to_user(p, dev->name, len) ? -EFAULT : len;
}
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) {
int len;
if (!dev->phys) return -ENOENT;
len = strlen(dev->phys) + 1;
if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
return copy_to_user(p, dev->phys, len) ? -EFAULT : len;
}
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) {
int len;
if (!dev->uniq) return -ENOENT;
len = strlen(dev->uniq) + 1;
if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
return copy_to_user(p, dev->uniq, len) ? -EFAULT : len;
}
if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
int t = _IOC_NR(cmd) & ABS_MAX;
abs.value = dev->abs[t];
abs.minimum = dev->absmin[t];
abs.maximum = dev->absmax[t];
abs.fuzz = dev->absfuzz[t];
abs.flat = dev->absflat[t];
if (copy_to_user(p, &abs, sizeof(struct input_absinfo)))
return -EFAULT;
return 0;
}
}
if (_IOC_DIR(cmd) == _IOC_WRITE) {
if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
int t = _IOC_NR(cmd) & ABS_MAX;
......@@ -386,8 +628,10 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
return 0;
}
}
}
return -EINVAL;
}
#endif
static struct file_operations evdev_fops = {
.owner = THIS_MODULE,
......@@ -396,7 +640,10 @@ static struct file_operations evdev_fops = {
.poll = evdev_poll,
.open = evdev_open,
.release = evdev_release,
.ioctl = evdev_ioctl,
.unlocked_ioctl = evdev_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = evdev_ioctl_compat,
#endif
.fasync = evdev_fasync,
.flush = evdev_flush
};
......
......@@ -49,22 +49,8 @@ config GAMEPORT_EMU10K1
To compile this driver as a module, choose M here: the
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
tristate "ForteMedia FM801 gameport support"
depends on PCI
config GAMEPORT_CS461X
tristate "Crystal SoundFusion gameport support"
depends on PCI
endif
......@@ -5,9 +5,7 @@
# Each configuration option enables a list of files.
obj-$(CONFIG_GAMEPORT) += gameport.o
obj-$(CONFIG_GAMEPORT_CS461X) += cs461x.o
obj-$(CONFIG_GAMEPORT_EMU10K1) += emu10k1-gp.o
obj-$(CONFIG_GAMEPORT_FM801) += fm801-gp.o
obj-$(CONFIG_GAMEPORT_L4) += lightning.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)
{
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
* not occupied by the ISA ports.
* Probe ISA ports after PnP, so that PnP ports that are already
* enabled get detected as PnP. This may be suboptimal in multi-device
* configurations, but saves hassle with simple setups.
*/
while (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;
}
......
/*
* $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)
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++;
if (handle->dev->open)
return handle->dev->open(handle->dev);
return 0;
if (!dev->users++ && dev->open)
err = dev->open(dev);
if (err)
handle->open--;
up(&dev->sem);
return err;
}
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)
{
struct input_dev *dev = handle->dev;
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--;
up(&dev->sem);
}
static void input_link_handle(struct input_handle *handle)
......@@ -415,6 +436,8 @@ void input_register_device(struct input_dev *dev)
set_bit(EV_SYN, dev->evbit);
init_MUTEX(&dev->sem);
/*
* 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.
......@@ -674,6 +697,8 @@ static int input_handlers_read(char *buf, char **start, off_t pos, int count, in
return (count > cnt) ? cnt : count;
}
static struct file_operations input_fileops;
static int __init input_proc_init(void)
{
struct proc_dir_entry *entry;
......@@ -688,6 +713,8 @@ static int __init input_proc_init(void)
return -ENOMEM;
}
entry->owner = THIS_MODULE;
input_fileops = *entry->proc_fops;
entry->proc_fops = &input_fileops;
entry->proc_fops->poll = input_devices_poll;
entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL);
if (entry == NULL) {
......
......@@ -285,48 +285,33 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait)
(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;
void __user *argp = (void __user *)arg;
int i, j;
if (!joydev->exist) return -ENODEV;
switch (cmd) {
case JS_SET_CAL:
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:
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:
return get_user(joydev->glue.JS_TIMEOUT, (int __user *) arg);
return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp);
case JS_GET_TIMEOUT:
return put_user(joydev->glue.JS_TIMEOUT, (int __user *) arg);
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;
return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp);
case JSIOCGVERSION:
return put_user(JS_VERSION, (__u32 __user *) arg);
return put_user(JS_VERSION, (__u32 __user *) argp);
case JSIOCGAXES:
return put_user(joydev->nabs, (__u8 __user *) arg);
return put_user(joydev->nabs, (__u8 __user *) argp);
case JSIOCGBUTTONS:
return put_user(joydev->nkey, (__u8 __user *) arg);
return put_user(joydev->nkey, (__u8 __user *) argp);
case JSIOCSCORR:
if (copy_from_user(joydev->corr, argp,
sizeof(struct js_corr) * joydev->nabs))
sizeof(joydev->corr[0]) * joydev->nabs))
return -EFAULT;
for (i = 0; i < joydev->nabs; i++) {
j = joydev->abspam[i];
......@@ -335,7 +320,7 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
return 0;
case JSIOCGCORR:
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:
if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1)))
return -EFAULT;
......@@ -371,6 +356,84 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
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 = {
.owner = THIS_MODULE,
.read = joydev_read,
......@@ -379,6 +442,9 @@ static struct file_operations joydev_fops = {
.open = joydev_open,
.release = joydev_release,
.ioctl = joydev_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = joydev_compat_ioctl,
#endif
.fasync = joydev_fasync,
};
......
......@@ -51,7 +51,8 @@ MODULE_PARM_DESC(map, "Map of attached joysticks in form of <a>,<b> (default is
__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 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)
static int amijoy_open(struct input_dev *dev)
{
int *used = dev->private;
int err;
if ((*used)++)
return 0;
err = down_interruptible(&amijoy_sem);
if (err)
return err;
if (request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", amijoy_interrupt)) {
(*used)--;
if (!amijoy_used && request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", amijoy_interrupt)) {
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)
{
int *used = dev->private;
if (!--(*used))
down(&amijoysem);
if (!--amijoy_used)
free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt);
up(&amijoy_sem);
}
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.version = 0x0100;
amijoy_dev[i].private = amijoy_used + i;
input_register_device(amijoy_dev + i);
printk(KERN_INFO "input: %s at joy%ddat\n", amijoy_name, i);
}
......
......@@ -98,6 +98,7 @@ struct db9 {
struct pardevice *pd;
int mode;
int used;
struct semaphore sem;
char phys[2][32];
};
......@@ -503,6 +504,11 @@ static int db9_open(struct input_dev *dev)
{
struct db9 *db9 = dev->private;
struct parport *port = db9->pd->port;
int err;
err = down_interruptible(&db9->sem);
if (err)
return err;
if (!db9->used++) {
parport_claim(db9->pd);
......@@ -514,6 +520,7 @@ static int db9_open(struct input_dev *dev)
mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME);
}
up(&db9->sem);
return 0;
}
......@@ -522,12 +529,14 @@ static void db9_close(struct input_dev *dev)
struct db9 *db9 = dev->private;
struct parport *port = db9->pd->port;
down(&db9->sem);
if (!--db9->used) {
del_timer(&db9->timer);
del_timer_sync(&db9->timer);
parport_write_control(port, 0x00);
parport_data_forward(port);
parport_release(db9->pd);
}
up(&db9->sem);
}
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);
return NULL;
}
memset(db9, 0, sizeof(struct db9));
init_MUTEX(&db9->sem);
db9->mode = config[1];
init_timer(&db9->timer);
db9->timer.data = (long) db9;
......
......@@ -81,6 +81,7 @@ struct gc {
struct timer_list timer;
unsigned char pads[GC_MAX + 1];
int used;
struct semaphore sem;
char phys[5][32];
};
......@@ -503,22 +504,33 @@ static void gc_timer(unsigned long private)
static int gc_open(struct input_dev *dev)
{
struct gc *gc = dev->private;
int err;
err = down_interruptible(&gc->sem);
if (err)
return err;
if (!gc->used++) {
parport_claim(gc->pd);
parport_write_control(gc->pd->port, 0x04);
mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
}
up(&gc->sem);
return 0;
}
static void gc_close(struct input_dev *dev)
{
struct gc *gc = dev->private;
down(&gc->sem);
if (!--gc->used) {
del_timer(&gc->timer);
del_timer_sync(&gc->timer);
parport_write_control(gc->pd->port, 0x00);
parport_release(gc->pd);
}
up(&gc->sem);
}
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;
}
if (!(gc = kmalloc(sizeof(struct gc), GFP_KERNEL))) {
if (!(gc = kcalloc(1, sizeof(struct gc), GFP_KERNEL))) {
parport_put_port(pp);
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);
......
......@@ -78,6 +78,7 @@ static struct iforce_device iforce_device[] = {
{ 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, 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 }
};
......
......@@ -229,6 +229,7 @@ static struct usb_device_id iforce_usb_ids [] = {
{ USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */
{ USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */
{ USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */
{ USB_DEVICE(0x06f8, 0xa302) }, /* Guillemot Jet Leader 3D */
{ } /* Terminating entry */
};
......
......@@ -84,6 +84,7 @@ static struct tgfx {
char phys[7][32];
int sticks;
int used;
struct semaphore sem;
} *tgfx_base[3];
/*
......@@ -123,22 +124,33 @@ static void tgfx_timer(unsigned long private)
static int tgfx_open(struct input_dev *dev)
{
struct tgfx *tgfx = dev->private;
int err;
err = down_interruptible(&tgfx->sem);
if (err)
return err;
if (!tgfx->used++) {
parport_claim(tgfx->pd);
parport_write_control(tgfx->pd->port, 0x04);
mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME);
}
up(&tgfx->sem);
return 0;
}
static void tgfx_close(struct input_dev *dev)
{
struct tgfx *tgfx = dev->private;
down(&tgfx->sem);
if (!--tgfx->used) {
del_timer(&tgfx->timer);
del_timer_sync(&tgfx->timer);
parport_write_control(tgfx->pd->port, 0x00);
parport_release(tgfx->pd);
}
up(&tgfx->sem);
}
/*
......@@ -166,11 +178,12 @@ static struct tgfx __init *tgfx_probe(int *config, int nargs)
return NULL;
}
if (!(tgfx = kmalloc(sizeof(struct tgfx), GFP_KERNEL))) {
if (!(tgfx = kcalloc(1, sizeof(struct tgfx), GFP_KERNEL))) {
parport_put_port(pp);
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);
......
......@@ -39,6 +39,7 @@
#define CORGI_KEY_CALENDER KEY_F1
#define CORGI_KEY_ADDRESS KEY_F2
#define CORGI_KEY_FN KEY_F3
#define CORGI_KEY_CANCEL KEY_F4
#define CORGI_KEY_OFF KEY_SUSPEND
#define CORGI_KEY_EXOK KEY_F5
#define CORGI_KEY_EXCANCEL KEY_F6
......@@ -46,6 +47,7 @@
#define CORGI_KEY_EXJOGUP KEY_F8
#define CORGI_KEY_JAP1 KEY_LEFTCTRL
#define CORGI_KEY_JAP2 KEY_LEFTALT
#define CORGI_KEY_MAIL KEY_F10
#define CORGI_KEY_OK KEY_F11
#define CORGI_KEY_MENU KEY_F12
#define CORGI_HINGE_0 KEY_KP0
......@@ -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 */
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 */
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 */
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, 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_HINGE_0, CORGI_HINGE_1, CORGI_HINGE_2 /* 125-127 */
};
......
......@@ -148,7 +148,7 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *
udelay(KB_DELAY);
rowd = ~locomo_readl(membase + LOCOMO_KIB);
for (row = 0; row < KB_ROWS; row++ ) {
for (row = 0; row < KB_ROWS; row++) {
scancode = SCANCODE(col, row);
if (rowd & KB_ROWMASK(row)) {
num_pressed += 1;
......
......@@ -40,7 +40,6 @@ struct dc_kbd {
struct input_dev dev;
unsigned char new[8];
unsigned char old[8];
int open;
};
......@@ -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)
{
int i;
......@@ -133,9 +116,6 @@ static int dc_kbd_connect(struct maple_device *dev)
clear_bit(0, kbd->dev.keybit);
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.id.bustype = BUS_MAPLE;
......
......@@ -298,10 +298,12 @@ static int uinput_alloc_device(struct file *file, const char __user *buffer, siz
/* check if absmin/absmax/absfuzz/absflat are filled as
* told in Documentation/input/input-programming.txt */
if (test_bit(EV_ABS, dev->evbit)) {
retval = uinput_validate_absbits(dev);
if (retval < 0)
int err = uinput_validate_absbits(dev);
if (err < 0) {
retval = err;
kfree(dev->name);
}
}
exit:
kfree(user_dev);
......
......@@ -15,4 +15,4 @@ obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
obj-$(CONFIG_MOUSE_HIL) += hil_ptr.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 @@
#define ALPS_DUALPOINT 0x01
#define ALPS_WHEEL 0x02
#define ALPS_FW_BK 0x04
#define ALPS_FW_BK_1 0x04
#define ALPS_4BTN 0x08
#define ALPS_OLDPROTO 0x10
#define ALPS_PASS 0x20
#define ALPS_FW_BK_2 0x40
static struct alps_model_info alps_model_data[] = {
{ { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */
......@@ -43,11 +44,11 @@ static struct alps_model_info alps_model_data[] = {
{ { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
{ { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, 0 },
{ { 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, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */
{ { 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 */
{ { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },
{ { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */
......@@ -81,6 +82,7 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
struct input_dev *dev = &psmouse->dev;
struct input_dev *dev2 = &priv->dev2;
int x, y, z, ges, fin, left, right, middle;
int back = 0, forward = 0;
input_regs(dev, regs);
......@@ -112,6 +114,18 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
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;
fin = packet[2] & 2;
......@@ -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_key(dev, BTN_TOOL_FINGER, z > 0);
if (priv->i->flags & ALPS_WHEEL)
input_report_rel(dev, REL_WHEEL, ((packet[0] >> 4) & 0x07) | ((packet[2] >> 2) & 0x08));
if (priv->i->flags & ALPS_FW_BK) {
input_report_key(dev, BTN_FORWARD, packet[0] & 0x10);
input_report_key(dev, BTN_BACK, packet[2] & 0x04);
if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
input_report_key(dev, BTN_FORWARD, forward);
input_report_key(dev, BTN_BACK, back);
}
input_sync(dev);
......@@ -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)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char param[3];
int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11;
if (ps2_command(ps2dev, NULL, cmd) ||
......@@ -267,7 +279,7 @@ static int alps_passthrough_mode(struct psmouse *psmouse, int enable)
return -1;
/* we may get 3 more bytes, just ignore them */
ps2_command(ps2dev, param, 0x0300);
ps2_drain(ps2dev, 3, 100);
return 0;
}
......@@ -425,7 +437,7 @@ int alps_init(struct psmouse *psmouse)
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_BACK)] |= BIT(BTN_BACK);
}
......@@ -468,10 +480,8 @@ int alps_detect(struct psmouse *psmouse, int set_properties)
if (set_properties) {
psmouse->vendor = "ALPS";
if (model->flags & ALPS_DUALPOINT)
psmouse->name = "DualPoint TouchPad";
else
psmouse->name = "GlidePoint";
psmouse->name = model->flags & ALPS_DUALPOINT ?
"DualPoint TouchPad" : "GlidePoint";
psmouse->model = version;
}
return 0;
......
......@@ -33,7 +33,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Amiga mouse driver");
MODULE_LICENSE("GPL");
static int amimouse_used = 0;
static int amimouse_lastx, amimouse_lasty;
static struct input_dev amimouse_dev;
......@@ -81,16 +80,12 @@ static int amimouse_open(struct input_dev *dev)
{
unsigned short joy0dat;
if (amimouse_used++)
return 0;
joy0dat = custom.joy0dat;
amimouse_lastx = joy0dat & 0xff;
amimouse_lasty = joy0dat >> 8;
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);
return -EBUSY;
}
......@@ -100,7 +95,6 @@ static int amimouse_open(struct input_dev *dev)
static void amimouse_close(struct input_dev *dev)
{
if (!--amimouse_used)
free_irq(IRQ_AMIGA_VERTB, amimouse_interrupt);
}
......
......@@ -87,29 +87,23 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)");
__obsolete_setup("inport_irq=");
static int inport_used;
static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int inport_open(struct input_dev *dev)
{
if (!inport_used++) {
if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL))
return -EBUSY;
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
}
return 0;
}
static void inport_close(struct input_dev *dev)
{
if (!--inport_used) {
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
free_irq(inport_irq, NULL);
}
}
static struct input_dev inport_dev = {
......
/*
* 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
......@@ -77,16 +77,11 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)");
__obsolete_setup("logibm_irq=");
static int logibm_used = 0;
static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int logibm_open(struct input_dev *dev)
{
if (logibm_used++)
return 0;
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);
return -EBUSY;
}
......@@ -96,8 +91,6 @@ static int logibm_open(struct input_dev *dev)
static void logibm_close(struct input_dev *dev)
{
if (--logibm_used)
return;
outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
free_irq(logibm_irq, NULL);
}
......
......@@ -15,80 +15,51 @@
MODULE_AUTHOR("YAEGASHI Takeshi <t@keshi.org>");
MODULE_DESCRIPTION("SEGA Dreamcast mouse driver");
struct dc_mouse {
struct input_dev dev;
int open;
};
static void dc_mouse_callback(struct mapleq *mq)
{
int buttons, relx, rely, relz;
struct maple_device *mapledev = mq->dev;
struct dc_mouse *mouse = mapledev->private_data;
struct input_dev *dev = &mouse->dev;
struct input_dev *dev = mapledev->private_data;
unsigned char *res = mq->recvbuf;
buttons = ~res[8];
relx=*(unsigned short *)(res+12)-512;
rely=*(unsigned short *)(res+14)-512;
relz=*(unsigned short *)(res+16)-512;
relx = *(unsigned short *)(res + 12) - 512;
rely = *(unsigned short *)(res + 14) - 512;
relz = *(unsigned short *)(res + 16) - 512;
input_report_key(dev, BTN_LEFT, buttons&4);
input_report_key(dev, BTN_MIDDLE, buttons&9);
input_report_key(dev, BTN_RIGHT, buttons&2);
input_report_key(dev, BTN_LEFT, buttons & 4);
input_report_key(dev, BTN_MIDDLE, buttons & 9);
input_report_key(dev, BTN_RIGHT, buttons & 2);
input_report_rel(dev, REL_X, relx);
input_report_rel(dev, REL_Y, rely);
input_report_rel(dev, REL_WHEEL, relz);
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)
{
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;
memset(mouse, 0, sizeof(struct dc_mouse));
dev->private_data = mouse;
mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
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);
dev->private_data = input_dev;
mouse->dev.private = mouse;
mouse->dev.open = dc_mouse_open;
mouse->dev.close = dc_mouse_close;
mouse->dev.event = NULL;
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.name = dev->product_name;
mouse->dev.id.bustype = BUS_MAPLE;
input_dev->name = dev->product_name;
input_dev->id.bustype = BUS_MAPLE;
input_register_device(&mouse->dev);
input_register_device(input_dev);
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;
}
......@@ -96,10 +67,10 @@ static int dc_mouse_connect(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);
kfree(mouse);
input_unregister_device(input_dev);
kfree(input_dev);
}
......
......@@ -56,7 +56,6 @@ static int pc110pad_io = 0x15e0;
static struct input_dev pc110pad_dev;
static int pc110pad_data[3];
static int pc110pad_count;
static int pc110pad_used;
static char *pc110pad_name = "IBM PC110 TouchPad";
static char *pc110pad_phys = "isa15e0/input0";
......@@ -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)
{
if (!--pc110pad_used)
outb(PC110PAD_OFF, pc110pad_io + 2);
}
static int pc110pad_open(struct input_dev *dev)
{
if (pc110pad_used++)
return 0;
pc110pad_interrupt(0,NULL,NULL);
pc110pad_interrupt(0,NULL,NULL);
pc110pad_interrupt(0,NULL,NULL);
......
This diff is collapsed.
......@@ -77,6 +77,8 @@ enum psmouse_type {
PSMOUSE_IMEX,
PSMOUSE_SYNAPTICS,
PSMOUSE_ALPS,
PSMOUSE_LIFEBOOK,
PSMOUSE_AUTO /* This one should always be last */
};
int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command);
......
......@@ -220,6 +220,7 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h
struct mousedev_list *list;
struct mousedev_motion *p;
unsigned long flags;
int wake_readers = 0;
list_for_each_entry(list, &mousedev->list, node) {
spin_lock_irqsave(&list->packet_lock, flags);
......@@ -255,10 +256,13 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h
spin_unlock_irqrestore(&list->packet_lock, flags);
if (list->ready)
if (list->ready) {
kill_fasync(&list->fasync, SIGIO, POLL_IN);
wake_readers = 1;
}
}
if (wake_readers)
wake_up_interruptible(&mousedev->wait);
}
......
......@@ -29,6 +29,7 @@ MODULE_LICENSE("GPL");
EXPORT_SYMBOL(ps2_init);
EXPORT_SYMBOL(ps2_sendbyte);
EXPORT_SYMBOL(ps2_drain);
EXPORT_SYMBOL(ps2_command);
EXPORT_SYMBOL(ps2_schedule_command);
EXPORT_SYMBOL(ps2_handle_ack);
......@@ -45,11 +46,11 @@ struct ps2work {
/*
* ps2_sendbyte() sends a byte to the mouse, and waits for acknowledge.
* It doesn't handle retransmission, though it could - because when there would
* be need for retransmissions, the mouse has to be replaced anyway.
* ps2_sendbyte() sends a byte to the device and waits for acknowledge.
* It doesn't handle retransmission, though it could - because if there
* 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)
......@@ -71,6 +72,91 @@ int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout)
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,
* 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)
int rc = -1;
int i;
if (receive > sizeof(ps2dev->cmdbuf)) {
WARN_ON(1);
return -1;
}
down(&ps2dev->cmd_sem);
serio_pause_rx(ps2dev->serio);
......@@ -101,7 +192,6 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
* ACKing the reset command, and so it can take a long
* time before the ACK arrrives.
*/
if (command & 0xff)
if (ps2_sendbyte(ps2dev, command & 0xff,
command == PS2_CMD_RESET_BAT ? 1000 : 200))
goto out;
......@@ -120,33 +210,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
if (ps2dev->cmdcnt && timeout > 0) {
if (command == PS2_CMD_RESET_BAT && timeout > msecs_to_jiffies(100)) {
/*
* 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);
}
timeout = ps2_adjust_timeout(ps2dev, command, timeout);
wait_event_timeout(ps2dev->wait,
!(ps2dev->flags & PS2_FLAG_CMD), timeout);
}
......@@ -160,7 +224,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
rc = 0;
out:
out:
serio_pause_rx(ps2dev->serio);
ps2dev->flags = 0;
serio_continue_rx(ps2dev->serio);
......
......@@ -356,7 +356,7 @@ static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data,
case STATE_DATA:
ts->chksum += data;
ts->buf[ts->idx]= data;
if(++ts->idx == ts->len)
if (++ts->idx == ts->len)
state = STATE_EOF;
break;
case STATE_EOF:
......
......@@ -77,7 +77,6 @@ MODULE_PARM_DESC(irq, "IRQ of MK712 touchscreen controller");
#define MK712_READ_ONE_POINT 0x20
#define MK712_POWERUP 0x40
static int mk712_used = 0;
static struct input_dev mk712_dev;
static DEFINE_SPINLOCK(mk712_lock);
......@@ -130,8 +129,6 @@ static int mk712_open(struct input_dev *dev)
spin_lock_irqsave(&mk712_lock, flags);
if (!mk712_used++) {
outb(0, mk712_io + MK712_CONTROL); /* Reset */
outb(MK712_ENABLE_INT | MK712_INT_ON_CONVERSION_COMPLETE |
......@@ -140,7 +137,6 @@ static int mk712_open(struct input_dev *dev)
MK712_POWERUP, mk712_io + MK712_CONTROL);
outb(10, mk712_io + MK712_RATE); /* 187 points per second */
}
spin_unlock_irqrestore(&mk712_lock, flags);
......@@ -153,7 +149,6 @@ static void mk712_close(struct input_dev *dev)
spin_lock_irqsave(&mk712_lock, flags);
if (!--mk712_used)
outb(0, mk712_io + MK712_CONTROL);
spin_unlock_irqrestore(&mk712_lock, flags);
......
......@@ -31,6 +31,7 @@ obj-$(CONFIG_USB_MOUSE) += input/
obj-$(CONFIG_USB_MTOUCH) += input/
obj-$(CONFIG_USB_POWERMATE) += input/
obj-$(CONFIG_USB_WACOM) += input/
obj-$(CONFIG_USB_ACECAD) += input/
obj-$(CONFIG_USB_XPAD) += input/
obj-$(CONFIG_USB_DABUSB) += media/
......
......@@ -151,6 +151,18 @@ config USB_WACOM
To compile this driver as a module, choose M here: the
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
tristate "KB Gear JamStudio tablet support"
depends on USB && INPUT
......@@ -190,6 +202,18 @@ config USB_MTOUCH
To compile this driver as a module, choose M here: the
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
tristate "eGalax TouchKit USB Touchscreen Driver"
depends on USB && INPUT
......
......@@ -33,7 +33,9 @@ obj-$(CONFIG_USB_KBD) += usbkbd.o
obj-$(CONFIG_USB_KBTAB) += kbtab.o
obj-$(CONFIG_USB_MOUSE) += usbmouse.o
obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o
obj-$(CONFIG_USB_ITMTOUCH) += itmtouch.o
obj-$(CONFIG_USB_EGALAX) += touchkitusb.o
obj-$(CONFIG_USB_POWERMATE) += powermate.o
obj-$(CONFIG_USB_WACOM) += wacom.o
obj-$(CONFIG_USB_ACECAD) += acecad.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);
......@@ -324,7 +324,6 @@ struct aiptek {
struct aiptek_settings curSetting; /* tablet's current programmable */
struct aiptek_settings newSetting; /* ... and new param settings */
unsigned int ifnum; /* interface number for IO */
int openCount; /* module use counter */
int diagnostic; /* tablet diagnostic codes */
unsigned long eventCount; /* event count */
int inDelay; /* jitter: in jitter delay? */
......@@ -814,15 +813,9 @@ static int aiptek_open(struct input_dev *inputdev)
{
struct aiptek *aiptek = inputdev->private;
if (aiptek->openCount++ > 0) {
return 0;
}
aiptek->urb->dev = aiptek->usbdev;
if (usb_submit_urb(aiptek->urb, GFP_KERNEL) != 0) {
aiptek->openCount--;
if (usb_submit_urb(aiptek->urb, GFP_KERNEL) != 0)
return -EIO;
}
return 0;
}
......@@ -834,9 +827,7 @@ static void aiptek_close(struct input_dev *inputdev)
{
struct aiptek *aiptek = inputdev->private;
if (--aiptek->openCount == 0) {
usb_kill_urb(aiptek->urb);
}
}
/***********************************************************************
......@@ -2252,7 +2243,6 @@ static void aiptek_disconnect(struct usb_interface *intf)
AIPTEK_PACKET_LENGTH,
aiptek->data, aiptek->data_dma);
kfree(aiptek);
aiptek = NULL;
}
}
......
......@@ -113,11 +113,11 @@
#define DATA_BUFSIZE 63 /* size of URB data buffers */
#define ATI_INPUTNUM 1 /* Which input device to register as */
static unsigned long channel_mask = 0;
static unsigned long channel_mask;
module_param(channel_mask, ulong, 0444);
MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore");
static int debug = 0;
static int debug;
module_param(debug, int, 0444);
MODULE_PARM_DESC(debug, "Enable extra debug messages and information");
......@@ -174,8 +174,6 @@ struct ati_remote {
dma_addr_t inbuf_dma;
dma_addr_t outbuf_dma;
int open; /* open counter */
unsigned char old_data[2]; /* Detect duplicate events */
unsigned long old_jiffies;
unsigned long acc_jiffies; /* handle acceleration */
......@@ -328,25 +326,16 @@ static void ati_remote_dump(unsigned char *data, unsigned int len)
static int ati_remote_open(struct input_dev *inputdev)
{
struct ati_remote *ati_remote = inputdev->private;
int retval = 0;
down(&disconnect_sem);
if (ati_remote->open++)
goto exit;
/* On first open, submit the read urb which was set up previously. */
ati_remote->irq_urb->dev = ati_remote->udev;
if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) {
dev_err(&ati_remote->interface->dev,
"%s: usb_submit_urb failed!\n", __FUNCTION__);
ati_remote->open--;
retval = -EIO;
return -EIO;
}
exit:
up(&disconnect_sem);
return retval;
return 0;
}
/*
......@@ -356,7 +345,6 @@ static void ati_remote_close(struct input_dev *inputdev)
{
struct ati_remote *ati_remote = inputdev->private;
if (!--ati_remote->open)
usb_kill_urb(ati_remote->irq_urb);
}
......@@ -489,8 +477,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs)
(ati_remote->old_data[1] == data[2]) &&
((ati_remote->old_jiffies + FILTER_TIME) > jiffies)) {
ati_remote->repeat_count++;
}
else {
} else {
ati_remote->repeat_count = 0;
}
......@@ -603,8 +590,6 @@ static void ati_remote_irq_in(struct urb *urb, struct pt_regs *regs)
*/
static void ati_remote_delete(struct ati_remote *ati_remote)
{
if (!ati_remote) return;
if (ati_remote->irq_urb)
usb_kill_urb(ati_remote->irq_urb);
......@@ -800,8 +785,6 @@ static void ati_remote_disconnect(struct usb_interface *interface)
{
struct ati_remote *ati_remote;
down(&disconnect_sem);
ati_remote = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
if (!ati_remote) {
......@@ -810,8 +793,6 @@ static void ati_remote_disconnect(struct usb_interface *interface)
}
ati_remote_delete(ati_remote);
up(&disconnect_sem);
}
/*
......
......@@ -765,7 +765,7 @@ static __inline__ __u32 s32ton(__s32 value, unsigned n)
static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
{
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)
......@@ -1233,6 +1233,13 @@ int hid_wait_io(struct hid_device *hid)
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,
unsigned char type, void *buf, int size)
{
......@@ -1301,10 +1308,6 @@ void hid_init_reports(struct hid_device *hid)
if (err)
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
......@@ -1318,6 +1321,10 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_WACOM_INTUOS3 0x00B0
#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_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001
......@@ -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_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_CS124U, 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)
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) {
dbg("reading report descriptor failed");
kfree(rdesc);
......
/******************************************************************************
* itmtouch.c -- Driver for ITM touchscreen panel
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Based upon original work by Chris Collins <xfire-itmtouch@xware.cx>.
*
* Kudos to ITM for providing me with the datasheet for the panel,
* even though it was a day later than I had finished writing this
* driver.
*
* It has meant that I've been able to correct my interpretation of the
* protocol packets however.
*
* CC -- 2003/9/29
*
* History
* 1.0 & 1.1 2003 (CC) vojtech@suse.cz
* Original version for 2.4.x kernels
*
* 1.2 02/03/2005 (HCE) hc@mivu.no
* Complete rewrite to support Linux 2.6.10, thanks to mtouchusb.c for hints.
* Unfortunately no calibration support at this time.
*
* 1.2.1 09/03/2005 (HCE) hc@mivu.no
* Code cleanup and adjusting syntax to start matching kernel standards
*
*****************************************************************************/
#include <linux/config.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
#else
#undef DEBUG
#endif
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb.h>
/* only an 8 byte buffer necessary for a single packet */
#define ITM_BUFSIZE 8
#define PATH_SIZE 64
#define USB_VENDOR_ID_ITMINC 0x0403
#define USB_PRODUCT_ID_TOUCHPANEL 0xf9e9
#define DRIVER_AUTHOR "Hans-Christian Egtvedt <hc@mivu.no>"
#define DRIVER_VERSION "v1.2.1"
#define DRIVER_DESC "USB ITM Inc Touch Panel Driver"
#define DRIVER_LICENSE "GPL"
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE( DRIVER_LICENSE );
struct itmtouch_dev {
struct usb_device *usbdev; /* usb device */
struct input_dev inputdev; /* input device */
struct urb *readurb; /* urb */
char rbuf[ITM_BUFSIZE]; /* data */
int users;
char name[128];
char phys[64];
};
static struct usb_device_id itmtouch_ids [] = {
{ USB_DEVICE(USB_VENDOR_ID_ITMINC, USB_PRODUCT_ID_TOUCHPANEL) },
{ }
};
static void itmtouch_irq(struct urb *urb, struct pt_regs *regs)
{
struct itmtouch_dev * itmtouch = urb->context;
unsigned char *data = urb->transfer_buffer;
struct input_dev *dev = &itmtouch->inputdev;
int retval;
switch (urb->status) {
case 0:
/* success */
break;
case -ETIMEDOUT:
/* this urb is timing out */
dbg("%s - urb timed out - was the device unplugged?",
__FUNCTION__);
return;
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 exit;
}
input_regs(dev, regs);
/* if pressure has been released, then don't report X/Y */
if (data[7] & 0x20) {
input_report_abs(dev, ABS_X, (data[0] & 0x1F) << 7 | (data[3] & 0x7F));
input_report_abs(dev, ABS_Y, (data[1] & 0x1F) << 7 | (data[4] & 0x7F));
}
input_report_abs(dev, ABS_PRESSURE, (data[2] & 1) << 7 | (data[5] & 0x7F));
input_report_key(dev, BTN_TOUCH, ~data[7] & 0x20);
input_sync(dev);
exit:
retval = usb_submit_urb (urb, GFP_ATOMIC);
if (retval)
printk(KERN_ERR "%s - usb_submit_urb failed with result: %d",
__FUNCTION__, retval);
}
static int itmtouch_open(struct input_dev *input)
{
struct itmtouch_dev *itmtouch = input->private;
itmtouch->readurb->dev = itmtouch->usbdev;
if (usb_submit_urb(itmtouch->readurb, GFP_KERNEL))
return -EIO;
return 0;
}
static void itmtouch_close(struct input_dev *input)
{
struct itmtouch_dev *itmtouch = input->private;
usb_kill_urb(itmtouch->readurb);
}
static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct itmtouch_dev *itmtouch;
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
struct usb_device *udev = interface_to_usbdev(intf);
unsigned int pipe;
unsigned int maxp;
char path[PATH_SIZE];
interface = intf->cur_altsetting;
endpoint = &interface->endpoint[0].desc;
if (!(itmtouch = kcalloc(1, sizeof(struct itmtouch_dev), GFP_KERNEL))) {
err("%s - Out of memory.", __FUNCTION__);
return -ENOMEM;
}
itmtouch->usbdev = udev;
itmtouch->inputdev.private = itmtouch;
itmtouch->inputdev.open = itmtouch_open;
itmtouch->inputdev.close = itmtouch_close;
usb_make_path(udev, path, PATH_SIZE);
itmtouch->inputdev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
itmtouch->inputdev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
itmtouch->inputdev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
itmtouch->inputdev.name = itmtouch->name;
itmtouch->inputdev.phys = itmtouch->phys;
itmtouch->inputdev.id.bustype = BUS_USB;
itmtouch->inputdev.id.vendor = udev->descriptor.idVendor;
itmtouch->inputdev.id.product = udev->descriptor.idProduct;
itmtouch->inputdev.id.version = udev->descriptor.bcdDevice;
itmtouch->inputdev.dev = &intf->dev;
if (!strlen(itmtouch->name))
sprintf(itmtouch->name, "USB ITM touchscreen");
/* device limits */
/* as specified by the ITM datasheet, X and Y are 12bit,
* Z (pressure) is 8 bit. However, the fields are defined up
* to 14 bits for future possible expansion.
*/
input_set_abs_params(&itmtouch->inputdev, ABS_X, 0, 0x0FFF, 2, 0);
input_set_abs_params(&itmtouch->inputdev, ABS_Y, 0, 0x0FFF, 2, 0);
input_set_abs_params(&itmtouch->inputdev, ABS_PRESSURE, 0, 0xFF, 2, 0);
/* initialise the URB so we can read from the transport stream */
pipe = usb_rcvintpipe(itmtouch->usbdev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
if (maxp > ITM_BUFSIZE)
maxp = ITM_BUFSIZE;
itmtouch->readurb = usb_alloc_urb(0, GFP_KERNEL);
if (!itmtouch->readurb) {
dbg("%s - usb_alloc_urb failed: itmtouch->readurb", __FUNCTION__);
kfree(itmtouch);
return -ENOMEM;
}
usb_fill_int_urb(itmtouch->readurb, itmtouch->usbdev, pipe, itmtouch->rbuf,
maxp, itmtouch_irq, itmtouch, endpoint->bInterval);
input_register_device(&itmtouch->inputdev);
printk(KERN_INFO "itmtouch: %s registered on %s\n", itmtouch->name, path);
usb_set_intfdata(intf, itmtouch);
return 0;
}
static void itmtouch_disconnect(struct usb_interface *intf)
{
struct itmtouch_dev *itmtouch = usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL);
if (itmtouch) {
input_unregister_device(&itmtouch->inputdev);
usb_kill_urb(itmtouch->readurb);
usb_free_urb(itmtouch->readurb);
kfree(itmtouch);
}
}
MODULE_DEVICE_TABLE(usb, itmtouch_ids);
static struct usb_driver itmtouch_driver = {
.owner = THIS_MODULE,
.name = "itmtouch",
.probe = itmtouch_probe,
.disconnect = itmtouch_disconnect,
.id_table = itmtouch_ids,
};
static int __init itmtouch_init(void)
{
info(DRIVER_DESC " " DRIVER_VERSION);
info(DRIVER_AUTHOR);
return usb_register(&itmtouch_driver);
}
static void __exit itmtouch_exit(void)
{
usb_deregister(&itmtouch_driver);
}
module_init(itmtouch_init);
module_exit(itmtouch_exit);
......@@ -36,7 +36,6 @@ struct kbtab {
struct input_dev dev;
struct usb_device *usbdev;
struct urb *irq;
int open;
int x, y;
int button;
int pressure;
......@@ -79,7 +78,7 @@ static void kbtab_irq(struct urb *urb, struct pt_regs *regs)
/*input_report_key(dev, BTN_TOUCH , data[0] & 0x01);*/
input_report_key(dev, BTN_RIGHT, data[0] & 0x02);
if( -1 == kb_pressure_click){
if (-1 == kb_pressure_click) {
input_report_abs(dev, ABS_PRESSURE, kbtab->pressure);
} else {
input_report_key(dev, BTN_LEFT, (kbtab->pressure > kb_pressure_click) ? 1 : 0);
......@@ -105,14 +104,9 @@ static int kbtab_open(struct input_dev *dev)
{
struct kbtab *kbtab = dev->private;
if (kbtab->open++)
return 0;
kbtab->irq->dev = kbtab->usbdev;
if (usb_submit_urb(kbtab->irq, GFP_KERNEL)) {
kbtab->open--;
if (usb_submit_urb(kbtab->irq, GFP_KERNEL))
return -EIO;
}
return 0;
}
......@@ -121,7 +115,6 @@ static void kbtab_close(struct input_dev *dev)
{
struct kbtab *kbtab = dev->private;
if (!--kbtab->open)
usb_kill_urb(kbtab->irq);
}
......
......@@ -98,12 +98,11 @@ struct mtouch_usb {
struct urb *irq;
struct usb_device *udev;
struct input_dev input;
int open;
char name[128];
char phys[64];
};
static struct usb_device_id mtouchusb_devices [] = {
static struct usb_device_id mtouchusb_devices[] = {
{ USB_DEVICE(0x0596, 0x0001) },
{ }
};
......@@ -138,43 +137,36 @@ static void mtouchusb_irq(struct urb *urb, struct pt_regs *regs)
input_regs(&mtouch->input, regs);
input_report_key(&mtouch->input, BTN_TOUCH,
MTOUCHUSB_GET_TOUCHED(mtouch->data));
input_report_abs(&mtouch->input, ABS_X,
MTOUCHUSB_GET_XC(mtouch->data));
input_report_abs(&mtouch->input, ABS_X, MTOUCHUSB_GET_XC(mtouch->data));
input_report_abs(&mtouch->input, ABS_Y,
(raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC)
- MTOUCHUSB_GET_YC(mtouch->data));
input_sync(&mtouch->input);
exit:
retval = usb_submit_urb (urb, GFP_ATOMIC);
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
err ("%s - usb_submit_urb failed with result: %d",
err("%s - usb_submit_urb failed with result: %d",
__FUNCTION__, retval);
}
static int mtouchusb_open (struct input_dev *input)
static int mtouchusb_open(struct input_dev *input)
{
struct mtouch_usb *mtouch = input->private;
if (mtouch->open++)
return 0;
mtouch->irq->dev = mtouch->udev;
if (usb_submit_urb (mtouch->irq, GFP_ATOMIC)) {
mtouch->open--;
if (usb_submit_urb(mtouch->irq, GFP_ATOMIC))
return -EIO;
}
return 0;
}
static void mtouchusb_close (struct input_dev *input)
static void mtouchusb_close(struct input_dev *input)
{
struct mtouch_usb *mtouch = input->private;
if (!--mtouch->open)
usb_kill_urb (mtouch->irq);
usb_kill_urb(mtouch->irq);
}
static int mtouchusb_alloc_buffers(struct usb_device *udev, struct mtouch_usb *mtouch)
......@@ -204,7 +196,7 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i
struct mtouch_usb *mtouch;
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
struct usb_device *udev = interface_to_usbdev (intf);
struct usb_device *udev = interface_to_usbdev(intf);
char path[64];
int nRet;
......@@ -216,7 +208,7 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i
dbg("%s - setting endpoint", __FUNCTION__);
endpoint = &interface->endpoint[0].desc;
if (!(mtouch = kmalloc (sizeof (struct mtouch_usb), GFP_KERNEL))) {
if (!(mtouch = kmalloc(sizeof(struct mtouch_usb), GFP_KERNEL))) {
err("%s - Out of memory.", __FUNCTION__);
return -ENOMEM;
}
......@@ -252,12 +244,12 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i
/* Used to Scale Compensated Data and Flip Y */
mtouch->input.absmin[ABS_X] = MTOUCHUSB_MIN_XC;
mtouch->input.absmax[ABS_X] = raw_coordinates ? \
mtouch->input.absmax[ABS_X] = raw_coordinates ?
MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC;
mtouch->input.absfuzz[ABS_X] = MTOUCHUSB_XC_FUZZ;
mtouch->input.absflat[ABS_X] = MTOUCHUSB_XC_FLAT;
mtouch->input.absmin[ABS_Y] = MTOUCHUSB_MIN_YC;
mtouch->input.absmax[ABS_Y] = raw_coordinates ? \
mtouch->input.absmax[ABS_Y] = raw_coordinates ?
MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC;
mtouch->input.absfuzz[ABS_Y] = MTOUCHUSB_YC_FUZZ;
mtouch->input.absflat[ABS_Y] = MTOUCHUSB_YC_FLAT;
......@@ -271,15 +263,10 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i
sprintf(mtouch->name, "USB Touchscreen %04x:%04x",
mtouch->input.id.vendor, mtouch->input.id.product);
nRet = usb_control_msg(mtouch->udev,
usb_rcvctrlpipe(udev, 0),
nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0),
MTOUCHUSB_RESET,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1,
0,
NULL,
0,
USB_CTRL_SET_TIMEOUT);
1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d",
__FUNCTION__, nRet);
......@@ -293,27 +280,18 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i
}
dbg("%s - usb_fill_int_urb", __FUNCTION__);
usb_fill_int_urb(mtouch->irq,
mtouch->udev,
usb_fill_int_urb(mtouch->irq, mtouch->udev,
usb_rcvintpipe(mtouch->udev, 0x81),
mtouch->data,
MTOUCHUSB_REPORT_DATA_SIZE,
mtouchusb_irq,
mtouch,
endpoint->bInterval);
mtouch->data, MTOUCHUSB_REPORT_DATA_SIZE,
mtouchusb_irq, mtouch, endpoint->bInterval);
dbg("%s - input_register_device", __FUNCTION__);
input_register_device(&mtouch->input);
nRet = usb_control_msg(mtouch->udev,
usb_rcvctrlpipe(udev, 0),
nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0),
MTOUCHUSB_ASYNC_REPORT,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1,
1,
NULL,
0,
USB_CTRL_SET_TIMEOUT);
1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",
__FUNCTION__, nRet);
......@@ -325,7 +303,7 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i
static void mtouchusb_disconnect(struct usb_interface *intf)
{
struct mtouch_usb *mtouch = usb_get_intfdata (intf);
struct mtouch_usb *mtouch = usb_get_intfdata(intf);
dbg("%s - called", __FUNCTION__);
usb_set_intfdata(intf, NULL);
......@@ -339,7 +317,7 @@ static void mtouchusb_disconnect(struct usb_interface *intf)
}
}
MODULE_DEVICE_TABLE (usb, mtouchusb_devices);
MODULE_DEVICE_TABLE(usb, mtouchusb_devices);
static struct usb_driver mtouchusb_driver = {
.owner = THIS_MODULE,
......@@ -349,12 +327,14 @@ static struct usb_driver mtouchusb_driver = {
.id_table = mtouchusb_devices,
};
static int __init mtouchusb_init(void) {
static int __init mtouchusb_init(void)
{
dbg("%s - called", __FUNCTION__);
return usb_register(&mtouchusb_driver);
}
static void __exit mtouchusb_cleanup(void) {
static void __exit mtouchusb_cleanup(void)
{
dbg("%s - called", __FUNCTION__);
usb_deregister(&mtouchusb_driver);
}
......@@ -362,6 +342,6 @@ static void __exit mtouchusb_cleanup(void) {
module_init(mtouchusb_init);
module_exit(mtouchusb_cleanup);
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
......@@ -69,7 +69,6 @@ struct touchkit_usb {
struct urb *irq;
struct usb_device *udev;
struct input_dev input;
int open;
char name[128];
char phys[64];
};
......@@ -134,15 +133,10 @@ static int touchkit_open(struct input_dev *input)
{
struct touchkit_usb *touchkit = input->private;
if (touchkit->open++)
return 0;
touchkit->irq->dev = touchkit->udev;
if (usb_submit_urb(touchkit->irq, GFP_ATOMIC)) {
touchkit->open--;
if (usb_submit_urb(touchkit->irq, GFP_ATOMIC))
return -EIO;
}
return 0;
}
......@@ -151,7 +145,6 @@ static void touchkit_close(struct input_dev *input)
{
struct touchkit_usb *touchkit = input->private;
if (!--touchkit->open)
usb_kill_urb(touchkit->irq);
}
......
......@@ -72,7 +72,6 @@ struct usb_kbd {
unsigned char newleds;
char name[128];
char phys[64];
int open;
unsigned char *new;
struct usb_ctrlrequest *cr;
......@@ -180,14 +179,9 @@ static int usb_kbd_open(struct input_dev *dev)
{
struct usb_kbd *kbd = dev->private;
if (kbd->open++)
return 0;
kbd->irq->dev = kbd->usbdev;
if (usb_submit_urb(kbd->irq, GFP_KERNEL)) {
kbd->open--;
if (usb_submit_urb(kbd->irq, GFP_KERNEL))
return -EIO;
}
return 0;
}
......@@ -196,7 +190,6 @@ static void usb_kbd_close(struct input_dev *dev)
{
struct usb_kbd *kbd = dev->private;
if (!--kbd->open)
usb_kill_urb(kbd->irq);
}
......
......@@ -51,7 +51,6 @@ struct usb_mouse {
struct usb_device *usbdev;
struct input_dev dev;
struct urb *irq;
int open;
signed char *data;
dma_addr_t data_dma;
......@@ -101,14 +100,9 @@ static int usb_mouse_open(struct input_dev *dev)
{
struct usb_mouse *mouse = dev->private;
if (mouse->open++)
return 0;
mouse->irq->dev = mouse->usbdev;
if (usb_submit_urb(mouse->irq, GFP_KERNEL)) {
mouse->open--;
if (usb_submit_urb(mouse->irq, GFP_KERNEL))
return -EIO;
}
return 0;
}
......@@ -117,7 +111,6 @@ static void usb_mouse_close(struct input_dev *dev)
{
struct usb_mouse *mouse = dev->private;
if (!--mouse->open)
usb_kill_urb(mouse->irq);
}
......
This diff is collapsed.
......@@ -110,7 +110,6 @@ struct usb_xpad {
dma_addr_t idata_dma;
char phys[65]; /* physical device path */
int open_count; /* reference count */
};
/*
......@@ -197,14 +196,9 @@ static int xpad_open (struct input_dev *dev)
{
struct usb_xpad *xpad = dev->private;
if (xpad->open_count++)
return 0;
xpad->irq_in->dev = xpad->udev;
if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) {
xpad->open_count--;
if (usb_submit_urb(xpad->irq_in, GFP_KERNEL))
return -EIO;
}
return 0;
}
......@@ -213,7 +207,6 @@ static void xpad_close (struct input_dev *dev)
{
struct usb_xpad *xpad = dev->private;
if (!--xpad->open_count)
usb_kill_urb(xpad->irq_in);
}
......
......@@ -859,6 +859,10 @@ struct input_dev {
int (*erase_effect)(struct input_dev *dev, int effect_id);
struct input_handle *grab;
struct semaphore sem; /* serializes open and close operations */
unsigned int users;
struct device *dev;
struct list_head h_list;
......
......@@ -111,18 +111,35 @@ struct js_corr {
#define JS_SET_ALL 8
struct JS_DATA_TYPE {
int buttons;
int x;
int y;
__s32 buttons;
__s32 x;
__s32 y;
};
struct JS_DATA_SAVE_TYPE {
int JS_TIMEOUT;
int BUSY;
long JS_EXPIRETIME;
long JS_TIMELIMIT;
struct JS_DATA_SAVE_TYPE_32 {
__s32 JS_TIMEOUT;
__s32 BUSY;
__s32 JS_EXPIRETIME;
__s32 JS_TIMELIMIT;
struct JS_DATA_TYPE JS_SAVE;
struct JS_DATA_TYPE JS_CORR;
};
struct JS_DATA_SAVE_TYPE_64 {
__s32 JS_TIMEOUT;
__s32 BUSY;
__s64 JS_EXPIRETIME;
__s64 JS_TIMELIMIT;
struct JS_DATA_TYPE JS_SAVE;
struct JS_DATA_TYPE JS_CORR;
};
#if BITS_PER_LONG == 64
#define JS_DATA_SAVE_TYPE JS_DATA_SAVE_TYPE_64
#elif BITS_PER_LONG == 32
#define JS_DATA_SAVE_TYPE JS_DATA_SAVE_TYPE_32
#else
#error Unexpected BITS_PER_LONG
#endif
#endif /* _LINUX_JOYSTICK_H */
......@@ -41,6 +41,7 @@ struct ps2dev {
void ps2_init(struct ps2dev *ps2dev, struct serio *serio);
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_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int command);
int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data);
......
......@@ -83,6 +83,7 @@ static inline void serio_register_port(struct serio *serio)
}
void serio_unregister_port(struct serio *serio);
void serio_unregister_child_port(struct serio *serio);
void __serio_unregister_port_delayed(struct serio *serio, struct module *owner);
static inline void serio_unregister_port_delayed(struct serio *serio)
{
......@@ -153,6 +154,11 @@ static inline int serio_pin_driver(struct serio *serio)
return down_interruptible(&serio->drv_sem);
}
static inline void serio_pin_driver_uninterruptible(struct serio *serio)
{
down(&serio->drv_sem);
}
static inline void serio_unpin_driver(struct serio *serio)
{
up(&serio->drv_sem);
......
......@@ -52,7 +52,7 @@ config SOUND_CMPCI_MIDI
config SOUND_CMPCI_JOYSTICK
bool "Enable joystick"
depends on SOUND_CMPCI && X86
depends on SOUND_CMPCI && X86 && (GAMEPORT=y || SOUND_CMPCI=GAMEPORT)
help
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
......
......@@ -162,6 +162,10 @@
#include <asm/page.h>
#include <asm/uaccess.h>
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
#define SUPPORT_JOYSTICK
#endif
/* --------------------------------------------------------------------- */
#undef OSS_DOCUMENTED_MIXER_SEMANTICS
......@@ -385,7 +389,10 @@ struct es1370_state {
unsigned char obuf[MIDIOUTBUF];
} midi;
#ifdef SUPPORT_JOYSTICK
struct gameport *gameport;
#endif
struct semaphore sem;
};
......@@ -2554,10 +2561,55 @@ static struct initvol {
{ SOUND_MIXER_WRITE_OGAIN, 0x4040 }
};
#ifdef SUPPORT_JOYSTICK
static int __devinit es1370_register_gameport(struct es1370_state *s)
{
struct gameport *gp;
if (!request_region(0x200, JOY_EXTENT, "es1370")) {
printk(KERN_ERR "es1370: joystick io port 0x200 in use\n");
return -EBUSY;
}
s->gameport = gp = gameport_allocate_port();
if (!gp) {
printk(KERN_ERR "es1370: can not allocate memory for gameport\n");
release_region(0x200, JOY_EXTENT);
return -ENOMEM;
}
gameport_set_name(gp, "ESS1370");
gameport_set_phys(gp, "pci%s/gameport0", pci_name(s->dev));
gp->dev.parent = &s->dev->dev;
gp->io = 0x200;
s->ctrl |= CTRL_JYSTK_EN;
outl(s->ctrl, s->io + ES1370_REG_CONTROL);
gameport_register_port(gp);
return 0;
}
static inline void es1370_unregister_gameport(struct es1370_state *s)
{
if (s->gameport) {
int gpio = s->gameport->io;
gameport_unregister_port(s->gameport);
release_region(gpio, JOY_EXTENT);
}
}
#else
static inline int es1370_register_gameport(struct es1370_state *s) { return -ENOSYS; }
static inline void es1370_unregister_gameport(struct es1370_state *s) { }
#endif /* SUPPORT_JOYSTICK */
static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
{
struct es1370_state *s;
struct gameport *gp = NULL;
mm_segment_t fs;
int i, val, ret;
......@@ -2606,27 +2658,13 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic
/* note: setting CTRL_SERR_DIS is reported to break
* mic bias setting (by Kim.Berts@fisub.mail.abb.com) */
s->ctrl = CTRL_CDC_EN | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL);
if (!request_region(0x200, JOY_EXTENT, "es1370")) {
printk(KERN_ERR "es1370: joystick io port 0x200 in use\n");
} else if (!(s->gameport = gp = gameport_allocate_port())) {
printk(KERN_ERR "es1370: can not allocate memory for gameport\n");
release_region(0x200, JOY_EXTENT);
} else {
gameport_set_name(gp, "ESS1370");
gameport_set_phys(gp, "pci%s/gameport0", pci_name(s->dev));
gp->dev.parent = &s->dev->dev;
gp->io = 0x200;
s->ctrl |= CTRL_JYSTK_EN;
}
if (lineout[devindex])
s->ctrl |= CTRL_XCTL0;
if (micbias[devindex])
s->ctrl |= CTRL_XCTL1;
s->sctrl = 0;
printk(KERN_INFO "es1370: found adapter at io %#lx irq %u\n"
KERN_INFO "es1370: features: joystick %s, line %s, mic impedance %s\n",
s->io, s->irq, (s->ctrl & CTRL_JYSTK_EN) ? "on" : "off",
(s->ctrl & CTRL_XCTL0) ? "out" : "in",
printk(KERN_INFO "es1370: adapter at io %#lx irq %u, line %s, mic impedance %s\n",
s->io, s->irq, (s->ctrl & CTRL_XCTL0) ? "out" : "in",
(s->ctrl & CTRL_XCTL1) ? "1" : "0");
/* register devices */
if ((s->dev_audio = register_sound_dsp(&es1370_audio_fops, -1)) < 0) {
......@@ -2673,9 +2711,7 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic
}
set_fs(fs);
/* register gameport */
if (gp)
gameport_register_port(gp);
es1370_register_gameport(s);
/* store it in the driver field */
pci_set_drvdata(pcidev, s);
......@@ -2697,10 +2733,6 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic
err_dev1:
printk(KERN_ERR "es1370: cannot register misc device\n");
free_irq(s->irq, s);
if (s->gameport) {
release_region(s->gameport->io, JOY_EXTENT);
gameport_free_port(s->gameport);
}
err_irq:
release_region(s->io, ES1370_EXTENT);
err_region:
......@@ -2719,11 +2751,7 @@ static void __devexit es1370_remove(struct pci_dev *dev)
outl(0, s->io+ES1370_REG_SERIAL_CONTROL); /* clear serial interrupts */
synchronize_irq(s->irq);
free_irq(s->irq, s);
if (s->gameport) {
int gpio = s->gameport->io;
gameport_unregister_port(s->gameport);
release_region(gpio, JOY_EXTENT);
}
es1370_unregister_gameport(s);
release_region(s->io, ES1370_EXTENT);
unregister_sound_dsp(s->dev_audio);
unregister_sound_mixer(s->dev_mixer);
......
......@@ -134,6 +134,10 @@
#include <asm/page.h>
#include <asm/uaccess.h>
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
#define SUPPORT_JOYSTICK
#endif
/* --------------------------------------------------------------------- */
#undef OSS_DOCUMENTED_MIXER_SEMANTICS
......@@ -454,7 +458,10 @@ struct es1371_state {
unsigned char obuf[MIDIOUTBUF];
} midi;
#ifdef SUPPORT_JOYSTICK
struct gameport *gameport;
#endif
struct semaphore sem;
};
......@@ -2787,12 +2794,63 @@ static struct
{ PCI_ANY_ID, PCI_ANY_ID }
};
#ifdef SUPPORT_JOYSTICK
static int __devinit es1371_register_gameport(struct es1371_state *s)
{
struct gameport *gp;
int gpio;
for (gpio = 0x218; gpio >= 0x200; gpio -= 0x08)
if (request_region(gpio, JOY_EXTENT, "es1371"))
break;
if (gpio < 0x200) {
printk(KERN_ERR PFX "no free joystick address found\n");
return -EBUSY;
}
s->gameport = gp = gameport_allocate_port();
if (!gp) {
printk(KERN_ERR PFX "can not allocate memory for gameport\n");
release_region(gpio, JOY_EXTENT);
return -ENOMEM;
}
gameport_set_name(gp, "ESS1371 Gameport");
gameport_set_phys(gp, "isa%04x/gameport0", gpio);
gp->dev.parent = &s->dev->dev;
gp->io = gpio;
s->ctrl |= CTRL_JYSTK_EN | (((gpio >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
outl(s->ctrl, s->io + ES1371_REG_CONTROL);
gameport_register_port(gp);
return 0;
}
static inline void es1371_unregister_gameport(struct es1371_state *s)
{
if (s->gameport) {
int gpio = s->gameport->io;
gameport_unregister_port(s->gameport);
release_region(gpio, JOY_EXTENT);
}
}
#else
static inline int es1371_register_gameport(struct es1371_state *s) { return -ENOSYS; }
static inline void es1371_unregister_gameport(struct es1371_state *s) { }
#endif /* SUPPORT_JOYSTICK */
static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
{
struct es1371_state *s;
struct gameport *gp;
mm_segment_t fs;
int i, gpio, val, res = -1;
int i, val, res = -1;
int idx;
unsigned long tmo;
signed long tmo2;
......@@ -2883,23 +2941,6 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic
}
}
for (gpio = 0x218; gpio >= 0x200; gpio -= 0x08)
if (request_region(gpio, JOY_EXTENT, "es1371"))
break;
if (gpio < 0x200) {
printk(KERN_ERR PFX "no free joystick address found\n");
} else if (!(s->gameport = gp = gameport_allocate_port())) {
printk(KERN_ERR PFX "can not allocate memory for gameport\n");
release_region(gpio, JOY_EXTENT);
} else {
gameport_set_name(gp, "ESS1371 Gameport");
gameport_set_phys(gp, "isa%04x/gameport0", gpio);
gp->dev.parent = &s->dev->dev;
gp->io = gpio;
s->ctrl |= CTRL_JYSTK_EN | (((gpio >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
}
s->sctrl = 0;
cssr = 0;
s->spdif_volume = -1;
......@@ -2969,9 +3010,7 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic
/* turn on S/PDIF output driver if requested */
outl(cssr, s->io+ES1371_REG_STATUS);
/* register gameport */
if (s->gameport)
gameport_register_port(s->gameport);
es1371_register_gameport(s);
/* store it in the driver field */
pci_set_drvdata(pcidev, s);
......@@ -2983,10 +3022,6 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic
return 0;
err_gp:
if (s->gameport) {
release_region(s->gameport->io, JOY_EXTENT);
gameport_free_port(s->gameport);
}
#ifdef ES1371_DEBUG
if (s->ps)
remove_proc_entry("es1371", NULL);
......@@ -3025,11 +3060,7 @@ static void __devexit es1371_remove(struct pci_dev *dev)
outl(0, s->io+ES1371_REG_SERIAL_CONTROL); /* clear serial interrupts */
synchronize_irq(s->irq);
free_irq(s->irq, s);
if (s->gameport) {
int gpio = s->gameport->io;
gameport_unregister_port(s->gameport);
release_region(gpio, JOY_EXTENT);
}
es1371_unregister_gameport(s);
release_region(s->io, ES1371_EXTENT);
unregister_sound_dsp(s->dev_audio);
unregister_sound_mixer(s->codec->dev_mixer);
......
......@@ -150,6 +150,10 @@
#define FMODE_DMFM 0x10
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
#define SUPPORT_JOYSTICK 1
#endif
static struct pci_driver solo1_driver;
/* --------------------------------------------------------------------- */
......@@ -227,7 +231,9 @@ struct solo1_state {
unsigned char obuf[MIDIOUTBUF];
} midi;
#if SUPPORT_JOYSTICK
struct gameport *gameport;
#endif
};
/* --------------------------------------------------------------------- */
......@@ -2281,6 +2287,7 @@ solo1_resume(struct pci_dev *pci_dev) {
return 0;
}
#ifdef SUPPORT_JOYSTICK
static int __devinit solo1_register_gameport(struct solo1_state *s, int io_port)
{
struct gameport *gp;
......@@ -2307,6 +2314,19 @@ static int __devinit solo1_register_gameport(struct solo1_state *s, int io_port)
return 0;
}
static inline void solo1_unregister_gameport(struct solo1_state *s)
{
if (s->gameport) {
int gpio = s->gameport->io;
gameport_unregister_port(s->gameport);
release_region(gpio, GAMEPORT_EXTENT);
}
}
#else
static inline int solo1_register_gameport(struct solo1_state *s, int io_port) { return -ENOSYS; }
static inline void solo1_unregister_gameport(struct solo1_state *s) { }
#endif /* SUPPORT_JOYSTICK */
static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
{
struct solo1_state *s;
......@@ -2438,11 +2458,7 @@ static void __devexit solo1_remove(struct pci_dev *dev)
synchronize_irq(s->irq);
pci_write_config_word(s->dev, 0x60, 0); /* turn off DDMA controller address space */
free_irq(s->irq, s);
if (s->gameport) {
int gpio = s->gameport->io;
gameport_unregister_port(s->gameport);
release_region(gpio, GAMEPORT_EXTENT);
}
solo1_unregister_gameport(s);
release_region(s->iobase, IOBASE_EXTENT);
release_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT);
release_region(s->ddmabase, DDMABASE_EXTENT);
......
......@@ -50,9 +50,12 @@
#include "sb.h"
#include "mpu401.h"
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
#define SUPPORT_JOYSTICK 1
#endif
static int mad16_conf;
static int mad16_cdsel;
static struct gameport *gameport;
static DEFINE_SPINLOCK(lock);
#define C928 1
......@@ -902,6 +905,10 @@ static int __initdata irq_map[16] =
-1, -1, -1, -1
};
#ifdef SUPPORT_JOYSTICK
static struct gameport *gameport;
static int __devinit mad16_register_gameport(int io_port)
{
if (!request_region(io_port, 1, "mad16 gameport")) {
......@@ -925,6 +932,20 @@ static int __devinit mad16_register_gameport(int io_port)
return 0;
}
static inline void mad16_unregister_gameport(void)
{
if (gameport) {
/* the gameport was initialized so we must free it up */
gameport_unregister_port(gameport);
gameport = NULL;
release_region(0x201, 1);
}
}
#else
static inline int mad16_register_gameport(int io_port) { return -ENOSYS; }
static inline void mad16_unregister_gameport(void) { }
#endif
static int __devinit init_mad16(void)
{
int dmatype = 0;
......@@ -1060,12 +1081,7 @@ static void __exit cleanup_mad16(void)
{
if (found_mpu)
unload_mad16_mpu(&cfg_mpu);
if (gameport) {
/* the gameport was initialized so we must free it up */
gameport_unregister_port(gameport);
gameport = NULL;
release_region(0x201, 1);
}
mad16_unregister_gameport();
unload_mad16(&cfg);
release_region(MC0_PORT, 12);
}
......
......@@ -122,6 +122,9 @@
#include "dm.h"
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
#define SUPPORT_JOYSTICK 1
#endif
/* --------------------------------------------------------------------- */
......@@ -365,7 +368,9 @@ struct sv_state {
unsigned char obuf[MIDIOUTBUF];
} midi;
#if SUPPORT_JOYSTICK
struct gameport *gameport;
#endif
};
/* --------------------------------------------------------------------- */
......@@ -2485,6 +2490,7 @@ static struct initvol {
#define RSRCISIOREGION(dev,num) (pci_resource_start((dev), (num)) != 0 && \
(pci_resource_flags((dev), (num)) & IORESOURCE_IO))
#ifdef SUPPORT_JOYSTICK
static int __devinit sv_register_gameport(struct sv_state *s, int io_port)
{
struct gameport *gp;
......@@ -2511,6 +2517,19 @@ static int __devinit sv_register_gameport(struct sv_state *s, int io_port)
return 0;
}
static inline void sv_unregister_gameport(struct sv_state *s)
{
if (s->gameport) {
int gpio = s->gameport->io;
gameport_unregister_port(s->gameport);
release_region(gpio, SV_EXTENT_GAME);
}
}
#else
static inline int sv_register_gameport(struct sv_state *s, int io_port) { return -ENOSYS; }
static inline void sv_unregister_gameport(struct sv_state *s) { }
#endif /* SUPPORT_JOYSTICK */
static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
{
static char __devinitdata sv_ddma_name[] = "S3 Inc. SonicVibes DDMA Controller";
......@@ -2711,11 +2730,7 @@ static void __devexit sv_remove(struct pci_dev *dev)
/*outb(0, s->iodmaa + SV_DMA_RESET);*/
/*outb(0, s->iodmac + SV_DMA_RESET);*/
free_irq(s->irq, s);
if (s->gameport) {
int gpio = s->gameport->io;
gameport_unregister_port(s->gameport);
release_region(gpio, SV_EXTENT_GAME);
}
sv_unregister_gameport(s);
release_region(s->iodmac, SV_EXTENT_DMA);
release_region(s->iodmaa, SV_EXTENT_DMA);
release_region(s->ioenh, SV_EXTENT_ENH);
......
......@@ -228,6 +228,10 @@
#define DRIVER_VERSION "0.14.10j-2.6"
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
#define SUPPORT_JOYSTICK 1
#endif
/* magic numbers to protect our data structures */
#define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */
#define TRIDENT_STATE_MAGIC 0x63657373 /* "cess" */
......@@ -4252,24 +4256,25 @@ trident_ac97_init(struct trident_card *card)
return num_ac97 + 1;
}
#ifdef SUPPORT_JOYSTICK
/* Gameport functions for the cards ADC gameport */
static unsigned char
trident_game_read(struct gameport *gameport)
static unsigned char trident_game_read(struct gameport *gameport)
{
struct trident_card *card = gameport->port_data;
return inb(TRID_REG(card, T4D_GAME_LEG));
}
static void
trident_game_trigger(struct gameport *gameport)
static void trident_game_trigger(struct gameport *gameport)
{
struct trident_card *card = gameport->port_data;
outb(0xff, TRID_REG(card, T4D_GAME_LEG));
}
static int
trident_game_cooked_read(struct gameport *gameport, int *axes, int *buttons)
static int trident_game_cooked_read(struct gameport *gameport,
int *axes, int *buttons)
{
struct trident_card *card = gameport->port_data;
int i;
......@@ -4285,8 +4290,7 @@ trident_game_cooked_read(struct gameport *gameport, int *axes, int *buttons)
return 0;
}
static int
trident_game_open(struct gameport *gameport, int mode)
static int trident_game_open(struct gameport *gameport, int mode)
{
struct trident_card *card = gameport->port_data;
......@@ -4305,8 +4309,7 @@ trident_game_open(struct gameport *gameport, int mode)
return 0;
}
static int __devinit
trident_register_gameport(struct trident_card *card)
static int __devinit trident_register_gameport(struct trident_card *card)
{
struct gameport *gp;
......@@ -4330,6 +4333,17 @@ trident_register_gameport(struct trident_card *card)
return 0;
}
static inline void trident_unregister_gameport(struct trident_card *card)
{
if (card->gameport)
gameport_unregister_port(card->gameport);
}
#else
static inline int trident_register_gameport(struct trident_card *card) { return -ENOSYS; }
static inline void trident_unregister_gameport(struct trident_card *card) { }
#endif /* SUPPORT_JOYSTICK */
/* install the driver, we do not allocate hardware channel nor DMA buffer */
/* now, they are defered until "ACCESS" time (in prog_dmabuf called by */
/* open/read/write/ioctl/mmap) */
......@@ -4569,8 +4583,7 @@ trident_remove(struct pci_dev *pci_dev)
}
/* Unregister gameport */
if (card->gameport)
gameport_unregister_port(card->gameport);
trident_unregister_gameport(card);
/* Kill interrupts, and SP/DIF */
trident_disable_loop_interrupts(card);
......
......@@ -1338,11 +1338,6 @@ static inline int snd_cs4281_create_gameport(cs4281_t *chip) { return -ENOSYS; }
static inline void snd_cs4281_free_gameport(cs4281_t *chip) { }
#endif /* CONFIG_GAMEPORT || (MODULE && CONFIG_GAMEPORT_MODULE) */
/*
*/
static int snd_cs4281_free(cs4281_t *chip)
{
snd_cs4281_free_gameport(chip);
......
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