Commit 508cf6ef authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/vojtech/input

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 9936b07d 44a56c6d
......@@ -146,7 +146,7 @@ static int __init button_init(void)
Note the button_used variable - we have to track how many times the open
function was called to know when exactly our device stops being used.
The open() callback should return a 0 in case of succes or any nonzero value
The open() callback should return a 0 in case of success or any nonzero value
in case of failure. The close() callback (which is void) must always succeed.
1.3 Basic event types
......@@ -178,7 +178,7 @@ set the corresponding bits and call the
function. Events are generated only for nonzero value.
However EV_ABS requires a little special care. Before calling
input_register_devices, you have to fill additional fields in the input_dev
input_register_device, you have to fill additional fields in the input_dev
struct for each absolute axis your device has. If our button device had also
the ABS_X axis:
......@@ -207,11 +207,11 @@ one device. You'll need it in the open and close callbacks.
1.5 NBITS(), LONG(), BIT()
~~~~~~~~~~~~~~~~~~~~~~~~~~
These three macros frin input.h help some bitfield computations:
These three macros from input.h help some bitfield computations:
NBITS(x) - returns the length of a bitfield array in longs for x bits
LONG(x) - returns the index in the array in longs for bit x
BIT(x) - returns the indes in a long for bit x
BIT(x) - returns the index in a long for bit x
1.6 The number, id* and name fields
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
......@@ -221,7 +221,7 @@ is registered. It has no use except for identifying the device to the user
in system messages.
The dev->name should be set before registering the input device by the input
device driver. It's a string like 'Generic button device' containing an
device driver. It's a string like 'Generic button device' containing a
user friendly name of the device.
The id* fields contain the bus ID (PCI, USB, ...), vendor ID and device ID
......@@ -237,7 +237,7 @@ The id and name fields can be passed to userland via the evdev interface.
1.7 The keycode, keycodemax, keycodesize fields
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
These two fields will be used for any inpur devices that report their data
These two fields will be used for any input devices that report their data
as scancodes. If not all scancodes can be known by autodetection, they may
need to be set by userland utilities. The keycode array then is an array
used to map from scancodes to input system keycodes. The keycode max will
......@@ -258,7 +258,7 @@ handled by the input system.
The other event types up to now are:
EV_LED - used for the keyboad LEDs.
EV_LED - used for the keyboard LEDs.
EV_SND - used for keyboard beeps.
They are very similar to for example key events, but they go in the other
......@@ -270,7 +270,7 @@ driver can handle these events, it has to set the respective bits in evbit,
int button_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
{
if (type == EV_SND && code == EV_BELL) {
if (type == EV_SND && code == SND_BELL) {
outb(value, BUTTON_BELL);
return 0;
}
......
......@@ -52,11 +52,13 @@ extern void ctrl_alt_del(void);
/*
* Some laptops take the 789uiojklm,. keys as number pad when NumLock is on.
* This seems a good reason to start with NumLock off. On PC9800 however there
* is no NumLock key and everyone expects the keypad to be used for numbers.
* This seems a good reason to start with NumLock off. On PC9800 and HIL keyboards
* of PARISC machines however there is no NumLock key and everyone expects the keypad
* to be used for numbers.
*/
#ifdef CONFIG_X86_PC9800
#if defined(CONFIG_X86_PC9800) || \
defined(CONFIG_PARISC) && (defined(CONFIG_KEYBOARD_HIL) || defined(CONFIG_KEYBOARD_HIL_OLD))
#define KBD_DEFLEDS (1 << VC_NUMLOCK)
#else
#define KBD_DEFLEDS 0
......
......@@ -395,7 +395,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
if (!perm)
return -EPERM;
if (arg)
arg = 1193180 / arg;
arg = 1193182 / arg;
kd_mksound(arg, 0);
return 0;
......@@ -412,7 +412,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
count = ticks ? (arg & 0xffff) : 0;
if (count)
count = 1193180 / count;
count = 1193182 / count;
kd_mksound(count, ticks);
return 0;
}
......
......@@ -29,6 +29,7 @@ struct evdev {
char name[16];
struct input_handle handle;
wait_queue_head_t wait;
struct evdev_list *grab;
struct list_head list;
};
......@@ -48,6 +49,17 @@ static void evdev_event(struct input_handle *handle, unsigned int type, unsigned
struct evdev *evdev = handle->private;
struct evdev_list *list;
if (evdev->grab) {
list = evdev->grab;
do_gettimeofday(&list->buffer[list->head].time);
list->buffer[list->head].type = type;
list->buffer[list->head].code = code;
list->buffer[list->head].value = value;
list->head = (list->head + 1) & (EVDEV_BUFFER_SIZE - 1);
kill_fasync(&list->fasync, SIGIO, POLL_IN);
} else
list_for_each_entry(list, &evdev->list, node) {
do_gettimeofday(&list->buffer[list->head].time);
......@@ -88,6 +100,11 @@ static int evdev_release(struct inode * inode, struct file * file)
{
struct evdev_list *list = file->private_data;
if (list->evdev->grab == list) {
input_release_device(&list->evdev->handle);
list->evdev->grab = NULL;
}
evdev_fasync(-1, file, 0);
list_del(&list->node);
......@@ -257,6 +274,22 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
return -EFAULT;
return 0;
case EVIOCGRAB:
if (arg) {
if (evdev->grab)
return -EBUSY;
if (input_grab_device(&evdev->handle))
return -EBUSY;
evdev->grab = list;
return 0;
} else {
if (evdev->grab != list)
return -EINVAL;
input_release_device(&evdev->handle);
evdev->grab = NULL;
return 0;
}
default:
if (_IOC_TYPE(cmd) != 'E' || _IOC_DIR(cmd) != _IOC_READ)
......
......@@ -37,7 +37,7 @@ static LIST_HEAD(gameport_dev_list);
#ifdef __i386__
#define DELTA(x,y) ((y)-(x)+((y)<(x)?1193180/HZ:0))
#define DELTA(x,y) ((y)-(x)+((y)<(x)?1193182/HZ:0))
#define GET_TIME(x) do { x = get_time_pit(); } while (0)
static unsigned int get_time_pit(void)
......
......@@ -33,6 +33,8 @@ EXPORT_SYMBOL(input_register_device);
EXPORT_SYMBOL(input_unregister_device);
EXPORT_SYMBOL(input_register_handler);
EXPORT_SYMBOL(input_unregister_handler);
EXPORT_SYMBOL(input_grab_device);
EXPORT_SYMBOL(input_release_device);
EXPORT_SYMBOL(input_open_device);
EXPORT_SYMBOL(input_close_device);
EXPORT_SYMBOL(input_accept_process);
......@@ -175,6 +177,9 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
if (type != EV_SYN)
dev->sync = 0;
if (dev->grab)
dev->grab->handler->event(dev->grab, type, code, value);
else
list_for_each_entry(handle, &dev->h_list, d_node)
if (handle->open)
handle->handler->event(handle, type, code, value);
......@@ -201,6 +206,21 @@ int input_accept_process(struct input_handle *handle, struct file *file)
return 0;
}
int input_grab_device(struct input_handle *handle)
{
if (handle->dev->grab)
return -EBUSY;
handle->dev->grab = handle;
return 0;
}
void input_release_device(struct input_handle *handle)
{
if (handle->dev->grab == handle)
handle->dev->grab = NULL;
}
int input_open_device(struct input_handle *handle)
{
if (handle->dev->pm_dev)
......@@ -221,6 +241,7 @@ int input_flush_device(struct input_handle* handle, struct file* file)
void input_close_device(struct input_handle *handle)
{
input_release_device(handle);
if (handle->dev->pm_dev)
pm_dev_idle(handle->dev->pm_dev);
if (handle->dev->close)
......
......@@ -138,7 +138,7 @@ struct analog_port {
#ifdef __i386__
#define GET_TIME(x) do { if (cpu_has_tsc) rdtscl(x); else x = get_time_pit(); } while (0)
#define DELTA(x,y) (cpu_has_tsc?((y)-(x)):((x)-(y)+((x)<(y)?1193180L/HZ:0)))
#define DELTA(x,y) (cpu_has_tsc?((y)-(x)):((x)-(y)+((x)<(y)?1193182L/HZ:0)))
#define TIME_NAME (cpu_has_tsc?"TSC":"PIT")
static unsigned int get_time_pit(void)
{
......
......@@ -39,7 +39,7 @@ static int atkbd_reset = 1;
static unsigned char atkbd_set2_keycode[512] = {
0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41, 85,
0, 56, 42, 0, 29, 16, 2, 89, 0, 0, 44, 31, 30, 17, 3, 90,
0, 56, 42,182, 29, 16, 2, 89, 0, 0, 44, 31, 30, 17, 3, 90,
0, 46, 45, 32, 18, 5, 4, 91, 0, 57, 47, 33, 20, 19, 6, 0,
0, 49, 48, 35, 34, 21, 7, 0, 0, 0, 50, 36, 22, 8, 9, 0,
0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0,
......
......@@ -271,7 +271,7 @@ static void sunkbd_connect(struct serio *serio, struct serio_dev *dev)
sprintf(sunkbd->name, "Sun Type %d keyboard", sunkbd->type);
memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode));
for (i = 0; i < 127; i++)
for (i = 0; i < 128; i++)
set_bit(sunkbd->keycode[i], sunkbd->dev.keybit);
clear_bit(0, sunkbd->dev.keybit);
......
......@@ -43,7 +43,7 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c
}
if (value > 20 && value < 32767)
count = 1193182 / value;
count = CLOCK_TICK_RATE / value;
spin_lock_irqsave(&i8253_beep_lock, flags);
......
......@@ -28,6 +28,19 @@ config MOUSE_PS2
The module will be called psmouse. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
config MOUSE_PS2_SYNAPTICS
bool "Synaptics TouchPad"
default n
depends on INPUT && INPUT_MOUSE && SERIO && MOUSE_PS2
---help---
Say Y here if you have a Synaptics TouchPad connected to your system.
This touchpad is found on many modern laptop computers.
Note that you also need a user space driver to interpret the data
generated by the kernel. A compatible driver for XFree86 is available
from http://...
If unsure, say Y.
config MOUSE_SERIAL
tristate "Serial mouse"
depends on INPUT && INPUT_MOUSE && SERIO
......
......@@ -13,3 +13,8 @@ obj-$(CONFIG_MOUSE_PC110PAD) += pc110pad.o
obj-$(CONFIG_MOUSE_PC9800) += 98busmouse.o
obj-$(CONFIG_MOUSE_PS2) += psmouse.o
obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
psmouse-objs := psmouse-base.o
ifeq ($(CONFIG_MOUSE_PS2_SYNAPTICS),y)
psmouse-objs += synaptics.o
endif
......@@ -17,6 +17,8 @@
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/init.h>
#include "psmouse.h"
#include "synaptics.h"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("PS/2 mouse driver");
......@@ -25,48 +27,7 @@ MODULE_LICENSE("GPL");
static int psmouse_noext;
#define PSMOUSE_CMD_SETSCALE11 0x00e6
#define PSMOUSE_CMD_SETRES 0x10e8
#define PSMOUSE_CMD_GETINFO 0x03e9
#define PSMOUSE_CMD_SETSTREAM 0x00ea
#define PSMOUSE_CMD_POLL 0x03eb
#define PSMOUSE_CMD_GETID 0x02f2
#define PSMOUSE_CMD_SETRATE 0x10f3
#define PSMOUSE_CMD_ENABLE 0x00f4
#define PSMOUSE_CMD_RESET_DIS 0x00f6
#define PSMOUSE_CMD_RESET_BAT 0x02ff
#define PSMOUSE_RET_BAT 0xaa
#define PSMOUSE_RET_ACK 0xfa
#define PSMOUSE_RET_NAK 0xfe
struct psmouse {
struct input_dev dev;
struct serio *serio;
char *vendor;
char *name;
unsigned char cmdbuf[8];
unsigned char packet[8];
unsigned char cmdcnt;
unsigned char pktcnt;
unsigned char type;
unsigned char model;
unsigned long last;
char acking;
volatile char ack;
char error;
char devname[64];
char phys[32];
};
#define PSMOUSE_PS2 1
#define PSMOUSE_PS2PP 2
#define PSMOUSE_PS2TPP 3
#define PSMOUSE_GENPS 4
#define PSMOUSE_IMPS 5
#define PSMOUSE_IMEX 6
static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2" };
static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "Synaptics"};
/*
* psmouse_process_packet() anlyzes the PS/2 mouse packet contents and
......@@ -209,6 +170,16 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
goto out;
}
if (psmouse->pktcnt == 1 && psmouse->type == PSMOUSE_SYNAPTICS) {
/*
* The synaptics driver has its own resync logic,
* so it needs to receive all bytes one at a time.
*/
synaptics_process_byte(psmouse, regs);
psmouse->pktcnt = 0;
goto out;
}
if (psmouse->pktcnt == 1 && psmouse->packet[0] == PSMOUSE_RET_BAT) {
serio_rescan(serio);
goto out;
......@@ -244,7 +215,7 @@ static int psmouse_sendbyte(struct psmouse *psmouse, unsigned char byte)
* then waits for the response and puts it in the param array.
*/
static int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
{
int timeout = 500000; /* 500 msec */
int send = (command >> 12) & 0xf;
......@@ -343,11 +314,11 @@ static int psmouse_extensions(struct psmouse *psmouse)
psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
if (param[1] == 0x47) {
/* We could do more here. But it's sufficient just
to stop the subsequent probes from screwing the
thing up. */
psmouse->vendor = "Synaptics";
psmouse->name = "TouchPad";
if (!synaptics_init(psmouse))
return PSMOUSE_SYNAPTICS;
else
return PSMOUSE_PS2;
}
......@@ -598,6 +569,7 @@ static void psmouse_disconnect(struct serio *serio)
struct psmouse *psmouse = serio->private;
input_unregister_device(&psmouse->dev);
serio_close(serio);
synaptics_disconnect(psmouse);
kfree(psmouse);
}
......
#ifndef _PSMOUSE_H
#define _PSMOUSE_H
#define PSMOUSE_CMD_SETSCALE11 0x00e6
#define PSMOUSE_CMD_SETRES 0x10e8
#define PSMOUSE_CMD_GETINFO 0x03e9
#define PSMOUSE_CMD_SETSTREAM 0x00ea
#define PSMOUSE_CMD_POLL 0x03eb
#define PSMOUSE_CMD_GETID 0x02f2
#define PSMOUSE_CMD_SETRATE 0x10f3
#define PSMOUSE_CMD_ENABLE 0x00f4
#define PSMOUSE_CMD_RESET_DIS 0x00f6
#define PSMOUSE_CMD_RESET_BAT 0x02ff
#define PSMOUSE_RET_BAT 0xaa
#define PSMOUSE_RET_ACK 0xfa
#define PSMOUSE_RET_NAK 0xfe
struct psmouse {
void *private;
struct input_dev dev;
struct serio *serio;
char *vendor;
char *name;
unsigned char cmdbuf[8];
unsigned char packet[8];
unsigned char cmdcnt;
unsigned char pktcnt;
unsigned char type;
unsigned char model;
unsigned long last;
char acking;
volatile char ack;
char error;
char devname[64];
char phys[32];
};
#define PSMOUSE_PS2 1
#define PSMOUSE_PS2PP 2
#define PSMOUSE_PS2TPP 3
#define PSMOUSE_GENPS 4
#define PSMOUSE_IMPS 5
#define PSMOUSE_IMEX 6
#define PSMOUSE_SYNAPTICS 7
int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command);
#endif /* _PSMOUSE_H */
This diff is collapsed.
/*
* Synaptics TouchPad PS/2 mouse driver
*
* 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 _SYNAPTICS_H
#define _SYNAPTICS_H
#ifdef CONFIG_MOUSE_PS2_SYNAPTICS
extern void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs);
extern int synaptics_init(struct psmouse *psmouse);
extern void synaptics_disconnect(struct psmouse *psmouse);
#else
static inline void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs) {}
static inline int synaptics_init(struct psmouse *psmouse) { return -1; }
static inline void synaptics_disconnect(struct psmouse *psmouse) {}
#endif
/* synaptics queries */
#define SYN_QUE_IDENTIFY 0x00
#define SYN_QUE_MODES 0x01
#define SYN_QUE_CAPABILITIES 0x02
#define SYN_QUE_MODEL 0x03
#define SYN_QUE_SERIAL_NUMBER_PREFIX 0x06
#define SYN_QUE_SERIAL_NUMBER_SUFFIX 0x07
#define SYN_QUE_RESOLUTION 0x08
/* synatics modes */
#define SYN_BIT_ABSOLUTE_MODE (1 << 7)
#define SYN_BIT_HIGH_RATE (1 << 6)
#define SYN_BIT_SLEEP_MODE (1 << 3)
#define SYN_BIT_DISABLE_GESTURE (1 << 2)
#define SYN_BIT_W_MODE (1 << 0)
/* synaptics model ID bits */
#define SYN_MODEL_ROT180(m) ((m) & (1 << 23))
#define SYN_MODEL_PORTRAIT(m) ((m) & (1 << 22))
#define SYN_MODEL_SENSOR(m) (((m) >> 16) & 0x3f)
#define SYN_MODEL_HARDWARE(m) (((m) >> 9) & 0x7f)
#define SYN_MODEL_NEWABS(m) ((m) & (1 << 7))
#define SYN_MODEL_PEN(m) ((m) & (1 << 6))
#define SYN_MODEL_SIMPLIC(m) ((m) & (1 << 5))
#define SYN_MODEL_GEOMETRY(m) ((m) & 0x0f)
/* synaptics capability bits */
#define SYN_CAP_EXTENDED(c) ((c) & (1 << 23))
#define SYN_CAP_SLEEP(c) ((c) & (1 << 4))
#define SYN_CAP_FOUR_BUTTON(c) ((c) & (1 << 3))
#define SYN_CAP_MULTIFINGER(c) ((c) & (1 << 1))
#define SYN_CAP_PALMDETECT(c) ((c) & (1 << 0))
#define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47)
/* synaptics modes query bits */
#define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7))
#define SYN_MODE_RATE(m) ((m) & (1 << 6))
#define SYN_MODE_BAUD_SLEEP(m) ((m) & (1 << 3))
#define SYN_MODE_DISABLE_GESTURE(m) ((m) & (1 << 2))
#define SYN_MODE_PACKSIZE(m) ((m) & (1 << 1))
#define SYN_MODE_WMODE(m) ((m) & (1 << 0))
/* synaptics identify query bits */
#define SYN_ID_MODEL(i) (((i) >> 4) & 0x0f)
#define SYN_ID_MAJOR(i) ((i) & 0x0f)
#define SYN_ID_MINOR(i) (((i) >> 16) & 0xff)
#define SYN_ID_IS_SYNAPTICS(i) ((((i) >> 8) & 0xff) == 0x47)
/*
* A structure to describe the state of the touchpad hardware (buttons and pad)
*/
struct synaptics_hw_state {
int x;
int y;
int z;
int w;
int left;
int right;
int up;
int down;
};
struct synaptics_data {
/* Data read from the touchpad */
unsigned long int model_id; /* Model-ID */
unsigned long int capabilities; /* Capabilities */
unsigned long int identity; /* Identification */
/* Data for normal processing */
unsigned char proto_buf[6]; /* Buffer for Packet */
unsigned char last_byte; /* last received byte */
int inSync; /* Packets in sync */
int proto_buf_tail;
int old_w; /* Previous w value */
};
#endif /* _SYNAPTICS_H */
......@@ -119,3 +119,14 @@ config SERIO_98KBD
The module will be called rpckbd.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
config SERIO_PCIPS2
tristate "PCI PS/2 keyboard and PS/2 mouse controller"
depends on PCI && SERIO
help
Say Y here if you have a Mobility Docking station with PS/2
keyboard and mice ports.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called rpckbd. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
......@@ -14,3 +14,4 @@ obj-$(CONFIG_SERIO_SA1111) += sa1111ps2.o
obj-$(CONFIG_SERIO_AMBAKMI) += ambakmi.o
obj-$(CONFIG_SERIO_Q40KBD) += q40kbd.o
obj-$(CONFIG_SERIO_98KBD) += 98kbd-io.o
obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o
......@@ -20,11 +20,14 @@
*/
#ifdef __alpha__
#define I8042_KBD_IRQ 1
#define I8042_AUX_IRQ (RTC_PORT(0) == 0x170 ? 9 : 12) /* Jensen is special */
# define I8042_KBD_IRQ 1
# define I8042_AUX_IRQ (RTC_PORT(0) == 0x170 ? 9 : 12) /* Jensen is special */
#elif defined(__ia64__)
# define I8042_KBD_IRQ isa_irq_to_vector(1)
# define I8042_AUX_IRQ isa_irq_to_vector(12)
#else
#define I8042_KBD_IRQ 1
#define I8042_AUX_IRQ 12
# define I8042_KBD_IRQ 1
# define I8042_AUX_IRQ 12
#endif
/*
......
/*
* linux/drivers/input/serio/pcips2.c
*
* Copyright (C) 2003 Russell King, All Rights Reserved.
*
* 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.
*
* I'm not sure if this is a generic PS/2 PCI interface or specific to
* the Mobility Electronics docking station.
*/
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/input.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <asm/io.h>
#define PS2_CTRL (0)
#define PS2_STATUS (1)
#define PS2_DATA (2)
#define PS2_CTRL_CLK (1<<0)
#define PS2_CTRL_DAT (1<<1)
#define PS2_CTRL_TXIRQ (1<<2)
#define PS2_CTRL_ENABLE (1<<3)
#define PS2_CTRL_RXIRQ (1<<4)
#define PS2_STAT_CLK (1<<0)
#define PS2_STAT_DAT (1<<1)
#define PS2_STAT_PARITY (1<<2)
#define PS2_STAT_RXFULL (1<<5)
#define PS2_STAT_TXBUSY (1<<6)
#define PS2_STAT_TXEMPTY (1<<7)
struct pcips2_data {
struct serio io;
unsigned int base;
struct pci_dev *dev;
};
static int pcips2_write(struct serio *io, unsigned char val)
{
struct pcips2_data *ps2if = io->driver;
unsigned int stat;
do {
stat = inb(ps2if->base + PS2_STATUS);
cpu_relax();
} while (!(stat & PS2_STAT_TXEMPTY));
outb(val, ps2if->base + PS2_DATA);
return 0;
}
static void pcips2_interrupt(int irq, void *devid, struct pt_regs *regs)
{
struct pcips2_data *ps2if = devid;
unsigned char status, scancode;
do {
unsigned int flag;
status = inb(ps2if->base + PS2_STATUS);
if (!(status & PS2_STAT_RXFULL))
break;
scancode = inb(ps2if->base + PS2_DATA);
if (status == 0xff && scancode == 0xff)
break;
flag = (status & PS2_STAT_PARITY) ? 0 : SERIO_PARITY;
if (hweight8(scancode) & 1)
flag ^= SERIO_PARITY;
serio_interrupt(&ps2if->io, scancode, flag, regs);
} while (1);
}
static void pcips2_flush_input(struct pcips2_data *ps2if)
{
unsigned char status, scancode;
do {
status = inb(ps2if->base + PS2_STATUS);
if (!(status & PS2_STAT_RXFULL))
break;
scancode = inb(ps2if->base + PS2_DATA);
if (status == 0xff && scancode == 0xff)
break;
} while (1);
}
static int pcips2_open(struct serio *io)
{
struct pcips2_data *ps2if = io->driver;
int ret, val = 0;
outb(PS2_CTRL_ENABLE, ps2if->base);
pcips2_flush_input(ps2if);
ret = request_irq(ps2if->dev->irq, pcips2_interrupt, SA_SHIRQ,
"pcips2", ps2if);
if (ret == 0)
val = PS2_CTRL_ENABLE | PS2_CTRL_RXIRQ;
outb(val, ps2if->base);
return ret;
}
static void pcips2_close(struct serio *io)
{
struct pcips2_data *ps2if = io->driver;
outb(0, ps2if->base);
free_irq(ps2if->dev->irq, ps2if);
}
static int __devinit pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct pcips2_data *ps2if;
int ret;
ret = pci_enable_device(dev);
if (ret)
return ret;
if (!request_region(pci_resource_start(dev, 0),
pci_resource_len(dev, 0), "pcips2")) {
ret = -EBUSY;
goto disable;
}
ps2if = kmalloc(sizeof(struct pcips2_data), GFP_KERNEL);
if (!ps2if) {
ret = -ENOMEM;
goto release;
}
memset(ps2if, 0, sizeof(struct pcips2_data));
ps2if->io.type = SERIO_8042;
ps2if->io.write = pcips2_write;
ps2if->io.open = pcips2_open;
ps2if->io.close = pcips2_close;
ps2if->io.name = dev->dev.name;
ps2if->io.phys = dev->dev.bus_id;
ps2if->io.driver = ps2if;
ps2if->dev = dev;
ps2if->base = pci_resource_start(dev, 0);
pci_set_drvdata(dev, ps2if);
serio_register_port(&ps2if->io);
return 0;
release:
release_region(pci_resource_start(dev, 0),
pci_resource_len(dev, 0));
disable:
pci_disable_device(dev);
return ret;
}
static void __devexit pcips2_remove(struct pci_dev *dev)
{
struct pcips2_data *ps2if = pci_get_drvdata(dev);
serio_unregister_port(&ps2if->io);
release_region(pci_resource_start(dev, 0),
pci_resource_len(dev, 0));
pci_set_drvdata(dev, NULL);
kfree(ps2if);
pci_disable_device(dev);
}
static struct pci_device_id pcips2_ids[] = {
{
.vendor = 0x14f2, /* MOBILITY */
.device = 0x0123, /* Keyboard */
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.class = PCI_CLASS_INPUT_KEYBOARD << 8,
.class_mask = 0xffff00,
},
{
.vendor = 0x14f2, /* MOBILITY */
.device = 0x0124, /* Mouse */
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.class = PCI_CLASS_INPUT_MOUSE << 8,
.class_mask = 0xffff00,
},
{ 0, }
};
static struct pci_driver pcips2_driver = {
.name = "pcips2",
.id_table = pcips2_ids,
.probe = pcips2_probe,
.remove = __devexit_p(pcips2_remove),
.driver = {
.devclass = &input_devclass,
},
};
static int __init pcips2_init(void)
{
return pci_module_init(&pcips2_driver);
}
static void __exit pcips2_exit(void)
{
pci_unregister_driver(&pcips2_driver);
}
module_init(pcips2_init);
module_exit(pcips2_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
MODULE_DESCRIPTION("PCI PS/2 keyboard/mouse driver");
MODULE_DEVICE_TABLE(pci, pcips2_ids);
......@@ -957,6 +957,10 @@ static void hid_output_field(struct hid_field *field, __u8 *data)
void hid_output_report(struct hid_report *report, __u8 *data)
{
unsigned n;
if (report->id > 0)
*data++ = report->id;
for (n = 0; n < report->maxfield; n++)
hid_output_field(report->field[n], data);
}
......@@ -1051,7 +1055,7 @@ static int hid_submit_out(struct hid_device *hid)
report = hid->out[hid->outtail];
hid_output_report(report, hid->outbuf);
hid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1;
hid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
hid->urbout->dev = hid->dev;
dbg("submitting out urb");
......@@ -1075,7 +1079,7 @@ static int hid_submit_ctrl(struct hid_device *hid)
if (dir == USB_DIR_OUT)
hid_output_report(report, hid->ctrlbuf);
hid->urbctrl->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + ((report->id > 0) && (dir != USB_DIR_OUT));
hid->urbctrl->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
hid->urbctrl->pipe = (dir == USB_DIR_OUT) ? usb_sndctrlpipe(hid->dev, 0) : usb_rcvctrlpipe(hid->dev, 0);
hid->urbctrl->dev = hid->dev;
......@@ -1351,6 +1355,9 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f
#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
#define USB_VENDOR_ID_A4TECH 0x09DA
#define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006
struct hid_blacklist {
__u16 idVendor;
__u16 idProduct;
......@@ -1398,6 +1405,7 @@ struct hid_blacklist {
{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK },
{ 0, 0 }
};
......
......@@ -376,6 +376,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
}
set_bit(usage->type, input->evbit);
if ((usage->type == EV_REL)
&& (device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK)
&& (usage->code == REL_WHEEL)) {
set_bit(REL_HWHEEL, bit);
}
while (usage->code <= max && test_and_set_bit(usage->code, bit)) {
usage->code = find_next_zero_bit(bit, max + 1, usage->code);
......@@ -426,6 +431,20 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
input_regs(input, regs);
if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK)
&& (usage->code == BTN_BACK)) {
if (value)
hid->quirks |= HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
else
hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
return;
}
if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON)
&& (usage->code == REL_WHEEL)) {
input_event(input, usage->type, REL_HWHEEL, value);
return;
}
if (usage->hat_min != usage->hat_max) {
value = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1;
if (value < 0 || value > 8) value = 0;
......
......@@ -201,13 +201,15 @@ struct hid_item {
* HID device quirks.
*/
#define HID_QUIRK_INVERT 0x01
#define HID_QUIRK_NOTOUCH 0x02
#define HID_QUIRK_IGNORE 0x04
#define HID_QUIRK_NOGET 0x08
#define HID_QUIRK_HIDDEV 0x10
#define HID_QUIRK_BADPAD 0x20
#define HID_QUIRK_MULTI_INPUT 0x40
#define HID_QUIRK_INVERT 0x001
#define HID_QUIRK_NOTOUCH 0x002
#define HID_QUIRK_IGNORE 0x004
#define HID_QUIRK_NOGET 0x008
#define HID_QUIRK_HIDDEV 0x010
#define HID_QUIRK_BADPAD 0x020
#define HID_QUIRK_MULTI_INPUT 0x040
#define HID_QUIRK_2WHEEL_MOUSE_HACK 0x080
#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x100
/*
* This is the global environment of the parser. This information is
......
......@@ -442,10 +442,14 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
if (copy_to_user((void *) arg, &dinfo, sizeof(dinfo)))
return -EFAULT;
return 0;
case HIDIOCGFLAG:
if (put_user(list->flags, (int *) arg))
return -EFAULT;
return 0;
case HIDIOCSFLAG:
{
int newflags;
......@@ -533,6 +537,8 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
if (copy_to_user((void *) arg, &rinfo, sizeof(rinfo)))
return -EFAULT;
return 0;
case HIDIOCGFIELDINFO:
if (copy_from_user(&finfo, (void *) arg, sizeof(finfo)))
return -EFAULT;
......@@ -564,6 +570,8 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
if (copy_to_user((void *) arg, &finfo, sizeof(finfo)))
return -EFAULT;
return 0;
case HIDIOCGUCODE:
if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
return -EFAULT;
......@@ -585,6 +593,8 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
if (copy_to_user((void *) arg, &uref, sizeof(uref)))
return -EFAULT;
return 0;
case HIDIOCGUSAGE:
case HIDIOCSUSAGE:
case HIDIOCGCOLLECTIONINDEX:
......
......@@ -15,7 +15,7 @@
#ifdef CONFIG_MELAN
# define CLOCK_TICK_RATE 1189200 /* AMD Elan has different frequency! */
#else
# define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
# define CLOCK_TICK_RATE 1193182 /* Underlying HZ */
#endif
#endif
......
......@@ -10,7 +10,7 @@
#include <asm/msr.h>
#include <asm/vsyscall.h>
#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
#define CLOCK_TICK_RATE 1193182 /* Underlying HZ */
#define CLOCK_TICK_FACTOR 20 /* Factor of both 1000000 and CLOCK_TICK_RATE */
#define FINETUNE ((((((int)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
(1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \
......
......@@ -77,6 +77,8 @@ struct input_absinfo {
#define EVIOCRMFF _IOW('E', 0x81, int) /* Erase a force effect */
#define EVIOCGEFFECTS _IOR('E', 0x84, int) /* Report number of effects playable at the same time */
#define EVIOCGRAB _IOW('E', 0x90, int) /* Grab/Release device */
/*
* Event types
*/
......@@ -471,6 +473,11 @@ struct input_absinfo {
#define KEY_TEEN 0x19e
#define KEY_TWEN 0x19f
#define KEY_DEL_EOL 0x1c0
#define KEY_DEL_EOS 0x1c1
#define KEY_INS_LINE 0x1c2
#define KEY_DEL_LINE 0x1c3
#define KEY_MAX 0x1ff
/*
......@@ -523,6 +530,7 @@ struct input_absinfo {
#define MSC_SERIAL 0x00
#define MSC_PULSELED 0x01
#define MSC_GESTURE 0x02
#define MSC_MAX 0x07
/*
......@@ -798,6 +806,8 @@ struct input_dev {
int (*upload_effect)(struct input_dev *dev, struct ff_effect *effect);
int (*erase_effect)(struct input_dev *dev, int effect_id);
struct input_handle *grab;
struct list_head h_list;
struct list_head node;
};
......@@ -888,6 +898,9 @@ void input_unregister_device(struct input_dev *);
void input_register_handler(struct input_handler *);
void input_unregister_handler(struct input_handler *);
int input_grab_device(struct input_handle *);
void input_release_device(struct input_handle *);
int input_open_device(struct input_handle *);
void input_close_device(struct input_handle *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment