Commit 29886383 authored by Vojtech Pavlik's avatar Vojtech Pavlik

Add keyboard, mouse and touchscreen drivers.

Add tsdev, power and evbug event handlers.
parent b65e5bd5
...@@ -64,6 +64,18 @@ CONFIG_INPUT_JOYDEV ...@@ -64,6 +64,18 @@ CONFIG_INPUT_JOYDEV
The module will be called joydev.o. If you want to compile it as a The module will be called joydev.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>. module, say M here and read <file:Documentation/modules.txt>.
CONFIG_INPUT_TSDEV
Say Y here if you have an application that only can understand the
Compaq touchscreen protocol for absolute pointer data. This is
useful namely for embedded configurations.
If unsure, say N.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called tsdev.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_INPUT_EVDEV CONFIG_INPUT_EVDEV
Say Y here if you want your input device events be accessible Say Y here if you want your input device events be accessible
under char device 13:64+ - /dev/input/eventX in a generic way. under char device 13:64+ - /dev/input/eventX in a generic way.
...@@ -72,3 +84,17 @@ CONFIG_INPUT_EVDEV ...@@ -72,3 +84,17 @@ CONFIG_INPUT_EVDEV
inserted in and removed from the running kernel whenever you want). inserted in and removed from the running kernel whenever you want).
The module will be called evdev.o. If you want to compile it as a The module will be called evdev.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>. module, say M here and read <file:Documentation/modules.txt>.
CONFIG_INPUT_EVBUG
Say Y here if you have a problem with the input subsystem and
want all events (keypresses, mouse movements), to be output to
the system log. While this is useful for debugging, it's also
a security threat - your keypresses include your passwords, of
course.
If unsure, say N.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called joydev.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
...@@ -6,20 +6,34 @@ mainmenu_option next_comment ...@@ -6,20 +6,34 @@ mainmenu_option next_comment
comment 'Input device support' comment 'Input device support'
tristate 'Input core support' CONFIG_INPUT tristate 'Input core support' CONFIG_INPUT
comment 'Userland interfaces'
dep_tristate ' Keyboard interface' CONFIG_INPUT_KEYBDEV $CONFIG_INPUT dep_tristate ' Keyboard interface' CONFIG_INPUT_KEYBDEV $CONFIG_INPUT
dep_tristate ' Mouse interface' CONFIG_INPUT_MOUSEDEV $CONFIG_INPUT dep_tristate ' Mouse interface' CONFIG_INPUT_MOUSEDEV $CONFIG_INPUT
dep_mbool ' Provide legacy /dev/psaux device' CONFIG_INPUT_MOUSEDEV_PSAUX $CONFIG_INPUT
if [ "$CONFIG_INPUT_MOUSEDEV" != "n" ]; then if [ "$CONFIG_INPUT_MOUSEDEV" != "n" ]; then
int ' Horizontal screen resolution' CONFIG_INPUT_MOUSEDEV_SCREEN_X 1024 int ' Horizontal screen resolution' CONFIG_INPUT_MOUSEDEV_SCREEN_X 1024
int ' Vertical screen resolution' CONFIG_INPUT_MOUSEDEV_SCREEN_Y 768 int ' Vertical screen resolution' CONFIG_INPUT_MOUSEDEV_SCREEN_Y 768
fi fi
dep_tristate ' Joystick interface' CONFIG_INPUT_JOYDEV $CONFIG_INPUT dep_tristate ' Joystick interface' CONFIG_INPUT_JOYDEV $CONFIG_INPUT
dep_tristate ' Touchscreen interface' CONFIG_INPUT_TSDEV $CONFIG_INPUT
if [ "$CONFIG_INPUT_TSDEV" != "n" ]; then
int ' Horizontal screen resolution' CONFIG_INPUT_TSDEV_SCREEN_X 240
int ' Vertical screen resolution' CONFIG_INPUT_TSDEV_SCREEN_Y 320
fi
dep_tristate ' Event interface' CONFIG_INPUT_EVDEV $CONFIG_INPUT dep_tristate ' Event interface' CONFIG_INPUT_EVDEV $CONFIG_INPUT
dep_tristate ' Event debugging' CONFIG_INPUT_EVBUG $CONFIG_INPUT
comment 'Input I/O drivers'
source drivers/input/gameport/Config.in source drivers/input/gameport/Config.in
source drivers/input/serio/Config.in source drivers/input/serio/Config.in
comment 'Input Device Drivers'
if [ "$CONFIG_INPUT" != "n" ]; then if [ "$CONFIG_INPUT" != "n" ]; then
source drivers/input/keyboard/Config.in
source drivers/input/mouse/Config.in
source drivers/input/joystick/Config.in source drivers/input/joystick/Config.in
source drivers/input/touchscreen/Config.in
fi fi
endmenu endmenu
...@@ -13,8 +13,14 @@ obj-$(CONFIG_INPUT_KEYBDEV) += keybdev.o ...@@ -13,8 +13,14 @@ obj-$(CONFIG_INPUT_KEYBDEV) += keybdev.o
obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o
obj-$(CONFIG_INPUT_JOYDEV) += joydev.o obj-$(CONFIG_INPUT_JOYDEV) += joydev.o
obj-$(CONFIG_INPUT_EVDEV) += evdev.o obj-$(CONFIG_INPUT_EVDEV) += evdev.o
obj-$(CONFIG_INPUT_TSDEV) += tsdev.o
obj-$(CONFIG_INPUT_POWER) += power.o
obj-$(CONFIG_INPUT_EVBUG) += evbug.o
obj-$(CONFIG_INPUT_KEYBOARD) += keyboard/
obj-$(CONFIG_INPUT_MOUSE) += mouse/
obj-$(CONFIG_INPUT_JOYSTICK) += joystick/ obj-$(CONFIG_INPUT_JOYSTICK) += joystick/
obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/
# The global Rules.make. # The global Rules.make.
......
/*
* $Id: evbug.c,v 1.10 2001/09/25 10:12:07 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
/*
* Input driver event debug module - dumps all events into syslog
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/init.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Input driver event debug module");
MODULE_LICENSE("GPL");
static void evbug_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
{
printk(KERN_DEBUG "evbug.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d\n", handle->dev->phys, type, code, value);
}
static struct input_handle *evbug_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
{
struct input_handle *handle;
if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
return NULL;
memset(handle, 0, sizeof(struct input_handle));
handle->dev = dev;
handle->handler = handler;
input_open_device(handle);
printk(KERN_DEBUG "evbug.c: Connected device: \"%s\", %s\n", dev->name, dev->phys);
return handle;
}
static void evbug_disconnect(struct input_handle *handle)
{
printk(KERN_DEBUG "evbug.c: Disconnected device: %s\n", handle->dev->phys);
input_close_device(handle);
kfree(handle);
}
static struct input_device_id evbug_ids[] = {
{ driver_info: 1 }, /* Matches all devices */
{ }, /* Terminating zero entry */
};
MODULE_DEVICE_TABLE(input, evbug_ids);
static struct input_handler evbug_handler = {
event: evbug_event,
connect: evbug_connect,
disconnect: evbug_disconnect,
name: "evbug",
id_table: evbug_ids,
};
int __init evbug_init(void)
{
input_register_handler(&evbug_handler);
return 0;
}
void __exit evbug_exit(void)
{
input_unregister_handler(&evbug_handler);
}
module_init(evbug_init);
module_exit(evbug_exit);
CONFIG_INPUT_KEYBOARD
Say Y here, and a list of supported keyboards will be displayed.
This option doesn't affect the kernel.
If unsure, say Y.
CONFIG_KEYBOARD_ATKBD
Say Y here if you want to use the standard AT keyboard. Usually
you'll need this, unless you have a different type keyboard (USB,
ADB or other).
If unsure, say Y.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called atkbd.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_KEYBOARD_SUNKBD
Say Y here if you want to use a Sun Type 4 or Type 5 keyboard,
connected either to the Sun keyboard connector or to an serial
(RS-232) port via a simple adapter.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called sunkbd.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_KEYBOARD_PS2SERKBD
Say Y here if you want to use a PS/2 to Serial converter with a
keyboard attached to it.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called ps2serkbd.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_KEYBOARD_XTKBD
Say Y here if you want to use the old IBM PC/XT keyboard (or
compatible) on your system. This is only possible with a
parallel port keyboard adapter, you cannot connect it to the
keyboard port on a PC that runs Linux.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called xtkbd.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_KEYBOARD_MAPLE
Say Y here if you have a DreamCast console running Linux and have
a keyboard attached to its Maple bus.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called maple_keyb.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_KEYBOARD_AMIGA
Say Y here if you are running Linux on any AMIGA and have a keyboard
attached.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called amikbd.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
#
# Input core configuration
#
bool 'Keyboards' CONFIG_INPUT_KEYBOARD
dep_tristate ' AT keyboard support' CONFIG_KEYBOARD_ATKBD $CONFIG_INPUT $CONFIG_INPUT_KEYBOARD $CONFIG_SERIO
dep_tristate ' Sun Type 4 and Type 5 keyboard support' CONFIG_KEYBOARD_SUNKBD $CONFIG_INPUT $CONFIG_INPUT_KEYBOARD $CONFIG_SERIO
dep_tristate ' PS/2 to Serial converter support' CONFIG_KEYBOARD_PS2SERKBD $CONFIG_INPUT $CONFIG_INPUT_KEYBOARD $CONFIG_SERIO
dep_tristate ' XT Keyboard support' CONFIG_KEYBOARD_XTKBD $CONFIG_INPUT $CONFIG_INPUT_KEYBOARD $CONFIG_SERIO
if [ "$CONFIG_SH_DREAMCAST" = "y" ]; then
dep_tristate ' Maple bus keyboard support' CONFIG_KEYBOARD_MAPLE $CONFIG_INPUT $CONFIG_INPUT_KEYBOARD $CONFIG_MAPLE
fi
if [ "$CONFIG_AMIGA" = "y" ]; then
dep_tristate ' Amiga keyboard' CONFIG_KEYBOARD_AMIGA $CONFIG_INPUT $CONFIG_INPUT_KEYBOARD
fi
#
# Makefile for the input core drivers.
#
# The target object and module list name.
O_TARGET := keybdrv.o
# Each configuration option enables a list of files.
obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o
obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o
obj-$(CONFIG_KEYBOARD_PS2SERKBD) += ps2serkbd.o
obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o
# The global Rules.make.
include $(TOPDIR)/Rules.make
/*
* $Id: amikbd.c,v 1.13 2002/02/01 16:02:24 vojtech Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik
*
* Based on the work of:
* Hamish Macdonald
*/
/*
* Amiga keyboard driver for Linux/m68k
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
#include <asm/amigaints.h>
#include <asm/amigahw.h>
#include <asm/irq.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Amiga keyboard driver");
MODULE_LICENSE("GPL");
static unsigned char amikbd_keycode[0x78] = {
41, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 43, 0, 82,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 0, 79, 80, 81,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 0, 75, 76, 77,
0, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 0, 83, 71, 72, 73,
57, 14, 15, 96, 28, 1,111, 0, 0, 0, 74, 0,103,108,106,105,
59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 98, 55, 78, 87,
42, 54, 58, 29, 56,100
}
static char *amikbd_messages[] = {
KERN_ALERT "amikbd: Ctrl-Amiga-Amiga reset warning!!\n",
KERN_WARNING "amikbd: keyboard lost sync\n",
KERN_WARNING "amikbd: keyboard buffer overflow\n",
KERN_WARNING "amikbd: keyboard controller failure\n",
KERN_ERR "amikbd: keyboard selftest failure\n",
KERN_INFO "amikbd: initiate power-up key stream\n",
KERN_INFO "amikbd: terminate power-up key stream\n",
KERN_WARNING "amikbd: keyboard interrupt\n"
};
static struct input_dev amikbd_dev;
static char *amikbd_name = "Amiga keyboard";
static char *amikbd_phys = "amikbd/input0";
static void amikbd_interrupt(int irq, void *dummy, struct pt_regs *fp)
{
unsigned char scancode, down;
scancode = ~ciaa.sdr; /* get and invert scancode (keyboard is active low) */
ciaa.cra |= 0x40; /* switch SP pin to output for handshake */
udelay(85); /* wait until 85 us have expired */
ciaa.cra &= ~0x40; /* switch CIA serial port to input mode */
down = scancode & 1; /* lowest bit is release bit */
scancode = scancode >> 1;
if (scancode < 0x78) { /* scancodes < 0x78 are keys */
scancode = amikbd_keycode[scancode];
if (scancode == KEY_CAPS) { /* CapsLock is a toggle switch key on Amiga */
input_report_key(&amikbd_dev, scancode, 1);
input_report_key(&amikbd_dev, scancode, 0);
return;
}
input_report_key(&amikbd_dev, scancode, down);
return;
}
printk(amikbd_messages[scancode - 0x78]); /* scancodes >= 0x78 are error codes */
}
static int __init amikbd_init(void)
{
int i;
if (!AMIGAHW_PRESENT(AMI_KEYBOARD))
return -EIO;
if (!request_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100, "amikeyb"))
return -EBUSY;
amikbd_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
amikbd_dev.keycode = amikbd_keycode;
for (i = 0; i < 0x78; i++)
if (amikbd_keycode[i])
set_bit(amikbd_keycode[i], amikbd_dev.keybit);
ciaa.cra &= ~0x41; /* serial data in, turn off TA */
request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", NULL);
amikbd_dev.name = amikbd_name;
amikbd_dev.phys = amikbd_phys;
amikbd_dev.idbus = BUS_AMIGA;
amikbd_dev.idvendor = 0x0001;
amikbd_dev.idproduct = 0x0001;
amikbd_dev.idversion = 0x0100;
input_register_device(&amikbd_dev);
printk(KERN_INFO "input: %s\n", amikbd_name);
return 0;
}
static void __exit amikbd_exit(void)
{
input_unregister_device(&amikbd_dev);
free_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt);
release_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100);
}
module_init(amikbd_init);
module_exit(amikbd_exit);
This diff is collapsed.
/*
* $Id: maple_keyb.c,v 1.1 2001/11/02 17:27:32 jsimmons Exp $
* SEGA Dreamcast keyboard driver
* Based on drivers/usb/usbkbd.c
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/maple.h>
MODULE_AUTHOR("YAEGASHI Takeshi <t@keshi.org>");
MODULE_DESCRIPTION("SEGA Dreamcast keyboard driver");
static unsigned char dc_kbd_keycode[256] = {
0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
27, 43, 84, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
72, 73, 82, 83, 86,127,116,117, 85, 89, 90, 91, 92, 93, 94, 95,
120,121,122,123,134,138,130,132,128,129,131,137,133,135,136,113,
115,114, 0, 0, 0,124, 0,181,182,183,184,185,186,187,188,189,
190,191,192,193,194,195,196,197,198, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
150,158,159,128,136,177,178,176,142,152,173,140
};
struct dc_kbd {
struct input_dev dev;
unsigned char new[8];
unsigned char old[8];
int open;
};
static void dc_scan_kbd(struct dc_kbd *kbd)
{
int i;
struct input_dev *dev = &kbd->dev;
for(i=0; i<8; i++)
input_report_key(dev,
dc_kbd_keycode[i+224],
(kbd->new[0]>>i)&1);
for(i=2; i<8; i++) {
if(kbd->old[i]>3&&memscan(kbd->new+2, kbd->old[i], 6)==NULL) {
if(dc_kbd_keycode[kbd->old[i]])
input_report_key(dev,
dc_kbd_keycode[kbd->old[i]],
0);
else
printk("Unknown key (scancode %#x) released.",
kbd->old[i]);
}
if(kbd->new[i]>3&&memscan(kbd->old+2, kbd->new[i], 6)!=NULL) {
if(dc_kbd_keycode[kbd->new[i]])
input_report_key(dev,
dc_kbd_keycode[kbd->new[i]],
1);
else
printk("Unknown key (scancode %#x) pressed.",
kbd->new[i]);
}
}
memcpy(kbd->old, kbd->new, 8);
}
static void dc_kbd_callback(struct mapleq *mq)
{
struct maple_device *mapledev = mq->dev;
struct dc_kbd *kbd = mapledev->private_data;
unsigned long *buf = mq->recvbuf;
if (buf[1] == mapledev->function) {
memcpy(kbd->new, buf+2, 8);
dc_scan_kbd(kbd);
}
}
static int dc_kbd_open(struct input_dev *dev)
{
struct dc_kbd *kbd = dev->private;
kbd->open++;
return 0;
}
static void dc_kbd_close(struct input_dev *dev)
{
struct dc_kbd *kbd = dev->private;
kbd->open--;
}
static int dc_kbd_connect(struct maple_device *dev)
{
int i;
unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
struct dc_kbd *kbd;
if (!(kbd = kmalloc(sizeof(struct dc_kbd), GFP_KERNEL)))
return -1;
memset(kbd, 0, sizeof(struct dc_kbd));
dev->private_data = kbd;
kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
for (i=0; i<255; i++)
set_bit(dc_kbd_keycode[i], kbd->dev.keybit);
clear_bit(0, kbd->dev.keybit);
kbd->dev.private = kbd;
kbd->dev.open = dc_kbd_open;
kbd->dev.close = dc_kbd_close;
kbd->dev.event = NULL;
kbd->dev.name = dev->product_name;
kbd->dev.idbus = BUS_MAPLE;
input_register_device(&kbd->dev);
maple_getcond_callback(dev, dc_kbd_callback, 1, MAPLE_FUNC_KEYBOARD);
printk(KERN_INFO "input%d: keyboard(0x%lx): %s\n",
kbd->dev.number, data, kbd->dev.name);
MOD_INC_USE_COUNT;
return 0;
}
static void dc_kbd_disconnect(struct maple_device *dev)
{
struct dc_kbd *kbd = dev->private_data;
input_unregister_device(&kbd->dev);
kfree(kbd);
MOD_DEC_USE_COUNT;
}
static struct maple_driver dc_kbd_driver = {
function: MAPLE_FUNC_KEYBOARD,
name: "Dreamcast keyboard",
connect: dc_kbd_connect,
disconnect: dc_kbd_disconnect,
};
static int __init dc_kbd_init(void)
{
maple_register_driver(&dc_kbd_driver);
return 0;
}
static void __exit dc_kbd_exit(void)
{
maple_unregister_driver(&dc_kbd_driver);
}
module_init(dc_kbd_init);
module_exit(dc_kbd_exit);
/*
* Local variables:
* c-basic-offset: 8
* End:
*/
/*
* based on: sunkbd.c and ps2serkbd.c
*
* $Id: ps2serkbd.c,v 1.5 2001/09/25 10:12:07 vojtech Exp $
*/
/*
* PS/2 keyboard via adapter at serial port driver for Linux
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/tqueue.h>
#define ATKBD_CMD_SETLEDS 0x10ed
#define ATKBD_CMD_GSCANSET 0x11f0
#define ATKBD_CMD_SSCANSET 0x10f0
#define ATKBD_CMD_GETID 0x02f2
#define ATKBD_CMD_ENABLE 0x00f4
#define ATKBD_CMD_RESET_DIS 0x00f5
#define ATKBD_CMD_SETALL_MB 0x00f8
#define ATKBD_CMD_EX_ENABLE 0x10ea
#define ATKBD_CMD_EX_SETLEDS 0x20eb
#define ATKBD_RET_ACK 0xfa
#define ATKBD_RET_NAK 0xfe
#define ATKBD_KEY_UNKNOWN 0
#define ATKBD_KEY_BAT 251
#define ATKBD_KEY_EMUL0 252
#define ATKBD_KEY_EMUL1 253
#define ATKBD_KEY_RELEASE 254
#define ATKBD_KEY_NULL 255
static unsigned char ps2serkbd_set2_keycode[512] = {
0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41, 85,
0, 56, 42, 0, 29, 16, 2, 89, 0, 0, 44, 31, 30, 17, 3, 90,
0, 46, 45, 32, 18, 5, 4, 91, 0, 57, 47, 33, 20, 19, 6, 0,
0, 49, 48, 35, 34, 21, 7, 0, 0, 0, 50, 36, 22, 8, 9, 0,
0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0,
122, 89, 40,120, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 0,
85, 86, 90, 91, 92, 93, 14, 94, 95, 79, 0, 75, 71,121, 0,123,
82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
252, 0, 0, 65, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,251, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
252,253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,
0, 0, 92, 90, 85, 0,137, 0, 0, 0, 0, 91, 89,144,115, 0,
136,100,255, 0, 97,149,164, 0,156, 0, 0,140,115, 0, 0,125,
0,150, 0,154,152,163,151,126,112,166, 0,140, 0,147, 0,127,
159,167,139,160,163, 0, 0,116,158, 0,150,165, 0, 0, 0,142,
157, 0,114,166,168, 0, 0, 0,155, 0, 98,113, 0,148, 0,138,
0, 0, 0, 0, 0, 0,153,140, 0, 0, 96, 0, 0, 0,143, 0,
133, 0,116, 0,143, 0,174,133, 0,107, 0,105,102, 0, 0,112,
110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119
};
/*
* Per-keyboard data.
*/
struct ps2serkbd {
unsigned char keycode[512];
struct input_dev dev;
struct serio *serio;
char name[64];
char phys[32];
struct tq_struct tq;
unsigned char cmdbuf[4];
unsigned char cmdcnt;
unsigned char set;
char release;
char ack;
char emul;
char error;
unsigned short id;
};
/*
* ps2serkbd_interrupt() is called by the low level driver when a character
* is received.
*/
static void ps2serkbd_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
{
static int event_count=0;
struct ps2serkbd* ps2serkbd = serio->private;
int code=data;
#if 0
printk(KERN_WARNING "ps2serkbd.c(%8d): (scancode %#x)\n", event_count, data);
#endif
event_count++;
switch (code) {
case ATKBD_RET_ACK:
ps2serkbd->ack = 1;
return;
case ATKBD_RET_NAK:
ps2serkbd->ack = -1;
return;
}
if (ps2serkbd->cmdcnt) {
ps2serkbd->cmdbuf[--ps2serkbd->cmdcnt] = code;
return;
}
switch (ps2serkbd->keycode[code]) {
case ATKBD_KEY_BAT:
queue_task(&ps2serkbd->tq, &tq_immediate);
mark_bh(IMMEDIATE_BH);
return;
case ATKBD_KEY_EMUL0:
ps2serkbd->emul = 1;
return;
case ATKBD_KEY_EMUL1:
ps2serkbd->emul = 2;
return;
case ATKBD_KEY_RELEASE:
ps2serkbd->release = 1;
return;
}
if (ps2serkbd->emul) {
if (--ps2serkbd->emul) return;
code |= 0x100;
}
switch (ps2serkbd->keycode[code]) {
case ATKBD_KEY_NULL:
break;
case ATKBD_KEY_UNKNOWN:
printk(KERN_WARNING "ps2serkbd.c: Unknown key (set %d, scancode %#x) %s.\n",
ps2serkbd->set, code, ps2serkbd->release ? "released" : "pressed");
break;
default:
input_report_key(&ps2serkbd->dev, ps2serkbd->keycode[code], !ps2serkbd->release);
}
ps2serkbd->release = 0;
}
/*
* ps2serkbd_event() handles events from the input module.
*/
static int ps2serkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
switch (type) {
case EV_LED:
return 0;
}
return -1;
}
static int ps2serkbd_initialize(struct ps2serkbd *ps2serkbd)
{
return 0;
}
static void ps2serkbd_reinit(void *data)
{
}
static void ps2serkbd_connect(struct serio *serio, struct serio_dev *dev)
{
struct ps2serkbd *ps2serkbd;
int i;
if ((serio->type & SERIO_TYPE) != SERIO_RS232)
return;
if ((serio->type & SERIO_PROTO) && (serio->type & SERIO_PROTO) != SERIO_PS2SER)
return;
if (!(ps2serkbd = kmalloc(sizeof(struct ps2serkbd), GFP_KERNEL)))
return;
memset(ps2serkbd, 0, sizeof(struct ps2serkbd));
ps2serkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
ps2serkbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
ps2serkbd->serio = serio;
ps2serkbd->dev.keycode = ps2serkbd->keycode;
ps2serkbd->dev.event = ps2serkbd_event;
ps2serkbd->dev.private = ps2serkbd;
ps2serkbd->tq.routine = ps2serkbd_reinit;
ps2serkbd->tq.data = ps2serkbd;
serio->private = ps2serkbd;
if (serio_open(serio, dev)) {
kfree(ps2serkbd);
return;
}
if (ps2serkbd_initialize(ps2serkbd) < 0) {
serio_close(serio);
kfree(ps2serkbd);
return;
}
ps2serkbd->set = 4;
if (ps2serkbd->set == 4) {
ps2serkbd->dev.ledbit[0] |= 0;
sprintf(ps2serkbd->name, "AT Set 2 Extended keyboard\n");
}
memcpy(ps2serkbd->keycode, ps2serkbd_set2_keycode, sizeof(ps2serkbd->keycode));
sprintf(ps2serkbd->phys, "%s/input0", serio->phys);
ps2serkbd->dev.name = ps2serkbd->name;
ps2serkbd->dev.phys = ps2serkbd->phys;
ps2serkbd->dev.idbus = BUS_RS232;
ps2serkbd->dev.idvendor = SERIO_PS2SER;
ps2serkbd->dev.idproduct = ps2serkbd->set;
ps2serkbd->dev.idversion = ps2serkbd->id;
for (i = 0; i < 512; i++)
if (ps2serkbd->keycode[i] && ps2serkbd->keycode[i] <= 250)
set_bit(ps2serkbd->keycode[i], ps2serkbd->dev.keybit);
input_register_device(&ps2serkbd->dev);
}
/*
* ps2serkbd_disconnect() unregisters and closes behind us.
*/
static void ps2serkbd_disconnect(struct serio *serio)
{
struct ps2serkbd *ps2serkbd = serio->private;
input_unregister_device(&ps2serkbd->dev);
serio_close(serio);
kfree(ps2serkbd);
}
static struct serio_dev ps2serkbd_dev = {
interrupt:
ps2serkbd_interrupt,
connect:
ps2serkbd_connect,
disconnect:
ps2serkbd_disconnect
};
/*
* The functions for insering/removing us as a module.
*/
int __init ps2serkbd_init(void)
{
serio_register_device(&ps2serkbd_dev);
return 0;
}
void __exit ps2serkbd_exit(void)
{
serio_unregister_device(&ps2serkbd_dev);
}
module_init(ps2serkbd_init);
module_exit(ps2serkbd_exit);
/*
* $Id: sunkbd.c,v 1.14 2001/09/25 10:12:07 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
/*
* Sun keyboard driver for Linux
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/tqueue.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Sun keyboard driver");
MODULE_LICENSE("GPL");
static unsigned char sunkbd_keycode[128] = {
0,128,114,129,115, 59, 60, 68, 61, 87, 62, 88, 63,100, 64, 0,
65, 66, 67, 56,103,119, 99, 70,105,130,131,108,106, 1, 2, 3,
4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 41, 14,110,113, 98, 55,
116,132, 83,133,102, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27,111,127, 71, 72, 73, 74,134,135,107, 0, 29, 30, 31, 32,
33, 34, 35, 36, 37, 38, 39, 40, 43, 28, 96, 75, 76, 77, 82,136,
104,137, 69, 42, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,101,
79, 80, 81, 0, 0, 0,138, 58,125, 57,126,109, 86, 78
};
#define SUNKBD_CMD_RESET 0x1
#define SUNKBD_CMD_BELLON 0x2
#define SUNKBD_CMD_BELLOFF 0x3
#define SUNKBD_CMD_CLICK 0xa
#define SUNKBD_CMD_NOCLICK 0xb
#define SUNKBD_CMD_SETLED 0xe
#define SUNKBD_CMD_LAYOUT 0xf
#define SUNKBD_RET_RESET 0xff
#define SUNKBD_RET_ALLUP 0x7f
#define SUNKBD_RET_LAYOUT 0xfe
#define SUNKBD_LAYOUT_5_MASK 0x20
#define SUNKBD_RELEASE 0x80
#define SUNKBD_KEY 0x7f
/*
* Per-keyboard data.
*/
struct sunkbd {
unsigned char keycode[128];
struct input_dev dev;
struct serio *serio;
struct tq_struct tq;
char name[64];
char phys[32];
char type;
char reset;
char layout;
};
/*
* sunkbd_interrupt() is called by the low level driver when a character
* is received.
*/
static void sunkbd_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
{
struct sunkbd* sunkbd = serio->private;
if (sunkbd->reset <= -1) { /* If cp[i] is 0xff, sunkbd->reset will stay -1. */
sunkbd->reset = data; /* The keyboard sends 0xff 0xff 0xID on powerup */
return;
}
if (sunkbd->layout == -1) {
sunkbd->layout = data;
return;
}
switch (data) {
case SUNKBD_RET_RESET:
queue_task(&sunkbd->tq, &tq_immediate);
mark_bh(IMMEDIATE_BH);
sunkbd->reset = -1;
return;
case SUNKBD_RET_LAYOUT:
sunkbd->layout = -1;
return;
case SUNKBD_RET_ALLUP: /* All keys released */
return;
default:
if (sunkbd->keycode[data & SUNKBD_KEY]) {
input_report_key(&sunkbd->dev, sunkbd->keycode[data & SUNKBD_KEY], !(data & SUNKBD_RELEASE));
} else {
printk(KERN_WARNING "sunkbd.c: Unknown key (scancode %#x) %s.\n",
data & SUNKBD_KEY, data & SUNKBD_RELEASE ? "released" : "pressed");
}
}
}
/*
* sunkbd_event() handles events from the input module.
*/
static int sunkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
struct sunkbd *sunkbd = dev->private;
switch (type) {
case EV_LED:
sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED);
sunkbd->serio->write(sunkbd->serio,
(!!test_bit(LED_CAPSL, dev->led) << 3) | (!!test_bit(LED_SCROLLL, dev->led) << 2) |
(!!test_bit(LED_COMPOSE, dev->led) << 1) | !!test_bit(LED_NUML, dev->led));
return 0;
case EV_SND:
switch (code) {
case SND_CLICK:
sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - value);
return 0;
case SND_BELL:
sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - value);
return 0;
}
break;
}
return -1;
}
/*
* sunkbd_initialize() checks for a Sun keyboard attached, and determines
* its type.
*/
static int sunkbd_initialize(struct sunkbd *sunkbd)
{
int t;
t = 1000;
sunkbd->reset = -2;
sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_RESET);
while (sunkbd->reset < 0 && --t) mdelay(1);
if (!t) return -1;
sunkbd->type = sunkbd->reset;
if (sunkbd->type == 4) { /* Type 4 keyboard */
t = 250;
sunkbd->layout = -2;
sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_LAYOUT);
while (sunkbd->layout < 0 && --t) mdelay(1);
if (!t) return -1;
if (sunkbd->layout & SUNKBD_LAYOUT_5_MASK) sunkbd->type = 5;
}
return 0;
}
/*
* sunkbd_reinit() sets leds and beeps to a state the computer remembers they
* were in.
*/
static void sunkbd_reinit(void *data)
{
struct sunkbd *sunkbd = data;
int t = 1000;
while (sunkbd->reset < 0 && --t) mdelay(1);
sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED);
sunkbd->serio->write(sunkbd->serio,
(!!test_bit(LED_CAPSL, sunkbd->dev.led) << 3) | (!!test_bit(LED_SCROLLL, sunkbd->dev.led) << 2) |
(!!test_bit(LED_COMPOSE, sunkbd->dev.led) << 1) | !!test_bit(LED_NUML, sunkbd->dev.led));
sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev.snd));
sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev.snd));
}
/*
* sunkbd_connect() probes for a Sun keyboard and fills the necessary structures.
*/
static void sunkbd_connect(struct serio *serio, struct serio_dev *dev)
{
struct sunkbd *sunkbd;
int i;
if ((serio->type & SERIO_TYPE) != SERIO_RS232)
return;
if ((serio->type & SERIO_PROTO) && (serio->type & SERIO_PROTO) != SERIO_SUNKBD)
return;
if (!(sunkbd = kmalloc(sizeof(struct sunkbd), GFP_KERNEL)))
return;
memset(sunkbd, 0, sizeof(struct sunkbd));
sunkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_SND) | BIT(EV_REP);
sunkbd->dev.ledbit[0] = BIT(LED_CAPSL) | BIT(LED_COMPOSE) | BIT(LED_SCROLLL) | BIT(LED_NUML);
sunkbd->dev.sndbit[0] = BIT(SND_CLICK) | BIT(SND_BELL);
sunkbd->serio = serio;
sunkbd->tq.routine = sunkbd_reinit;
sunkbd->tq.data = sunkbd;
sunkbd->dev.keycode = sunkbd->keycode;
sunkbd->dev.event = sunkbd_event;
sunkbd->dev.private = sunkbd;
serio->private = sunkbd;
if (serio_open(serio, dev)) {
kfree(sunkbd);
return;
}
if (sunkbd_initialize(sunkbd) < 0) {
serio_close(serio);
kfree(sunkbd);
return;
}
sprintf(sunkbd->name, "Sun Type %d keyboard", sunkbd->type);
memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode));
for (i = 0; i < 255; i++)
set_bit(sunkbd->keycode[i], sunkbd->dev.keybit);
clear_bit(0, sunkbd->dev.keybit);
sprintf(sunkbd->name, "%s/input", serio->phys);
sunkbd->dev.name = sunkbd->name;
sunkbd->dev.phys = sunkbd->phys;
sunkbd->dev.idbus = BUS_RS232;
sunkbd->dev.idvendor = SERIO_SUNKBD;
sunkbd->dev.idproduct = sunkbd->type;
sunkbd->dev.idversion = 0x0100;
input_register_device(&sunkbd->dev);
printk(KERN_INFO "input: %s on %s\n", sunkbd->name, serio->phys);
}
/*
* sunkbd_disconnect() unregisters and closes behind us.
*/
static void sunkbd_disconnect(struct serio *serio)
{
struct sunkbd *sunkbd = serio->private;
input_unregister_device(&sunkbd->dev);
serio_close(serio);
kfree(sunkbd);
}
static struct serio_dev sunkbd_dev = {
interrupt: sunkbd_interrupt,
connect: sunkbd_connect,
disconnect: sunkbd_disconnect
};
/*
* The functions for insering/removing us as a module.
*/
int __init sunkbd_init(void)
{
serio_register_device(&sunkbd_dev);
return 0;
}
void __exit sunkbd_exit(void)
{
serio_unregister_device(&sunkbd_dev);
}
module_init(sunkbd_init);
module_exit(sunkbd_exit);
/*
* $Id: xtkbd.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
/*
* XT keyboard driver for Linux
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/serio.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("XT keyboard driver");
MODULE_LICENSE("GPL");
#define XTKBD_EMUL0 0xe0
#define XTKBD_EMUL1 0xe1
#define XTKBD_KEY 0x7f
#define XTKBD_RELEASE 0x80
static unsigned char xtkbd_keycode[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,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 0, 0, 0, 87, 88, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 87, 88, 0, 0, 0, 0,110,111,103,108,105,
106
};
static char *xtkbd_name = "XT Keyboard";
struct xtkbd {
unsigned char keycode[256];
struct input_dev dev;
struct serio *serio;
char phys[32];
};
void xtkbd_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
{
struct xtkbd *xtkbd = serio->private;
switch (data) {
case XTKBD_EMUL0:
case XTKBD_EMUL1:
return;
default:
if (xtkbd->keycode[data & XTKBD_KEY]) {
input_report_key(&xtkbd->dev, xtkbd->keycode[data & XTKBD_KEY], !(data & XTKBD_RELEASE));
} else {
printk(KERN_WARNING "xtkbd.c: Unknown key (scancode %#x) %s.\n",
data & XTKBD_KEY, data & XTKBD_RELEASE ? "released" : "pressed");
}
}
}
void xtkbd_connect(struct serio *serio, struct serio_dev *dev)
{
struct xtkbd *xtkbd;
int i;
if ((serio->type & SERIO_TYPE) != SERIO_XT)
return;
if (!(xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL)))
return;
memset(xtkbd, 0, sizeof(struct xtkbd));
xtkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
xtkbd->serio = serio;
xtkbd->dev.keycode = xtkbd->keycode;
xtkbd->dev.private = xtkbd;
serio->private = xtkbd;
if (serio_open(serio, dev)) {
kfree(xtkbd);
return;
}
memcpy(xtkbd->keycode, xtkbd_keycode, sizeof(xtkbd->keycode));
for (i = 0; i < 255; i++)
set_bit(xtkbd->keycode[i], xtkbd->dev.keybit);
clear_bit(0, xtkbd->dev.keybit);
sprintf(xtkbd->phys, "%s/input0", serio->phys);
xtkbd->dev.name = xtkbd_name;
xtkbd->dev.phys = xtkbd->phys;
xtkbd->dev.idbus = BUS_XTKBD;
xtkbd->dev.idvendor = 0x0001;
xtkbd->dev.idproduct = 0x0001;
xtkbd->dev.idversion = 0x0100;
input_register_device(&xtkbd->dev);
printk(KERN_INFO "input: %s on %s\n", xtkbd_name, serio->phys);
}
void xtkbd_disconnect(struct serio *serio)
{
struct xtkbd *xtkbd = serio->private;
input_unregister_device(&xtkbd->dev);
serio_close(serio);
kfree(xtkbd);
}
struct serio_dev xtkbd_dev = {
interrupt: xtkbd_interrupt,
connect: xtkbd_connect,
disconnect: xtkbd_disconnect
};
int __init xtkbd_init(void)
{
serio_register_device(&xtkbd_dev);
return 0;
}
void __exit xtkbd_exit(void)
{
serio_unregister_device(&xtkbd_dev);
}
module_init(xtkbd_init);
module_exit(xtkbd_exit);
CONFIG_INPUT_MOUSE
Say Y here, and a list of supported mice will be displayed.
This option doesn't affect the kernel.
If unsure, say Y.
CONFIG_MOUSE_PS2
Say Y here if you have a PS/2 mouse connected to your system. This
includes the standard 2 or 3-button PS/2 mouse, as well as PS/2
mice with wheels and extra buttons, Microsoft, Logitech or Genius
compatible.
If unsure, say Y.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called psmouse.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_MOUSE_SERIAL
Say Y here if you have a serial (RS-232, COM port) mouse connected
to your system. This includes Sun, MouseSystems, Microsoft,
Logitech and all other compatible serial mice.
If unsure, say N.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called sermouse.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_MOUSE_INPORT
Say Y here if you have an InPort, Microsoft or ATI XL busmouse.
They are rather rare these days.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called inport.o. If you want to compile it as a
module, say M here and read <file.:Documentation/modules.txt>.
CONFIG_MOUSE_ATIXL
Say Y here if your mouse is of the ATI XL variety.
CONFIG_MOUSE_LOGIBM
Say Y here if you have a Logitech busmouse.
They are rather rare these days.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called logibm.o. If you want to compile it as a
module, say M here and read <file.:Documentation/modules.txt>.
CONFIG_MOUSE_PC110PAD
Say Y if you have the IBM PC-110 micro-notebook and want its
touchscreen supported.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called pc110pad.o. If you want to compile it as a
module, say M here and read <file.:Documentation/modules.txt>.
CONFIG_MOUSE_MAPLE
Say Y if you have a DreamCast console and a mouse attached to
its Maple bus.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called maplemouse.o. If you want to compile it as a
module, say M here and read <file.:Documentation/modules.txt>.
CONFIG_MOUSE_AMIGA
Say Y here if you have an Amiga and want its native mouse
supported by the kernel.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called amimouse.o. If you want to compile it as a
module, say M here and read <file.:Documentation/modules.txt>.
CONFIG_MOUSE_ACORN
Say Y here if you have the Acorn RiscPC computer and want its
native mouse supported.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called rpcmouse.o. If you want to compile it as a
module, say M here and read <file.:Documentation/modules.txt>.
#
# Mouse driver configuration
#
bool 'Mice' CONFIG_INPUT_MOUSE
dep_tristate ' PS/2 mouse' CONFIG_MOUSE_PS2 $CONFIG_INPUT $CONFIG_INPUT_MOUSE $CONFIG_SERIO
dep_tristate ' Serial mouse' CONFIG_MOUSE_SERIAL $CONFIG_INPUT $CONFIG_INPUT_MOUSE $CONFIG_SERIO
dep_tristate ' InPort/MS/ATIXL busmouse' CONFIG_MOUSE_INPORT $CONFIG_INPUT $CONFIG_INPUT_MOUSE $CONFIG_ISA
if [ "$CONFIG_MOUSE_INPORT" != "n" ]; then
bool ' ATI XL variant' CONFIG_MOUSE_ATIXL
fi
dep_tristate ' Logitech busmouse' CONFIG_MOUSE_LOGIBM $CONFIG_INPUT $CONFIG_INPUT_MOUSE $CONFIG_ISA
dep_tristate ' IBM PC110 touchpad' CONFIG_MOUSE_PC110PAD $CONFIG_INPUT $CONFIG_INPUT_MOUSE $CONFIG_ISA
if [ "$CONFIG_SH_DREAMCAST" = "y" ]; then
dep_tristate ' Maple bus mouse' CONFIG_MOUSE_MAPLE $CONFIG_INPUT $CONFIG_INPUT_MOUSE $CONFIG_MAPLE
fi
if [ "$CONFIG_AMIGA" = "y" ]; then
dep_tristate ' Amiga mouse' CONFIG_MOUSE_AMIGA $CONFIG_INPUT $CONFIG_INPUT_MOUSE
fi
if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
dep_tristate ' Acorn RiscPC mouse' CONFIG_MOUSE_ACORN $CONFIG_INPUT $CONFIG_INPUT_MOUSE
fi
#
# Makefile for the mouse drivers.
#
# The target object and module list name.
O_TARGET := mousedrv.o
# Each configuration option enables a list of files.
obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o
obj-$(CONFIG_MOUSE_ACORN) += rpcmouse.o
obj-$(CONFIG_MOUSE_INPORT) += inport.o
obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o
obj-$(CONFIG_MOUSE_MAPLE) += maplemouse.o
obj-$(CONFIG_MOUSE_PC110PAD) += pc110pad.o
obj-$(CONFIG_MOUSE_PS2) += psmouse.o
obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
# The global Rules.make.
include $(TOPDIR)/Rules.make
/*
* $Id: amimouse.c,v 1.9 2001/09/25 10:12:07 vojtech Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik
*
* Based on the work of:
* Michael Rausch James Banks
* Matther Dillon David Giller
* Nathan Laredo Linus Torvalds
* Johan Myreen Jes Sorensen
* Russel King
*/
/*
* Amiga mouse driver for Linux/m68k
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
#include <asm/irq.h>
#include <asm/setup.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/amigahw.h>
#include <asm/amigaints.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Amiga mouse driver");
MODULE_LICENSE("GPL");
static int amimouse_used = 0;
static int amimouse_lastx, amimouse_lasty;
static struct input_dev amimouse_dev;
static char *amimouse_name = "Amiga mouse";
static char *amimouse_phys = "amimouse/input0";
static void amimouse_interrupt(int irq, void *dummy, struct pt_regs *fp)
{
unsigned short joy0dat, potgor;
int nx, ny, dx, dy;
joy0dat = custom.joy0dat;
nx = joy0dat & 0xff;
ny = joy0dat >> 8;
dx = nx - amimouse_lastx;
dy = ny - amimouse_lasty;
if (dx < -127) dx = (256 + nx) - lastx;
if (dx > 127) dx = (nx - 256) - lastx;
if (dy < -127) dy = (256 + ny) - lasty;
if (dy > 127) dy = (ny - 256) - lasty;
amimouse_lastx = nx;
amimouse_lasty = ny;
potgor = custom.potgor;
input_report_rel(&amimouse_dev, REL_X, dx);
input_report_rel(&amimouse_dev, REL_Y, dy);
input_report_key(&amimouse_dev, BTN_LEFT, ciaa.pra & 0x40);
input_report_key(&amimouse_dev, BTN_MIDDLE, potgor & 0x0100);
input_report_key(&amimouse_dev, BTN_RIGHT, potgor & 0x0400);
}
static int amimouse_open(struct input_dev *dev)
{
unsigned short joy0dat;
if (amimouse_used++)
return 0;
joy0dat = custom.joy0dat;
amimouse_lastx = joy0dat & 0xff;
amimouse_lasty = joy0dat >> 8;
if (request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse", NULL)) {
amimouse_used--;
printk(KERN_ERR "amimouse.c: Can't allocate irq %d\n", amimouse_irq);
return -EBUSY;
}
return 0;
}
static void amimouse_close(struct input_dev *dev)
{
if (!--amimouse_used)
free_irq(IRQ_AMIGA_VERTB, amimouse_interrupt);
}
static int __init amimouse_init(void)
{
if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE))
return -ENODEV;
amimouse_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
amimouse_dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
amimouse_dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
amimouse_dev.open = amimouse_open;
amimouse_dev.close = amimouse_close;
amimouse_dev.name = amimouse_name;
amimouse_dev.phys = amimouse_phys;
amimouse_dev.idbus = BUS_AMIGA;
amimouse_dev.idvendor = 0x0001;
amimouse_dev.idproduct = 0x0002;
amimouse_dev.idversion = 0x0100;
input_register_device(&amimouse_dev);
printk(KERN_INFO "input: %s at joy0dat\n", amimouse_name);
}
static void __exit amimouse_exit(void)
{
input_unregister_device(&amimouse_dev);
}
module_init(amimouse_init);
module_exit(amimouse_exit);
/*
* $Id: inport.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*
* Based on the work of:
* Teemu Rantanen Derrick Cole
* Peter Cervasio Christoph Niemann
* Philip Blundell Russell King
* Bob Harris
*/
/*
* Inport (ATI XL and Microsoft) busmouse driver for Linux
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/module.h>
#include <linux/config.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/input.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Inport (ATI XL and Microsoft) busmouse driver");
MODULE_LICENSE("GPL");
#define INPORT_BASE 0x23c
#define INPORT_EXTENT 4
#define INPORT_CONTROL_PORT INPORT_BASE + 0
#define INPORT_DATA_PORT INPORT_BASE + 1
#define INPORT_SIGNATURE_PORT INPORT_BASE + 2
#define INPORT_REG_BTNS 0x00
#define INPORT_REG_X 0x01
#define INPORT_REG_Y 0x02
#define INPORT_REG_MODE 0x07
#define INPORT_RESET 0x80
#ifdef CONFIG_INPUT_ATIXL
#define INPORT_NAME "ATI XL Mouse"
#define INPORT_VENDOR 0x0002
#define INPORT_SPEED_30HZ 0x01
#define INPORT_SPEED_50HZ 0x02
#define INPORT_SPEED_100HZ 0x03
#define INPORT_SPEED_200HZ 0x04
#define INPORT_MODE_BASE INPORT_SPEED_100HZ
#define INPORT_MODE_IRQ 0x08
#else
#define INPORT_NAME "Microsoft InPort Mouse"
#define INPORT_VENDOR 0x0001
#define INPORT_MODE_BASE 0x10
#define INPORT_MODE_IRQ 0x01
#endif
#define INPORT_MODE_HOLD 0x20
#define INPORT_IRQ 5
MODULE_PARM(inport_irq, "i");
static int inport_irq = INPORT_IRQ;
static int inport_used = 0;
static void inport_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int inport_open(struct input_dev *dev)
{
if (!inport_used++) {
if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL))
return -EBUSY;
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
}
return 0;
}
static void inport_close(struct input_dev *dev)
{
if (!--inport_used) {
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
free_irq(inport_irq, NULL);
}
}
static struct input_dev inport_dev = {
evbit: { BIT(EV_KEY) | BIT(EV_REL) },
keybit: { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
relbit: { BIT(REL_X) | BIT(REL_Y) },
open: inport_open,
close: inport_close,
name: INPORT_NAME,
phys: "isa023c/input0",
idbus: BUS_ISA,
idvendor: INPORT_VENDOR,
idproduct: 0x0001,
idversion: 0x0100,
};
static void inport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned char buttons;
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_HOLD | INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
outb(INPORT_REG_X, INPORT_CONTROL_PORT);
input_report_rel(&inport_dev, REL_X, inb(INPORT_DATA_PORT));
outb(INPORT_REG_Y, INPORT_CONTROL_PORT);
input_report_rel(&inport_dev, REL_Y, inb(INPORT_DATA_PORT));
outb(INPORT_REG_BTNS, INPORT_CONTROL_PORT);
buttons = inb(INPORT_DATA_PORT);
input_report_key(&inport_dev, BTN_MIDDLE, buttons & 1);
input_report_key(&inport_dev, BTN_LEFT, buttons & 2);
input_report_key(&inport_dev, BTN_RIGHT, buttons & 4);
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
}
#ifndef MODULE
static int __init inport_setup(char *str)
{
int ints[4];
str = get_options(str, ARRAY_SIZE(ints), ints);
if (ints[0] > 0) inport_irq = ints[1];
return 1;
}
__setup("inport_irq=", inport_setup);
#endif
static int __init inport_init(void)
{
unsigned char a,b,c;
if (check_region(INPORT_BASE, INPORT_EXTENT))
return -EBUSY;
a = inb(INPORT_SIGNATURE_PORT);
b = inb(INPORT_SIGNATURE_PORT);
c = inb(INPORT_SIGNATURE_PORT);
if (( a == b ) || ( a != c ))
return -ENODEV;
outb(INPORT_RESET, INPORT_CONTROL_PORT);
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
request_region(INPORT_BASE, INPORT_EXTENT, "inport");
input_register_device(&inport_dev);
printk(KERN_INFO "input: " INPORT_NAME " at %#x irq %d\n",
INPORT_BASE, inport_irq);
return 0;
}
static void __exit inport_exit(void)
{
input_unregister_device(&inport_dev);
release_region(INPORT_BASE, INPORT_EXTENT);
}
module_init(inport_init);
module_exit(inport_exit);
/*
* $Id: logibm.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*
* Based on the work of:
* James Banks Matthew Dillon
* David Giller Nathan Laredo
* Linus Torvalds Johan Myreen
* Cliff Matthews Philip Blundell
* Russell King
*/
/*
* Logitech Bus Mouse Driver for Linux
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/input.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Logitech busmouse driver");
MODULE_LICENSE("GPL");
#define LOGIBM_BASE 0x23c
#define LOGIBM_EXTENT 4
#define LOGIBM_DATA_PORT LOGIBM_BASE + 0
#define LOGIBM_SIGNATURE_PORT LOGIBM_BASE + 1
#define LOGIBM_CONTROL_PORT LOGIBM_BASE + 2
#define LOGIBM_CONFIG_PORT LOGIBM_BASE + 3
#define LOGIBM_ENABLE_IRQ 0x00
#define LOGIBM_DISABLE_IRQ 0x10
#define LOGIBM_READ_X_LOW 0x80
#define LOGIBM_READ_X_HIGH 0xa0
#define LOGIBM_READ_Y_LOW 0xc0
#define LOGIBM_READ_Y_HIGH 0xe0
#define LOGIBM_DEFAULT_MODE 0x90
#define LOGIBM_CONFIG_BYTE 0x91
#define LOGIBM_SIGNATURE_BYTE 0xa5
#define LOGIBM_IRQ 5
MODULE_PARM(logibm_irq, "i");
static int logibm_irq = LOGIBM_IRQ;
static int logibm_used = 0;
static void logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int logibm_open(struct input_dev *dev)
{
if (logibm_used++)
return 0;
if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) {
logibm_used--;
printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq);
return -EBUSY;
}
outb(LOGIBM_ENABLE_IRQ, LOGIBM_CONTROL_PORT);
return 0;
}
static void logibm_close(struct input_dev *dev)
{
if (--logibm_used)
return;
outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
free_irq(logibm_irq, NULL);
}
static struct input_dev logibm_dev = {
evbit: { BIT(EV_KEY) | BIT(EV_REL) },
keybit: { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
relbit: { BIT(REL_X) | BIT(REL_Y) },
open: logibm_open,
close: logibm_close,
name: "Logitech bus mouse",
phys: "isa023c/input0",
idbus: BUS_ISA,
idvendor: 0x0003,
idproduct: 0x0001,
idversion: 0x0100,
};
static void logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
char dx, dy;
unsigned char buttons;
outb(LOGIBM_READ_X_LOW, LOGIBM_CONTROL_PORT);
dx = (inb(LOGIBM_DATA_PORT) & 0xf);
outb(LOGIBM_READ_X_HIGH, LOGIBM_CONTROL_PORT);
dx |= (inb(LOGIBM_DATA_PORT) & 0xf) << 4;
outb(LOGIBM_READ_Y_LOW, LOGIBM_CONTROL_PORT);
dy = (inb(LOGIBM_DATA_PORT) & 0xf);
outb(LOGIBM_READ_Y_HIGH, LOGIBM_CONTROL_PORT);
buttons = inb(LOGIBM_DATA_PORT);
dy |= (buttons & 0xf) << 4;
buttons = ~buttons;
input_report_rel(&logibm_dev, REL_X, dx);
input_report_rel(&logibm_dev, REL_Y, 255 - dy);
input_report_key(&logibm_dev, BTN_MIDDLE, buttons & 1);
input_report_key(&logibm_dev, BTN_LEFT, buttons & 2);
input_report_key(&logibm_dev, BTN_RIGHT, buttons & 4);
}
#ifndef MODULE
static int __init logibm_setup(char *str)
{
int ints[4];
str = get_options(str, ARRAY_SIZE(ints), ints);
if (ints[0] > 0) logibm_irq = ints[1];
return 1;
}
__setup("logibm_irq=", logibm_setup);
#endif
static int __init logibm_init(void)
{
if (request_region(LOGIBM_BASE, LOGIBM_EXTENT, "logibm")) {
printk(KERN_ERR "logibm.c: Can't allocate ports at %#x\n", LOGIBM_BASE);
return -EBUSY;
}
outb(LOGIBM_CONFIG_BYTE, LOGIBM_CONFIG_PORT);
outb(LOGIBM_SIGNATURE_BYTE, LOGIBM_SIGNATURE_PORT);
udelay(100);
if (inb(LOGIBM_SIGNATURE_PORT) != LOGIBM_SIGNATURE_BYTE) {
release_region(LOGIBM_BASE, LOGIBM_EXTENT);
printk(KERN_ERR "logibm.c: Didn't find Logitech busmouse at %#x\n", LOGIBM_BASE);
return -ENODEV;
}
outb(LOGIBM_DEFAULT_MODE, LOGIBM_CONFIG_PORT);
outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
input_register_device(&logibm_dev);
printk(KERN_INFO "input: Logitech bus mouse at %#x irq %d\n", LOGIBM_BASE, logibm_irq);
return 0;
}
static void __exit logibm_exit(void)
{
input_unregister_device(&logibm_dev);
release_region(LOGIBM_BASE, LOGIBM_EXTENT);
}
module_init(logibm_init);
module_exit(logibm_exit);
/*
* $Id: maplemouse.c,v 1.1 2001/11/02 17:27:32 jsimmons Exp $
* SEGA Dreamcast mouse driver
* Based on drivers/usb/usbmouse.c
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/maple.h>
MODULE_AUTHOR("YAEGASHI Takeshi <t@keshi.org>");
MODULE_DESCRIPTION("SEGA Dreamcast mouse driver");
struct dc_mouse {
struct input_dev dev;
int open;
};
static void dc_mouse_callback(struct mapleq *mq)
{
int buttons, relx, rely, relz;
struct maple_device *mapledev = mq->dev;
struct dc_mouse *mouse = mapledev->private_data;
struct input_dev *dev = &mouse->dev;
unsigned char *res = mq->recvbuf;
buttons = ~res[8];
relx=*(unsigned short *)(res+12)-512;
rely=*(unsigned short *)(res+14)-512;
relz=*(unsigned short *)(res+16)-512;
input_report_key(dev, BTN_LEFT, buttons&4);
input_report_key(dev, BTN_MIDDLE, buttons&9);
input_report_key(dev, BTN_RIGHT, buttons&2);
input_report_rel(dev, REL_X, relx);
input_report_rel(dev, REL_Y, rely);
input_report_rel(dev, REL_WHEEL, relz);
}
static int dc_mouse_open(struct input_dev *dev)
{
struct dc_mouse *mouse = dev->private;
mouse->open++;
return 0;
}
static void dc_mouse_close(struct input_dev *dev)
{
struct dc_mouse *mouse = dev->private;
mouse->open--;
}
static int dc_mouse_connect(struct maple_device *dev)
{
unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
struct dc_mouse *mouse;
if (!(mouse = kmalloc(sizeof(struct dc_mouse), GFP_KERNEL)))
return -1;
memset(mouse, 0, sizeof(struct dc_mouse));
dev->private_data = mouse;
mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
mouse->dev.private = mouse;
mouse->dev.open = dc_mouse_open;
mouse->dev.close = dc_mouse_close;
mouse->dev.event = NULL;
mouse->dev.name = dev->product_name;
mouse->dev.idbus = BUS_MAPLE;
input_register_device(&mouse->dev);
maple_getcond_callback(dev, dc_mouse_callback, 1, MAPLE_FUNC_MOUSE);
printk(KERN_INFO "input%d: mouse(0x%lx): %s\n",
mouse->dev.number, data, mouse->dev.name);
MOD_INC_USE_COUNT;
return 0;
}
static void dc_mouse_disconnect(struct maple_device *dev)
{
struct dc_mouse *mouse = dev->private_data;
input_unregister_device(&mouse->dev);
kfree(mouse);
MOD_DEC_USE_COUNT;
}
static struct maple_driver dc_mouse_driver = {
function: MAPLE_FUNC_MOUSE,
name: "Dreamcast mouse",
connect: dc_mouse_connect,
disconnect: dc_mouse_disconnect,
};
static int __init dc_mouse_init(void)
{
maple_register_driver(&dc_mouse_driver);
return 0;
}
static void __exit dc_mouse_exit(void)
{
maple_unregister_driver(&dc_mouse_driver);
}
module_init(dc_mouse_init);
module_exit(dc_mouse_exit);
/*
* Local variables:
* c-basic-offset: 8
* End:
*/
/*
* $Id: pc110pad.c,v 1.12 2001/09/25 10:12:07 vojtech Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik
*
* Based on the work of:
* Alan Cox Robin O'Leary
*/
/*
* IBM PC110 touchpad driver for Linux
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/input.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/irq.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("IBM PC110 touchpad driver");
MODULE_LICENSE("GPL");
#define PC110PAD_OFF 0x30
#define PC110PAD_ON 0x38
static int pc110pad_irq = 10;
static int pc110pad_io = 0x15e0;
static struct input_dev pc110pad_dev;
static int pc110pad_data[3];
static int pc110pad_count;
static int pc110pad_used;
static char *pc110pad_name = "IBM PC110 TouchPad";
static char *pc110pad_phys = "isa15e0/input0";
static void pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs)
{
int value = inb_p(pc110pad_io);
int handshake = inb_p(pc110pad_io + 2);
outb_p(handshake | 1, pc110pad_io + 2);
outb_p(handshake & ~1, pc110pad_io + 2);
inb_p(0x64);
pc110pad_data[pc110pad_count++] = value;
if (pc110pad_count < 3) return;
input_report_key(&pc110pad_dev, BTN_TOUCH,
pc110pad_data[0] & 0x01);
input_report_abs(&pc110pad_dev, ABS_X,
pc110pad_data[1] | ((pc110pad_data[0] << 3) & 0x80) | ((pc110pad_data[0] << 1) & 0x100));
input_report_abs(&pc110pad_dev, ABS_Y,
pc110pad_data[2] | ((pc110pad_data[0] << 4) & 0x80));
pc110pad_count = 0;
}
static void pc110pad_close(struct input_dev *dev)
{
if (!--pc110pad_used)
outb(PC110PAD_OFF, pc110pad_io + 2);
}
static int pc110pad_open(struct input_dev *dev)
{
unsigned long flags;
if (pc110pad_used++)
return 0;
save_flags(flags);
cli();
pc110pad_interrupt(0,0,0);
pc110pad_interrupt(0,0,0);
pc110pad_interrupt(0,0,0);
outb(PC110PAD_ON, pc110pad_io + 2);
pc110pad_count = 0;
restore_flags(flags);
return 0;
}
static int __init pc110pad_init(void)
{
if (request_region(pc110pad_io, 4, "pc110pad"))
{
printk(KERN_ERR "pc110pad: I/O area %#x-%#x in use.\n", pc110pad_io, pc110pad_io + 4);
return -EBUSY;
}
outb(PC110PAD_OFF, pc110pad_io + 2);
if (request_irq(pc110pad_irq, pc110pad_interrupt, 0, "pc110pad", 0))
{
release_region(pc110pad_io, 4);
printk(KERN_ERR "pc110pad: Unable to get irq %d.\n", pc110pad_irq);
return -EBUSY;
}
pc110pad_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
pc110pad_dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
pc110pad_dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
pc110pad_dev.absmax[ABS_X] = 0x1ff;
pc110pad_dev.absmax[ABS_Y] = 0x0ff;
pc110pad_dev.open = pc110pad_open;
pc110pad_dev.close = pc110pad_close;
pc110pad_dev.name = pc110pad_name;
pc110pad_dev.phys = pc110pad_phys;
pc110pad_dev.idbus = BUS_ISA;
pc110pad_dev.idvendor = 0x0003;
pc110pad_dev.idproduct = 0x0001;
pc110pad_dev.idversion = 0x0100;
input_register_device(&pc110pad_dev);
printk(KERN_INFO "input: %s at %#x irq %d\n",
pc110pad_name, pc110pad_io, pc110pad_irq);
return 0;
}
static void __exit pc110pad_exit(void)
{
input_unregister_device(&pc110pad_dev);
outb(PC110PAD_OFF, pc110pad_io + 2);
free_irq(pc110pad_irq, 0);
release_region(pc110pad_io, 4);
}
module_init(pc110pad_init);
module_exit(pc110pad_exit);
This diff is collapsed.
/*
* $Id: rpcmouse.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik
*
* Based on the work of:
* Russel King
*/
/*
* Acorn RiscPC mouse driver for Linux/ARM
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/ptrace.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/iomd.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Acorn RiscPC mouse driver");
MODULE_LICENSE("GPL");
#define IOMD_MOUSEBTN 0x800C4000
static short rpcmouse_lastx, rpcmouse_lasty;
static struct input_dev rpcmouse_dev = {
evbit: { BIT(EV_KEY) | BIT(EV_REL) },
keybit: { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
relbit: { BIT(REL_X) | BIT(REL_Y) },
name: "Acorn RiscPC Mouse",
phys: "rpcmouse/input0",
idbus: BUS_ISA,
idvendor: 0x0005,
idproduct: 0x0001,
idversion: 0x0100,
};
static void rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs)
{
short x, y, dx, dy, b;
x = (short) inl(IOMD_MOUSEX);
y = (short) inl(IOMD_MOUSEY);
b = (short) inl(IOMD_MOUSEBTN);
dx = x - rpcmouse_lastx;
dy = y - rpcmouse_lasty;
rpcmouse_lastx = x;
rpcmouse_lasty = y;
input_report_rel(&rpcmouse_dev, REL_X, dx);
input_report_rel(&rpcmouse_dev, REL_Y, dy);
input_report_key(&amimouse_dev, BTN_LEFT, buttons & 0x10);
input_report_key(&amimouse_dev, BTN_MIDDLE, buttons & 0x20);
input_report_key(&amimouse_dev, BTN_RIGHT, buttons & 0x40);
}
static int __init rpcmouse_init(void)
{
rpcmouse_lastx = (short) inl(IOMD_MOUSEX);
rpcmouse_lasty = (short) inl(IOMD_MOUSEY);
if (request_irq(IRQ_VSYNCPULSE, rpcmouse_irq, SA_SHIRQ, "rpcmouse", NULL)) {
printk(KERN_ERR "rpcmouse: unable to allocate VSYNC interrupt\n");
return -1;
}
input_register_device(&rpcmouse_dev);
printk(KERN_INFO "input%d: Acorn RiscPC mouse irq %d", IRQ_VSYNCPULSE);
return 0;
}
static void __exit rpcmouse_exit(void)
{
input_unregister_device(&rpcmouse_dev);
free_irq(IRQ_VSYNCPULSE, NULL);
}
module_init(rpcmouse_init);
module_exit(rpcmouse_exit);
/*
* $Id: sermouse.c,v 1.15 2001/10/09 22:34:17 jsimmons Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
/*
* Serial mouse driver for Linux
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/config.h>
#include <linux/serio.h>
#include <linux/init.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Serial mouse driver");
MODULE_LICENSE("GPL");
static char *sermouse_protocols[] = { "None", "Mouse Systems Mouse", "Sun Mouse", "Microsoft Mouse",
"Logitech M+ Mouse", "Microsoft MZ Mouse", "Logitech MZ+ Mouse",
"Logitech MZ++ Mouse"};
struct sermouse {
struct input_dev dev;
signed char buf[8];
unsigned char count;
unsigned char type;
unsigned long last;
char phys[32];
};
/*
* sermouse_process_msc() analyzes the incoming MSC/Sun bytestream and
* applies some prediction to the data, resulting in 96 updates per
* second, which is as good as a PS/2 or USB mouse.
*/
static void sermouse_process_msc(struct sermouse *sermouse, signed char data)
{
struct input_dev *dev = &sermouse->dev;
signed char *buf = sermouse->buf;
switch (sermouse->count) {
case 0:
if ((data & 0xf8) != 0x80) return;
input_report_key(dev, BTN_LEFT, !(data & 4));
input_report_key(dev, BTN_RIGHT, !(data & 1));
input_report_key(dev, BTN_MIDDLE, !(data & 2));
break;
case 1:
case 3:
input_report_rel(dev, REL_X, data / 2);
input_report_rel(dev, REL_Y, -buf[1]);
buf[0] = data - data / 2;
break;
case 2:
case 4:
input_report_rel(dev, REL_X, buf[0]);
input_report_rel(dev, REL_Y, buf[1] - data);
buf[1] = data / 2;
break;
}
if (++sermouse->count == (5 - ((sermouse->type == SERIO_SUN) << 1)))
sermouse->count = 0;
}
/*
* sermouse_process_ms() anlyzes the incoming MS(Z/+/++) bytestream and
* generates events. With prediction it gets 80 updates/sec, assuming
* standard 3-byte packets and 1200 bps.
*/
static void sermouse_process_ms(struct sermouse *sermouse, signed char data)
{
struct input_dev *dev = &sermouse->dev;
signed char *buf = sermouse->buf;
if (data & 0x40) sermouse->count = 0;
switch (sermouse->count) {
case 0:
buf[1] = data;
input_report_key(dev, BTN_LEFT, (data >> 5) & 1);
input_report_key(dev, BTN_RIGHT, (data >> 4) & 1);
break;
case 1:
buf[2] = data;
data = (signed char) (((buf[1] << 6) & 0xc0) | (data & 0x3f));
input_report_rel(dev, REL_X, data / 2);
input_report_rel(dev, REL_Y, buf[4]);
buf[3] = data - data / 2;
break;
case 2:
/* Guessing the state of the middle button on 3-button MS-protocol mice - ugly. */
if ((sermouse->type == SERIO_MS) && !data && !buf[2] && !((buf[0] & 0xf0) ^ buf[1]))
input_report_key(dev, BTN_MIDDLE, !test_bit(BTN_MIDDLE, dev->key));
buf[0] = buf[1];
data = (signed char) (((buf[1] << 4) & 0xc0) | (data & 0x3f));
input_report_rel(dev, REL_X, buf[3]);
input_report_rel(dev, REL_Y, data - buf[4]);
buf[4] = data / 2;
break;
case 3:
switch (sermouse->type) {
case SERIO_MS:
sermouse->type = SERIO_MP;
case SERIO_MP:
if ((data >> 2) & 3) break; /* M++ Wireless Extension packet. */
input_report_key(dev, BTN_MIDDLE, (data >> 5) & 1);
input_report_key(dev, BTN_SIDE, (data >> 4) & 1);
break;
case SERIO_MZP:
case SERIO_MZPP:
input_report_key(dev, BTN_SIDE, (data >> 5) & 1);
case SERIO_MZ:
input_report_key(dev, BTN_MIDDLE, (data >> 4) & 1);
input_report_rel(dev, REL_WHEEL, (data & 7) - (data & 8));
break;
}
break;
case 4:
case 6: /* MZ++ packet type. We can get these bytes for M++ too but we ignore them later. */
buf[1] = (data >> 2) & 0x0f;
break;
case 5:
case 7: /* Ignore anything besides MZ++ */
if (sermouse->type != SERIO_MZPP) break;
switch (buf[1]) {
case 1: /* Extra mouse info */
input_report_key(dev, BTN_SIDE, (data >> 4) & 1);
input_report_key(dev, BTN_EXTRA, (data >> 5) & 1);
input_report_rel(dev, data & 0x80 ? REL_HWHEEL : REL_WHEEL, (data & 7) - (data & 8));
break;
default: /* We don't decode anything else yet. */
printk(KERN_WARNING
"sermouse.c: Received MZ++ packet %x, don't know how to handle.\n", buf[1]);
break;
}
break;
}
sermouse->count++;
}
/*
* sermouse_interrupt() handles incoming characters, either gathering them into
* packets or passing them to the command routine as command output.
*/
static void sermouse_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
{
struct sermouse *sermouse = serio->private;
if (jiffies - sermouse->last > 2) sermouse->count = 0;
sermouse->last = jiffies;
if (sermouse->type > SERIO_SUN)
sermouse_process_ms(sermouse, data);
else
sermouse_process_msc(sermouse, data);
}
/*
* sermouse_disconnect() cleans up after we don't want talk
* to the mouse anymore.
*/
static void sermouse_disconnect(struct serio *serio)
{
struct sermouse *sermouse = serio->private;
input_unregister_device(&sermouse->dev);
serio_close(serio);
kfree(sermouse);
}
/*
* sermouse_connect() is a callback form the serio module when
* an unhandled serio port is found.
*/
static void sermouse_connect(struct serio *serio, struct serio_dev *dev)
{
struct sermouse *sermouse;
unsigned char c;
if ((serio->type & SERIO_TYPE) != SERIO_RS232)
return;
if (!(serio->type & SERIO_PROTO) || ((serio->type & SERIO_PROTO) > SERIO_MZPP))
return;
if (!(sermouse = kmalloc(sizeof(struct sermouse), GFP_KERNEL)))
return;
memset(sermouse, 0, sizeof(struct sermouse));
sermouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
sermouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
sermouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
sermouse->dev.private = sermouse;
serio->private = sermouse;
sermouse->type = serio->type & SERIO_PROTO;
c = (serio->type & SERIO_EXTRA) >> 16;
if (c & 0x01) set_bit(BTN_MIDDLE, &sermouse->dev.keybit);
if (c & 0x02) set_bit(BTN_SIDE, &sermouse->dev.keybit);
if (c & 0x04) set_bit(BTN_EXTRA, &sermouse->dev.keybit);
if (c & 0x10) set_bit(REL_WHEEL, &sermouse->dev.relbit);
if (c & 0x20) set_bit(REL_HWHEEL, &sermouse->dev.relbit);
sprintf(sermouse->phys, "%s/input0", serio->phys);
sermouse->dev.name = sermouse_protocols[sermouse->type];
sermouse->dev.phys = sermouse->phys;
sermouse->dev.idbus = BUS_RS232;
sermouse->dev.idvendor = sermouse->type;
sermouse->dev.idproduct = c;
sermouse->dev.idversion = 0x0100;
if (serio_open(serio, dev)) {
kfree(sermouse);
return;
}
input_register_device(&sermouse->dev);
printk(KERN_INFO "input: %s on %s\n", sermouse_protocols[sermouse->type], serio->phys);
}
static struct serio_dev sermouse_dev = {
interrupt: sermouse_interrupt,
connect: sermouse_connect,
disconnect: sermouse_disconnect
};
int __init sermouse_init(void)
{
serio_register_device(&sermouse_dev);
return 0;
}
void __exit sermouse_exit(void)
{
serio_unregister_device(&sermouse_dev);
}
module_init(sermouse_init);
module_exit(sermouse_exit);
/*
* $Id: power.c,v 1.10 2001/09/25 09:17:15 vojtech Exp $
*
* Copyright (c) 2001 "Crazy" James Simmons
*
* Input driver Power Management.
*
* Sponsored by Transvirtual Technology.
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <jsimmons@transvirtual.com>.
*/
#include <linux/module.h>
#include <linux/config.h>
#include <linux/input.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/tty.h>
#include <linux/delay.h>
#include <linux/pm.h>
static struct input_handler power_handler;
/*
* Power management can't be done in a interrupt context. So we have to
* use keventd.
*/
static int suspend_button_pushed = 0;
static void suspend_button_task_handler(void *data)
{
//extern void pm_do_suspend(void);
udelay(200); /* debounce */
//pm_do_suspend();
suspend_button_pushed = 0;
}
static struct tq_struct suspend_button_task = {
routine: suspend_button_task_handler
};
static void power_event(struct input_handle *handle, unsigned int type,
unsigned int code, int down)
{
struct input_dev *dev = handle->dev;
printk("Entering power_event\n");
if (type != EV_KEY || type != EV_PWR) return;
if (type == EV_PWR) {
switch (code) {
case KEY_SUSPEND:
printk("Powering down entire device\n");
//pm_send_all(PM_SUSPEND, dev);
if (!suspend_button_pushed) {
suspend_button_pushed = 1;
schedule_task(&suspend_button_task);
}
break;
case KEY_POWER:
/* Hum power down the machine. */
break;
default:
return;
}
} else {
switch (code) {
case KEY_SUSPEND:
printk("Powering down input device\n");
/* This is risky. See pm.h for details. */
if (dev->state != PM_RESUME)
dev->state = PM_RESUME;
else
dev->state = PM_SUSPEND;
pm_send(dev->pm_dev, dev->state, dev);
break;
case KEY_POWER:
/* Turn the input device off completely ? */
break;
default:
return;
}
}
return;
}
static struct input_handle *power_connect(struct input_handler *handler,
struct input_dev *dev,
struct input_device_id *id)
{
struct input_handle *handle;
if (!test_bit(EV_KEY, dev->evbit) || !test_bit(EV_PWR, dev->evbit))
return NULL;
if (!test_bit(KEY_SUSPEND, dev->keybit) || (!test_bit(KEY_POWER, dev->keybit)))
return NULL;
if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
return NULL;
memset(handle, 0, sizeof(struct input_handle));
handle->dev = dev;
handle->handler = handler;
input_open_device(handle);
printk(KERN_INFO "power.c: Adding power management to input layer\n");
return handle;
}
static void power_disconnect(struct input_handle *handle)
{
input_close_device(handle);
kfree(handle);
}
static struct input_device_id power_ids[] = {
{
flags: INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
evbit: { BIT(EV_KEY) },
keybit: { [LONG(KEY_SUSPEND)] = BIT(KEY_SUSPEND) }
},
{
flags: INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
evbit: { BIT(EV_KEY) },
keybit: { [LONG(KEY_POWER)] = BIT(KEY_POWER) }
},
{
flags: INPUT_DEVICE_ID_MATCH_EVBIT,
evbit: { BIT(EV_PWR) },
},
{ }, /* Terminating entry */
};
MODULE_DEVICE_TABLE(input, power_ids);
static struct input_handler power_handler = {
event: power_event,
connect: power_connect,
disconnect: power_disconnect,
name: "power",
id_table: power_ids,
};
static int __init power_init(void)
{
input_register_handler(&power_handler);
return 0;
}
static void __exit power_exit(void)
{
input_unregister_handler(&power_handler);
}
module_init(power_init);
module_exit(power_exit);
MODULE_AUTHOR("James Simmons <jsimmons@transvirtual.com>");
MODULE_DESCRIPTION("Input Power Management driver");
CONFIG_INPUT_TOUCHSCREEN
Say Y here, and a list of supported touchscreens will be displayed.
This option doesn't affect the kernel.
If unsure, say Y.
CONFIG_TOUCHSCREEN_GUNZE
Say Y here if you have the Gunze AHL-51 touchscreen connected to
your system.
If unsure, say N.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called gunze.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
#
# Mouse driver configuration
#
bool 'Touchscreens' CONFIG_INPUT_TOUCHSCREEN
dep_tristate ' Gunze AHL-51S touchscreen' CONFIG_TOUCHSCREEN_GUNZE $CONFIG_INPUT $CONFIG_INPUT_TOUCHSCREEN $CONFIG_SERIO
#
# Makefile for the mouse drivers.
#
# The target object and module list name.
O_TARGET := tsdrv.o
# Each configuration option enables a list of files.
obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o
# The global Rules.make.
include $(TOPDIR)/Rules.make
/*
* $Id: gunze.c,v 1.12 2001/09/25 10:12:07 vojtech Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik
*/
/*
* Gunze AHL-51S touchscreen driver for Linux
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/init.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Gunze AHL-51S touchscreen driver");
MODULE_LICENSE("GPL");
/*
* Definitions & global arrays.
*/
#define GUNZE_MAX_LENGTH 10
static char *gunze_name = "Gunze AHL-51S TouchScreen";
/*
* Per-touchscreen data.
*/
struct gunze {
struct input_dev dev;
struct serio *serio;
int idx;
unsigned char data[GUNZE_MAX_LENGTH];
char phys[32];
};
static void gunze_process_packet(struct gunze* gunze)
{
struct input_dev *dev = &gunze->dev;
if (gunze->idx != GUNZE_MAX_LENGTH || gunze->data[5] != ',' ||
(gunze->data[0] != 'T' && gunze->data[0] != 'R')) {
gunze->data[10] = 0;
printk(KERN_WARNING "gunze.c: bad packet: >%s<\n", gunze->data);
return;
}
input_report_abs(dev, ABS_X, simple_strtoul(gunze->data + 1, NULL, 10) * 4);
input_report_abs(dev, ABS_Y, 3072 - simple_strtoul(gunze->data + 6, NULL, 10) * 3);
input_report_key(dev, BTN_TOUCH, gunze->data[0] == 'T');
}
static void gunze_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
{
struct gunze* gunze = serio->private;
if (data == '\r') {
gunze_process_packet(gunze);
gunze->idx = 0;
} else {
if (gunze->idx < GUNZE_MAX_LENGTH)
gunze->data[gunze->idx++] = data;
}
}
/*
* gunze_disconnect() is the opposite of gunze_connect()
*/
static void gunze_disconnect(struct serio *serio)
{
struct gunze* gunze = serio->private;
input_unregister_device(&gunze->dev);
serio_close(serio);
kfree(gunze);
}
/*
* gunze_connect() is the routine that is called when someone adds a
* new serio device. It looks whether it was registered as a Gunze touchscreen
* and if yes, registers it as an input device.
*/
static void gunze_connect(struct serio *serio, struct serio_dev *dev)
{
struct gunze *gunze;
if (serio->type != (SERIO_RS232 | SERIO_GUNZE))
return;
if (!(gunze = kmalloc(sizeof(struct gunze), GFP_KERNEL)))
return;
memset(gunze, 0, sizeof(struct gunze));
gunze->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
gunze->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
gunze->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
gunze->dev.absmin[ABS_X] = 96; gunze->dev.absmin[ABS_Y] = 72;
gunze->dev.absmax[ABS_X] = 4000; gunze->dev.absmax[ABS_Y] = 3000;
gunze->serio = serio;
serio->private = gunze;
sprintf(gunze->phys, "%s/input0", serio->phys);
gunze->dev.private = gunze;
gunze->dev.name = gunze_name;
gunze->dev.phys = gunze->phys;
gunze->dev.idbus = BUS_RS232;
gunze->dev.idvendor = SERIO_GUNZE;
gunze->dev.idproduct = 0x0051;
gunze->dev.idversion = 0x0100;
if (serio_open(serio, dev)) {
kfree(gunze);
return;
}
input_register_device(&gunze->dev);
printk(KERN_INFO "input: %s on %s\n", gunze_name, serio->phys);
}
/*
* The serio device structure.
*/
static struct serio_dev gunze_dev = {
interrupt: gunze_interrupt,
connect: gunze_connect,
disconnect: gunze_disconnect,
};
/*
* The functions for inserting/removing us as a module.
*/
int __init gunze_init(void)
{
serio_register_device(&gunze_dev);
return 0;
}
void __exit gunze_exit(void)
{
serio_unregister_device(&gunze_dev);
}
module_init(gunze_init);
module_exit(gunze_exit);
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