Commit a9e078f4 authored by Vojtech Pavlik's avatar Vojtech Pavlik

Merge suse.cz:/home/vojtech/bk/linus into suse.cz:/home/vojtech/bk/input

parents 07f0a148 7c5241b3
......@@ -335,6 +335,7 @@ controller (compatible with DirectPadPro):
* Analog PSX Pad (red mode)
* Analog PSX Pad (green mode)
* PSX Rumble Pad
* PSX DDR Pad
2.4 Sega
~~~~~~~~
......@@ -452,14 +453,22 @@ uses the following kernel/module command line:
5 | Multisystem 2-button joystick
6 | N64 pad
7 | Sony PSX controller
8 | Sony PSX DDR controller
The exact type of the PSX controller type is autoprobed, so you must have
your controller plugged in before initializing.
The exact type of the PSX controller type is autoprobed when used so
hot swapping should work (but is not recomended).
Should you want to use more than one of parallel ports at once, you can use
gamecon.map2 and gamecon.map3 as additional command line parameters for two
more parallel ports.
There are two options specific to PSX driver portion. gamecon.psx_delay sets
the command delay when talking to the controllers. The default of 25 should
work but you can try lowering it for better performace. If your pads don't
respond try raising it untill they work. Setting the type to 8 allows the
driver to be used with Dance Dance Revolution or similar games. Arrow keys are
registered as key presses instead of X and Y axes.
3.2 db9.c
~~~~~~~~~
Apart from making an interface, there is nothing difficult on using the
......
......@@ -650,6 +650,12 @@ running once the system is up.
mga= [HW,DRM]
mousedev.tap_time=
[MOUSE] Maximum time between finger touching and
leaving touchpad surface for touch to be considered
a tap and be reported as a left button click (for
touchpads working in absolute mode only).
Format: <msecs>
mousedev.xres= [MOUSE] Horizontal screen resolution, used for devices
reporting absolute coordinates, such as tablets
mousedev.yres= [MOUSE] Vertical screen resolution, used for devices
......
......@@ -37,9 +37,9 @@ obj-$(CONFIG_PARIDE) += block/paride/
obj-$(CONFIG_TC) += tc/
obj-$(CONFIG_USB) += usb/
obj-$(CONFIG_USB_GADGET) += usb/gadget/
obj-$(CONFIG_SERIO) += input/serio/
obj-$(CONFIG_INPUT) += input/
obj-$(CONFIG_GAMEPORT) += input/gameport/
obj-$(CONFIG_SERIO) += input/serio/
obj-$(CONFIG_I2O) += message/
obj-$(CONFIG_I2C) += i2c/
obj-$(CONFIG_PHONE) += telephony/
......
......@@ -123,7 +123,7 @@ int shift_state = 0;
*/
static struct input_handler kbd_handler;
static unsigned long key_down[256/BITS_PER_LONG]; /* keyboard key bitmap */
static unsigned long key_down[NBITS(KEY_MAX)]; /* keyboard key bitmap */
static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */
static int dead_key_next;
static int npadch = -1; /* -1 or number assembled on pad */
......@@ -142,7 +142,7 @@ static struct ledptr {
/* Simple translation table for the SysRq keys */
#ifdef CONFIG_MAGIC_SYSRQ
unsigned char kbd_sysrq_xlate[128] =
unsigned char kbd_sysrq_xlate[KEY_MAX] =
"\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
"qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
"dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
......@@ -941,6 +941,9 @@ void kbd_refresh_leds(struct input_handle *handle)
#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64) || defined(CONFIG_PARISC) || defined(CONFIG_SUPERH)
#define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\
((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001))
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,
......@@ -1007,6 +1010,8 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode,
#else
#define HW_RAW(dev) 0
#warning "Cannot generate rawmode keyboard for your architecture yet."
static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag)
......@@ -1019,7 +1024,15 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char u
}
#endif
void kbd_keycode(unsigned int keycode, int down, struct pt_regs *regs)
void kbd_rawcode(unsigned char data)
{
struct vc_data *vc = vc_cons[fg_console].d;
kbd = kbd_table + fg_console;
if (kbd->kbdmode == VC_RAW)
put_queue(vc, data);
}
void kbd_keycode(unsigned int keycode, int down, int hw_raw, struct pt_regs *regs)
{
struct vc_data *vc = vc_cons[fg_console].d;
unsigned short keysym, *key_map;
......@@ -1053,7 +1066,7 @@ void kbd_keycode(unsigned int keycode, int down, struct pt_regs *regs)
return;
#endif /* CONFIG_MAC_EMUMOUSEBTN */
if ((raw_mode = (kbd->kbdmode == VC_RAW)))
if ((raw_mode = (kbd->kbdmode == VC_RAW)) && !hw_raw)
if (emulate_raw(vc, keycode, !down << 7))
if (keycode < BTN_MISC)
printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode);
......@@ -1119,6 +1132,9 @@ void kbd_keycode(unsigned int keycode, int down, struct pt_regs *regs)
return;
}
if (keycode > NR_KEYS)
return;
keysym = key_map[keycode];
type = KTYP(keysym);
......@@ -1148,11 +1164,12 @@ void kbd_keycode(unsigned int keycode, int down, struct pt_regs *regs)
}
static void kbd_event(struct input_handle *handle, unsigned int event_type,
unsigned int keycode, int down)
unsigned int event_code, int value)
{
if (event_type != EV_KEY)
return;
kbd_keycode(keycode, down, handle->dev->regs);
if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev))
kbd_rawcode(value);
if (event_type == EV_KEY)
kbd_keycode(event_code, value, HW_RAW(handle->dev), handle->dev->regs);
tasklet_schedule(&keyboard_tasklet);
do_poke_blanked_console = 1;
schedule_console_callback();
......
......@@ -50,8 +50,11 @@ struct emu {
};
static struct pci_device_id emu_tbl[] = {
{ 0x1102, 0x7002, PCI_ANY_ID, PCI_ANY_ID }, /* SB Live gameport */
{ 0x1102, 0x7003, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy gameport */
{ 0x1102, 0x7004, PCI_ANY_ID, PCI_ANY_ID }, /* Dell SB Live */
{ 0x1102, 0x7005, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy LS gameport */
{ 0, }
};
......
......@@ -247,7 +247,7 @@ config JOYSTICK_AMIGA
To compile this driver as a module, choose M here: the
module will be called amijoy.
config INPUT_JOYDUMP
config JOYSTICK_JOYDUMP
tristate "Gameport data dumper"
depends on INPUT && INPUT_JOYSTICK
help
......
/*
* $Id: gamecon.c,v 1.22 2002/07/01 15:42:25 vojtech Exp $
* NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux
*
* Copyright (c) 1999-2001 Vojtech Pavlik
* Copyright (c) 1999-2004 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (c) 2004 Peter Nelson <rufus-kernel@hackish.org>
*
* Based on the work of:
* Andree Borrmann John Dahlstrom
* David Kuder Nathan Hand
*/
/*
* NES, SNES, N64, MultiSystem, PSX gamepad 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
......@@ -72,8 +69,9 @@ __obsolete_setup("gc_3=");
#define GC_MULTI2 5
#define GC_N64 6
#define GC_PSX 7
#define GC_DDR 8
#define GC_MAX 7
#define GC_MAX 8
#define GC_REFRESH_TIME HZ/100
......@@ -91,7 +89,8 @@ static struct gc *gc_base[3];
static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 };
static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick",
"Multisystem 2-button joystick", "N64 controller", "PSX controller" };
"Multisystem 2-button joystick", "N64 controller", "PSX controller"
"PSX DDR controller" };
/*
* N64 support.
*/
......@@ -237,7 +236,7 @@ static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data)
#define GC_PSX_RUMBLE 7 /* Rumble in Red mode */
#define GC_PSX_CLOCK 0x04 /* Pin 4 */
#define GC_PSX_COMMAND 0x01 /* Pin 1 */
#define GC_PSX_COMMAND 0x01 /* Pin 2 */
#define GC_PSX_POWER 0xf8 /* Pins 5-9 */
#define GC_PSX_SELECT 0x02 /* Pin 3 */
......@@ -253,25 +252,29 @@ __obsolete_setup("gc_psx_delay=");
static short gc_psx_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_HAT0X, ABS_HAT0Y };
static short gc_psx_btn[] = { BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_A, BTN_B, BTN_X, BTN_Y,
BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR };
static short gc_psx_ddr_btn[] = { BTN_0, BTN_1, BTN_2, BTN_3 };
/*
* gc_psx_command() writes 8bit command and reads 8bit data from
* the psx pad.
*/
static int gc_psx_command(struct gc *gc, int b)
static void gc_psx_command(struct gc *gc, int b, unsigned char data[GC_PSX_LENGTH])
{
int i, cmd, data = 0;
int i, j, cmd, read;
for (i = 0; i < 5; i++)
data[i] = 0;
for (i = 0; i < 8; i++, b >>= 1) {
cmd = (b & 1) ? GC_PSX_COMMAND : 0;
parport_write_data(gc->pd->port, cmd | GC_PSX_POWER);
udelay(gc_psx_delay);
data |= ((parport_read_status(gc->pd->port) ^ 0x80) & gc->pads[GC_PSX]) ? (1 << i) : 0;
read = parport_read_status(gc->pd->port) ^ 0x80;
for (j = 0; j < 5; j++)
data[j] |= (read & gc_status_bit[j] & gc->pads[GC_PSX]) ? (1 << i) : 0;
parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER);
udelay(gc_psx_delay);
}
return data;
}
/*
......@@ -279,30 +282,39 @@ static int gc_psx_command(struct gc *gc, int b)
* device identifier code.
*/
static int gc_psx_read_packet(struct gc *gc, unsigned char *data)
static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_LENGTH], unsigned char id[5])
{
int i, id;
int i, j, max_len = 0;
unsigned long flags;
unsigned char data2[5];
parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); /* Select pad */
udelay(gc_psx_delay * 2);
udelay(gc_psx_delay);
parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_POWER); /* Deselect, begin command */
udelay(gc_psx_delay * 2);
udelay(gc_psx_delay);
local_irq_save(flags);
gc_psx_command(gc, 0x01); /* Access pad */
id = gc_psx_command(gc, 0x42); /* Get device id */
if (gc_psx_command(gc, 0) == 0x5a) { /* Okay? */
for (i = 0; i < GC_PSX_LEN(id) * 2; i++)
data[i] = gc_psx_command(gc, 0);
} else id = 0;
gc_psx_command(gc, 0x01, data2); /* Access pad */
gc_psx_command(gc, 0x42, id); /* Get device ids */
gc_psx_command(gc, 0, data2); /* Dump status */
for (i =0; i < 5; i++) /* Find the longest pad */
if((gc_status_bit[i] & gc->pads[GC_PSX]) && (GC_PSX_LEN(id[i]) > max_len))
max_len = GC_PSX_LEN(id[i]);
for (i = 0; i < max_len * 2; i++) { /* Read in all the data */
gc_psx_command(gc, 0, data2);
for (j = 0; j < 5; j++)
data[j][i] = data2[j];
}
local_irq_restore(flags);
parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);
return GC_PSX_ID(id);
for(i = 0; i < 5; i++) /* Set id's to the real value */
id[i] = GC_PSX_ID(id[i]);
}
/*
......@@ -316,6 +328,7 @@ static void gc_timer(unsigned long private)
struct gc *gc = (void *) private;
struct input_dev *dev = gc->dev;
unsigned char data[GC_MAX_LENGTH];
unsigned char data_psx[5][GC_PSX_LENGTH];
int i, j, s;
/*
......@@ -412,53 +425,72 @@ static void gc_timer(unsigned long private)
* PSX controllers
*/
if (gc->pads[GC_PSX]) {
if (gc->pads[GC_PSX] || gc->pads[GC_DDR]) {
for (i = 0; i < 5; i++)
if (gc->pads[GC_PSX] & gc_status_bit[i])
break;
gc_psx_read_packet(gc, data_psx, data);
switch (gc_psx_read_packet(gc, data)) {
for (i = 0; i < 5; i++) {
switch (data[i]) {
case GC_PSX_RUMBLE:
input_report_key(dev + i, BTN_THUMBL, ~data[0] & 0x04);
input_report_key(dev + i, BTN_THUMBR, ~data[0] & 0x02);
input_sync(dev + i);
input_report_key(dev + i, BTN_THUMBL, ~data_psx[i][0] & 0x04);
input_report_key(dev + i, BTN_THUMBR, ~data_psx[i][0] & 0x02);
case GC_PSX_NEGCON:
case GC_PSX_ANALOG:
if(gc->pads[GC_DDR] & gc_status_bit[i]) {
for(j = 0; j < 4; j++)
input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
} else {
for (j = 0; j < 4; j++)
input_report_abs(dev + i, gc_psx_abs[j], data[j + 2]);
input_report_abs(dev + i, gc_psx_abs[j+2], data_psx[i][j + 2]);
input_report_abs(dev + i, ABS_HAT0X, !(data[0] & 0x20) - !(data[0] & 0x80));
input_report_abs(dev + i, ABS_HAT0Y, !(data[0] & 0x40) - !(data[0] & 0x10));
input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
}
for (j = 0; j < 8; j++)
input_report_key(dev + i, gc_psx_btn[j], ~data[1] & (1 << j));
input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
input_report_key(dev + i, BTN_START, ~data[0] & 0x08);
input_report_key(dev + i, BTN_SELECT, ~data[0] & 0x01);
input_report_key(dev + i, BTN_START, ~data_psx[i][0] & 0x08);
input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01);
input_sync(dev + i);
break;
case GC_PSX_NORMAL:
input_report_abs(dev + i, ABS_X, 128 + !(data[0] & 0x20) * 127 - !(data[0] & 0x80) * 128);
input_report_abs(dev + i, ABS_Y, 128 + !(data[0] & 0x40) * 127 - !(data[0] & 0x10) * 128);
if(gc->pads[GC_DDR] & gc_status_bit[i]) {
for(j = 0; j < 4; j++)
input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
} else {
input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
/* for some reason if the extra axes are left unset they drift */
/* for (j = 0; j < 4; j++)
input_report_abs(dev + i, gc_psx_abs[j+2], 128);
* This needs to be debugged properly,
* maybe fuzz processing needs to be done in input_sync()
* --vojtech
*/
}
for (j = 0; j < 8; j++)
input_report_key(dev + i, gc_psx_btn[j], ~data[1] & (1 << j));
input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
input_report_key(dev + i, BTN_START, ~data[0] & 0x08);
input_report_key(dev + i, BTN_SELECT, ~data[0] & 0x01);
input_report_key(dev + i, BTN_START, ~data_psx[i][0] & 0x08);
input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01);
input_sync(dev + i);
break;
case 0: /* not a pad, ignore */
break;
}
}
}
......@@ -490,8 +522,7 @@ static struct gc __init *gc_probe(int *config, int nargs)
{
struct gc *gc;
struct parport *pp;
int i, j, psx;
unsigned char data[32];
int i, j;
if (config[0] < 0)
return NULL;
......@@ -588,25 +619,16 @@ static struct gc __init *gc_probe(int *config, int nargs)
break;
case GC_PSX:
psx = gc_psx_read_packet(gc, data);
switch(psx) {
case GC_PSX_NEGCON:
case GC_PSX_NORMAL:
case GC_PSX_ANALOG:
case GC_PSX_RUMBLE:
for (j = 0; j < 6; j++) {
psx = gc_psx_abs[j];
set_bit(psx, gc->dev[i].absbit);
if (j < 4) {
gc->dev[i].absmin[psx] = 4;
gc->dev[i].absmax[psx] = 252;
gc->dev[i].absflat[psx] = 2;
case GC_DDR:
if(config[i + 1] == GC_DDR) {
for (j = 0; j < 4; j++)
set_bit(gc_psx_ddr_btn[j], gc->dev[i].keybit);
} else {
gc->dev[i].absmin[psx] = -1;
gc->dev[i].absmax[psx] = 1;
for (j = 0; j < 6; j++) {
set_bit(gc_psx_abs[j], gc->dev[i].absbit);
gc->dev[i].absmin[gc_psx_abs[j]] = 4;
gc->dev[i].absmax[gc_psx_abs[j]] = 252;
gc->dev[i].absflat[gc_psx_abs[j]] = 2;
}
}
......@@ -614,18 +636,6 @@ static struct gc __init *gc_probe(int *config, int nargs)
set_bit(gc_psx_btn[j], gc->dev[i].keybit);
break;
case 0:
gc->pads[GC_PSX] &= ~gc_status_bit[i];
printk(KERN_ERR "gamecon.c: No PSX controller found.\n");
break;
default:
gc->pads[GC_PSX] &= ~gc_status_bit[i];
printk(KERN_WARNING "gamecon.c: Unsupported PSX controller %#x,"
" please report to <vojtech@ucw.cz>.\n", psx);
}
break;
}
sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i);
......
......@@ -524,7 +524,7 @@ static int __init iforce_init(void)
usb_register(&iforce_usb_driver);
#endif
#ifdef CONFIG_JOYSTICK_IFORCE_232
serio_register_device(&iforce_serio_dev);
serio_register_driver(&iforce_serio_drv);
#endif
return 0;
}
......@@ -535,7 +535,7 @@ static void __exit iforce_exit(void)
usb_deregister(&iforce_usb_driver);
#endif
#ifdef CONFIG_JOYSTICK_IFORCE_232
serio_unregister_device(&iforce_serio_dev);
serio_unregister_driver(&iforce_serio_drv);
#endif
}
......
......@@ -124,7 +124,7 @@ static irqreturn_t iforce_serio_irq(struct serio *serio,
return IRQ_HANDLED;
}
static void iforce_serio_connect(struct serio *serio, struct serio_dev *dev)
static void iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
{
struct iforce *iforce;
if (serio->type != (SERIO_RS232 | SERIO_IFORCE))
......@@ -137,7 +137,7 @@ static void iforce_serio_connect(struct serio *serio, struct serio_dev *dev)
iforce->serio = serio;
serio->private = iforce;
if (serio_open(serio, dev)) {
if (serio_open(serio, drv)) {
kfree(iforce);
return;
}
......@@ -158,7 +158,11 @@ static void iforce_serio_disconnect(struct serio *serio)
kfree(iforce);
}
struct serio_dev iforce_serio_dev = {
struct serio_driver iforce_serio_drv = {
.driver = {
.name = "iforce",
},
.description = "RS232 I-Force joysticks and wheels driver",
.write_wakeup = iforce_serio_write_wakeup,
.interrupt = iforce_serio_irq,
.connect = iforce_serio_connect,
......
......@@ -187,5 +187,5 @@ int iforce_upload_constant(struct iforce*, struct ff_effect*, int is_update);
int iforce_upload_condition(struct iforce*, struct ff_effect*, int is_update);
/* Public variables */
extern struct serio_dev iforce_serio_dev;
extern struct serio_driver iforce_serio_drv;
extern struct usb_driver iforce_usb_driver;
......@@ -35,8 +35,10 @@
#include <linux/serio.h>
#include <linux/init.h>
#define DRIVER_DESC "Magellan and SpaceMouse 6dof controller driver"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Magellan and SpaceMouse 6dof controller driver");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
/*
......@@ -146,7 +148,7 @@ static void magellan_disconnect(struct serio *serio)
* it as an input device.
*/
static void magellan_connect(struct serio *serio, struct serio_dev *dev)
static void magellan_connect(struct serio *serio, struct serio_driver *drv)
{
struct magellan *magellan;
int i, t;
......@@ -184,7 +186,7 @@ static void magellan_connect(struct serio *serio, struct serio_dev *dev)
serio->private = magellan;
if (serio_open(serio, dev)) {
if (serio_open(serio, drv)) {
kfree(magellan);
return;
}
......@@ -199,7 +201,11 @@ static void magellan_connect(struct serio *serio, struct serio_dev *dev)
* The serio device structure.
*/
static struct serio_dev magellan_dev = {
static struct serio_driver magellan_drv = {
.driver = {
.name = "magellan",
},
.description = DRIVER_DESC,
.interrupt = magellan_interrupt,
.connect = magellan_connect,
.disconnect = magellan_disconnect,
......@@ -211,13 +217,13 @@ static struct serio_dev magellan_dev = {
int __init magellan_init(void)
{
serio_register_device(&magellan_dev);
serio_register_driver(&magellan_drv);
return 0;
}
void __exit magellan_exit(void)
{
serio_unregister_device(&magellan_dev);
serio_unregister_driver(&magellan_drv);
}
module_init(magellan_init);
......
......@@ -39,8 +39,10 @@
#include <linux/input.h>
#include <linux/serio.h>
#define DRIVER_DESC "SpaceTec SpaceBall 2003/3003/4000 FLX driver"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("SpaceTec SpaceBall 2003/3003/4000 FLX driver");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
/*
......@@ -201,7 +203,7 @@ static void spaceball_disconnect(struct serio *serio)
* it as an input device.
*/
static void spaceball_connect(struct serio *serio, struct serio_dev *dev)
static void spaceball_connect(struct serio *serio, struct serio_driver *drv)
{
struct spaceball *spaceball;
int i, t, id;
......@@ -254,7 +256,7 @@ static void spaceball_connect(struct serio *serio, struct serio_dev *dev)
serio->private = spaceball;
if (serio_open(serio, dev)) {
if (serio_open(serio, drv)) {
kfree(spaceball);
return;
}
......@@ -269,7 +271,11 @@ static void spaceball_connect(struct serio *serio, struct serio_dev *dev)
* The serio device structure.
*/
static struct serio_dev spaceball_dev = {
static struct serio_driver spaceball_drv = {
.driver = {
.name = "spaceball",
},
.description = DRIVER_DESC,
.interrupt = spaceball_interrupt,
.connect = spaceball_connect,
.disconnect = spaceball_disconnect,
......@@ -281,13 +287,13 @@ static struct serio_dev spaceball_dev = {
int __init spaceball_init(void)
{
serio_register_device(&spaceball_dev);
serio_register_driver(&spaceball_drv);
return 0;
}
void __exit spaceball_exit(void)
{
serio_unregister_device(&spaceball_dev);
serio_unregister_driver(&spaceball_drv);
}
module_init(spaceball_init);
......
......@@ -38,8 +38,10 @@
#include <linux/input.h>
#include <linux/serio.h>
#define DRIVER_DESC "SpaceTec SpaceOrb 360 and Avenger 6dof controller driver"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("SpaceTec SpaceOrb 360 and Avenger 6dof controller driver");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
/*
......@@ -162,7 +164,7 @@ static void spaceorb_disconnect(struct serio *serio)
* it as an input device.
*/
static void spaceorb_connect(struct serio *serio, struct serio_dev *dev)
static void spaceorb_connect(struct serio *serio, struct serio_driver *drv)
{
struct spaceorb *spaceorb;
int i, t;
......@@ -201,7 +203,7 @@ static void spaceorb_connect(struct serio *serio, struct serio_dev *dev)
serio->private = spaceorb;
if (serio_open(serio, dev)) {
if (serio_open(serio, drv)) {
kfree(spaceorb);
return;
}
......@@ -213,7 +215,11 @@ static void spaceorb_connect(struct serio *serio, struct serio_dev *dev)
* The serio device structure.
*/
static struct serio_dev spaceorb_dev = {
static struct serio_driver spaceorb_drv = {
.driver = {
.name = "spaceorb",
},
.description = DRIVER_DESC,
.interrupt = spaceorb_interrupt,
.connect = spaceorb_connect,
.disconnect = spaceorb_disconnect,
......@@ -225,13 +231,13 @@ static struct serio_dev spaceorb_dev = {
int __init spaceorb_init(void)
{
serio_register_device(&spaceorb_dev);
serio_register_driver(&spaceorb_drv);
return 0;
}
void __exit spaceorb_exit(void)
{
serio_unregister_device(&spaceorb_dev);
serio_unregister_driver(&spaceorb_drv);
}
module_init(spaceorb_init);
......
......@@ -36,8 +36,10 @@
#include <linux/serio.h>
#include <linux/init.h>
#define DRIVER_DESC "Gravis Stinger gamepad driver"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Gravis Stinger gamepad driver");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
/*
......@@ -134,7 +136,7 @@ static void stinger_disconnect(struct serio *serio)
* it as an input device.
*/
static void stinger_connect(struct serio *serio, struct serio_dev *dev)
static void stinger_connect(struct serio *serio, struct serio_driver *drv)
{
struct stinger *stinger;
int i;
......@@ -172,7 +174,7 @@ static void stinger_connect(struct serio *serio, struct serio_dev *dev)
stinger->dev.private = stinger;
serio->private = stinger;
if (serio_open(serio, dev)) {
if (serio_open(serio, drv)) {
kfree(stinger);
return;
}
......@@ -187,7 +189,11 @@ static void stinger_connect(struct serio *serio, struct serio_dev *dev)
* The serio device structure.
*/
static struct serio_dev stinger_dev = {
static struct serio_driver stinger_drv = {
.driver = {
.name = "stinger",
},
.description = DRIVER_DESC,
.interrupt = stinger_interrupt,
.connect = stinger_connect,
.disconnect = stinger_disconnect,
......@@ -199,13 +205,13 @@ static struct serio_dev stinger_dev = {
int __init stinger_init(void)
{
serio_register_device(&stinger_dev);
serio_register_driver(&stinger_drv);
return 0;
}
void __exit stinger_exit(void)
{
serio_unregister_device(&stinger_dev);
serio_unregister_driver(&stinger_drv);
}
module_init(stinger_init);
......
......@@ -187,7 +187,7 @@ static void twidjoy_disconnect(struct serio *serio)
* it as an input device.
*/
static void twidjoy_connect(struct serio *serio, struct serio_dev *dev)
static void twidjoy_connect(struct serio *serio, struct serio_driver *drv)
{
struct twidjoy_button_spec *bp;
struct twidjoy *twidjoy;
......@@ -232,7 +232,7 @@ static void twidjoy_connect(struct serio *serio, struct serio_dev *dev)
twidjoy->dev.private = twidjoy;
serio->private = twidjoy;
if (serio_open(serio, dev)) {
if (serio_open(serio, drv)) {
kfree(twidjoy);
return;
}
......@@ -246,7 +246,11 @@ static void twidjoy_connect(struct serio *serio, struct serio_dev *dev)
* The serio device structure.
*/
static struct serio_dev twidjoy_dev = {
static struct serio_driver twidjoy_drv = {
.driver = {
.name = "twidjoy",
},
.description = DRIVER_DESC,
.interrupt = twidjoy_interrupt,
.connect = twidjoy_connect,
.disconnect = twidjoy_disconnect,
......@@ -258,13 +262,13 @@ static struct serio_dev twidjoy_dev = {
int __init twidjoy_init(void)
{
serio_register_device(&twidjoy_dev);
serio_register_driver(&twidjoy_drv);
return 0;
}
void __exit twidjoy_exit(void)
{
serio_unregister_device(&twidjoy_dev);
serio_unregister_driver(&twidjoy_drv);
}
module_init(twidjoy_init);
......
......@@ -35,8 +35,10 @@
#include <linux/serio.h>
#include <linux/init.h>
#define DRIVER_DESC "Logitech WingMan Warrior joystick driver"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Logitech WingMan Warrior joystick driver");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
/*
......@@ -139,7 +141,7 @@ static void warrior_disconnect(struct serio *serio)
* it as an input device.
*/
static void warrior_connect(struct serio *serio, struct serio_dev *dev)
static void warrior_connect(struct serio *serio, struct serio_driver *drv)
{
struct warrior *warrior;
int i;
......@@ -185,7 +187,7 @@ static void warrior_connect(struct serio *serio, struct serio_dev *dev)
serio->private = warrior;
if (serio_open(serio, dev)) {
if (serio_open(serio, drv)) {
kfree(warrior);
return;
}
......@@ -199,7 +201,11 @@ static void warrior_connect(struct serio *serio, struct serio_dev *dev)
* The serio device structure.
*/
static struct serio_dev warrior_dev = {
static struct serio_driver warrior_drv = {
.driver = {
.name = "warrior",
},
.description = DRIVER_DESC,
.interrupt = warrior_interrupt,
.connect = warrior_connect,
.disconnect = warrior_disconnect,
......@@ -211,13 +217,13 @@ static struct serio_dev warrior_dev = {
int __init warrior_init(void)
{
serio_register_device(&warrior_dev);
serio_register_driver(&warrior_drv);
return 0;
}
void __exit warrior_exit(void)
{
serio_unregister_device(&warrior_dev);
serio_unregister_driver(&warrior_drv);
}
module_init(warrior_init);
......
This diff is collapsed.
......@@ -76,8 +76,10 @@
#include <linux/serio.h>
#include <linux/workqueue.h>
#define DRIVER_DESC "LK keyboard driver"
MODULE_AUTHOR ("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
MODULE_DESCRIPTION ("LK keyboard driver");
MODULE_DESCRIPTION (DRIVER_DESC);
MODULE_LICENSE ("GPL");
/*
......@@ -622,7 +624,7 @@ lkkbd_reinit (void *data)
* lkkbd_connect() probes for a LK keyboard and fills the necessary structures.
*/
static void
lkkbd_connect (struct serio *serio, struct serio_dev *dev)
lkkbd_connect (struct serio *serio, struct serio_driver *drv)
{
struct lkkbd *lk;
int i;
......@@ -665,7 +667,7 @@ lkkbd_connect (struct serio *serio, struct serio_dev *dev)
serio->private = lk;
if (serio_open (serio, dev)) {
if (serio_open (serio, drv)) {
kfree (lk);
return;
}
......@@ -703,7 +705,11 @@ lkkbd_disconnect (struct serio *serio)
kfree (lk);
}
static struct serio_dev lkkbd_dev = {
static struct serio_driver lkkbd_drv = {
.driver = {
.name = "lkkbd",
},
.description = DRIVER_DESC,
.connect = lkkbd_connect,
.disconnect = lkkbd_disconnect,
.interrupt = lkkbd_interrupt,
......@@ -715,14 +721,14 @@ static struct serio_dev lkkbd_dev = {
int __init
lkkbd_init (void)
{
serio_register_device (&lkkbd_dev);
serio_register_driver(&lkkbd_drv);
return 0;
}
void __exit
lkkbd_exit (void)
{
serio_unregister_device (&lkkbd_dev);
serio_unregister_driver(&lkkbd_drv);
}
module_init (lkkbd_init);
......
......@@ -32,8 +32,10 @@
#include <linux/init.h>
#include <linux/serio.h>
#define DRIVER_DESC "Newton keyboard driver"
MODULE_AUTHOR("Justin Cormack <j.cormack@doc.ic.ac.uk>");
MODULE_DESCRIPTION("Newton keyboard driver");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
#define NKBD_KEY 0x7f
......@@ -82,7 +84,7 @@ irqreturn_t nkbd_interrupt(struct serio *serio,
}
void nkbd_connect(struct serio *serio, struct serio_dev *dev)
void nkbd_connect(struct serio *serio, struct serio_driver *drv)
{
struct nkbd *nkbd;
int i;
......@@ -106,7 +108,7 @@ void nkbd_connect(struct serio *serio, struct serio_dev *dev)
nkbd->dev.private = nkbd;
serio->private = nkbd;
if (serio_open(serio, dev)) {
if (serio_open(serio, drv)) {
kfree(nkbd);
return;
}
......@@ -138,21 +140,25 @@ void nkbd_disconnect(struct serio *serio)
kfree(nkbd);
}
struct serio_dev nkbd_dev = {
struct serio_driver nkbd_drv = {
.driver = {
.name = "newtonkbd",
},
.description = DRIVER_DESC,
.interrupt = nkbd_interrupt,
.connect = nkbd_connect,
.disconnect = nkbd_disconnect
.disconnect = nkbd_disconnect,
};
int __init nkbd_init(void)
{
serio_register_device(&nkbd_dev);
serio_register_driver(&nkbd_drv);
return 0;
}
void __exit nkbd_exit(void)
{
serio_unregister_device(&nkbd_dev);
serio_unregister_driver(&nkbd_drv);
}
module_init(nkbd_init);
......
......@@ -37,8 +37,10 @@
#include <linux/serio.h>
#include <linux/workqueue.h>
#define DRIVER_DESC "Sun keyboard driver"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Sun keyboard driver");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
static unsigned char sunkbd_keycode[128] = {
......@@ -221,7 +223,7 @@ static void sunkbd_reinit(void *data)
* sunkbd_connect() probes for a Sun keyboard and fills the necessary structures.
*/
static void sunkbd_connect(struct serio *serio, struct serio_dev *dev)
static void sunkbd_connect(struct serio *serio, struct serio_driver *drv)
{
struct sunkbd *sunkbd;
int i;
......@@ -257,7 +259,7 @@ static void sunkbd_connect(struct serio *serio, struct serio_dev *dev)
serio->private = sunkbd;
if (serio_open(serio, dev)) {
if (serio_open(serio, drv)) {
kfree(sunkbd);
return;
}
......@@ -301,10 +303,14 @@ static void sunkbd_disconnect(struct serio *serio)
kfree(sunkbd);
}
static struct serio_dev sunkbd_dev = {
static struct serio_driver sunkbd_drv = {
.driver = {
.name = "sunkbd",
},
.description = DRIVER_DESC,
.interrupt = sunkbd_interrupt,
.connect = sunkbd_connect,
.disconnect = sunkbd_disconnect
.disconnect = sunkbd_disconnect,
};
/*
......@@ -313,13 +319,13 @@ static struct serio_dev sunkbd_dev = {
int __init sunkbd_init(void)
{
serio_register_device(&sunkbd_dev);
serio_register_driver(&sunkbd_drv);
return 0;
}
void __exit sunkbd_exit(void)
{
serio_unregister_device(&sunkbd_dev);
serio_unregister_driver(&sunkbd_drv);
}
module_init(sunkbd_init);
......
......@@ -34,8 +34,10 @@
#include <linux/init.h>
#include <linux/serio.h>
#define DRIVER_DESC "XT keyboard driver"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("XT keyboard driver");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
#define XTKBD_EMUL0 0xe0
......@@ -86,7 +88,7 @@ irqreturn_t xtkbd_interrupt(struct serio *serio,
return IRQ_HANDLED;
}
void xtkbd_connect(struct serio *serio, struct serio_dev *dev)
void xtkbd_connect(struct serio *serio, struct serio_driver *drv)
{
struct xtkbd *xtkbd;
int i;
......@@ -111,7 +113,7 @@ void xtkbd_connect(struct serio *serio, struct serio_dev *dev)
serio->private = xtkbd;
if (serio_open(serio, dev)) {
if (serio_open(serio, drv)) {
kfree(xtkbd);
return;
}
......@@ -143,21 +145,25 @@ void xtkbd_disconnect(struct serio *serio)
kfree(xtkbd);
}
struct serio_dev xtkbd_dev = {
struct serio_driver xtkbd_drv = {
.driver = {
.name = "xtkbd",
},
.description = DRIVER_DESC,
.interrupt = xtkbd_interrupt,
.connect = xtkbd_connect,
.disconnect = xtkbd_disconnect
.disconnect = xtkbd_disconnect,
};
int __init xtkbd_init(void)
{
serio_register_device(&xtkbd_dev);
serio_register_driver(&xtkbd_drv);
return 0;
}
void __exit xtkbd_exit(void)
{
serio_unregister_device(&xtkbd_dev);
serio_unregister_driver(&xtkbd_drv);
}
module_init(xtkbd_init);
......
......@@ -279,6 +279,9 @@ static unsigned int uinput_poll(struct file *file, poll_table *wait)
{
struct uinput_device *udev = file->private_data;
if (!test_bit(UIST_CREATED, &(udev->state)))
return 0;
poll_wait(file, &udev->waitq, wait);
if (udev->head != udev->tail)
......
......@@ -30,8 +30,6 @@ config MOUSE_PS2
and a new verion of GPM at:
http://www.geocities.com/dt_or/gpm/gpm.html
to take advantage of the advanced features of the touchpad.
If you do not want install specialized drivers but want tapping
working please use option psmouse.proto=imps.
If unsure, say Y.
......
......@@ -277,7 +277,7 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties)
protocol = PSMOUSE_PS2TPP;
}
} else if (get_model_info(model) != NULL) {
} else if (model_info != NULL) {
param[0] = param[1] = param[2] = 0;
ps2pp_cmd(psmouse, param, 0x39); /* Magic knock */
......
This diff is collapsed.
......@@ -22,6 +22,11 @@
#define PSMOUSE_ACTIVATED 1
#define PSMOUSE_IGNORE 2
#define PSMOUSE_FLAG_ACK 0 /* Waiting for ACK/NAK */
#define PSMOUSE_FLAG_CMD 1 /* Waiting for command to finish */
#define PSMOUSE_FLAG_CMD1 2 /* First byte of command response */
#define PSMOUSE_FLAG_ID 3 /* First byte is not keyboard ID */
/* psmouse protocol handler return codes */
typedef enum {
PSMOUSE_BAD_DATA,
......@@ -29,20 +34,10 @@ typedef enum {
PSMOUSE_FULL_PACKET
} psmouse_ret_t;
struct psmouse;
struct psmouse_ptport {
struct serio serio;
void (*activate)(struct psmouse *parent);
void (*deactivate)(struct psmouse *parent);
};
struct psmouse {
void *private;
struct input_dev dev;
struct serio *serio;
struct psmouse_ptport *ptport;
char *vendor;
char *name;
unsigned char cmdbuf[8];
......@@ -54,15 +49,18 @@ struct psmouse {
unsigned long last;
unsigned long out_of_sync;
unsigned char state;
char acking;
volatile char ack;
unsigned char nak;
char error;
char devname[64];
char phys[32];
unsigned long flags;
psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs);
int (*reconnect)(struct psmouse *psmouse);
void (*disconnect)(struct psmouse *psmouse);
void (*pt_activate)(struct psmouse *psmouse);
void (*pt_deactivate)(struct psmouse *psmouse);
};
#define PSMOUSE_PS2 1
......
......@@ -37,8 +37,10 @@
#include <linux/serio.h>
#include <linux/init.h>
#define DRIVER_DESC "Serial mouse driver"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Serial mouse driver");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
static char *sermouse_protocols[] = { "None", "Mouse Systems Mouse", "Sun Mouse", "Microsoft Mouse",
......@@ -237,7 +239,7 @@ static void sermouse_disconnect(struct serio *serio)
* an unhandled serio port is found.
*/
static void sermouse_connect(struct serio *serio, struct serio_dev *dev)
static void sermouse_connect(struct serio *serio, struct serio_driver *drv)
{
struct sermouse *sermouse;
unsigned char c;
......@@ -279,7 +281,7 @@ static void sermouse_connect(struct serio *serio, struct serio_dev *dev)
sermouse->dev.id.product = c;
sermouse->dev.id.version = 0x0100;
if (serio_open(serio, dev)) {
if (serio_open(serio, drv)) {
kfree(sermouse);
return;
}
......@@ -289,21 +291,25 @@ static void sermouse_connect(struct serio *serio, struct serio_dev *dev)
printk(KERN_INFO "input: %s on %s\n", sermouse_protocols[sermouse->type], serio->phys);
}
static struct serio_dev sermouse_dev = {
static struct serio_driver sermouse_drv = {
.driver = {
.name = "sermouse",
},
.description = DRIVER_DESC,
.interrupt = sermouse_interrupt,
.connect = sermouse_connect,
.disconnect = sermouse_disconnect
.disconnect = sermouse_disconnect,
};
int __init sermouse_init(void)
{
serio_register_device(&sermouse_dev);
serio_register_driver(&sermouse_drv);
return 0;
}
void __exit sermouse_exit(void)
{
serio_unregister_device(&sermouse_dev);
serio_unregister_driver(&sermouse_drv);
}
module_init(sermouse_init);
......
......@@ -212,9 +212,9 @@ static int synaptics_set_mode(struct psmouse *psmouse, int mode)
/*****************************************************************************
* Synaptics pass-through PS/2 port support
****************************************************************************/
static int synaptics_pt_write(struct serio *port, unsigned char c)
static int synaptics_pt_write(struct serio *serio, unsigned char c)
{
struct psmouse *parent = port->driver;
struct psmouse *parent = serio->parent->private;
char rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */
if (psmouse_sliced_command(parent, c))
......@@ -248,7 +248,7 @@ static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet
static void synaptics_pt_activate(struct psmouse *psmouse)
{
struct psmouse *child = psmouse->ptport->serio.private;
struct psmouse *child = psmouse->serio->child->private;
/* adjust the touchpad to child's choice of protocol */
if (child && child->type >= PSMOUSE_GENPS) {
......@@ -259,23 +259,25 @@ static void synaptics_pt_activate(struct psmouse *psmouse)
static void synaptics_pt_create(struct psmouse *psmouse)
{
struct psmouse_ptport *port;
struct serio *serio;
psmouse->ptport = port = kmalloc(sizeof(struct psmouse_ptport), GFP_KERNEL);
if (!port) {
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (!serio) {
printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n");
return;
}
memset(port, 0, sizeof(struct psmouse_ptport));
memset(serio, 0, sizeof(struct serio));
port->serio.type = SERIO_PS_PSTHRU;
port->serio.name = "Synaptics pass-through";
port->serio.phys = "synaptics-pt/serio0";
port->serio.write = synaptics_pt_write;
port->serio.driver = psmouse;
serio->type = SERIO_PS_PSTHRU;
strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name));
serio->write = synaptics_pt_write;
serio->parent = psmouse->serio;
port->activate = synaptics_pt_activate;
psmouse->pt_activate = synaptics_pt_activate;
psmouse->serio->child = serio;
}
/*****************************************************************************
......@@ -470,8 +472,8 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse, struct pt_r
if (unlikely(priv->pkt_type == SYN_NEWABS))
priv->pkt_type = synaptics_detect_pkt_type(psmouse);
if (psmouse->ptport && psmouse->ptport->serio.dev && synaptics_is_pt_packet(psmouse->packet))
synaptics_pass_pt_packet(&psmouse->ptport->serio, psmouse->packet);
if (psmouse->serio->child && psmouse->serio->child->drv && synaptics_is_pt_packet(psmouse->packet))
synaptics_pass_pt_packet(psmouse->serio->child, psmouse->packet);
else
synaptics_process_packet(psmouse);
......
......@@ -82,8 +82,10 @@
#include <linux/serio.h>
#include <linux/init.h>
#define DRIVER_DESC "Serial DEC VSXXX-AA/GA mouse / DEC tablet driver"
MODULE_AUTHOR ("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
MODULE_DESCRIPTION ("Serial DEC VSXXX-AA/GA mouse / DEC tablet driver");
MODULE_DESCRIPTION (DRIVER_DESC);
MODULE_LICENSE ("GPL");
#undef VSXXXAA_DEBUG
......@@ -482,7 +484,7 @@ vsxxxaa_disconnect (struct serio *serio)
}
static void
vsxxxaa_connect (struct serio *serio, struct serio_dev *dev)
vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
{
struct vsxxxaa *mouse;
......@@ -524,7 +526,7 @@ vsxxxaa_connect (struct serio *serio, struct serio_dev *dev)
mouse->dev.id.bustype = BUS_RS232;
mouse->serio = serio;
if (serio_open (serio, dev)) {
if (serio_open (serio, drv)) {
kfree (mouse);
return;
}
......@@ -540,7 +542,11 @@ vsxxxaa_connect (struct serio *serio, struct serio_dev *dev)
printk (KERN_INFO "input: %s on %s\n", mouse->name, mouse->phys);
}
static struct serio_dev vsxxxaa_dev = {
static struct serio_driver vsxxxaa_drv = {
.driver = {
.name = "vsxxxaa",
},
.description = DRIVER_DESC,
.connect = vsxxxaa_connect,
.interrupt = vsxxxaa_interrupt,
.disconnect = vsxxxaa_disconnect,
......@@ -549,14 +555,14 @@ static struct serio_dev vsxxxaa_dev = {
int __init
vsxxxaa_init (void)
{
serio_register_device (&vsxxxaa_dev);
serio_register_driver(&vsxxxaa_drv);
return 0;
}
void __exit
vsxxxaa_exit (void)
{
serio_unregister_device (&vsxxxaa_dev);
serio_unregister_driver(&vsxxxaa_drv);
}
module_init (vsxxxaa_init);
......
......@@ -48,8 +48,13 @@ static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y;
module_param(yres, uint, 0);
MODULE_PARM_DESC(yres, "Vertical screen resolution");
static unsigned tap_time = 200;
module_param(tap_time, uint, 0);
MODULE_PARM_DESC(tap_time, "Tap time for touchpads in absolute mode (msecs)");
struct mousedev_motion {
int dx, dy, dz;
unsigned long buttons;
};
struct mousedev {
......@@ -62,21 +67,31 @@ struct mousedev {
struct input_handle handle;
struct mousedev_motion packet;
unsigned long buttons;
unsigned int pkt_count;
int old_x[4], old_y[4];
unsigned int touch;
unsigned long touch;
};
enum mousedev_emul {
MOUSEDEV_EMUL_PS2,
MOUSEDEV_EMUL_IMPS,
MOUSEDEV_EMUL_EXPS
} __attribute__ ((packed));
#define PACKET_QUEUE_LEN 16
struct mousedev_list {
struct fasync_struct *fasync;
struct mousedev *mousedev;
struct list_head node;
int dx, dy, dz;
unsigned long buttons;
struct mousedev_motion packets[PACKET_QUEUE_LEN];
unsigned int head, tail;
spinlock_t packet_lock;
signed char ps2[6];
unsigned char ready, buffer, bufsiz;
unsigned char mode, imexseq, impsseq;
unsigned char imexseq, impsseq;
enum mousedev_emul mode;
};
#define MOUSEDEV_SEQ_LEN 6
......@@ -165,30 +180,70 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int
}
if (value) {
set_bit(index, &mousedev->buttons);
set_bit(index, &mousedev_mix.buttons);
set_bit(index, &mousedev->packet.buttons);
set_bit(index, &mousedev_mix.packet.buttons);
} else {
clear_bit(index, &mousedev->buttons);
clear_bit(index, &mousedev_mix.buttons);
clear_bit(index, &mousedev->packet.buttons);
clear_bit(index, &mousedev_mix.packet.buttons);
}
}
static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_motion *packet)
{
struct mousedev_list *list;
struct mousedev_motion *p;
unsigned long flags;
list_for_each_entry(list, &mousedev->list, node) {
list->dx += packet->dx;
list->dy += packet->dy;
list->dz += packet->dz;
list->buttons = mousedev->buttons;
spin_lock_irqsave(&list->packet_lock, flags);
p = &list->packets[list->head];
if (list->ready && p->buttons != packet->buttons) {
unsigned int new_head = (list->head + 1) % PACKET_QUEUE_LEN;
if (new_head != list->tail) {
p = &list->packets[list->head = new_head];
memset(p, 0, sizeof(struct mousedev_motion));
}
}
p->dx += packet->dx;
p->dy += packet->dy;
p->dz += packet->dz;
p->buttons = mousedev->packet.buttons;
list->ready = 1;
spin_unlock_irqrestore(&list->packet_lock, flags);
kill_fasync(&list->fasync, SIGIO, POLL_IN);
}
wake_up_interruptible(&mousedev->wait);
}
static void mousedev_touchpad_touch(struct mousedev *mousedev, int value)
{
if (!value) {
if (mousedev->touch &&
!time_after(jiffies, mousedev->touch + msecs_to_jiffies(tap_time))) {
/*
* Toggle left button to emulate tap.
* We rely on the fact that mousedev_mix always has 0
* motion packet so we won't mess current position.
*/
set_bit(0, &mousedev->packet.buttons);
set_bit(0, &mousedev_mix.packet.buttons);
mousedev_notify_readers(mousedev, &mousedev_mix.packet);
mousedev_notify_readers(&mousedev_mix, &mousedev_mix.packet);
clear_bit(0, &mousedev->packet.buttons);
clear_bit(0, &mousedev_mix.packet.buttons);
}
mousedev->touch = mousedev->pkt_count = 0;
}
else
if (!mousedev->touch)
mousedev->touch = jiffies;
}
static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
{
struct mousedev *mousedev = handle->private;
......@@ -212,12 +267,8 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
case EV_KEY:
if (value != 2) {
if (code == BTN_TOUCH && test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) {
/* Handle touchpad data */
mousedev->touch = value;
if (!mousedev->touch)
mousedev->pkt_count = 0;
}
if (code == BTN_TOUCH && test_bit(BTN_TOOL_FINGER, handle->dev->keybit))
mousedev_touchpad_touch(mousedev, value);
else
mousedev_key_event(mousedev, code, value);
}
......@@ -237,7 +288,7 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
mousedev_notify_readers(mousedev, &mousedev->packet);
mousedev_notify_readers(&mousedev_mix, &mousedev->packet);
memset(&mousedev->packet, 0, sizeof(struct mousedev_motion));
mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0;
}
break;
}
......@@ -322,6 +373,7 @@ static int mousedev_open(struct inode * inode, struct file * file)
return -ENOMEM;
memset(list, 0, sizeof(struct mousedev_list));
spin_lock_init(&list->packet_lock);
list->mousedev = mousedev_table[i];
list_add_tail(&list->node, &mousedev_table[i]->list);
file->private_data = list;
......@@ -341,32 +393,56 @@ static int mousedev_open(struct inode * inode, struct file * file)
return 0;
}
static void mousedev_packet(struct mousedev_list *list, unsigned char off)
static inline int mousedev_limit_delta(int delta, int limit)
{
list->ps2[off] = 0x08 | ((list->dx < 0) << 4) | ((list->dy < 0) << 5) | (list->buttons & 0x07);
list->ps2[off + 1] = (list->dx > 127 ? 127 : (list->dx < -127 ? -127 : list->dx));
list->ps2[off + 2] = (list->dy > 127 ? 127 : (list->dy < -127 ? -127 : list->dy));
list->dx -= list->ps2[off + 1];
list->dy -= list->ps2[off + 2];
list->bufsiz = off + 3;
if (list->mode == 2) {
list->ps2[off + 3] = (list->dz > 7 ? 7 : (list->dz < -7 ? -7 : list->dz));
list->dz -= list->ps2[off + 3];
list->ps2[off + 3] = (list->ps2[off + 3] & 0x0f) | ((list->buttons & 0x18) << 1);
list->bufsiz++;
} else {
list->ps2[off] |= ((list->buttons & 0x10) >> 3) | ((list->buttons & 0x08) >> 1);
return delta > limit ? limit : (delta < -limit ? -limit : delta);
}
static void mousedev_packet(struct mousedev_list *list, signed char *ps2_data)
{
struct mousedev_motion *p;
unsigned long flags;
spin_lock_irqsave(&list->packet_lock, flags);
p = &list->packets[list->tail];
ps2_data[0] = 0x08 | ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07);
ps2_data[1] = mousedev_limit_delta(p->dx, 127);
ps2_data[2] = mousedev_limit_delta(p->dy, 127);
p->dx -= ps2_data[1];
p->dy -= ps2_data[2];
switch (list->mode) {
case MOUSEDEV_EMUL_EXPS:
ps2_data[3] = mousedev_limit_delta(p->dz, 127);
p->dz -= ps2_data[3];
ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1);
list->bufsiz = 4;
break;
case MOUSEDEV_EMUL_IMPS:
ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
ps2_data[3] = mousedev_limit_delta(p->dz, 127);
p->dz -= ps2_data[3];
list->bufsiz = 4;
break;
case MOUSEDEV_EMUL_PS2:
default:
ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
p->dz = 0;
list->bufsiz = 3;
break;
}
if (list->mode == 1) {
list->ps2[off + 3] = (list->dz > 127 ? 127 : (list->dz < -127 ? -127 : list->dz));
list->dz -= list->ps2[off + 3];
list->bufsiz++;
if (!p->dx && !p->dy && !p->dz) {
if (list->tail != list->head)
list->tail = (list->tail + 1) % PACKET_QUEUE_LEN;
if (list->tail == list->head)
list->ready = 0;
}
if (!list->dx && !list->dy && (!list->mode || !list->dz)) list->ready = 0;
list->buffer = list->bufsiz;
spin_unlock_irqrestore(&list->packet_lock, flags);
}
......@@ -384,31 +460,31 @@ static ssize_t mousedev_write(struct file * file, const char __user * buffer, si
if (c == mousedev_imex_seq[list->imexseq]) {
if (++list->imexseq == MOUSEDEV_SEQ_LEN) {
list->imexseq = 0;
list->mode = 2;
list->mode = MOUSEDEV_EMUL_EXPS;
}
} else list->imexseq = 0;
if (c == mousedev_imps_seq[list->impsseq]) {
if (++list->impsseq == MOUSEDEV_SEQ_LEN) {
list->impsseq = 0;
list->mode = 1;
list->mode = MOUSEDEV_EMUL_IMPS;
}
} else list->impsseq = 0;
list->ps2[0] = 0xfa;
list->bufsiz = 1;
switch (c) {
case 0xeb: /* Poll */
mousedev_packet(list, 1);
mousedev_packet(list, &list->ps2[1]);
list->bufsiz++; /* account for leading ACK */
break;
case 0xf2: /* Get ID */
switch (list->mode) {
case 0: list->ps2[1] = 0; break;
case 1: list->ps2[1] = 3; break;
case 2: list->ps2[1] = 4; break;
case MOUSEDEV_EMUL_PS2: list->ps2[1] = 0; break;
case MOUSEDEV_EMUL_IMPS: list->ps2[1] = 3; break;
case MOUSEDEV_EMUL_EXPS: list->ps2[1] = 4; break;
}
list->bufsiz = 2;
break;
......@@ -419,13 +495,15 @@ static ssize_t mousedev_write(struct file * file, const char __user * buffer, si
break;
case 0xff: /* Reset */
list->impsseq = 0;
list->imexseq = 0;
list->mode = 0;
list->ps2[1] = 0xaa;
list->ps2[2] = 0x00;
list->impsseq = list->imexseq = 0;
list->mode = MOUSEDEV_EMUL_PS2;
list->ps2[1] = 0xaa; list->ps2[2] = 0x00;
list->bufsiz = 3;
break;
default:
list->bufsiz = 1;
break;
}
list->buffer = list->bufsiz;
......@@ -451,8 +529,10 @@ static ssize_t mousedev_read(struct file * file, char __user * buffer, size_t co
if (retval)
return retval;
if (!list->buffer && list->ready)
mousedev_packet(list, 0);
if (!list->buffer && list->ready) {
mousedev_packet(list, list->ps2);
list->buffer = list->bufsiz;
}
if (count > list->buffer)
count = list->buffer;
......
......@@ -130,3 +130,19 @@ config SERIO_MACEPS2
To compile this driver as a module, choose M here: the
module will be called maceps2.
config SERIO_RAW
tristate "Raw access to serio ports"
depends on SERIO
help
Say Y here if you want to have raw access to serio ports, such as
AUX ports on i8042 keyboard controller. Each serio port that is
bound to this driver will be accessible via a char device with
major 10 and dynamically allocated minor. The driver will try
allocating minor 1 (that historically corresponds to /dev/psaux)
first. To bind this driver to a serio port use sysfs interface:
echo -n "serio_raw" > /sys/bus/serio/devices/serioX/driver
To compile this driver as a module, choose M here: the
module will be called serio_raw.
......@@ -17,3 +17,4 @@ obj-$(CONFIG_SERIO_98KBD) += 98kbd-io.o
obj-$(CONFIG_SERIO_GSCPS2) += gscps2.o
obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o
obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o
obj-$(CONFIG_SERIO_RAW) += serio_raw.o
......@@ -29,7 +29,7 @@
#define KMI_BASE (kmi->base)
struct amba_kmi_port {
struct serio io;
struct serio *io;
struct clk *clk;
unsigned char *base;
unsigned int irq;
......@@ -44,7 +44,7 @@ static irqreturn_t amba_kmi_int(int irq, void *dev_id, struct pt_regs *regs)
int handled = IRQ_NONE;
while (status & KMIIR_RXINTR) {
serio_interrupt(&kmi->io, readb(KMIDATA), 0, regs);
serio_interrupt(kmi->io, readb(KMIDATA), 0, regs);
status = readb(KMIIR);
handled = IRQ_HANDLED;
}
......@@ -54,7 +54,7 @@ static irqreturn_t amba_kmi_int(int irq, void *dev_id, struct pt_regs *regs)
static int amba_kmi_write(struct serio *io, unsigned char val)
{
struct amba_kmi_port *kmi = io->driver;
struct amba_kmi_port *kmi = io->port_data;
unsigned int timeleft = 10000; /* timeout in 100ms */
while ((readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && timeleft--)
......@@ -68,7 +68,7 @@ static int amba_kmi_write(struct serio *io, unsigned char val)
static int amba_kmi_open(struct serio *io)
{
struct amba_kmi_port *kmi = io->driver;
struct amba_kmi_port *kmi = io->port_data;
unsigned int divisor;
int ret;
......@@ -105,7 +105,7 @@ static int amba_kmi_open(struct serio *io)
static void amba_kmi_close(struct serio *io)
{
struct amba_kmi_port *kmi = io->driver;
struct amba_kmi_port *kmi = io->port_data;
writeb(0, KMICR);
......@@ -117,6 +117,7 @@ static void amba_kmi_close(struct serio *io)
static int amba_kmi_probe(struct amba_device *dev, void *id)
{
struct amba_kmi_port *kmi;
struct serio *io;
int ret;
ret = amba_request_regions(dev, NULL);
......@@ -124,21 +125,25 @@ static int amba_kmi_probe(struct amba_device *dev, void *id)
return ret;
kmi = kmalloc(sizeof(struct amba_kmi_port), GFP_KERNEL);
if (!kmi) {
io = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (!kmi || !io) {
ret = -ENOMEM;
goto out;
}
memset(kmi, 0, sizeof(struct amba_kmi_port));
kmi->io.type = SERIO_8042;
kmi->io.write = amba_kmi_write;
kmi->io.open = amba_kmi_open;
kmi->io.close = amba_kmi_close;
kmi->io.name = dev->dev.bus_id;
kmi->io.phys = dev->dev.bus_id;
kmi->io.driver = kmi;
memset(io, 0, sizeof(struct serio));
io->type = SERIO_8042;
io->write = amba_kmi_write;
io->open = amba_kmi_open;
io->close = amba_kmi_close;
strlcpy(io->name, dev->dev.bus_id, sizeof(io->name));
strlcpy(io->phys, dev->dev.bus_id, sizeof(io->phys));
io->port_data = kmi;
io->dev.parent = &dev->dev;
kmi->io = io;
kmi->base = ioremap(dev->res.start, KMI_SIZE);
if (!kmi->base) {
ret = -ENOMEM;
......@@ -154,13 +159,14 @@ static int amba_kmi_probe(struct amba_device *dev, void *id)
kmi->irq = dev->irq[0];
amba_set_drvdata(dev, kmi);
serio_register_port(&kmi->io);
serio_register_port(kmi->io);
return 0;
unmap:
iounmap(kmi->base);
out:
kfree(kmi);
kfree(io);
amba_release_regions(dev);
return ret;
}
......@@ -171,7 +177,7 @@ static int amba_kmi_remove(struct amba_device *dev)
amba_set_drvdata(dev, NULL);
serio_unregister_port(&kmi->io);
serio_unregister_port(kmi->io);
clk_put(kmi->clk);
iounmap(kmi->base);
kfree(kmi);
......@@ -184,7 +190,7 @@ static int amba_kmi_resume(struct amba_device *dev)
struct amba_kmi_port *kmi = amba_get_drvdata(dev);
/* kick the serio layer to rescan this port */
serio_rescan(&kmi->io);
serio_reconnect(kmi->io);
return 0;
}
......@@ -214,7 +220,7 @@ static int __init amba_kmi_init(void)
static void __exit amba_kmi_exit(void)
{
return amba_driver_unregister(&ambakmi_driver);
amba_driver_unregister(&ambakmi_driver);
}
module_init(amba_kmi_init);
......
......@@ -43,9 +43,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("82C710 C&T mouse port chip driver");
MODULE_LICENSE("GPL");
static char ct82c710_name[] = "C&T 82c710 mouse port";
static char ct82c710_phys[16];
/*
* ct82c710 interface
*/
......@@ -61,10 +58,20 @@ static char ct82c710_phys[16];
#define CT82C710_IRQ 12
static struct serio *ct82c710_port;
static int ct82c710_data;
static int ct82c710_status;
static irqreturn_t ct82c710_interrupt(int cpl, void *dev_id, struct pt_regs * regs);
/*
* Interrupt handler for the 82C710 mouse port. A character
* is waiting in the 82C710.
*/
static irqreturn_t ct82c710_interrupt(int cpl, void *dev_id, struct pt_regs * regs)
{
return serio_interrupt(ct82c710_port, inb(ct82c710_data), 0, regs);
}
/*
* Wait for device to send output char and flush any input char.
......@@ -139,26 +146,6 @@ static int ct82c710_write(struct serio *port, unsigned char c)
return 0;
}
static struct serio ct82c710_port =
{
.type = SERIO_8042,
.name = ct82c710_name,
.phys = ct82c710_phys,
.write = ct82c710_write,
.open = ct82c710_open,
.close = ct82c710_close,
};
/*
* Interrupt handler for the 82C710 mouse port. A character
* is waiting in the 82C710.
*/
static irqreturn_t ct82c710_interrupt(int cpl, void *dev_id, struct pt_regs * regs)
{
return serio_interrupt(&ct82c710_port, inb(ct82c710_data), 0, regs);
}
/*
* See if we can find a 82C710 device. Read mouse address.
*/
......@@ -183,6 +170,24 @@ static int __init ct82c710_probe(void)
return 0;
}
static struct serio * __init ct82c710_allocate_port(void)
{
struct serio *serio;
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) {
memset(serio, 0, sizeof(struct serio));
serio->type = SERIO_8042;
serio->open = ct82c710_open;
serio->close = ct82c710_close;
serio->write = ct82c710_write;
strlcpy(serio->name, "C&T 82c710 mouse port", sizeof(serio->name));
snprintf(serio->phys, sizeof(serio->phys), "isa%04x/serio0", ct82c710_data);
}
return serio;
}
int __init ct82c710_init(void)
{
if (ct82c710_probe())
......@@ -191,9 +196,12 @@ int __init ct82c710_init(void)
if (request_region(ct82c710_data, 2, "ct82c710"))
return -EBUSY;
sprintf(ct82c710_phys, "isa%04x/serio0", ct82c710_data);
if (!(ct82c710_port = ct82c710_allocate_port())) {
release_region(ct82c710_data, 2);
return -ENOMEM;
}
serio_register_port(&ct82c710_port);
serio_register_port(ct82c710_port);
printk(KERN_INFO "serio: C&T 82c710 mouse port at %#x irq %d\n",
ct82c710_data, CT82C710_IRQ);
......@@ -203,7 +211,7 @@ int __init ct82c710_init(void)
void __exit ct82c710_exit(void)
{
serio_unregister_port(&ct82c710_port);
serio_unregister_port(ct82c710_port);
release_region(ct82c710_data, 2);
}
......
......@@ -91,7 +91,7 @@ static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs);
struct gscps2port {
struct list_head node;
struct parisc_device *padev;
struct serio port;
struct serio *port;
spinlock_t lock;
char *addr;
u8 act, append; /* position in buffer[] */
......@@ -100,7 +100,6 @@ struct gscps2port {
u8 str;
} buffer[BUFFER_SIZE+1];
int id;
char name[32];
};
/*
......@@ -272,7 +271,7 @@ static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs)
rxflags = ((status & GSC_STAT_TERR) ? SERIO_TIMEOUT : 0 ) |
((status & GSC_STAT_PERR) ? SERIO_PARITY : 0 );
serio_interrupt(&ps2port->port, data, rxflags, regs);
serio_interrupt(ps2port->port, data, rxflags, regs);
} /* while() */
......@@ -288,7 +287,7 @@ static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs)
static int gscps2_write(struct serio *port, unsigned char data)
{
struct gscps2port *ps2port = port->driver;
struct gscps2port *ps2port = port->port_data;
if (!gscps2_writeb_output(ps2port, data)) {
printk(KERN_DEBUG PFX "sending byte %#x failed.\n", data);
......@@ -304,7 +303,7 @@ static int gscps2_write(struct serio *port, unsigned char data)
static int gscps2_open(struct serio *port)
{
struct gscps2port *ps2port = port->driver;
struct gscps2port *ps2port = port->port_data;
gscps2_reset(ps2port);
......@@ -319,7 +318,7 @@ static int gscps2_open(struct serio *port)
static void gscps2_close(struct serio *port)
{
struct gscps2port *ps2port = port->driver;
struct gscps2port *ps2port = port->port_data;
gscps2_enable(ps2port, DISABLE);
}
......@@ -344,6 +343,7 @@ static struct serio gscps2_serio_port =
static int __init gscps2_probe(struct parisc_device *dev)
{
struct gscps2port *ps2port;
struct serio *serio;
unsigned long hpa = dev->hpa;
int ret;
......@@ -355,34 +355,45 @@ static int __init gscps2_probe(struct parisc_device *dev)
hpa += GSC_DINO_OFFSET;
ps2port = kmalloc(sizeof(struct gscps2port), GFP_KERNEL);
if (!ps2port)
return -ENOMEM;
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (!ps2port || !serio) {
ret = -ENOMEM;
goto fail_nomem;
}
dev_set_drvdata(&dev->dev, ps2port);
memset(ps2port, 0, sizeof(struct gscps2port));
memset(serio, 0, sizeof(struct serio));
ps2port->port = serio;
ps2port->padev = dev;
ps2port->addr = ioremap(hpa, GSC_STATUS + 4);
spin_lock_init(&ps2port->lock);
gscps2_reset(ps2port);
ps2port->id = readb(ps2port->addr+GSC_ID) & 0x0f;
snprintf(ps2port->name, sizeof(ps2port->name)-1, "%s %s",
gscps2_serio_port.name,
(ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse" );
memcpy(&ps2port->port, &gscps2_serio_port, sizeof(gscps2_serio_port));
ps2port->port.driver = ps2port;
ps2port->port.name = ps2port->name;
ps2port->port.phys = dev->dev.bus_id;
ps2port->id = readb(ps2port->addr + GSC_ID) & 0x0f;
snprintf(serio->name, sizeof(serio->name), "GSC PS/2 %s",
(ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse");
strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
serio->idbus = BUS_GSC;
serio->idvendor = PCI_VENDOR_ID_HP;
serio->idproduct = 0x0001;
serio->idversion = 0x0010;
serio->type = SERIO_8042;
serio->write = gscps2_write;
serio->open = gscps2_open;
serio->close = gscps2_close;
serio->port_data = ps2port;
serio->dev.parent = &dev->dev;
list_add_tail(&ps2port->node, &ps2port_list);
ret = -EBUSY;
if (request_irq(dev->irq, gscps2_interrupt, SA_SHIRQ, ps2port->name, ps2port))
if (request_irq(dev->irq, gscps2_interrupt, SA_SHIRQ, ps2port->port->name, ps2port))
goto fail_miserably;
if ( (ps2port->id != GSC_ID_KEYBOARD) && (ps2port->id != GSC_ID_MOUSE) ) {
if (ps2port->id != GSC_ID_KEYBOARD && ps2port->id != GSC_ID_MOUSE) {
printk(KERN_WARNING PFX "Unsupported PS/2 port at 0x%08lx (id=%d) ignored\n",
hpa, ps2port->id);
ret = -ENODEV;
......@@ -395,12 +406,12 @@ static int __init gscps2_probe(struct parisc_device *dev)
#endif
printk(KERN_INFO "serio: %s port at 0x%p irq %d @ %s\n",
ps2port->name,
ps2port->port->name,
ps2port->addr,
ps2port->padev->irq,
ps2port->port.phys);
ps2port->port->phys);
serio_register_port(&ps2port->port);
serio_register_port(ps2port->port);
return 0;
......@@ -411,7 +422,10 @@ static int __init gscps2_probe(struct parisc_device *dev)
list_del(&ps2port->node);
iounmap(ps2port->addr);
release_mem_region(dev->hpa, GSC_STATUS + 4);
fail_nomem:
kfree(ps2port);
kfree(serio);
return ret;
}
......@@ -424,7 +438,7 @@ static int __devexit gscps2_remove(struct parisc_device *dev)
{
struct gscps2port *ps2port = dev_get_drvdata(&dev->dev);
serio_unregister_port(&ps2port->port);
serio_unregister_port(ps2port->port);
free_irq(dev->irq, ps2port);
gscps2_flush(ps2port);
list_del(&ps2port->node);
......
......@@ -65,6 +65,31 @@ static inline void i8042_write_command(int val)
return;
}
#if defined(__i386__)
#include <linux/dmi.h>
static struct dmi_system_id __initdata i8042_dmi_table[] = {
{
.ident = "Compaq Proliant 8500",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"),
DMI_MATCH(DMI_PRODUCT_VERSION, "8500"),
},
},
{
.ident = "Compaq Proliant DL760",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"),
DMI_MATCH(DMI_PRODUCT_VERSION, "DL760"),
},
},
{ }
};
#endif
static inline int i8042_platform_init(void)
{
/*
......@@ -79,6 +104,12 @@ static inline int i8042_platform_init(void)
#if !defined(__i386__) && !defined(__x86_64__)
i8042_reset = 1;
#endif
#if defined(__i386__)
if (dmi_check_system(i8042_dmi_table))
i8042_noloop = 1;
#endif
return 0;
}
......
This diff is collapsed.
......@@ -103,6 +103,13 @@
#define I8042_BUFFER_SIZE 32
/*
* Number of AUX ports on controllers supporting active multiplexing
* specification
*/
#define I8042_NUM_MUX_PORTS 4
/*
* Debug.
*/
......
......@@ -46,15 +46,17 @@ MODULE_LICENSE("GPL");
#define PS2_CONTROL_RX_CLOCK_ENABLE BIT(4) /* pause reception if set to 0 */
#define PS2_CONTROL_RESET BIT(5) /* reset */
struct maceps2_data {
struct mace_ps2port *port;
int irq;
};
static struct maceps2_data port_data[2];
static struct serio *maceps2_port[2];
static int maceps2_write(struct serio *dev, unsigned char val)
{
struct mace_ps2port *port = ((struct maceps2_data *)dev->driver)->port;
struct mace_ps2port *port = ((struct maceps2_data *)dev->port_data)->port;
unsigned int timeout = MACE_PS2_TIMEOUT;
do {
......@@ -68,11 +70,10 @@ static int maceps2_write(struct serio *dev, unsigned char val)
return -1;
}
static irqreturn_t maceps2_interrupt(int irq, void *dev_id,
struct pt_regs *regs)
static irqreturn_t maceps2_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct serio *dev = dev_id;
struct mace_ps2port *port = ((struct maceps2_data *)dev->driver)->port;
struct mace_ps2port *port = ((struct maceps2_data *)dev->port_data)->port;
unsigned int byte;
if (mace_read(port->status) & PS2_STATUS_RX_FULL) {
......@@ -85,7 +86,7 @@ static irqreturn_t maceps2_interrupt(int irq, void *dev_id,
static int maceps2_open(struct serio *dev)
{
struct maceps2_data *data = (struct maceps2_data *)dev->driver;
struct maceps2_data *data = (struct maceps2_data *)dev->port_data;
if (request_irq(data->irq, maceps2_interrupt, 0, "PS/2 port", dev)) {
printk(KERN_ERR "Could not allocate PS/2 IRQ\n");
......@@ -106,7 +107,7 @@ static int maceps2_open(struct serio *dev)
static void maceps2_close(struct serio *dev)
{
struct maceps2_data *data = (struct maceps2_data *)dev->driver;
struct maceps2_data *data = (struct maceps2_data *)dev->port_data;
mace_write(PS2_CONTROL_TX_CLOCK_DISABLE | PS2_CONTROL_RESET,
data->port->control);
......@@ -114,46 +115,52 @@ static void maceps2_close(struct serio *dev)
free_irq(data->irq, dev);
}
static struct maceps2_data port0_data, port1_data;
static struct serio maceps2_port0 =
static struct serio * __init maceps2_allocate_port(int idx)
{
.type = SERIO_8042,
.open = maceps2_open,
.close = maceps2_close,
.write = maceps2_write,
.name = "MACE PS/2 port0",
.phys = "mace/serio0",
.driver = &port0_data,
};
struct serio *serio;
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) {
memset(serio, 0, sizeof(struct serio));
serio->type = SERIO_8042;
serio->write = maceps2_write;
serio->open = maceps2_open;
serio->close = maceps2_close;
snprintf(serio->name, sizeof(serio->name), "MACE PS/2 port%d", idx);
snprintf(serio->phys, sizeof(serio->phys), "mace/serio%d", idx);
serio->port_data = &port_data[idx];
}
return serio;
}
static struct serio maceps2_port1 =
{
.type = SERIO_8042,
.open = maceps2_open,
.close = maceps2_close,
.write = maceps2_write,
.name = "MACE PS/2 port1",
.phys = "mace/serio1",
.driver = &port1_data,
};
static int __init maceps2_init(void)
{
port0_data.port = &mace->perif.ps2.keyb;
port0_data.irq = MACEISA_KEYB_IRQ;
port1_data.port = &mace->perif.ps2.mouse;
port1_data.irq = MACEISA_MOUSE_IRQ;
serio_register_port(&maceps2_port0);
serio_register_port(&maceps2_port1);
port_data[0].port = &mace->perif.ps2.keyb;
port_data[0].irq = MACEISA_KEYB_IRQ;
port_data[1].port = &mace->perif.ps2.mouse;
port_data[1].irq = MACEISA_MOUSE_IRQ;
maceps2_port[0] = maceps2_allocate_port(0);
maceps2_port[1] = maceps2_allocate_port(1);
if (!maceps2_port[0] || !maceps2_port[1]) {
kfree(maceps2_port[0]);
kfree(maceps2_port[1]);
return -ENOMEM;
}
serio_register_port(maceps2_port[0]);
serio_register_port(maceps2_port[1]);
return 0;
}
static void __exit maceps2_exit(void)
{
serio_unregister_port(&maceps2_port0);
serio_unregister_port(&maceps2_port1);
serio_unregister_port(maceps2_port[0]);
serio_unregister_port(maceps2_port[1]);
}
module_init(maceps2_init);
......
......@@ -53,9 +53,7 @@ static int parkbd_writing;
static unsigned long parkbd_start;
static struct pardevice *parkbd_dev;
static char parkbd_name[] = "PARKBD AT/XT keyboard adapter";
static char parkbd_phys[32];
static struct serio *parkbd_port;
static int parkbd_readlines(void)
{
......@@ -86,13 +84,6 @@ static int parkbd_write(struct serio *port, unsigned char c)
return 0;
}
static struct serio parkbd_port =
{
.write = parkbd_write,
.name = parkbd_name,
.phys = parkbd_phys,
};
static void parkbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
......@@ -125,7 +116,7 @@ static void parkbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
parkbd_buffer |= (parkbd_readlines() >> 1) << parkbd_counter++;
if (parkbd_counter == parkbd_mode + 10)
serio_interrupt(&parkbd_port, (parkbd_buffer >> (2 - parkbd_mode)) & 0xff, 0, regs);
serio_interrupt(parkbd_port, (parkbd_buffer >> (2 - parkbd_mode)) & 0xff, 0, regs);
}
parkbd_last = jiffies;
......@@ -163,16 +154,38 @@ static int parkbd_getport(void)
return 0;
}
static struct serio * __init parkbd_allocate_serio(void)
{
struct serio *serio;
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) {
serio->type = parkbd_mode;
serio->write = parkbd_write,
strlcpy(serio->name, "PARKBD AT/XT keyboard adapter", sizeof(serio->name));
snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", parkbd_dev->port->name);
}
return serio;
}
int __init parkbd_init(void)
{
if (parkbd_getport()) return -1;
parkbd_writelines(3);
parkbd_port.type = parkbd_mode;
int err;
err = parkbd_getport();
if (err)
return err;
parkbd_port = parkbd_allocate_serio();
if (!parkbd_port) {
parport_release(parkbd_dev);
return -ENOMEM;
}
sprintf(parkbd_phys, "%s/serio0", parkbd_dev->port->name);
parkbd_writelines(3);
serio_register_port(&parkbd_port);
serio_register_port(parkbd_port);
printk(KERN_INFO "serio: PARKBD %s adapter on %s\n",
parkbd_mode ? "AT" : "XT", parkbd_dev->port->name);
......@@ -183,7 +196,7 @@ int __init parkbd_init(void)
void __exit parkbd_exit(void)
{
parport_release(parkbd_dev);
serio_unregister_port(&parkbd_port);
serio_unregister_port(parkbd_port);
parport_unregister_device(parkbd_dev);
}
......
......@@ -38,14 +38,14 @@
#define PS2_STAT_TXEMPTY (1<<7)
struct pcips2_data {
struct serio io;
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;
struct pcips2_data *ps2if = io->port_data;
unsigned int stat;
do {
......@@ -80,7 +80,7 @@ static irqreturn_t pcips2_interrupt(int irq, void *devid, struct pt_regs *regs)
if (hweight8(scancode) & 1)
flag ^= SERIO_PARITY;
serio_interrupt(&ps2if->io, scancode, flag, regs);
serio_interrupt(ps2if->io, scancode, flag, regs);
} while (1);
return IRQ_RETVAL(handled);
}
......@@ -101,7 +101,7 @@ static void pcips2_flush_input(struct pcips2_data *ps2if)
static int pcips2_open(struct serio *io)
{
struct pcips2_data *ps2if = io->driver;
struct pcips2_data *ps2if = io->port_data;
int ret, val = 0;
outb(PS2_CTRL_ENABLE, ps2if->base);
......@@ -119,7 +119,7 @@ static int pcips2_open(struct serio *io)
static void pcips2_close(struct serio *io)
{
struct pcips2_data *ps2if = io->driver;
struct pcips2_data *ps2if = io->port_data;
outb(0, ps2if->base);
......@@ -129,6 +129,7 @@ static void pcips2_close(struct serio *io)
static int __devinit pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct pcips2_data *ps2if;
struct serio *serio;
int ret;
ret = pci_enable_device(dev);
......@@ -142,29 +143,35 @@ static int __devinit pcips2_probe(struct pci_dev *dev, const struct pci_device_i
}
ps2if = kmalloc(sizeof(struct pcips2_data), GFP_KERNEL);
if (!ps2if) {
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (!ps2if || !serio) {
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 = pci_name(dev);
ps2if->io.phys = dev->dev.bus_id;
ps2if->io.driver = ps2if;
memset(serio, 0, sizeof(struct serio));
serio->type = SERIO_8042;
serio->write = pcips2_write;
serio->open = pcips2_open;
serio->close = pcips2_close;
strlcpy(serio->name, pci_name(dev), sizeof(serio->name));
strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
serio->port_data = ps2if;
serio->dev.parent = &dev->dev;
ps2if->io = serio;
ps2if->dev = dev;
ps2if->base = pci_resource_start(dev, 0);
pci_set_drvdata(dev, ps2if);
serio_register_port(&ps2if->io);
serio_register_port(ps2if->io);
return 0;
release:
kfree(ps2if);
kfree(serio);
release_region(pci_resource_start(dev, 0),
pci_resource_len(dev, 0));
disable:
......@@ -176,7 +183,7 @@ static void __devexit pcips2_remove(struct pci_dev *dev)
{
struct pcips2_data *ps2if = pci_get_drvdata(dev);
serio_unregister_port(&ps2if->io);
serio_unregister_port(ps2if->io);
release_region(pci_resource_start(dev, 0),
pci_resource_len(dev, 0));
pci_set_drvdata(dev, NULL);
......
......@@ -47,43 +47,98 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Q40 PS/2 keyboard controller driver");
MODULE_LICENSE("GPL");
static struct serio q40kbd_port =
{
.type = SERIO_8042,
.name = "Q40 kbd port",
.phys = "Q40",
.write = NULL,
};
static irqreturn_t q40kbd_interrupt(int irq, void *dev_id,
struct pt_regs *regs)
spinlock_t q40kbd_lock = SPIN_LOCK_UNLOCKED;
static struct serio *q40kbd_port;
static irqreturn_t q40kbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long flags;
spin_lock_irqsave(&q40kbd_lock, flags);
if (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG))
serio_interrupt(&q40kbd_port, master_inb(KEYCODE_REG), 0, regs);
serio_interrupt(q40kbd_port, master_inb(KEYCODE_REG), 0, regs);
master_outb(-1, KEYBOARD_UNLOCK_REG);
spin_unlock_irqrestore(&q40kbd_lock, flags);
return IRQ_HANDLED;
}
static int __init q40kbd_init(void)
/*
* q40kbd_flush() flushes all data that may be in the keyboard buffers
*/
static void q40kbd_flush(void)
{
int maxread = 100;
unsigned long flags;
if (!MACH_IS_Q40)
return -EIO;
/* allocate the IRQ */
request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, "q40kbd", NULL);
spin_lock_irqsave(&q40kbd_lock, flags);
/* flush any pending input */
while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)))
master_inb(KEYCODE_REG);
spin_unlock_irqrestore(&q40kbd_lock, flags);
}
/*
* q40kbd_open() is called when a port is open by the higher layer.
* It allocates the interrupt and enables in in the chip.
*/
static int q40kbd_open(struct serio *port)
{
q40kbd_flush();
if (request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, "q40kbd", NULL)) {
printk(KERN_ERR "q40kbd.c: Can't get irq %d.\n", Q40_IRQ_KEYBOARD);
return -1;
}
/* off we go */
master_outb(-1,KEYBOARD_UNLOCK_REG);
master_outb(1,KEY_IRQ_ENABLE_REG);
master_outb(-1, KEYBOARD_UNLOCK_REG);
master_outb(1, KEY_IRQ_ENABLE_REG);
return 0;
}
serio_register_port(&q40kbd_port);
static void q40kbd_close(struct serio *port)
{
master_outb(0, KEY_IRQ_ENABLE_REG);
master_outb(-1, KEYBOARD_UNLOCK_REG);
free_irq(Q40_IRQ_KEYBOARD, NULL);
q40kbd_flush();
}
static struct serio * __init q40kbd_allocate_port(void)
{
struct serio *serio;
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) {
memset(serio, 0, sizeof(struct serio));
serio->type = SERIO_8042;
serio->open = q40kbd_open;
serio->close = q40kbd_close;
strlcpy(serio->name, "Q40 Kbd Port", sizeof(serio->name));
strlcpy(serio->phys, "Q40", sizeof(serio->phys));
}
return serio;
}
static int __init q40kbd_init(void)
{
if (!MACH_IS_Q40)
return -EIO;
if (!(q40kbd_port = q40kbd_allocate_port()))
return -ENOMEM;
serio_register_port(q40kbd_port);
printk(KERN_INFO "serio: Q40 kbd registered\n");
return 0;
......@@ -91,11 +146,7 @@ static int __init q40kbd_init(void)
static void __exit q40kbd_exit(void)
{
master_outb(0,KEY_IRQ_ENABLE_REG);
master_outb(-1,KEYBOARD_UNLOCK_REG);
serio_unregister_port(&q40kbd_port);
free_irq(Q40_IRQ_KEYBOARD, NULL);
serio_unregister_port(q40kbd_port);
}
module_init(q40kbd_init);
......
......@@ -44,6 +44,8 @@ MODULE_AUTHOR("Vojtech Pavlik, Russell King");
MODULE_DESCRIPTION("Acorn RiscPC PS/2 keyboard controller driver");
MODULE_LICENSE("GPL");
static struct serio *rpckbd_port;
static int rpckbd_write(struct serio *port, unsigned char val)
{
while (!(iomd_readb(IOMD_KCTRL) & (1 << 7)))
......@@ -101,25 +103,41 @@ static void rpckbd_close(struct serio *port)
free_irq(IRQ_KEYBOARDTX, port);
}
static struct serio rpckbd_port =
/*
* Allocate and initialize serio structure for subsequent registration
* with serio core.
*/
static struct serio * __init rpckbd_allocate_port(void)
{
.type = SERIO_8042,
.open = rpckbd_open,
.close = rpckbd_close,
.write = rpckbd_write,
.name = "RiscPC PS/2 kbd port",
.phys = "rpckbd/serio0",
};
struct serio *serio;
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) {
memset(serio, 0, sizeof(struct serio));
serio->type = SERIO_8042;
serio->write = rpckbd_write;
serio->open = rpckbd_open;
serio->close = rpckbd_close;
strlcpy(serio->name, "RiscPC PS/2 kbd port", sizeof(serio->name));
strlcpy(serio->phys, "rpckbd/serio0", sizeof(serio->phys));
}
return serio;
}
static int __init rpckbd_init(void)
{
serio_register_port(&rpckbd_port);
if (!(rpckbd_port = rpckbd_allocate_port()))
return -ENOMEM;
serio_register_port(rpckbd_port);
return 0;
}
static void __exit rpckbd_exit(void)
{
serio_unregister_port(&rpckbd_port);
serio_unregister_port(rpckbd_port);
}
module_init(rpckbd_init);
......
......@@ -26,7 +26,7 @@
#include <asm/hardware/sa1111.h>
struct ps2if {
struct serio io;
struct serio *io;
struct sa1111_dev *dev;
unsigned long base;
unsigned int open;
......@@ -59,7 +59,7 @@ static irqreturn_t ps2_rxint(int irq, void *dev_id, struct pt_regs *regs)
if (hweight8(scancode) & 1)
flag ^= SERIO_PARITY;
serio_interrupt(&ps2if->io, scancode, flag, regs);
serio_interrupt(ps2if->io, scancode, flag, regs);
status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
}
......@@ -95,7 +95,7 @@ static irqreturn_t ps2_txint(int irq, void *dev_id, struct pt_regs *regs)
*/
static int ps2_write(struct serio *io, unsigned char val)
{
struct ps2if *ps2if = io->driver;
struct ps2if *ps2if = io->port_data;
unsigned long flags;
unsigned int head;
......@@ -122,7 +122,7 @@ static int ps2_write(struct serio *io, unsigned char val)
static int ps2_open(struct serio *io)
{
struct ps2if *ps2if = io->driver;
struct ps2if *ps2if = io->port_data;
int ret;
sa1111_enable_device(ps2if->dev);
......@@ -154,7 +154,7 @@ static int ps2_open(struct serio *io)
static void ps2_close(struct serio *io)
{
struct ps2if *ps2if = io->driver;
struct ps2if *ps2if = io->port_data;
sa1111_writel(0, ps2if->base + SA1111_PS2CR);
......@@ -232,22 +232,28 @@ static int __init ps2_test(struct ps2if *ps2if)
static int ps2_probe(struct sa1111_dev *dev)
{
struct ps2if *ps2if;
struct serio *serio;
int ret;
ps2if = kmalloc(sizeof(struct ps2if), GFP_KERNEL);
if (!ps2if) {
return -ENOMEM;
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (!ps2if || !serio) {
ret = -ENOMEM;
goto free;
}
memset(ps2if, 0, sizeof(struct ps2if));
ps2if->io.type = SERIO_8042;
ps2if->io.write = ps2_write;
ps2if->io.open = ps2_open;
ps2if->io.close = ps2_close;
ps2if->io.name = dev->dev.bus_id;
ps2if->io.phys = dev->dev.bus_id;
ps2if->io.driver = ps2if;
memset(serio, 0, sizeof(struct serio));
serio->type = SERIO_8042;
serio->write = ps2_write;
serio->open = ps2_open;
serio->close = ps2_close;
strlcpy(serio->name, dev->dev.bus_id, sizeof(serio->name));
strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
serio->port_data = ps2if;
serio->dev.parent = &dev->dev;
ps2if->io = serio;
ps2if->dev = dev;
sa1111_set_drvdata(dev, ps2if);
......@@ -292,7 +298,7 @@ static int ps2_probe(struct sa1111_dev *dev)
ps2_clear_input(ps2if);
sa1111_disable_device(ps2if->dev);
serio_register_port(&ps2if->io);
serio_register_port(ps2if->io);
return 0;
out:
......@@ -302,6 +308,7 @@ static int ps2_probe(struct sa1111_dev *dev)
free:
sa1111_set_drvdata(dev, NULL);
kfree(ps2if);
kfree(serio);
return ret;
}
......@@ -312,7 +319,7 @@ static int ps2_remove(struct sa1111_dev *dev)
{
struct ps2if *ps2if = sa1111_get_drvdata(dev);
serio_unregister_port(&ps2if->io);
serio_unregister_port(ps2if->io);
release_mem_region(dev->res.start,
dev->res.end - dev->res.start + 1);
sa1111_set_drvdata(dev, NULL);
......
This diff is collapsed.
/*
* Raw serio device providing access to a raw byte stream from underlying
* serio port. Closely emulates behavior of pre-2.6 /dev/psaux device
*
* Copyright (c) 2004 Dmitry Torokhov
*
* 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/slab.h>
#include <linux/poll.h>
#include <linux/module.h>
#include <linux/serio.h>
#include <linux/init.h>
#include <linux/major.h>
#include <linux/device.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/miscdevice.h>
#include <linux/wait.h>
#define DRIVER_DESC "Raw serio driver"
MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
#define SERIO_RAW_QUEUE_LEN 64
struct serio_raw {
unsigned char queue[SERIO_RAW_QUEUE_LEN];
unsigned int tail, head;
char name[16];
unsigned int refcnt;
struct serio *serio;
struct miscdevice dev;
wait_queue_head_t wait;
struct list_head list;
struct list_head node;
};
struct serio_raw_list {
struct fasync_struct *fasync;
struct serio_raw *serio_raw;
struct list_head node;
};
static DECLARE_MUTEX(serio_raw_sem);
static LIST_HEAD(serio_raw_list);
static unsigned int serio_raw_no;
/*********************************************************************
* Interface with userspace (file operations) *
*********************************************************************/
static int serio_raw_fasync(int fd, struct file *file, int on)
{
struct serio_raw_list *list = file->private_data;
int retval;
retval = fasync_helper(fd, file, on, &list->fasync);
return retval < 0 ? retval : 0;
}
static struct serio_raw *serio_raw_locate(int minor)
{
struct serio_raw *serio_raw;
list_for_each_entry(serio_raw, &serio_raw_list, node) {
if (serio_raw->dev.minor == minor)
return serio_raw;
}
return NULL;
}
static int serio_raw_open(struct inode *inode, struct file *file)
{
struct serio_raw *serio_raw;
struct serio_raw_list *list;
int retval = 0;
retval = down_interruptible(&serio_raw_sem);
if (retval)
return retval;
if (!(serio_raw = serio_raw_locate(iminor(inode)))) {
retval = -ENODEV;
goto out;
}
if (!serio_raw->serio) {
retval = -ENODEV;
goto out;
}
if (!(list = kmalloc(sizeof(struct serio_raw_list), GFP_KERNEL))) {
retval = -ENOMEM;
goto out;
}
memset(list, 0, sizeof(struct serio_raw_list));
list->serio_raw = serio_raw;
file->private_data = list;
serio_raw->refcnt++;
list_add_tail(&list->node, &serio_raw->list);
out:
up(&serio_raw_sem);
return retval;
}
static int serio_raw_cleanup(struct serio_raw *serio_raw)
{
if (--serio_raw->refcnt == 0) {
misc_deregister(&serio_raw->dev);
list_del_init(&serio_raw->node);
kfree(serio_raw);
return 1;
}
return 0;
}
static int serio_raw_release(struct inode *inode, struct file *file)
{
struct serio_raw_list *list = file->private_data;
struct serio_raw *serio_raw = list->serio_raw;
down(&serio_raw_sem);
serio_raw_fasync(-1, file, 0);
serio_raw_cleanup(serio_raw);
up(&serio_raw_sem);
return 0;
}
static int serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
{
unsigned long flags;
int empty;
spin_lock_irqsave(&serio_raw->serio->lock, flags);
empty = serio_raw->head == serio_raw->tail;
if (!empty) {
*c = serio_raw->queue[serio_raw->tail];
serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN;
}
spin_unlock_irqrestore(&serio_raw->serio->lock, flags);
return !empty;
}
static ssize_t serio_raw_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
struct serio_raw_list *list = file->private_data;
struct serio_raw *serio_raw = list->serio_raw;
char c;
ssize_t retval = 0;
if (!serio_raw->serio)
return -ENODEV;
if (serio_raw->head == serio_raw->tail && (file->f_flags & O_NONBLOCK))
return -EAGAIN;
retval = wait_event_interruptible(list->serio_raw->wait,
serio_raw->head != serio_raw->tail || !serio_raw->serio);
if (retval)
return retval;
if (!serio_raw->serio)
return -ENODEV;
while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) {
if (put_user(c, buffer++))
return -EFAULT;
retval++;
}
return retval;
}
static ssize_t serio_raw_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
struct serio_raw_list *list = file->private_data;
ssize_t written = 0;
int retval;
unsigned char c;
retval = down_interruptible(&serio_raw_sem);
if (retval)
return retval;
if (!list->serio_raw->serio) {
retval = -ENODEV;
goto out;
}
if (count > 32)
count = 32;
while (count--) {
if (get_user(c, buffer++)) {
retval = -EFAULT;
goto out;
}
if (serio_write(list->serio_raw->serio, c)) {
retval = -EIO;
goto out;
}
written++;
};
out:
up(&serio_raw_sem);
return written;
}
static unsigned int serio_raw_poll(struct file *file, poll_table *wait)
{
struct serio_raw_list *list = file->private_data;
poll_wait(file, &list->serio_raw->wait, wait);
if (list->serio_raw->head != list->serio_raw->tail)
return POLLIN | POLLRDNORM;
return 0;
}
struct file_operations serio_raw_fops = {
.owner = THIS_MODULE,
.open = serio_raw_open,
.release = serio_raw_release,
.read = serio_raw_read,
.write = serio_raw_write,
.poll = serio_raw_poll,
.fasync = serio_raw_fasync,
};
/*********************************************************************
* Interface with serio port *
*********************************************************************/
static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data,
unsigned int dfl, struct pt_regs *regs)
{
struct serio_raw *serio_raw = serio->private;
struct serio_raw_list *list;
unsigned int head = serio_raw->head;
/* we are holding serio->lock here so we are prootected */
serio_raw->queue[head] = data;
head = (head + 1) % SERIO_RAW_QUEUE_LEN;
if (likely(head != serio_raw->tail)) {
serio_raw->head = head;
list_for_each_entry(list, &serio_raw->list, node)
kill_fasync(&list->fasync, SIGIO, POLL_IN);
wake_up_interruptible(&serio_raw->wait);
}
return IRQ_HANDLED;
}
static void serio_raw_connect(struct serio *serio, struct serio_driver *drv)
{
struct serio_raw *serio_raw;
int err;
if ((serio->type & SERIO_TYPE) != SERIO_8042)
return;
if (!(serio_raw = kmalloc(sizeof(struct serio_raw), GFP_KERNEL))) {
printk(KERN_ERR "serio_raw.c: can't allocate memory for a device\n");
return;
}
down(&serio_raw_sem);
memset(serio_raw, 0, sizeof(struct serio_raw));
snprintf(serio_raw->name, sizeof(serio_raw->name), "serio_raw%d", serio_raw_no++);
serio_raw->refcnt = 1;
serio_raw->serio = serio;
INIT_LIST_HEAD(&serio_raw->list);
init_waitqueue_head(&serio_raw->wait);
serio->private = serio_raw;
if (serio_open(serio, drv))
goto out_free;
list_add_tail(&serio_raw->node, &serio_raw_list);
serio_raw->dev.minor = PSMOUSE_MINOR;
serio_raw->dev.name = serio_raw->name;
serio_raw->dev.fops = &serio_raw_fops;
err = misc_register(&serio_raw->dev);
if (err) {
serio_raw->dev.minor = MISC_DYNAMIC_MINOR;
err = misc_register(&serio_raw->dev);
}
if (err) {
printk(KERN_INFO "serio_raw: failed to register raw access device for %s\n",
serio->phys);
goto out_close;
}
printk(KERN_INFO "serio_raw: raw access enabled on %s (%s, minor %d)\n",
serio->phys, serio_raw->name, serio_raw->dev.minor);
goto out;
out_close:
serio_close(serio);
list_del_init(&serio_raw->node);
out_free:
serio->private = NULL;
kfree(serio_raw);
out:
up(&serio_raw_sem);
}
static int serio_raw_reconnect(struct serio *serio)
{
struct serio_raw *serio_raw = serio->private;
struct serio_driver *drv = serio->drv;
if (!drv || !serio_raw) {
printk(KERN_DEBUG "serio_raw: reconnect request, but serio is disconnected, ignoring...\n");
return -1;
}
/*
* Nothing needs to be done here, we just need this method to
* keep the same device.
*/
return 0;
}
static void serio_raw_disconnect(struct serio *serio)
{
struct serio_raw *serio_raw;
down(&serio_raw_sem);
serio_raw = serio->private;
serio_close(serio);
serio->private = NULL;
serio_raw->serio = NULL;
if (!serio_raw_cleanup(serio_raw))
wake_up_interruptible(&serio_raw->wait);
up(&serio_raw_sem);
}
static struct serio_driver serio_raw_drv = {
.driver = {
.name = "serio_raw",
},
.description = DRIVER_DESC,
.interrupt = serio_raw_interrupt,
.connect = serio_raw_connect,
.reconnect = serio_raw_reconnect,
.disconnect = serio_raw_disconnect,
.manual_bind = 1,
};
int __init serio_raw_init(void)
{
serio_register_driver(&serio_raw_drv);
return 0;
}
void __exit serio_raw_exit(void)
{
serio_unregister_driver(&serio_raw_drv);
}
module_init(serio_raw_init);
module_exit(serio_raw_exit);
......@@ -31,28 +31,25 @@ MODULE_ALIAS_LDISC(N_MOUSE);
struct serport {
struct tty_struct *tty;
wait_queue_head_t wait;
struct serio serio;
struct serio *serio;
unsigned long flags;
char phys[32];
};
char serport_name[] = "Serial port";
/*
* Callback functions from the serio code.
*/
static int serport_serio_write(struct serio *serio, unsigned char data)
{
struct serport *serport = serio->driver;
struct serport *serport = serio->port_data;
return -(serport->tty->driver->write(serport->tty, 0, &data, 1) != 1);
}
static void serport_serio_close(struct serio *serio)
{
struct serport *serport = serio->driver;
struct serport *serport = serio->port_data;
serport->serio.type = 0;
serport->serio->type = 0;
wake_up_interruptible(&serport->wait);
}
......@@ -64,26 +61,30 @@ static void serport_serio_close(struct serio *serio)
static int serport_ldisc_open(struct tty_struct *tty)
{
struct serport *serport;
struct serio *serio;
char name[64];
serport = kmalloc(sizeof(struct serport), GFP_KERNEL);
if (unlikely(!serport))
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (unlikely(!serport || !serio)) {
kfree(serport);
kfree(serio);
return -ENOMEM;
memset(serport, 0, sizeof(struct serport));
}
memset(serport, 0, sizeof(struct serport));
serport->serio = serio;
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
serport->tty = tty;
tty->disc_data = serport;
snprintf(serport->phys, sizeof(serport->phys), "%s/serio0", tty_name(tty, name));
serport->serio.name = serport_name;
serport->serio.phys = serport->phys;
serport->serio.type = SERIO_RS232;
serport->serio.write = serport_serio_write;
serport->serio.close = serport_serio_close;
serport->serio.driver = serport;
memset(serio, 0, sizeof(struct serio));
strlcpy(serio->name, "Serial port", sizeof(serio->name));
snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", tty_name(tty, name));
serio->type = SERIO_RS232;
serio->write = serport_serio_write;
serio->close = serport_serio_close;
serio->port_data = serport;
init_waitqueue_head(&serport->wait);
......@@ -114,7 +115,7 @@ static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *c
struct serport *serport = (struct serport*) tty->disc_data;
int i;
for (i = 0; i < count; i++)
serio_interrupt(&serport->serio, cp[i], 0, NULL);
serio_interrupt(serport->serio, cp[i], 0, NULL);
}
/*
......@@ -142,10 +143,10 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
if (test_and_set_bit(SERPORT_BUSY, &serport->flags))
return -EBUSY;
serio_register_port(&serport->serio);
serio_register_port(serport->serio);
printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name));
wait_event_interruptible(serport->wait, !serport->serio.type);
serio_unregister_port(&serport->serio);
wait_event_interruptible(serport->wait, !serport->serio->type);
serio_unregister_port(serport->serio);
clear_bit(SERPORT_BUSY, &serport->flags);
......@@ -161,7 +162,7 @@ static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsi
struct serport *serport = (struct serport*) tty->disc_data;
if (cmd == SPIOCSTYPE)
return get_user(serport->serio.type, (unsigned long __user *) arg);
return get_user(serport->serio->type, (unsigned long __user *) arg);
return -EINVAL;
}
......@@ -170,7 +171,7 @@ static void serport_ldisc_write_wakeup(struct tty_struct * tty)
{
struct serport *sp = (struct serport *) tty->disc_data;
serio_dev_write_wakeup(&sp->serio);
serio_drv_write_wakeup(sp->serio);
}
/*
......
......@@ -36,8 +36,10 @@
#include <linux/serio.h>
#include <linux/init.h>
#define DRIVER_DESC "Gunze AHL-51S touchscreen driver"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Gunze AHL-51S touchscreen driver");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
/*
......@@ -111,7 +113,7 @@ static void gunze_disconnect(struct serio *serio)
* and if yes, registers it as an input device.
*/
static void gunze_connect(struct serio *serio, struct serio_dev *dev)
static void gunze_connect(struct serio *serio, struct serio_driver *drv)
{
struct gunze *gunze;
......@@ -142,7 +144,7 @@ static void gunze_connect(struct serio *serio, struct serio_dev *dev)
gunze->dev.id.product = 0x0051;
gunze->dev.id.version = 0x0100;
if (serio_open(serio, dev)) {
if (serio_open(serio, drv)) {
kfree(gunze);
return;
}
......@@ -156,7 +158,11 @@ static void gunze_connect(struct serio *serio, struct serio_dev *dev)
* The serio device structure.
*/
static struct serio_dev gunze_dev = {
static struct serio_driver gunze_drv = {
.driver = {
.name = "gunze",
},
.description = DRIVER_DESC,
.interrupt = gunze_interrupt,
.connect = gunze_connect,
.disconnect = gunze_disconnect,
......@@ -168,13 +174,13 @@ static struct serio_dev gunze_dev = {
int __init gunze_init(void)
{
serio_register_device(&gunze_dev);
serio_register_driver(&gunze_drv);
return 0;
}
void __exit gunze_exit(void)
{
serio_unregister_device(&gunze_dev);
serio_unregister_driver(&gunze_drv);
}
module_init(gunze_init);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -115,6 +115,8 @@
#include <linux/filter.h>
#include <linux/msdos_fs.h>
#include <linux/hiddev.h>
#undef INCLUDES
#endif
......
This diff is collapsed.
This diff is collapsed.
......@@ -527,6 +527,8 @@ struct input_absinfo {
#define MSC_SERIAL 0x00
#define MSC_PULSELED 0x01
#define MSC_GESTURE 0x02
#define MSC_RAW 0x03
#define MSC_SCAN 0x04
#define MSC_MAX 0x07
/*
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment