mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-18 11:54:37 +08:00
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.
This commit is contained in:
commit
3e0777b8fa
@ -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,10 @@ 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;
|
||||
@ -386,9 +478,161 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct file_operations evdev_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = evdev_read,
|
||||
@ -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
|
||||
|
@ -1,322 +0,0 @@
|
||||
/*
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1,186 +0,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 = {
|
||||
|
134
drivers/input/mouse/lifebook.c
Normal file
134
drivers/input/mouse/lifebook.c
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* 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, ¶m, 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, ¶ms[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;
|
||||
}
|
||||
|
17
drivers/input/mouse/lifebook.h
Normal file
17
drivers/input/mouse/lifebook.h
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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;
|
||||
dev->private_data = input_dev;
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
init_input_dev(&mouse->dev);
|
||||
input_dev->name = dev->product_name;
|
||||
input_dev->id.bustype = BUS_MAPLE;
|
||||
|
||||
mouse->dev.private = mouse;
|
||||
mouse->dev.open = dc_mouse_open;
|
||||
mouse->dev.close = dc_mouse_close;
|
||||
mouse->dev.event = NULL;
|
||||
|
||||
mouse->dev.name = dev->product_name;
|
||||
mouse->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);
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "synaptics.h"
|
||||
#include "logips2pp.h"
|
||||
#include "alps.h"
|
||||
#include "lifebook.h"
|
||||
|
||||
#define DRIVER_DESC "PS/2 mouse driver"
|
||||
|
||||
@ -31,10 +32,9 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static unsigned int psmouse_max_proto = -1U;
|
||||
static unsigned int psmouse_max_proto = PSMOUSE_AUTO;
|
||||
static int psmouse_set_maxproto(const char *val, struct kernel_param *kp);
|
||||
static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp);
|
||||
static char *psmouse_proto_abbrev[] = { NULL, "bare", NULL, NULL, NULL, "imps", "exps", NULL, NULL, NULL };
|
||||
#define param_check_proto_abbrev(name, p) __param_check(name, p, unsigned int)
|
||||
#define param_set_proto_abbrev psmouse_set_maxproto
|
||||
#define param_get_proto_abbrev psmouse_get_maxproto
|
||||
@ -57,6 +57,7 @@ static unsigned int psmouse_resetafter;
|
||||
module_param_named(resetafter, psmouse_resetafter, uint, 0644);
|
||||
MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");
|
||||
|
||||
PSMOUSE_DEFINE_ATTR(protocol);
|
||||
PSMOUSE_DEFINE_ATTR(rate);
|
||||
PSMOUSE_DEFINE_ATTR(resolution);
|
||||
PSMOUSE_DEFINE_ATTR(resetafter);
|
||||
@ -67,7 +68,23 @@ __obsolete_setup("psmouse_smartscroll=");
|
||||
__obsolete_setup("psmouse_resetafter=");
|
||||
__obsolete_setup("psmouse_rate=");
|
||||
|
||||
static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "ThinkPS/2", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2", "AlpsPS/2" };
|
||||
/*
|
||||
* psmouse_sem protects all operations changing state of mouse
|
||||
* (connecting, disconnecting, changing rate or resolution via
|
||||
* sysfs). We could use a per-device semaphore but since there
|
||||
* rarely more than one PS/2 mouse connected and since semaphore
|
||||
* is taken in "slow" paths it is not worth it.
|
||||
*/
|
||||
static DECLARE_MUTEX(psmouse_sem);
|
||||
|
||||
struct psmouse_protocol {
|
||||
enum psmouse_type type;
|
||||
char *name;
|
||||
char *alias;
|
||||
int maxproto;
|
||||
int (*detect)(struct psmouse *, int);
|
||||
int (*init)(struct psmouse *);
|
||||
};
|
||||
|
||||
/*
|
||||
* psmouse_process_byte() analyzes the PS/2 data stream and reports
|
||||
@ -407,12 +424,15 @@ static int thinking_detect(struct psmouse *psmouse, int set_properties)
|
||||
*/
|
||||
static int ps2bare_detect(struct psmouse *psmouse, int set_properties)
|
||||
{
|
||||
if (set_properties) {
|
||||
if (!psmouse->vendor) psmouse->vendor = "Generic";
|
||||
if (!psmouse->name) psmouse->name = "Mouse";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* psmouse_extensions() probes for any extensions to the basic PS/2 protocol
|
||||
* the mouse may have.
|
||||
@ -423,6 +443,17 @@ static int psmouse_extensions(struct psmouse *psmouse,
|
||||
{
|
||||
int synaptics_hardware = 0;
|
||||
|
||||
/*
|
||||
* We always check for lifebook because it does not disturb mouse
|
||||
* (it only checks DMI information).
|
||||
*/
|
||||
if (lifebook_detect(psmouse, set_properties) == 0) {
|
||||
if (max_proto > PSMOUSE_IMEX) {
|
||||
if (!set_properties || lifebook_init(psmouse) == 0)
|
||||
return PSMOUSE_LIFEBOOK;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Try Kensington ThinkingMouse (we try first, because synaptics probe
|
||||
* upsets the thinkingmouse).
|
||||
@ -506,6 +537,103 @@ static int psmouse_extensions(struct psmouse *psmouse,
|
||||
return PSMOUSE_PS2;
|
||||
}
|
||||
|
||||
static struct psmouse_protocol psmouse_protocols[] = {
|
||||
{
|
||||
.type = PSMOUSE_PS2,
|
||||
.name = "PS/2",
|
||||
.alias = "bare",
|
||||
.maxproto = 1,
|
||||
.detect = ps2bare_detect,
|
||||
},
|
||||
{
|
||||
.type = PSMOUSE_PS2PP,
|
||||
.name = "PS2++",
|
||||
.alias = "logitech",
|
||||
.detect = ps2pp_init,
|
||||
},
|
||||
{
|
||||
.type = PSMOUSE_THINKPS,
|
||||
.name = "ThinkPS/2",
|
||||
.alias = "thinkps",
|
||||
.detect = thinking_detect,
|
||||
},
|
||||
{
|
||||
.type = PSMOUSE_GENPS,
|
||||
.name = "GenPS/2",
|
||||
.alias = "genius",
|
||||
.detect = genius_detect,
|
||||
},
|
||||
{
|
||||
.type = PSMOUSE_IMPS,
|
||||
.name = "ImPS/2",
|
||||
.alias = "imps",
|
||||
.maxproto = 1,
|
||||
.detect = intellimouse_detect,
|
||||
},
|
||||
{
|
||||
.type = PSMOUSE_IMEX,
|
||||
.name = "ImExPS/2",
|
||||
.alias = "exps",
|
||||
.maxproto = 1,
|
||||
.detect = im_explorer_detect,
|
||||
},
|
||||
{
|
||||
.type = PSMOUSE_SYNAPTICS,
|
||||
.name = "SynPS/2",
|
||||
.alias = "synaptics",
|
||||
.detect = synaptics_detect,
|
||||
.init = synaptics_init,
|
||||
},
|
||||
{
|
||||
.type = PSMOUSE_ALPS,
|
||||
.name = "AlpsPS/2",
|
||||
.alias = "alps",
|
||||
.detect = alps_detect,
|
||||
.init = alps_init,
|
||||
},
|
||||
{
|
||||
.type = PSMOUSE_LIFEBOOK,
|
||||
.name = "LBPS/2",
|
||||
.alias = "lifebook",
|
||||
.init = lifebook_init,
|
||||
},
|
||||
{
|
||||
.type = PSMOUSE_AUTO,
|
||||
.name = "auto",
|
||||
.alias = "any",
|
||||
.maxproto = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct psmouse_protocol *psmouse_protocol_by_type(enum psmouse_type type)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(psmouse_protocols); i++)
|
||||
if (psmouse_protocols[i].type == type)
|
||||
return &psmouse_protocols[i];
|
||||
|
||||
WARN_ON(1);
|
||||
return &psmouse_protocols[0];
|
||||
}
|
||||
|
||||
static struct psmouse_protocol *psmouse_protocol_by_name(const char *name, size_t len)
|
||||
{
|
||||
struct psmouse_protocol *p;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(psmouse_protocols); i++) {
|
||||
p = &psmouse_protocols[i];
|
||||
|
||||
if ((strlen(p->name) == len && !strncmp(p->name, name, len)) ||
|
||||
(strlen(p->alias) == len && !strncmp(p->alias, name, len)))
|
||||
return &psmouse_protocols[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* psmouse_probe() probes for a PS/2 mouse.
|
||||
*/
|
||||
@ -653,30 +781,84 @@ static void psmouse_cleanup(struct serio *serio)
|
||||
|
||||
static void psmouse_disconnect(struct serio *serio)
|
||||
{
|
||||
struct psmouse *psmouse, *parent;
|
||||
struct psmouse *psmouse, *parent = NULL;
|
||||
|
||||
psmouse = serio_get_drvdata(serio);
|
||||
|
||||
device_remove_file(&serio->dev, &psmouse_attr_protocol);
|
||||
device_remove_file(&serio->dev, &psmouse_attr_rate);
|
||||
device_remove_file(&serio->dev, &psmouse_attr_resolution);
|
||||
device_remove_file(&serio->dev, &psmouse_attr_resetafter);
|
||||
|
||||
psmouse = serio_get_drvdata(serio);
|
||||
down(&psmouse_sem);
|
||||
|
||||
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
|
||||
|
||||
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
|
||||
parent = serio_get_drvdata(serio->parent);
|
||||
if (parent->pt_deactivate)
|
||||
parent->pt_deactivate(parent);
|
||||
psmouse_deactivate(parent);
|
||||
}
|
||||
|
||||
if (psmouse->disconnect)
|
||||
psmouse->disconnect(psmouse);
|
||||
|
||||
if (parent && parent->pt_deactivate)
|
||||
parent->pt_deactivate(parent);
|
||||
|
||||
psmouse_set_state(psmouse, PSMOUSE_IGNORE);
|
||||
|
||||
input_unregister_device(&psmouse->dev);
|
||||
serio_close(serio);
|
||||
serio_set_drvdata(serio, NULL);
|
||||
kfree(psmouse);
|
||||
|
||||
if (parent)
|
||||
psmouse_activate(parent);
|
||||
|
||||
up(&psmouse_sem);
|
||||
}
|
||||
|
||||
static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_protocol *proto)
|
||||
{
|
||||
memset(&psmouse->dev, 0, sizeof(struct input_dev));
|
||||
|
||||
init_input_dev(&psmouse->dev);
|
||||
|
||||
psmouse->dev.private = psmouse;
|
||||
psmouse->dev.dev = &psmouse->ps2dev.serio->dev;
|
||||
|
||||
psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
|
||||
psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
|
||||
psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
|
||||
|
||||
psmouse->set_rate = psmouse_set_rate;
|
||||
psmouse->set_resolution = psmouse_set_resolution;
|
||||
psmouse->protocol_handler = psmouse_process_byte;
|
||||
psmouse->pktsize = 3;
|
||||
|
||||
if (proto && (proto->detect || proto->init)) {
|
||||
if (proto->detect && proto->detect(psmouse, 1) < 0)
|
||||
return -1;
|
||||
|
||||
if (proto->init && proto->init(psmouse) < 0)
|
||||
return -1;
|
||||
|
||||
psmouse->type = proto->type;
|
||||
}
|
||||
else
|
||||
psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1);
|
||||
|
||||
sprintf(psmouse->devname, "%s %s %s",
|
||||
psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name);
|
||||
|
||||
psmouse->dev.name = psmouse->devname;
|
||||
psmouse->dev.phys = psmouse->phys;
|
||||
psmouse->dev.id.bustype = BUS_I8042;
|
||||
psmouse->dev.id.vendor = 0x0002;
|
||||
psmouse->dev.id.product = psmouse->type;
|
||||
psmouse->dev.id.version = psmouse->model;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -688,6 +870,8 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
|
||||
struct psmouse *psmouse, *parent = NULL;
|
||||
int retval;
|
||||
|
||||
down(&psmouse_sem);
|
||||
|
||||
/*
|
||||
* If this is a pass-through port deactivate parent so the device
|
||||
* connected to this port can be successfully identified
|
||||
@ -697,20 +881,14 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
|
||||
psmouse_deactivate(parent);
|
||||
}
|
||||
|
||||
if (!(psmouse = kmalloc(sizeof(struct psmouse), GFP_KERNEL))) {
|
||||
if (!(psmouse = kcalloc(1, sizeof(struct psmouse), GFP_KERNEL))) {
|
||||
retval = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memset(psmouse, 0, sizeof(struct psmouse));
|
||||
|
||||
ps2_init(&psmouse->ps2dev, serio);
|
||||
sprintf(psmouse->phys, "%s/input0", serio->phys);
|
||||
psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
|
||||
psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
|
||||
psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
|
||||
psmouse->dev.private = psmouse;
|
||||
psmouse->dev.dev = &serio->dev;
|
||||
|
||||
psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
|
||||
|
||||
serio_set_drvdata(serio, psmouse);
|
||||
@ -734,25 +912,10 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
|
||||
psmouse->resolution = psmouse_resolution;
|
||||
psmouse->resetafter = psmouse_resetafter;
|
||||
psmouse->smartscroll = psmouse_smartscroll;
|
||||
psmouse->set_rate = psmouse_set_rate;
|
||||
psmouse->set_resolution = psmouse_set_resolution;
|
||||
psmouse->protocol_handler = psmouse_process_byte;
|
||||
psmouse->pktsize = 3;
|
||||
|
||||
psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1);
|
||||
|
||||
sprintf(psmouse->devname, "%s %s %s",
|
||||
psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name);
|
||||
|
||||
psmouse->dev.name = psmouse->devname;
|
||||
psmouse->dev.phys = psmouse->phys;
|
||||
psmouse->dev.id.bustype = BUS_I8042;
|
||||
psmouse->dev.id.vendor = 0x0002;
|
||||
psmouse->dev.id.product = psmouse->type;
|
||||
psmouse->dev.id.version = psmouse->model;
|
||||
psmouse_switch_protocol(psmouse, NULL);
|
||||
|
||||
input_register_device(&psmouse->dev);
|
||||
|
||||
printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys);
|
||||
|
||||
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
|
||||
@ -762,6 +925,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
|
||||
if (parent && parent->pt_activate)
|
||||
parent->pt_activate(parent);
|
||||
|
||||
device_create_file(&serio->dev, &psmouse_attr_protocol);
|
||||
device_create_file(&serio->dev, &psmouse_attr_rate);
|
||||
device_create_file(&serio->dev, &psmouse_attr_resolution);
|
||||
device_create_file(&serio->dev, &psmouse_attr_resetafter);
|
||||
@ -771,10 +935,11 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
|
||||
retval = 0;
|
||||
|
||||
out:
|
||||
/* If this is a pass-through port the parent awaits to be activated */
|
||||
/* If this is a pass-through port the parent needs to be re-activated */
|
||||
if (parent)
|
||||
psmouse_activate(parent);
|
||||
|
||||
up(&psmouse_sem);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -791,6 +956,8 @@ static int psmouse_reconnect(struct serio *serio)
|
||||
return -1;
|
||||
}
|
||||
|
||||
down(&psmouse_sem);
|
||||
|
||||
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
|
||||
parent = serio_get_drvdata(serio->parent);
|
||||
psmouse_deactivate(parent);
|
||||
@ -823,6 +990,7 @@ out:
|
||||
if (parent)
|
||||
psmouse_activate(parent);
|
||||
|
||||
up(&psmouse_sem);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -893,26 +1061,109 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun
|
||||
|
||||
if (serio->drv != &psmouse_drv) {
|
||||
retval = -ENODEV;
|
||||
goto out;
|
||||
goto out_unpin;
|
||||
}
|
||||
|
||||
retval = down_interruptible(&psmouse_sem);
|
||||
if (retval)
|
||||
goto out_unpin;
|
||||
|
||||
if (psmouse->state == PSMOUSE_IGNORE) {
|
||||
retval = -ENODEV;
|
||||
goto out_up;
|
||||
}
|
||||
|
||||
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
|
||||
parent = serio_get_drvdata(serio->parent);
|
||||
psmouse_deactivate(parent);
|
||||
}
|
||||
|
||||
psmouse_deactivate(psmouse);
|
||||
|
||||
retval = handler(psmouse, buf, count);
|
||||
|
||||
if (retval != -ENODEV)
|
||||
psmouse_activate(psmouse);
|
||||
|
||||
if (parent)
|
||||
psmouse_activate(parent);
|
||||
|
||||
out:
|
||||
out_up:
|
||||
up(&psmouse_sem);
|
||||
out_unpin:
|
||||
serio_unpin_driver(serio);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%s\n", psmouse_protocol_by_type(psmouse->type)->name);
|
||||
}
|
||||
|
||||
static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *buf, size_t count)
|
||||
{
|
||||
struct serio *serio = psmouse->ps2dev.serio;
|
||||
struct psmouse *parent = NULL;
|
||||
struct psmouse_protocol *proto;
|
||||
int retry = 0;
|
||||
|
||||
if (!(proto = psmouse_protocol_by_name(buf, count)))
|
||||
return -EINVAL;
|
||||
|
||||
if (psmouse->type == proto->type)
|
||||
return count;
|
||||
|
||||
while (serio->child) {
|
||||
if (++retry > 3) {
|
||||
printk(KERN_WARNING "psmouse: failed to destroy child port, protocol change aborted.\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
up(&psmouse_sem);
|
||||
serio_unpin_driver(serio);
|
||||
serio_unregister_child_port(serio);
|
||||
serio_pin_driver_uninterruptible(serio);
|
||||
down(&psmouse_sem);
|
||||
|
||||
if (serio->drv != &psmouse_drv)
|
||||
return -ENODEV;
|
||||
|
||||
if (psmouse->type == proto->type)
|
||||
return count; /* switched by other thread */
|
||||
}
|
||||
|
||||
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
|
||||
parent = serio_get_drvdata(serio->parent);
|
||||
if (parent->pt_deactivate)
|
||||
parent->pt_deactivate(parent);
|
||||
}
|
||||
|
||||
if (psmouse->disconnect)
|
||||
psmouse->disconnect(psmouse);
|
||||
|
||||
psmouse_set_state(psmouse, PSMOUSE_IGNORE);
|
||||
input_unregister_device(&psmouse->dev);
|
||||
|
||||
psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
|
||||
|
||||
if (psmouse_switch_protocol(psmouse, proto) < 0) {
|
||||
psmouse_reset(psmouse);
|
||||
/* default to PSMOUSE_PS2 */
|
||||
psmouse_switch_protocol(psmouse, &psmouse_protocols[0]);
|
||||
}
|
||||
|
||||
psmouse_initialize(psmouse);
|
||||
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
|
||||
|
||||
input_register_device(&psmouse->dev);
|
||||
printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys);
|
||||
|
||||
if (parent && parent->pt_activate)
|
||||
parent->pt_activate(parent);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t psmouse_attr_show_rate(struct psmouse *psmouse, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", psmouse->rate);
|
||||
@ -969,34 +1220,26 @@ static ssize_t psmouse_attr_set_resetafter(struct psmouse *psmouse, const char *
|
||||
|
||||
static int psmouse_set_maxproto(const char *val, struct kernel_param *kp)
|
||||
{
|
||||
int i;
|
||||
struct psmouse_protocol *proto;
|
||||
|
||||
if (!val)
|
||||
return -EINVAL;
|
||||
|
||||
if (!strncmp(val, "any", 3)) {
|
||||
*((unsigned int *)kp->arg) = -1U;
|
||||
return 0;
|
||||
}
|
||||
proto = psmouse_protocol_by_name(val, strlen(val));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(psmouse_proto_abbrev); i++) {
|
||||
if (!psmouse_proto_abbrev[i])
|
||||
continue;
|
||||
if (!proto || !proto->maxproto)
|
||||
return -EINVAL;
|
||||
|
||||
if (!strncmp(val, psmouse_proto_abbrev[i], strlen(psmouse_proto_abbrev[i]))) {
|
||||
*((unsigned int *)kp->arg) = i;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*((unsigned int *)kp->arg) = proto->type;
|
||||
|
||||
return -EINVAL; \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp)
|
||||
{
|
||||
return sprintf(buffer, "%s\n",
|
||||
psmouse_max_proto < ARRAY_SIZE(psmouse_proto_abbrev) ?
|
||||
psmouse_proto_abbrev[psmouse_max_proto] : "any");
|
||||
int type = *((unsigned int *)kp->arg);
|
||||
|
||||
return sprintf(buffer, "%s\n", psmouse_protocol_by_type(type)->name);
|
||||
}
|
||||
|
||||
static int __init psmouse_init(void)
|
||||
|
@ -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
|
||||
|
285
drivers/usb/input/acecad.c
Normal file
285
drivers/usb/input/acecad.c
Normal file
@ -0,0 +1,285 @@
|
||||
/*
|
||||
* 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);
|
||||
|
268
drivers/usb/input/itmtouch.c
Normal file
268
drivers/usb/input/itmtouch.c
Normal file
@ -0,0 +1,268 @@
|
||||
/******************************************************************************
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
* Copyright (c) 2000 Daniel Egger <egger@suse.de>
|
||||
* Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com>
|
||||
* Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be>
|
||||
* Copyright (c) 2002-2004 Ping Cheng <pingc@wacom.com>
|
||||
* Copyright (c) 2002-2005 Ping Cheng <pingc@wacom.com>
|
||||
*
|
||||
* ChangeLog:
|
||||
* v0.1 (vp) - Initial release
|
||||
@ -51,6 +51,9 @@
|
||||
* - Cleanups here and there
|
||||
* v1.30.1 (pi) - Added Graphire3 support
|
||||
* v1.40 (pc) - Add support for several new devices, fix eraser reporting, ...
|
||||
* v1.43 (pc) - Added support for Cintiq 21UX
|
||||
- Fixed a Graphire bug
|
||||
- Merged wacom_intuos3_irq into wacom_intuos_irq
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -72,7 +75,7 @@
|
||||
/*
|
||||
* Version Information
|
||||
*/
|
||||
#define DRIVER_VERSION "v1.40"
|
||||
#define DRIVER_VERSION "v1.43"
|
||||
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
|
||||
#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
|
||||
#define DRIVER_LICENSE "GPL"
|
||||
@ -83,6 +86,16 @@ MODULE_LICENSE(DRIVER_LICENSE);
|
||||
|
||||
#define USB_VENDOR_ID_WACOM 0x056a
|
||||
|
||||
enum {
|
||||
PENPARTNER = 0,
|
||||
GRAPHIRE,
|
||||
PL,
|
||||
INTUOS,
|
||||
INTUOS3,
|
||||
CINTIQ,
|
||||
MAX_TYPE
|
||||
};
|
||||
|
||||
struct wacom_features {
|
||||
char *name;
|
||||
int pktlen;
|
||||
@ -102,7 +115,6 @@ struct wacom {
|
||||
struct urb *irq;
|
||||
struct wacom_features *features;
|
||||
int tool[2];
|
||||
int open;
|
||||
__u32 serial[2];
|
||||
char phys[32];
|
||||
};
|
||||
@ -166,8 +178,7 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs)
|
||||
if (!wacom->tool[0]) {
|
||||
/* Going into proximity select tool */
|
||||
wacom->tool[1] = (data[4] & 0x20)? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* was entered with stylus2 pressed */
|
||||
if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20) ) {
|
||||
/* report out proximity for previous tool */
|
||||
@ -182,16 +193,15 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs)
|
||||
wacom->tool[1] = BTN_TOOL_PEN;
|
||||
}
|
||||
input_report_key(dev, wacom->tool[1], prox); /* report in proximity for tool */
|
||||
input_report_abs(dev, ABS_X, data[3] | ((__u32)data[2] << 7) | ((__u32)(data[1] & 0x03) << 14));
|
||||
input_report_abs(dev, ABS_Y, data[6] | ((__u32)data[5] << 7) | ((__u32)(data[4] & 0x03) << 14));
|
||||
input_report_abs(dev, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
|
||||
input_report_abs(dev, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
|
||||
input_report_abs(dev, ABS_PRESSURE, pressure);
|
||||
|
||||
input_report_key(dev, BTN_TOUCH, data[4] & 0x08);
|
||||
input_report_key(dev, BTN_STYLUS, data[4] & 0x10);
|
||||
/* Only allow the stylus2 button to be reported for the pen tool. */
|
||||
input_report_key(dev, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* report proximity-out of a (valid) tool */
|
||||
if (wacom->tool[1] != BTN_TOOL_RUBBER) {
|
||||
/* Unknown tool selected default to pen tool */
|
||||
@ -203,7 +213,7 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs)
|
||||
wacom->tool[0] = prox; /* Save proximity state */
|
||||
input_sync(dev);
|
||||
|
||||
exit:
|
||||
exit:
|
||||
retval = usb_submit_urb (urb, GFP_ATOMIC);
|
||||
if (retval)
|
||||
err ("%s - usb_submit_urb failed with result %d",
|
||||
@ -232,20 +242,16 @@ static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (data[0] != 2)
|
||||
{
|
||||
if (data[0] != 2) {
|
||||
printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
input_regs(dev, regs);
|
||||
if (data[1] & 0x04)
|
||||
{
|
||||
if (data[1] & 0x04) {
|
||||
input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x20);
|
||||
input_report_key(dev, BTN_TOUCH, data[1] & 0x08);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x20);
|
||||
input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
|
||||
}
|
||||
@ -257,7 +263,7 @@ static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs)
|
||||
|
||||
input_sync(dev);
|
||||
|
||||
exit:
|
||||
exit:
|
||||
retval = usb_submit_urb (urb, GFP_ATOMIC);
|
||||
if (retval)
|
||||
err ("%s - usb_submit_urb failed with result %d",
|
||||
@ -300,7 +306,7 @@ static void wacom_penpartner_irq(struct urb *urb, struct pt_regs *regs)
|
||||
input_report_key(dev, BTN_STYLUS, (data[5] & 0x40));
|
||||
input_sync(dev);
|
||||
|
||||
exit:
|
||||
exit:
|
||||
retval = usb_submit_urb (urb, GFP_ATOMIC);
|
||||
if (retval)
|
||||
err ("%s - usb_submit_urb failed with result %d",
|
||||
@ -340,14 +346,16 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
|
||||
|
||||
input_regs(dev, regs);
|
||||
|
||||
if (data[1] & 0x10) { /* in prox */
|
||||
|
||||
switch ((data[1] >> 5) & 3) {
|
||||
|
||||
case 0: /* Pen */
|
||||
input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x80);
|
||||
wacom->tool[0] = BTN_TOOL_PEN;
|
||||
break;
|
||||
|
||||
case 1: /* Rubber */
|
||||
input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x80);
|
||||
wacom->tool[0] = BTN_TOOL_RUBBER;
|
||||
break;
|
||||
|
||||
case 2: /* Mouse with wheel */
|
||||
@ -356,31 +364,29 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
|
||||
/* fall through */
|
||||
|
||||
case 3: /* Mouse without wheel */
|
||||
input_report_key(dev, BTN_TOOL_MOUSE, data[7] > 24);
|
||||
wacom->tool[0] = BTN_TOOL_MOUSE;
|
||||
input_report_key(dev, BTN_LEFT, data[1] & 0x01);
|
||||
input_report_key(dev, BTN_RIGHT, data[1] & 0x02);
|
||||
input_report_abs(dev, ABS_DISTANCE, data[7]);
|
||||
|
||||
input_report_abs(dev, ABS_X, x);
|
||||
input_report_abs(dev, ABS_Y, y);
|
||||
|
||||
input_sync(dev);
|
||||
goto exit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (data[1] & 0x80) {
|
||||
input_report_abs(dev, ABS_X, x);
|
||||
input_report_abs(dev, ABS_Y, y);
|
||||
}
|
||||
|
||||
if (wacom->tool[0] != BTN_TOOL_MOUSE) {
|
||||
input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6]));
|
||||
input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
|
||||
input_report_key(dev, BTN_STYLUS, data[1] & 0x02);
|
||||
input_report_key(dev, BTN_STYLUS2, data[1] & 0x04);
|
||||
}
|
||||
|
||||
input_report_key(dev, wacom->tool[0], data[1] & 0x10);
|
||||
input_sync(dev);
|
||||
|
||||
exit:
|
||||
exit:
|
||||
retval = usb_submit_urb (urb, GFP_ATOMIC);
|
||||
if (retval)
|
||||
err ("%s - usb_submit_urb failed with result %d",
|
||||
@ -398,14 +404,13 @@ static int wacom_intuos_inout(struct urb *urb)
|
||||
idx = data[1] & 0x01;
|
||||
|
||||
/* Enter report */
|
||||
if ((data[1] & 0xfc) == 0xc0)
|
||||
{
|
||||
if ((data[1] & 0xfc) == 0xc0) {
|
||||
/* serial number of the tool */
|
||||
wacom->serial[idx] = ((__u32)(data[3] & 0x0f) << 28) +
|
||||
((__u32)data[4] << 20) + ((__u32)data[5] << 12) +
|
||||
((__u32)data[6] << 4) + (data[7] >> 4);
|
||||
wacom->serial[idx] = ((data[3] & 0x0f) << 28) +
|
||||
(data[4] << 20) + (data[5] << 12) +
|
||||
(data[6] << 4) + (data[7] >> 4);
|
||||
|
||||
switch (((__u32)data[2] << 4) | (data[3] >> 4)) {
|
||||
switch ((data[2] << 4) | (data[3] >> 4)) {
|
||||
case 0x812: /* Inking pen */
|
||||
case 0x801: /* Intuos3 Inking pen */
|
||||
case 0x012:
|
||||
@ -449,7 +454,7 @@ static int wacom_intuos_inout(struct urb *urb)
|
||||
case 0x112:
|
||||
case 0x913: /* Intuos3 Airbrush */
|
||||
wacom->tool[idx] = BTN_TOOL_AIRBRUSH;
|
||||
break; /* Airbrush */
|
||||
break;
|
||||
default: /* Unknown tool */
|
||||
wacom->tool[idx] = BTN_TOOL_PEN;
|
||||
}
|
||||
@ -478,9 +483,8 @@ static void wacom_intuos_general(struct urb *urb)
|
||||
unsigned int t;
|
||||
|
||||
/* general pen packet */
|
||||
if ((data[1] & 0xb8) == 0xa0)
|
||||
{
|
||||
t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3);
|
||||
if ((data[1] & 0xb8) == 0xa0) {
|
||||
t = (data[6] << 2) | ((data[7] >> 6) & 3);
|
||||
input_report_abs(dev, ABS_PRESSURE, t);
|
||||
input_report_abs(dev, ABS_TILT_X,
|
||||
((data[7] << 1) & 0x7e) | (data[8] >> 7));
|
||||
@ -491,10 +495,9 @@ static void wacom_intuos_general(struct urb *urb)
|
||||
}
|
||||
|
||||
/* airbrush second packet */
|
||||
if ((data[1] & 0xbc) == 0xb4)
|
||||
{
|
||||
if ((data[1] & 0xbc) == 0xb4) {
|
||||
input_report_abs(dev, ABS_WHEEL,
|
||||
((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
|
||||
(data[6] << 2) | ((data[7] >> 6) & 3));
|
||||
input_report_abs(dev, ABS_TILT_X,
|
||||
((data[7] << 1) & 0x7e) | (data[8] >> 7));
|
||||
input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
|
||||
@ -526,7 +529,7 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (data[0] != 2 && data[0] != 5 && data[0] != 6) {
|
||||
if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) {
|
||||
dbg("wacom_intuos_irq: received unknown report #%d", data[0]);
|
||||
goto exit;
|
||||
}
|
||||
@ -536,107 +539,10 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
|
||||
/* tool number */
|
||||
idx = data[1] & 0x01;
|
||||
|
||||
/* process in/out prox events */
|
||||
if (wacom_intuos_inout(urb)) goto exit;
|
||||
|
||||
input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2]));
|
||||
input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4]));
|
||||
input_report_abs(dev, ABS_DISTANCE, data[9]);
|
||||
|
||||
/* process general packets */
|
||||
wacom_intuos_general(urb);
|
||||
|
||||
if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) { /* 4D mouse or Lens cursor packets */
|
||||
|
||||
if (data[1] & 0x02) { /* Rotation packet */
|
||||
|
||||
t = ((__u32)data[6] << 3) | ((data[7] >> 5) & 7);
|
||||
input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ? ((t - 1) / 2) : -t / 2);
|
||||
|
||||
} else {
|
||||
|
||||
if ((data[1] & 0x10) == 0) { /* 4D mouse packets */
|
||||
|
||||
input_report_key(dev, BTN_LEFT, data[8] & 0x01);
|
||||
input_report_key(dev, BTN_MIDDLE, data[8] & 0x02);
|
||||
input_report_key(dev, BTN_RIGHT, data[8] & 0x04);
|
||||
|
||||
input_report_key(dev, BTN_SIDE, data[8] & 0x20);
|
||||
input_report_key(dev, BTN_EXTRA, data[8] & 0x10);
|
||||
t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3);
|
||||
input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
|
||||
|
||||
} else {
|
||||
if (wacom->tool[idx] == BTN_TOOL_MOUSE) { /* 2D mouse packets */
|
||||
input_report_key(dev, BTN_LEFT, data[8] & 0x04);
|
||||
input_report_key(dev, BTN_MIDDLE, data[8] & 0x08);
|
||||
input_report_key(dev, BTN_RIGHT, data[8] & 0x10);
|
||||
input_report_rel(dev, REL_WHEEL,
|
||||
(-(__u32)(data[8] & 0x01) + (__u32)((data[8] & 0x02) >> 1)));
|
||||
}
|
||||
else { /* Lens cursor packets */
|
||||
input_report_key(dev, BTN_LEFT, data[8] & 0x01);
|
||||
input_report_key(dev, BTN_MIDDLE, data[8] & 0x02);
|
||||
input_report_key(dev, BTN_RIGHT, data[8] & 0x04);
|
||||
input_report_key(dev, BTN_SIDE, data[8] & 0x10);
|
||||
input_report_key(dev, BTN_EXTRA, data[8] & 0x08);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input_report_key(dev, wacom->tool[idx], 1);
|
||||
input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
|
||||
input_sync(dev);
|
||||
|
||||
exit:
|
||||
retval = usb_submit_urb (urb, GFP_ATOMIC);
|
||||
if (retval)
|
||||
err ("%s - usb_submit_urb failed with result %d",
|
||||
__FUNCTION__, retval);
|
||||
}
|
||||
|
||||
static void wacom_intuos3_irq(struct urb *urb, struct pt_regs *regs)
|
||||
{
|
||||
struct wacom *wacom = urb->context;
|
||||
unsigned char *data = wacom->data;
|
||||
struct input_dev *dev = &wacom->dev;
|
||||
unsigned int t;
|
||||
int idx, retval;
|
||||
|
||||
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 exit;
|
||||
}
|
||||
|
||||
/* check for valid report */
|
||||
if (data[0] != 2 && data[0] != 5 && data[0] != 12)
|
||||
{
|
||||
printk(KERN_INFO "wacom_intuos3_irq: received unknown report #%d\n", data[0]);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
input_regs(dev, regs);
|
||||
|
||||
/* tool index is always 0 here since there is no dual input tool */
|
||||
idx = data[1] & 0x01;
|
||||
|
||||
/* pad packets. Works as a second tool and is always in prox */
|
||||
if (data[0] == 12)
|
||||
{
|
||||
if (data[0] == 12) {
|
||||
/* initiate the pad as a device */
|
||||
if (wacom->tool[1] != BTN_TOOL_FINGER)
|
||||
{
|
||||
if (wacom->tool[1] != BTN_TOOL_FINGER) {
|
||||
wacom->tool[1] = BTN_TOOL_FINGER;
|
||||
input_report_key(dev, wacom->tool[1], 1);
|
||||
}
|
||||
@ -656,37 +562,78 @@ static void wacom_intuos3_irq(struct urb *urb, struct pt_regs *regs)
|
||||
}
|
||||
|
||||
/* process in/out prox events */
|
||||
if (wacom_intuos_inout(urb)) goto exit;
|
||||
if (wacom_intuos_inout(urb))
|
||||
goto exit;
|
||||
|
||||
input_report_abs(dev, ABS_X, ((__u32)data[2] << 9) | ((__u32)data[3] << 1) | ((data[9] >> 1) & 1));
|
||||
input_report_abs(dev, ABS_Y, ((__u32)data[4] << 9) | ((__u32)data[5] << 1) | (data[9] & 1));
|
||||
/* Cintiq doesn't send data when RDY bit isn't set */
|
||||
if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40))
|
||||
return;
|
||||
|
||||
if (wacom->features->type >= INTUOS3) {
|
||||
input_report_abs(dev, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
|
||||
input_report_abs(dev, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1));
|
||||
input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 2) & 0x3f));
|
||||
} else {
|
||||
input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2]));
|
||||
input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4]));
|
||||
input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 3) & 0x1f));
|
||||
}
|
||||
|
||||
/* process general packets */
|
||||
wacom_intuos_general(urb);
|
||||
|
||||
if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0)
|
||||
{
|
||||
/* Marker pen rotation packet. Reported as wheel due to valuator limitation */
|
||||
if (data[1] & 0x02)
|
||||
{
|
||||
t = ((__u32)data[6] << 3) | ((data[7] >> 5) & 7);
|
||||
/* 4D mouse, 2D mouse, marker pen rotation, or Lens cursor packets */
|
||||
if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) {
|
||||
|
||||
if (data[1] & 0x02) {
|
||||
/* Rotation packet */
|
||||
if (wacom->features->type >= INTUOS3) {
|
||||
/* I3 marker pen rotation reported as wheel
|
||||
* due to valuator limitation
|
||||
*/
|
||||
t = (data[6] << 3) | ((data[7] >> 5) & 7);
|
||||
t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) :
|
||||
((t-1) / 2 + 450)) : (450 - t / 2) ;
|
||||
input_report_abs(dev, ABS_WHEEL, t);
|
||||
} else {
|
||||
/* 4D mouse rotation packet */
|
||||
t = (data[6] << 3) | ((data[7] >> 5) & 7);
|
||||
input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ?
|
||||
((t - 1) / 2) : -t / 2);
|
||||
}
|
||||
|
||||
/* 2D mouse packets */
|
||||
if (wacom->tool[idx] == BTN_TOOL_MOUSE)
|
||||
{
|
||||
} else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3) {
|
||||
/* 4D mouse packet */
|
||||
input_report_key(dev, BTN_LEFT, data[8] & 0x01);
|
||||
input_report_key(dev, BTN_MIDDLE, data[8] & 0x02);
|
||||
input_report_key(dev, BTN_RIGHT, data[8] & 0x04);
|
||||
|
||||
input_report_key(dev, BTN_SIDE, data[8] & 0x20);
|
||||
input_report_key(dev, BTN_EXTRA, data[8] & 0x10);
|
||||
t = (data[6] << 2) | ((data[7] >> 6) & 3);
|
||||
input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
|
||||
|
||||
} else if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
|
||||
/* 2D mouse packet */
|
||||
input_report_key(dev, BTN_LEFT, data[8] & 0x04);
|
||||
input_report_key(dev, BTN_MIDDLE, data[8] & 0x08);
|
||||
input_report_key(dev, BTN_RIGHT, data[8] & 0x10);
|
||||
input_report_rel(dev, REL_WHEEL, ((data[8] & 0x02) >> 1)
|
||||
- (data[8] & 0x01));
|
||||
|
||||
/* I3 2D mouse side buttons */
|
||||
if (wacom->features->type == INTUOS3) {
|
||||
input_report_key(dev, BTN_SIDE, data[8] & 0x40);
|
||||
input_report_key(dev, BTN_EXTRA, data[8] & 0x20);
|
||||
/* mouse wheel is positive when rolled backwards */
|
||||
input_report_rel(dev, REL_WHEEL, ((__u32)((data[8] & 0x02) >> 1)
|
||||
- (__u32)(data[8] & 0x01)));
|
||||
}
|
||||
|
||||
} else if (wacom->features->type < INTUOS3) {
|
||||
/* Lens cursor packets */
|
||||
input_report_key(dev, BTN_LEFT, data[8] & 0x01);
|
||||
input_report_key(dev, BTN_MIDDLE, data[8] & 0x02);
|
||||
input_report_key(dev, BTN_RIGHT, data[8] & 0x04);
|
||||
input_report_key(dev, BTN_SIDE, data[8] & 0x10);
|
||||
input_report_key(dev, BTN_EXTRA, data[8] & 0x08);
|
||||
}
|
||||
}
|
||||
|
||||
@ -702,34 +649,35 @@ exit:
|
||||
}
|
||||
|
||||
static struct wacom_features wacom_features[] = {
|
||||
{ "Wacom Penpartner", 7, 5040, 3780, 255, 32, 0, wacom_penpartner_irq },
|
||||
{ "Wacom Graphire", 8, 10206, 7422, 511, 32, 1, wacom_graphire_irq },
|
||||
{ "Wacom Graphire2 4x5", 8, 10206, 7422, 511, 32, 1, wacom_graphire_irq },
|
||||
{ "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, 1, wacom_graphire_irq },
|
||||
{ "Wacom Graphire3", 8, 10208, 7424, 511, 32, 1, wacom_graphire_irq },
|
||||
{ "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, 1, wacom_graphire_irq },
|
||||
{ "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 15, 2, wacom_intuos_irq },
|
||||
{ "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq },
|
||||
{ "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 15, 2, wacom_intuos_irq },
|
||||
{ "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 15, 2, wacom_intuos_irq },
|
||||
{ "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 15, 2, wacom_intuos_irq },
|
||||
{ "Wacom PL400", 8, 5408, 4056, 255, 32, 3, wacom_pl_irq },
|
||||
{ "Wacom PL500", 8, 6144, 4608, 255, 32, 3, wacom_pl_irq },
|
||||
{ "Wacom PL600", 8, 6126, 4604, 255, 32, 3, wacom_pl_irq },
|
||||
{ "Wacom PL600SX", 8, 6260, 5016, 255, 32, 3, wacom_pl_irq },
|
||||
{ "Wacom PL550", 8, 6144, 4608, 511, 32, 3, wacom_pl_irq },
|
||||
{ "Wacom PL800", 8, 7220, 5780, 511, 32, 3, wacom_pl_irq },
|
||||
{ "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 15, 2, wacom_intuos_irq },
|
||||
{ "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq },
|
||||
{ "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 15, 2, wacom_intuos_irq },
|
||||
{ "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, 2, wacom_intuos_irq },
|
||||
{ "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, 2, wacom_intuos_irq },
|
||||
{ "Wacom Volito", 8, 5104, 3712, 511, 32, 1, wacom_graphire_irq },
|
||||
{ "Wacom Cintiq Partner",8, 20480, 15360, 511, 32, 3, wacom_ptu_irq },
|
||||
{ "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 15, 4, wacom_intuos3_irq },
|
||||
{ "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 15, 4, wacom_intuos3_irq },
|
||||
{ "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 15, 4, wacom_intuos3_irq },
|
||||
{ "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq },
|
||||
{ "Wacom Penpartner", 7, 5040, 3780, 255, 32, PENPARTNER, wacom_penpartner_irq },
|
||||
{ "Wacom Graphire", 8, 10206, 7422, 511, 32, GRAPHIRE, wacom_graphire_irq },
|
||||
{ "Wacom Graphire2 4x5", 8, 10206, 7422, 511, 32, GRAPHIRE, wacom_graphire_irq },
|
||||
{ "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq },
|
||||
{ "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq },
|
||||
{ "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq },
|
||||
{ "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 15, INTUOS, wacom_intuos_irq },
|
||||
{ "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq },
|
||||
{ "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 15, INTUOS, wacom_intuos_irq },
|
||||
{ "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 15, INTUOS, wacom_intuos_irq },
|
||||
{ "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 15, INTUOS, wacom_intuos_irq },
|
||||
{ "Wacom PL400", 8, 5408, 4056, 255, 32, PL, wacom_pl_irq },
|
||||
{ "Wacom PL500", 8, 6144, 4608, 255, 32, PL, wacom_pl_irq },
|
||||
{ "Wacom PL600", 8, 6126, 4604, 255, 32, PL, wacom_pl_irq },
|
||||
{ "Wacom PL600SX", 8, 6260, 5016, 255, 32, PL, wacom_pl_irq },
|
||||
{ "Wacom PL550", 8, 6144, 4608, 511, 32, PL, wacom_pl_irq },
|
||||
{ "Wacom PL800", 8, 7220, 5780, 511, 32, PL, wacom_pl_irq },
|
||||
{ "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 15, INTUOS, wacom_intuos_irq },
|
||||
{ "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq },
|
||||
{ "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 15, INTUOS, wacom_intuos_irq },
|
||||
{ "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, INTUOS, wacom_intuos_irq },
|
||||
{ "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, INTUOS, wacom_intuos_irq },
|
||||
{ "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq },
|
||||
{ "Wacom Cintiq Partner",8, 20480, 15360, 511, 32, PL, wacom_ptu_irq },
|
||||
{ "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 15, INTUOS3, wacom_intuos_irq },
|
||||
{ "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 15, INTUOS3, wacom_intuos_irq },
|
||||
{ "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 15, INTUOS3, wacom_intuos_irq },
|
||||
{ "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 15, CINTIQ, wacom_intuos_irq },
|
||||
{ "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq },
|
||||
{ }
|
||||
};
|
||||
|
||||
@ -761,6 +709,7 @@ static struct usb_device_id wacom_ids[] = {
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
|
||||
{ }
|
||||
};
|
||||
@ -771,14 +720,9 @@ static int wacom_open(struct input_dev *dev)
|
||||
{
|
||||
struct wacom *wacom = dev->private;
|
||||
|
||||
if (wacom->open++)
|
||||
return 0;
|
||||
|
||||
wacom->irq->dev = wacom->usbdev;
|
||||
if (usb_submit_urb(wacom->irq, GFP_KERNEL)) {
|
||||
wacom->open--;
|
||||
if (usb_submit_urb(wacom->irq, GFP_KERNEL))
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -787,7 +731,6 @@ static void wacom_close(struct input_dev *dev)
|
||||
{
|
||||
struct wacom *wacom = dev->private;
|
||||
|
||||
if (!--wacom->open)
|
||||
usb_kill_urb(wacom->irq);
|
||||
}
|
||||
|
||||
@ -823,7 +766,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||
wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS);
|
||||
|
||||
switch (wacom->features->type) {
|
||||
case 1:
|
||||
case GRAPHIRE:
|
||||
wacom->dev.evbit[0] |= BIT(EV_REL);
|
||||
wacom->dev.relbit[0] |= BIT(REL_WHEEL);
|
||||
wacom->dev.absbit[0] |= BIT(ABS_DISTANCE);
|
||||
@ -831,13 +774,14 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||
wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2);
|
||||
break;
|
||||
|
||||
case 4: /* new functions for Intuos3 */
|
||||
case INTUOS3:
|
||||
case CINTIQ:
|
||||
wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
|
||||
wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
|
||||
wacom->dev.absbit[0] |= BIT(ABS_RX) | BIT(ABS_RY);
|
||||
/* fall through */
|
||||
|
||||
case 2:
|
||||
case INTUOS:
|
||||
wacom->dev.evbit[0] |= BIT(EV_MSC) | BIT(EV_REL);
|
||||
wacom->dev.mscbit[0] |= BIT(MSC_SERIAL);
|
||||
wacom->dev.relbit[0] |= BIT(REL_WHEEL);
|
||||
@ -847,7 +791,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||
wacom->dev.absbit[0] |= BIT(ABS_DISTANCE) | BIT(ABS_WHEEL) | BIT(ABS_TILT_X) | BIT(ABS_TILT_Y) | BIT(ABS_RZ) | BIT(ABS_THROTTLE);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
case PL:
|
||||
wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER);
|
||||
break;
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user