Commit 51847e22 authored by Vojtech Pavlik's avatar Vojtech Pavlik Committed by Linus Torvalds

[PATCH] Input drivers, step #3

This patch updates the input core to the current version, fixing a bunch
of bugs, adding hotplug support and a listing of available input devices
in /proc. The later is very useful for troubleshooting.

Vojtech Pavlik
SuSE Labs
parent 3ba2a466
/*
* $Id: evdev.c,v 1.27 2001/05/28 09:06:44 vojtech Exp $
* $Id: evdev.c,v 1.42 2002/01/02 11:59:56 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*
* Event char devices, giving access to raw input device events.
*
* Sponsored by SuSE
*/
/*
......@@ -24,8 +22,8 @@
* 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@suse.cz>, or by paper mail:
* Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#define EVDEV_MINOR_BASE 64
......@@ -42,7 +40,9 @@
struct evdev {
int exist;
int open;
int open_for_write;
int minor;
char name[16];
struct input_handle handle;
wait_queue_head_t wait;
devfs_handle_t devfs;
......@@ -89,6 +89,11 @@ static int evdev_fasync(int fd, struct file *file, int on)
return retval < 0 ? retval : 0;
}
static int evdev_flush(struct file * file)
{
return input_flush_device(&((struct evdev_list*)file->private_data)->evdev->handle, file);
}
static int evdev_release(struct inode * inode, struct file * file)
{
struct evdev_list *list = file->private_data;
......@@ -120,10 +125,16 @@ static int evdev_open(struct inode * inode, struct file * file)
{
struct evdev_list *list;
int i = minor(inode->i_rdev) - EVDEV_MINOR_BASE;
int accept_err;
if (i >= EVDEV_MINORS || !evdev_table[i])
return -ENODEV;
/* Ask the driver if he wishes to accept the open() */
if ((accept_err = input_accept_process(&(evdev_table[i]->handle), file))) {
return accept_err;
}
if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL)))
return -ENOMEM;
memset(list, 0, sizeof(struct evdev_list));
......@@ -167,7 +178,7 @@ static ssize_t evdev_read(struct file * file, char * buffer, size_t count, loff_
if (list->head == list->tail) {
add_wait_queue(&list->evdev->wait, &wait);
current->state = TASK_INTERRUPTIBLE;
set_current_state(TASK_INTERRUPTIBLE);
while (list->head == list->tail) {
......@@ -187,7 +198,7 @@ static ssize_t evdev_read(struct file * file, char * buffer, size_t count, loff_
schedule();
}
current->state = TASK_RUNNING;
set_current_state(TASK_RUNNING);
remove_wait_queue(&list->evdev->wait, &wait);
}
......@@ -219,7 +230,7 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
struct evdev_list *list = file->private_data;
struct evdev *evdev = list->evdev;
struct input_dev *dev = evdev->handle.dev;
int retval;
int retval, t, u;
switch (cmd) {
......@@ -232,6 +243,40 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
if ((retval = put_user(dev->idproduct, ((short *) arg) + 2))) return retval;
if ((retval = put_user(dev->idversion, ((short *) arg) + 3))) return retval;
return 0;
case EVIOCGREP:
if ((retval = put_user(dev->rep[0], ((int *) arg) + 0))) return retval;
if ((retval = put_user(dev->rep[1], ((int *) arg) + 1))) return retval;
return 0;
case EVIOCSREP:
if ((retval = get_user(dev->rep[0], ((int *) arg) + 0))) return retval;
if ((retval = get_user(dev->rep[1], ((int *) arg) + 1))) return retval;
return 0;
case EVIOCGKEYCODE:
if ((retval = get_user(t, ((int *) arg) + 0))) return retval;
if (t < 0 || t > dev->keycodemax) return -EINVAL;
switch (dev->keycodesize) {
case 1: u = *(u8*)(dev->keycode + t); break;
case 2: u = *(u16*)(dev->keycode + t * 2); break;
case 4: u = *(u32*)(dev->keycode + t * 4); break;
default: return -EINVAL;
}
if ((retval = put_user(u, ((int *) arg) + 1))) return retval;
return 0;
case EVIOCSKEYCODE:
if ((retval = get_user(t, ((int *) arg) + 0))) return retval;
if (t < 0 || t > dev->keycodemax) return -EINVAL;
if ((retval = get_user(u, ((int *) arg) + 1))) return retval;
switch (dev->keycodesize) {
case 1: *(u8*)(dev->keycode + t) = u; break;
case 2: *(u16*)(dev->keycode + t * 2) = u; break;
case 4: *(u32*)(dev->keycode + t * 4) = u; break;
default: return -EINVAL;
}
return 0;
case EVIOCSFF:
if (dev->upload_effect) {
......@@ -280,22 +325,55 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
default: return -EINVAL;
}
len = NBITS(len) * sizeof(long);
if (len > _IOC_SIZE(cmd)) {
printk(KERN_WARNING "evdev.c: Truncating bitfield length from %d to %d\n",
len, _IOC_SIZE(cmd));
len = _IOC_SIZE(cmd);
}
if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
return copy_to_user((char *) arg, bits, len) ? -EFAULT : len;
}
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) {
int len;
len = NBITS(KEY_MAX) * sizeof(long);
if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
return copy_to_user((char *) arg, dev->key, len) ? -EFAULT : len;
}
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) {
int len;
len = NBITS(LED_MAX) * sizeof(long);
if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
return copy_to_user((char *) arg, dev->led, len) ? -EFAULT : len;
}
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) {
int len;
len = NBITS(SND_MAX) * sizeof(long);
if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
return copy_to_user((char *) arg, dev->snd, len) ? -EFAULT : len;
}
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
int len;
if (!dev->name) return 0;
if (!dev->name) return -ENOENT;
len = strlen(dev->name) + 1;
if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
return copy_to_user((char *) arg, 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((char *) arg, 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((char *) arg, dev->uniq, len) ? -EFAULT : len;
}
if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
int t = _IOC_NR(cmd) & ABS_MAX;
......@@ -321,9 +399,10 @@ static struct file_operations evdev_fops = {
release: evdev_release,
ioctl: evdev_ioctl,
fasync: evdev_fasync,
flush: evdev_flush
};
static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev)
static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
{
struct evdev *evdev;
int minor;
......@@ -342,16 +421,17 @@ static struct input_handle *evdev_connect(struct input_handler *handler, struct
evdev->minor = minor;
evdev_table[minor] = evdev;
sprintf(evdev->name, "event%d", minor);
evdev->handle.dev = dev;
evdev->handle.name = evdev->name;
evdev->handle.handler = handler;
evdev->handle.private = evdev;
evdev->exist = 1;
evdev->devfs = input_register_minor("event%d", minor, EVDEV_MINOR_BASE);
// printk(KERN_INFO "event%d: Event device for input%d\n", minor, dev->number);
evdev->exist = 1;
return &evdev->handle;
}
......@@ -372,12 +452,21 @@ static void evdev_disconnect(struct input_handle *handle)
}
}
static struct input_device_id evdev_ids[] = {
{ driver_info: 1 }, /* Matches all devices */
{ }, /* Terminating zero entry */
};
MODULE_DEVICE_TABLE(input, evdev_ids);
static struct input_handler evdev_handler = {
event: evdev_event,
connect: evdev_connect,
disconnect: evdev_disconnect,
fops: &evdev_fops,
minor: EVDEV_MINOR_BASE,
name: "evdev",
id_table: evdev_ids,
};
static int __init evdev_init(void)
......@@ -394,7 +483,6 @@ static void __exit evdev_exit(void)
module_init(evdev_init);
module_exit(evdev_exit);
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("Event character device driver");
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Input driver event char devices");
MODULE_LICENSE("GPL");
This diff is collapsed.
/*
* $Id: joydev.c,v 1.19 2001/01/10 19:49:40 vojtech Exp $
* $Id: joydev.c,v 1.38 2001/12/27 10:37:41 vojtech Exp $
*
* Copyright (c) 1999-2000 Vojtech Pavlik
* Copyright (c) 1999-2001 Vojtech Pavlik
* Copyright (c) 1999 Colin Van Dyke
*
* Joystick device driver for the input driver suite.
*
* Sponsored by SuSE and Intel
*/
/*
......@@ -25,8 +23,8 @@
* 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@suse.cz>, or by paper mail:
* Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
* 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>
......@@ -45,14 +43,22 @@
#include <linux/init.h>
#include <linux/smp_lock.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Joystick device interfaces");
MODULE_SUPPORTED_DEVICE("input/js");
MODULE_LICENSE("GPL");
#define JOYDEV_MINOR_BASE 0
#define JOYDEV_MINORS 32
#define JOYDEV_BUFFER_SIZE 64
#define MSECS(t) (1000 * ((t) / HZ) + 1000 * ((t) % HZ) / HZ)
struct joydev {
int exist;
int open;
int minor;
char name[16];
struct input_handle handle;
wait_queue_head_t wait;
devfs_handle_t devfs;
......@@ -81,11 +87,6 @@ struct joydev_list {
static struct joydev *joydev_table[JOYDEV_MINORS];
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("Joystick device driver");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("input/js");
static int joydev_correct(int value, struct js_corr *corr)
{
switch (corr->type) {
......@@ -133,7 +134,7 @@ static void joydev_event(struct input_handle *handle, unsigned int type, unsigne
return;
}
event.time = jiffies * (1000 / HZ);
event.time = MSECS(jiffies);
while (list) {
......@@ -163,7 +164,7 @@ static int joydev_release(struct inode * inode, struct file * file)
{
struct joydev_list *list = file->private_data;
struct joydev_list **listptr;
listptr = &list->joydev->list;
joydev_fasync(-1, file, 0);
......@@ -249,7 +250,7 @@ static ssize_t joydev_read(struct file *file, char *buf, size_t count, loff_t *p
if (list->head == list->tail && list->startup == joydev->nabs + joydev->nkey) {
add_wait_queue(&list->joydev->wait, &wait);
current->state = TASK_INTERRUPTIBLE;
set_current_state(TASK_INTERRUPTIBLE);
while (list->head == list->tail) {
......@@ -265,7 +266,7 @@ static ssize_t joydev_read(struct file *file, char *buf, size_t count, loff_t *p
schedule();
}
current->state = TASK_RUNNING;
set_current_state(TASK_RUNNING);
remove_wait_queue(&list->joydev->wait, &wait);
}
......@@ -276,7 +277,7 @@ static ssize_t joydev_read(struct file *file, char *buf, size_t count, loff_t *p
struct js_event event;
event.time = jiffies * (1000/HZ);
event.time = MSECS(jiffies);
if (list->startup < joydev->nkey) {
event.type = JS_EVENT_BUTTON | JS_EVENT_INIT;
......@@ -360,9 +361,9 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
return copy_to_user((struct js_corr *) arg, joydev->corr,
sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0;
case JSIOCSAXMAP:
if (copy_from_user((__u8 *) arg, joydev->abspam, sizeof(__u8) * ABS_MAX))
if (copy_from_user(joydev->abspam, (__u8 *) arg, sizeof(__u8) * ABS_MAX))
return -EFAULT;
for (i = 0; i < ABS_MAX; i++) {
for (i = 0; i < joydev->nabs; i++) {
if (joydev->abspam[i] > ABS_MAX) return -EINVAL;
joydev->absmap[joydev->abspam[i]] = i;
}
......@@ -371,11 +372,11 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
return copy_to_user((__u8 *) arg, joydev->abspam,
sizeof(__u8) * ABS_MAX) ? -EFAULT : 0;
case JSIOCSBTNMAP:
if (copy_from_user((__u16 *) arg, joydev->absmap, sizeof(__u16) * (KEY_MAX - BTN_MISC)))
if (copy_from_user(joydev->keypam, (__u16 *) arg, sizeof(__u16) * (KEY_MAX - BTN_MISC)))
return -EFAULT;
for (i = 0; i < KEY_MAX - BTN_MISC; i++); {
for (i = 0; i < joydev->nkey; i++); {
if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC) return -EINVAL;
joydev->keymap[joydev->abspam[i - BTN_MISC]] = i;
joydev->keymap[joydev->keypam[i] - BTN_MISC] = i;
}
return 0;
case JSIOCGBTNMAP:
......@@ -405,15 +406,13 @@ static struct file_operations joydev_fops = {
fasync: joydev_fasync,
};
static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev)
static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
{
struct joydev *joydev;
int i, j, minor;
int i, j, t, minor;
if (!(test_bit(EV_KEY, dev->evbit) && test_bit(EV_ABS, dev->evbit) &&
(test_bit(ABS_X, dev->absbit) || test_bit(ABS_Y, dev->absbit)) &&
(test_bit(BTN_TRIGGER, dev->keybit) || test_bit(BTN_A, dev->keybit)
|| test_bit(BTN_1, dev->keybit)))) return NULL;
if (test_bit(BTN_TOUCH, dev->keybit))
return NULL;
for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
if (minor == JOYDEV_MINORS) {
......@@ -430,12 +429,13 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
joydev->minor = minor;
joydev_table[minor] = joydev;
sprintf(joydev->name, "js%d", minor);
joydev->handle.dev = dev;
joydev->handle.name = joydev->name;
joydev->handle.handler = handler;
joydev->handle.private = joydev;
joydev->exist = 1;
for (i = 0; i < ABS_MAX; i++)
if (test_bit(i, dev->absbit)) {
joydev->absmap[i] = joydev->nabs;
......@@ -467,15 +467,17 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
joydev->corr[i].prec = dev->absfuzz[j];
joydev->corr[i].coef[0] = (dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j];
joydev->corr[i].coef[1] = (dev->absmax[j] + dev->absmin[j]) / 2 + dev->absflat[j];
joydev->corr[i].coef[2] = (1 << 29) / ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]);
joydev->corr[i].coef[3] = (1 << 29) / ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]);
if (!(t = ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j])))
continue;
joydev->corr[i].coef[2] = (1 << 29) / t;
joydev->corr[i].coef[3] = (1 << 29) / t;
joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
}
joydev->devfs = input_register_minor("js%d", minor, JOYDEV_MINOR_BASE);
// printk(KERN_INFO "js%d: Joystick device for input%d\n", minor, dev->number);
joydev->exist = 1;
return &joydev->handle;
}
......@@ -495,12 +497,35 @@ static void joydev_disconnect(struct input_handle *handle)
}
}
static struct input_device_id joydev_ids[] = {
{
flags: INPUT_DEVICE_ID_MATCH_EVBIT,
evbit: { BIT(EV_KEY) | BIT(EV_ABS) },
absbit: { BIT(ABS_X) },
},
{
flags: INPUT_DEVICE_ID_MATCH_EVBIT,
evbit: { BIT(EV_KEY) | BIT(EV_ABS) },
absbit: { BIT(ABS_WHEEL) },
},
{
flags: INPUT_DEVICE_ID_MATCH_EVBIT,
evbit: { BIT(EV_KEY) | BIT(EV_ABS) },
absbit: { BIT(ABS_THROTTLE) },
},
{ }, /* Terminating entry */
};
MODULE_DEVICE_TABLE(input, joydev_ids);
static struct input_handler joydev_handler = {
event: joydev_event,
connect: joydev_connect,
disconnect: joydev_disconnect,
fops: &joydev_fops,
minor: JOYDEV_MINOR_BASE,
name: "joydev",
id_table: joydev_ids,
};
static int __init joydev_init(void)
......
......@@ -641,7 +641,7 @@ static int iforce_upload_periodic(struct iforce* iforce, struct ff_effect* effec
effect->replay.delay,
effect->trigger.button,
effect->trigger.interval,
effect->u.periodic.direction);
effect->direction);
return err;
}
......@@ -680,7 +680,7 @@ static int iforce_upload_constant(struct iforce* iforce, struct ff_effect* effec
effect->replay.delay,
effect->trigger.button,
effect->trigger.interval,
effect->u.constant.direction);
effect->direction);
return err;
}
......@@ -722,7 +722,7 @@ static int iforce_upload_interactive(struct iforce* iforce, struct ff_effect* ef
case 0: /* Only one axis, choose orientation */
mod1 = mod_chunk->start;
mod2 = 0xffff;
direction = effect->u.interactive.direction;
direction = effect->direction;
axes = 0x20;
break;
......
/*
* $Id: keybdev.c,v 1.3 2000/05/28 17:31:36 vojtech Exp $
* $Id: keybdev.c,v 1.16 2002/01/09 04:21:41 lethal Exp $
*
* Copyright (c) 1999-2000 Vojtech Pavlik
* Copyright (c) 1999-2001 Vojtech Pavlik
*
* Input driver to keyboard driver binding.
*
* Sponsored by SuSE
* Input core to console keyboard binding.
*/
/*
......@@ -24,8 +22,8 @@
* 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@suse.cz>, or by paper mail:
* Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/config.h>
......@@ -37,10 +35,16 @@
#include <linux/module.h>
#include <linux/kbd_kern.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Input core to console keyboard binding");
MODULE_LICENSE("GPL");
char keybdev_name[] = "keyboard";
#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(__alpha__) || \
defined(__mips__) || defined(CONFIG_SPARC64) || defined(CONFIG_SUPERH) || \
defined(CONFIG_PPC) || defined(__mc68000__) || defined(__hppa__) || \
defined(__arm__)
defined(__arm__) || defined(__x86_64__)
static int x86_sysrq_alt = 0;
#ifdef CONFIG_SPARC64
......@@ -48,8 +52,6 @@ static int sparc_l1_a_state = 0;
extern void batten_down_hatches(void);
#endif
static int jp_kbd_109 = 1; /* Yes, .jp is the default. See 51142. */
static unsigned short x86_keycodes[256] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
......@@ -62,7 +64,7 @@ static unsigned short x86_keycodes[256] =
360, 93, 94, 95, 98,376,100,101,357,316,354,304,289,102,351,355,
103,104,105,275,281,272,306,106,274,107,288,364,358,363,362,361,
291,108,381,290,287,292,279,305,280, 99,112,257,258,113,270,114,
118,117,125,374,379,259,260,261,262,263,264,265,266,267,268,269,
118,117,125,374,379,115,112,125,121,123,264,265,266,267,268,269,
271,273,276,277,278,282,283,295,296,297,299,300,301,302,303,307,
308,310,313,314,315,317,318,319,320,321,322,323,324,325,326,330,
332,340,341,342,343,344,345,346,356,359,365,368,369,370,371,372 };
......@@ -167,26 +169,38 @@ void keybdev_ledfunc(unsigned int led)
}
}
/* Tell the user who may be running in X and not see the console that we have
panic'ed. This is to distingush panics from "real" lockups.
Could in theory send the panic message as morse, but that is left as an
exercise for the reader. */
void panic_blink(void)
{
static unsigned long last_jiffie;
static char led;
/* Roughly 1/2s frequency. KDB uses about 1s. Make sure it is different. */
if (jiffies - last_jiffie > HZ/2) {
led ^= 0x01 | 0x04;
keybdev_ledfunc(led);
last_jiffie = jiffies;
}
}
void keybdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int down)
{
if (type != EV_KEY) return;
if (emulate_raw(code, down))
printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", code);
emulate_raw(code, down);
tasklet_schedule(&keyboard_tasklet);
}
static struct input_handle *keybdev_connect(struct input_handler *handler, struct input_dev *dev)
static struct input_handle *keybdev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
{
struct input_handle *handle;
int i;
if (!test_bit(EV_KEY, dev->evbit))
return NULL;
for (i = KEY_RESERVED; i < BTN_MISC; i++)
if (test_bit(i, dev->keybit)) break;
for (i = KEY_ESC; i < BTN_MISC; i++)
if (test_bit(i, dev->keybit))
break;
if (i == BTN_MISC)
return NULL;
......@@ -196,41 +210,42 @@ static struct input_handle *keybdev_connect(struct input_handler *handler, struc
memset(handle, 0, sizeof(struct input_handle));
handle->dev = dev;
handle->name = keybdev_name;
handle->handler = handler;
input_open_device(handle);
// printk(KERN_INFO "keybdev.c: Adding keyboard: input%d\n", dev->number);
return handle;
}
static void keybdev_disconnect(struct input_handle *handle)
{
// printk(KERN_INFO "keybdev.c: Removing keyboard: input%d\n", handle->dev->number);
input_close_device(handle);
kfree(handle);
}
static struct input_device_id keybdev_ids[] = {
{
flags: INPUT_DEVICE_ID_MATCH_EVBIT,
evbit: { BIT(EV_KEY) },
},
{ }, /* Terminating entry */
};
MODULE_DEVICE_TABLE(input, keybdev_ids);
static struct input_handler keybdev_handler = {
event: keybdev_event,
connect: keybdev_connect,
disconnect: keybdev_disconnect,
name: "keybdev",
id_table: keybdev_ids,
};
static int __init keybdev_init(void)
{
input_register_handler(&keybdev_handler);
kbd_ledfunc = keybdev_ledfunc;
if (jp_kbd_109) {
x86_keycodes[0xb5] = 0x73; /* backslash, underscore */
x86_keycodes[0xb6] = 0x70;
x86_keycodes[0xb7] = 0x7d; /* Yen, pipe */
x86_keycodes[0xb8] = 0x79;
x86_keycodes[0xb9] = 0x7b;
}
return 0;
}
......@@ -243,7 +258,3 @@ static void __exit keybdev_exit(void)
module_init(keybdev_init);
module_exit(keybdev_exit);
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("Input driver to keyboard driver binding");
MODULE_PARM(jp_kbd_109, "i");
MODULE_LICENSE("GPL");
/*
* $Id: mousedev.c,v 1.24 2000/11/15 10:57:45 vojtech Exp $
* $Id: mousedev.c,v 1.38 2001/12/26 21:08:33 jsimmons Exp $
*
* Copyright (c) 1999-2000 Vojtech Pavlik
* Copyright (c) 1999-2001 Vojtech Pavlik
*
* Input driver to ImExPS/2 device driver module.
*
* Sponsored by SuSE
* Input driver to ExplorerPS/2 device driver module.
*/
/*
......@@ -24,8 +22,8 @@
* 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@suse.cz>, or by paper mail:
* Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#define MOUSEDEV_MINOR_BASE 32
......@@ -41,6 +39,10 @@
#include <linux/smp_lock.h>
#include <linux/random.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Mouse (ExplorerPS/2) device interfaces");
MODULE_LICENSE("GPL");
#ifndef CONFIG_INPUT_MOUSEDEV_SCREEN_X
#define CONFIG_INPUT_MOUSEDEV_SCREEN_X 1024
#endif
......@@ -52,6 +54,7 @@ struct mousedev {
int exist;
int open;
int minor;
char name[16];
wait_queue_head_t wait;
struct mousedev_list *list;
struct input_handle handle;
......@@ -89,8 +92,6 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
struct mousedev_list *list;
int index, size;
add_mouse_randomness((type << 4) ^ code ^ (code >> 4) ^ value);
while (*mousedev) {
list = (*mousedev)->list;
while (list) {
......@@ -101,13 +102,23 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
switch (code) {
case ABS_X:
size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X];
list->dx += (value * xres - list->oldx) / size;
list->oldx += list->dx * size;
if (size != 0) {
list->dx += (value * xres - list->oldx) / size;
list->oldx += list->dx * size;
} else {
list->dx += value - list->oldx;
list->oldx += list->dx;
}
break;
case ABS_Y:
size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y];
list->dy -= (value * yres - list->oldy) / size;
list->oldy -= list->dy * size;
if (size != 0) {
list->dy -= (value * yres - list->oldy) / size;
list->oldy -= list->dy * size;
} else {
list->dy -= value - list->oldy;
list->oldy -= list->dy;
}
break;
}
break;
......@@ -169,7 +180,7 @@ static int mousedev_release(struct inode * inode, struct file * file)
{
struct mousedev_list *list = file->private_data;
struct mousedev_list **listptr;
listptr = &list->mousedev->list;
mousedev_fasync(-1, file, 0);
......@@ -344,7 +355,7 @@ static ssize_t mousedev_read(struct file * file, char * buffer, size_t count, lo
if (!list->ready && !list->buffer) {
add_wait_queue(&list->mousedev->wait, &wait);
current->state = TASK_INTERRUPTIBLE;
set_current_state(TASK_INTERRUPTIBLE);
while (!list->ready) {
......@@ -360,7 +371,7 @@ static ssize_t mousedev_read(struct file * file, char * buffer, size_t count, lo
schedule();
}
current->state = TASK_RUNNING;
set_current_state(TASK_RUNNING);
remove_wait_queue(&list->mousedev->wait, &wait);
}
......@@ -401,19 +412,11 @@ struct file_operations mousedev_fops = {
fasync: mousedev_fasync,
};
static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev)
static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
{
struct mousedev *mousedev;
int minor = 0;
if (!test_bit(EV_KEY, dev->evbit) ||
(!test_bit(BTN_LEFT, dev->keybit) && !test_bit(BTN_TOUCH, dev->keybit)))
return NULL;
if ((!test_bit(EV_REL, dev->evbit) || !test_bit(REL_X, dev->relbit)) &&
(!test_bit(EV_ABS, dev->evbit) || !test_bit(ABS_X, dev->absbit)))
return NULL;
for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
if (minor == MOUSEDEV_MINORS) {
printk(KERN_ERR "mousedev: no more free mousedev devices\n");
......@@ -425,11 +428,12 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru
memset(mousedev, 0, sizeof(struct mousedev));
init_waitqueue_head(&mousedev->wait);
mousedev->exist = 1;
mousedev->minor = minor;
mousedev_table[minor] = mousedev;
sprintf(mousedev->name, "mouse%d", minor);
mousedev->handle.dev = dev;
mousedev->handle.name = mousedev->name;
mousedev->handle.handler = handler;
mousedev->handle.private = mousedev;
......@@ -438,7 +442,7 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru
if (mousedev_mix.open)
input_open_device(&mousedev->handle);
// printk(KERN_INFO "mouse%d: PS/2 mouse device for input%d\n", minor, dev->number);
mousedev->exist = 1;
return &mousedev->handle;
}
......@@ -459,6 +463,26 @@ static void mousedev_disconnect(struct input_handle *handle)
kfree(mousedev);
}
}
static struct input_device_id mousedev_ids[] = {
{
flags: INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT,
evbit: { BIT(EV_KEY) | BIT(EV_REL) },
keybit: { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) },
relbit: { BIT(REL_X) | BIT(REL_Y) },
}, /* A mouse like device, at least one button, two relative axes */
{
flags: INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
evbit: { BIT(EV_KEY) | BIT(EV_ABS) },
keybit: { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
absbit: { BIT(ABS_X) | BIT(ABS_Y) },
}, /* A tablet like device, at least touch detection, two absolute axes */
{ }, /* Terminating entry */
};
MODULE_DEVICE_TABLE(input, mousedev_ids);
static struct input_handler mousedev_handler = {
event: mousedev_event,
......@@ -466,6 +490,8 @@ static struct input_handler mousedev_handler = {
disconnect: mousedev_disconnect,
fops: &mousedev_fops,
minor: MOUSEDEV_MINOR_BASE,
name: "mousedev",
id_table: mousedev_ids,
};
static int __init mousedev_init(void)
......@@ -493,10 +519,6 @@ static void __exit mousedev_exit(void)
module_init(mousedev_init);
module_exit(mousedev_exit);
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("Input driver to PS/2 or ImPS/2 device driver");
MODULE_LICENSE("GPL");
MODULE_PARM(xres, "i");
MODULE_PARM_DESC(xres, "Horizontal screen resolution");
MODULE_PARM(yres, "i");
......
......@@ -2,11 +2,9 @@
#define _GAMEPORT_H
/*
* $Id: gameport.h,v 1.11 2001/04/26 10:24:46 vojtech Exp $
* $Id: gameport.h,v 1.20 2002/01/03 08:55:05 vojtech Exp $
*
* Copyright (c) 1999-2000 Vojtech Pavlik
*
* Sponsored by SuSE
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
/*
......@@ -26,21 +24,27 @@
*
* 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, Ucitelska 1576, Prague 8, 182 00 Czech Republic
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/sched.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <linux/input.h>
struct gameport;
struct gameport {
void *private;
void *private; /* Private pointer for joystick drivers */
void *driver; /* Private pointer for gameport drivers */
char *name;
char *phys;
int number;
unsigned short idbus;
unsigned short idvendor;
unsigned short idproduct;
unsigned short idversion;
int io;
int speed;
int fuzz;
......@@ -59,6 +63,7 @@ struct gameport {
struct gameport_dev {
void *private;
char *name;
void (*connect)(struct gameport *, struct gameport_dev *dev);
void (*disconnect)(struct gameport *);
......@@ -74,8 +79,8 @@ void gameport_rescan(struct gameport *gameport);
void gameport_register_port(struct gameport *gameport);
void gameport_unregister_port(struct gameport *gameport);
#else
static void __inline__ gameport_register_port(struct gameport *gameport) { return; }
static void __inline__ gameport_unregister_port(struct gameport *gameport) { return; }
void __inline__ gameport_register_port(struct gameport *gameport) { return; }
void __inline__ gameport_unregister_port(struct gameport *gameport) { return; }
#endif
void gameport_register_device(struct gameport_dev *dev);
......@@ -94,6 +99,7 @@ void gameport_unregister_device(struct gameport_dev *dev);
#define GAMEPORT_ID_VENDOR_MICROSOFT 0x0007
#define GAMEPORT_ID_VENDOR_THRUSTMASTER 0x0008
#define GAMEPORT_ID_VENDOR_GRAVIS 0x0009
#define GAMEPORT_ID_VENDOR_GUILLEMOT 0x000a
static __inline__ void gameport_trigger(struct gameport *gameport)
{
......@@ -134,7 +140,7 @@ static __inline__ int gameport_time(struct gameport *gameport, int time)
static __inline__ void wait_ms(unsigned int ms)
{
current->state = TASK_UNINTERRUPTIBLE;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1 + ms * HZ / 1000);
}
......
This diff is collapsed.
......@@ -2,31 +2,29 @@
#define _SERIO_H
/*
* $Id: serio.h,v 1.11 2001/05/29 02:58:50 jsimmons Exp $
* $Id: serio.h,v 1.21 2001/12/19 05:15:21 skids Exp $
*
* Copyright (C) 1999 Vojtech Pavlik
*
* Sponsored by SuSE
* Copyright (C) 1999-2001 Vojtech Pavlik
*/
/*
* 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
* 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, Ucitelska 1576, Prague 8, 182 00 Czech Republic
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
/*
......@@ -42,23 +40,31 @@ struct serio {
void *private;
void *driver;
char *name;
char *phys;
int number;
unsigned short idbus;
unsigned short idvendor;
unsigned short idproduct;
unsigned short idversion;
unsigned long type;
int number;
int (*write)(struct serio *, unsigned char);
int (*open)(struct serio *);
void (*close)(struct serio *);
struct serio_dev *dev;
struct serio *next;
};
struct serio_dev {
void *private;
char *name;
void (*write_wakeup)(struct serio *);
void (*interrupt)(struct serio *, unsigned char, unsigned int);
void (*connect)(struct serio *, struct serio_dev *dev);
void (*disconnect)(struct serio *);
......@@ -80,6 +86,13 @@ static __inline__ int serio_write(struct serio *serio, unsigned char data)
return serio->write(serio, data);
}
static __inline__ void serio_dev_write_wakeup(struct serio *serio)
{
if (serio->dev && serio->dev->write_wakeup) {
serio->dev->write_wakeup(serio);
}
}
#define SERIO_TIMEOUT 1
#define SERIO_PARITY 2
......@@ -87,6 +100,7 @@ static __inline__ int serio_write(struct serio *serio, unsigned char data)
#define SERIO_XT 0x00000000UL
#define SERIO_8042 0x01000000UL
#define SERIO_RS232 0x02000000UL
#define SERIO_HIL_MLC 0x03000000UL
#define SERIO_PROTO 0xFFUL
#define SERIO_MSC 0x01
......@@ -108,6 +122,9 @@ static __inline__ int serio_write(struct serio *serio, unsigned char data)
#define SERIO_STOWAWAY 0x20
#define SERIO_H3600 0x21
#define SERIO_PS2SER 0x22
#define SERIO_TWIDKBD 0x23
#define SERIO_TWIDJOY 0x24
#define SERIO_HIL 0x25
#define SERIO_ID 0xff00UL
#define SERIO_EXTRA 0xff0000UL
......
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