aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/Kconfig157
-rw-r--r--drivers/input/Makefile19
-rw-r--r--drivers/input/evbug.c103
-rw-r--r--drivers/input/evdev.c492
-rw-r--r--drivers/input/gameport/Kconfig90
-rw-r--r--drivers/input/gameport/Makefile13
-rw-r--r--drivers/input/gameport/cs461x.c322
-rw-r--r--drivers/input/gameport/emu10k1-gp.c132
-rw-r--r--drivers/input/gameport/fm801-gp.c163
-rw-r--r--drivers/input/gameport/gameport.c797
-rw-r--r--drivers/input/gameport/lightning.c344
-rw-r--r--drivers/input/gameport/ns558.c291
-rw-r--r--drivers/input/gameport/vortex.c186
-rw-r--r--drivers/input/input.c748
-rw-r--r--drivers/input/joydev.c533
-rw-r--r--drivers/input/joystick/Kconfig256
-rw-r--r--drivers/input/joystick/Makefile30
-rw-r--r--drivers/input/joystick/a3d.c417
-rw-r--r--drivers/input/joystick/adi.c560
-rw-r--r--drivers/input/joystick/amijoy.c161
-rw-r--r--drivers/input/joystick/analog.c772
-rw-r--r--drivers/input/joystick/cobra.c264
-rw-r--r--drivers/input/joystick/db9.c647
-rw-r--r--drivers/input/joystick/gamecon.c697
-rw-r--r--drivers/input/joystick/gf2k.c380
-rw-r--r--drivers/input/joystick/grip.c422
-rw-r--r--drivers/input/joystick/grip_mp.c677
-rw-r--r--drivers/input/joystick/guillemot.c289
-rw-r--r--drivers/input/joystick/iforce/Kconfig32
-rw-r--r--drivers/input/joystick/iforce/Makefile20
-rw-r--r--drivers/input/joystick/iforce/iforce-ff.c543
-rw-r--r--drivers/input/joystick/iforce/iforce-main.c557
-rw-r--r--drivers/input/joystick/iforce/iforce-packets.c319
-rw-r--r--drivers/input/joystick/iforce/iforce-serio.c193
-rw-r--r--drivers/input/joystick/iforce/iforce-usb.c243
-rw-r--r--drivers/input/joystick/iforce/iforce.h191
-rw-r--r--drivers/input/joystick/interact.c322
-rw-r--r--drivers/input/joystick/joydump.c175
-rw-r--r--drivers/input/joystick/magellan.c247
-rw-r--r--drivers/input/joystick/sidewinder.c807
-rw-r--r--drivers/input/joystick/spaceball.c319
-rw-r--r--drivers/input/joystick/spaceorb.c263
-rw-r--r--drivers/input/joystick/stinger.c236
-rw-r--r--drivers/input/joystick/tmdc.c384
-rw-r--r--drivers/input/joystick/turbografx.c258
-rw-r--r--drivers/input/joystick/twidjoy.c296
-rw-r--r--drivers/input/joystick/warrior.c248
-rw-r--r--drivers/input/keyboard/Kconfig185
-rw-r--r--drivers/input/keyboard/Makefile19
-rw-r--r--drivers/input/keyboard/amikbd.c241
-rw-r--r--drivers/input/keyboard/atkbd.c1148
-rw-r--r--drivers/input/keyboard/corgikbd.c361
-rw-r--r--drivers/input/keyboard/hil_kbd.c375
-rw-r--r--drivers/input/keyboard/hilkbd.c343
-rw-r--r--drivers/input/keyboard/hpps2atkbd.h110
-rw-r--r--drivers/input/keyboard/lkkbd.c752
-rw-r--r--drivers/input/keyboard/locomokbd.c309
-rw-r--r--drivers/input/keyboard/maple_keyb.c190
-rw-r--r--drivers/input/keyboard/newtonkbd.c184
-rw-r--r--drivers/input/keyboard/sunkbd.c353
-rw-r--r--drivers/input/keyboard/xtkbd.c188
-rw-r--r--drivers/input/misc/Kconfig60
-rw-r--r--drivers/input/misc/Makefile12
-rw-r--r--drivers/input/misc/hp_sdc_rtc.c724
-rw-r--r--drivers/input/misc/m68kspkr.c83
-rw-r--r--drivers/input/misc/pcspkr.c97
-rw-r--r--drivers/input/misc/sparcspkr.c189
-rw-r--r--drivers/input/misc/uinput.c620
-rw-r--r--drivers/input/mouse/Kconfig138
-rw-r--r--drivers/input/mouse/Makefile18
-rw-r--r--drivers/input/mouse/alps.c477
-rw-r--r--drivers/input/mouse/alps.h32
-rw-r--r--drivers/input/mouse/amimouse.c137
-rw-r--r--drivers/input/mouse/hil_ptr.c414
-rw-r--r--drivers/input/mouse/inport.c196
-rw-r--r--drivers/input/mouse/logibm.c183
-rw-r--r--drivers/input/mouse/logips2pp.c397
-rw-r--r--drivers/input/mouse/logips2pp.h16
-rw-r--r--drivers/input/mouse/maplemouse.c134
-rw-r--r--drivers/input/mouse/pc110pad.c178
-rw-r--r--drivers/input/mouse/psmouse-base.c1011
-rw-r--r--drivers/input/mouse/psmouse.h106
-rw-r--r--drivers/input/mouse/rpcmouse.c107
-rw-r--r--drivers/input/mouse/sermouse.c370
-rw-r--r--drivers/input/mouse/synaptics.c700
-rw-r--r--drivers/input/mouse/synaptics.h110
-rw-r--r--drivers/input/mouse/vsxxxaa.c591
-rw-r--r--drivers/input/mousedev.c758
-rw-r--r--drivers/input/power.c169
-rw-r--r--drivers/input/serio/Kconfig183
-rw-r--r--drivers/input/serio/Makefile23
-rw-r--r--drivers/input/serio/ambakmi.c231
-rw-r--r--drivers/input/serio/ct82c710.c225
-rw-r--r--drivers/input/serio/gscps2.c467
-rw-r--r--drivers/input/serio/hil_mlc.c949
-rw-r--r--drivers/input/serio/hp_sdc.c1054
-rw-r--r--drivers/input/serio/hp_sdc_mlc.c358
-rw-r--r--drivers/input/serio/i8042-io.h93
-rw-r--r--drivers/input/serio/i8042-ip22io.h76
-rw-r--r--drivers/input/serio/i8042-jazzio.h69
-rw-r--r--drivers/input/serio/i8042-ppcio.h136
-rw-r--r--drivers/input/serio/i8042-sparcio.h116
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h333
-rw-r--r--drivers/input/serio/i8042.c1116
-rw-r--r--drivers/input/serio/i8042.h133
-rw-r--r--drivers/input/serio/libps2.c305
-rw-r--r--drivers/input/serio/maceps2.c176
-rw-r--r--drivers/input/serio/parkbd.c218
-rw-r--r--drivers/input/serio/pcips2.c234
-rw-r--r--drivers/input/serio/q40kbd.c163
-rw-r--r--drivers/input/serio/rpckbd.c156
-rw-r--r--drivers/input/serio/sa1111ps2.c359
-rw-r--r--drivers/input/serio/serio.c859
-rw-r--r--drivers/input/serio/serio_raw.c403
-rw-r--r--drivers/input/serio/serport.c226
-rw-r--r--drivers/input/touchscreen/Kconfig98
-rw-r--r--drivers/input/touchscreen/Makefile13
-rw-r--r--drivers/input/touchscreen/corgi_ts.c380
-rw-r--r--drivers/input/touchscreen/elo.c315
-rw-r--r--drivers/input/touchscreen/gunze.c205
-rw-r--r--drivers/input/touchscreen/h3600_ts_input.c528
-rw-r--r--drivers/input/touchscreen/hp680_ts_input.c135
-rw-r--r--drivers/input/touchscreen/mk712.c222
-rw-r--r--drivers/input/touchscreen/mtouch.c219
-rw-r--r--drivers/input/tsdev.c492
125 files changed, 39668 insertions, 0 deletions
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
new file mode 100644
index 000000000000..58223b5d842a
--- /dev/null
+++ b/drivers/input/Kconfig
@@ -0,0 +1,157 @@
1#
2# Input device configuration
3#
4
5menu "Input device support"
6
7config INPUT
8 tristate "Generic input layer (needed for keyboard, mouse, ...)" if EMBEDDED
9 default y
10 ---help---
11 Say Y here if you have any input device (mouse, keyboard, tablet,
12 joystick, steering wheel ...) connected to your system and want
13 it to be available to applications. This includes standard PS/2
14 keyboard and mouse.
15
16 Say N here if you have a headless (no monitor, no keyboard) system.
17
18 More information is available: <file:Documentation/input/input.txt>
19
20 If unsure, say Y.
21
22 To compile this driver as a module, choose M here: the
23 module will be called input.
24
25if INPUT
26
27comment "Userland interfaces"
28
29config INPUT_MOUSEDEV
30 tristate "Mouse interface" if EMBEDDED
31 default y
32 ---help---
33 Say Y here if you want your mouse to be accessible as char devices
34 13:32+ - /dev/input/mouseX and 13:63 - /dev/input/mice as an
35 emulated IntelliMouse Explorer PS/2 mouse. That way, all user space
36 programs (including SVGAlib, GPM and X) will be able to use your
37 mouse.
38
39 If unsure, say Y.
40
41 To compile this driver as a module, choose M here: the
42 module will be called mousedev.
43
44config INPUT_MOUSEDEV_PSAUX
45 bool "Provide legacy /dev/psaux device"
46 default y
47 depends on INPUT_MOUSEDEV
48 ---help---
49 Say Y here if you want your mouse also be accessible as char device
50 10:1 - /dev/psaux. The data available through /dev/psaux is exactly
51 the same as the data from /dev/input/mice.
52
53 If unsure, say Y.
54
55
56config INPUT_MOUSEDEV_SCREEN_X
57 int "Horizontal screen resolution"
58 depends on INPUT_MOUSEDEV
59 default "1024"
60 help
61 If you're using a digitizer, or a graphic tablet, and want to use
62 it as a mouse then the mousedev driver needs to know the X window
63 screen resolution you are using to correctly scale the data. If
64 you're not using a digitizer, this value is ignored.
65
66config INPUT_MOUSEDEV_SCREEN_Y
67 int "Vertical screen resolution"
68 depends on INPUT_MOUSEDEV
69 default "768"
70 help
71 If you're using a digitizer, or a graphic tablet, and want to use
72 it as a mouse then the mousedev driver needs to know the X window
73 screen resolution you are using to correctly scale the data. If
74 you're not using a digitizer, this value is ignored.
75
76config INPUT_JOYDEV
77 tristate "Joystick interface"
78 ---help---
79 Say Y here if you want your joystick or gamepad to be
80 accessible as char device 13:0+ - /dev/input/jsX device.
81
82 If unsure, say Y.
83
84 More information is available: <file:Documentation/input/joystick.txt>
85
86 To compile this driver as a module, choose M here: the
87 module will be called joydev.
88
89config INPUT_TSDEV
90 tristate "Touchscreen interface"
91 ---help---
92 Say Y here if you have an application that only can understand the
93 Compaq touchscreen protocol for absolute pointer data. This is
94 useful namely for embedded configurations.
95
96 If unsure, say N.
97
98 To compile this driver as a module, choose M here: the
99 module will be called tsdev.
100
101config INPUT_TSDEV_SCREEN_X
102 int "Horizontal screen resolution"
103 depends on INPUT_TSDEV
104 default "240"
105
106config INPUT_TSDEV_SCREEN_Y
107 int "Vertical screen resolution"
108 depends on INPUT_TSDEV
109 default "320"
110
111config INPUT_EVDEV
112 tristate "Event interface"
113 help
114 Say Y here if you want your input device events be accessible
115 under char device 13:64+ - /dev/input/eventX in a generic way.
116
117 To compile this driver as a module, choose M here: the
118 module will be called evdev.
119
120config INPUT_EVBUG
121 tristate "Event debugging"
122 ---help---
123 Say Y here if you have a problem with the input subsystem and
124 want all events (keypresses, mouse movements), to be output to
125 the system log. While this is useful for debugging, it's also
126 a security threat - your keypresses include your passwords, of
127 course.
128
129 If unsure, say N.
130
131 To compile this driver as a module, choose M here: the
132 module will be called evbug.
133
134comment "Input Device Drivers"
135
136source "drivers/input/keyboard/Kconfig"
137
138source "drivers/input/mouse/Kconfig"
139
140source "drivers/input/joystick/Kconfig"
141
142source "drivers/input/touchscreen/Kconfig"
143
144source "drivers/input/misc/Kconfig"
145
146endif
147
148menu "Hardware I/O ports"
149
150source "drivers/input/serio/Kconfig"
151
152source "drivers/input/gameport/Kconfig"
153
154endmenu
155
156endmenu
157
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
new file mode 100644
index 000000000000..1a6ff4982f30
--- /dev/null
+++ b/drivers/input/Makefile
@@ -0,0 +1,19 @@
1#
2# Makefile for the input core drivers.
3#
4
5# Each configuration option enables a list of files.
6
7obj-$(CONFIG_INPUT) += input.o
8obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o
9obj-$(CONFIG_INPUT_JOYDEV) += joydev.o
10obj-$(CONFIG_INPUT_EVDEV) += evdev.o
11obj-$(CONFIG_INPUT_TSDEV) += tsdev.o
12obj-$(CONFIG_INPUT_POWER) += power.o
13obj-$(CONFIG_INPUT_EVBUG) += evbug.o
14
15obj-$(CONFIG_INPUT_KEYBOARD) += keyboard/
16obj-$(CONFIG_INPUT_MOUSE) += mouse/
17obj-$(CONFIG_INPUT_JOYSTICK) += joystick/
18obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/
19obj-$(CONFIG_INPUT_MISC) += misc/
diff --git a/drivers/input/evbug.c b/drivers/input/evbug.c
new file mode 100644
index 000000000000..d7828936fd8f
--- /dev/null
+++ b/drivers/input/evbug.c
@@ -0,0 +1,103 @@
1/*
2 * $Id: evbug.c,v 1.10 2001/09/25 10:12:07 vojtech Exp $
3 *
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 */
6
7/*
8 * Input driver event debug module - dumps all events into syslog
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/slab.h>
32#include <linux/module.h>
33#include <linux/input.h>
34#include <linux/init.h>
35#include <linux/device.h>
36
37MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
38MODULE_DESCRIPTION("Input driver event debug module");
39MODULE_LICENSE("GPL");
40
41static char evbug_name[] = "evbug";
42
43static void evbug_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
44{
45 printk(KERN_DEBUG "evbug.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d\n", handle->dev->phys, type, code, value);
46}
47
48static struct input_handle *evbug_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
49{
50 struct input_handle *handle;
51
52 if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
53 return NULL;
54 memset(handle, 0, sizeof(struct input_handle));
55
56 handle->dev = dev;
57 handle->handler = handler;
58 handle->name = evbug_name;
59
60 input_open_device(handle);
61
62 printk(KERN_DEBUG "evbug.c: Connected device: \"%s\", %s\n", dev->name, dev->phys);
63
64 return handle;
65}
66
67static void evbug_disconnect(struct input_handle *handle)
68{
69 printk(KERN_DEBUG "evbug.c: Disconnected device: %s\n", handle->dev->phys);
70
71 input_close_device(handle);
72
73 kfree(handle);
74}
75
76static struct input_device_id evbug_ids[] = {
77 { .driver_info = 1 }, /* Matches all devices */
78 { }, /* Terminating zero entry */
79};
80
81MODULE_DEVICE_TABLE(input, evbug_ids);
82
83static struct input_handler evbug_handler = {
84 .event = evbug_event,
85 .connect = evbug_connect,
86 .disconnect = evbug_disconnect,
87 .name = "evbug",
88 .id_table = evbug_ids,
89};
90
91static int __init evbug_init(void)
92{
93 input_register_handler(&evbug_handler);
94 return 0;
95}
96
97static void __exit evbug_exit(void)
98{
99 input_unregister_handler(&evbug_handler);
100}
101
102module_init(evbug_init);
103module_exit(evbug_exit);
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
new file mode 100644
index 000000000000..17552a29978b
--- /dev/null
+++ b/drivers/input/evdev.c
@@ -0,0 +1,492 @@
1/*
2 * Event char devices, giving access to raw input device events.
3 *
4 * Copyright (c) 1999-2002 Vojtech Pavlik
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 */
10
11#define EVDEV_MINOR_BASE 64
12#define EVDEV_MINORS 32
13#define EVDEV_BUFFER_SIZE 64
14
15#include <linux/poll.h>
16#include <linux/slab.h>
17#include <linux/module.h>
18#include <linux/init.h>
19#include <linux/input.h>
20#include <linux/major.h>
21#include <linux/smp_lock.h>
22#include <linux/device.h>
23#include <linux/devfs_fs_kernel.h>
24
25struct evdev {
26 int exist;
27 int open;
28 int minor;
29 char name[16];
30 struct input_handle handle;
31 wait_queue_head_t wait;
32 struct evdev_list *grab;
33 struct list_head list;
34};
35
36struct evdev_list {
37 struct input_event buffer[EVDEV_BUFFER_SIZE];
38 int head;
39 int tail;
40 struct fasync_struct *fasync;
41 struct evdev *evdev;
42 struct list_head node;
43};
44
45static struct evdev *evdev_table[EVDEV_MINORS];
46
47static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
48{
49 struct evdev *evdev = handle->private;
50 struct evdev_list *list;
51
52 if (evdev->grab) {
53 list = evdev->grab;
54
55 do_gettimeofday(&list->buffer[list->head].time);
56 list->buffer[list->head].type = type;
57 list->buffer[list->head].code = code;
58 list->buffer[list->head].value = value;
59 list->head = (list->head + 1) & (EVDEV_BUFFER_SIZE - 1);
60
61 kill_fasync(&list->fasync, SIGIO, POLL_IN);
62 } else
63 list_for_each_entry(list, &evdev->list, node) {
64
65 do_gettimeofday(&list->buffer[list->head].time);
66 list->buffer[list->head].type = type;
67 list->buffer[list->head].code = code;
68 list->buffer[list->head].value = value;
69 list->head = (list->head + 1) & (EVDEV_BUFFER_SIZE - 1);
70
71 kill_fasync(&list->fasync, SIGIO, POLL_IN);
72 }
73
74 wake_up_interruptible(&evdev->wait);
75}
76
77static int evdev_fasync(int fd, struct file *file, int on)
78{
79 int retval;
80 struct evdev_list *list = file->private_data;
81 retval = fasync_helper(fd, file, on, &list->fasync);
82 return retval < 0 ? retval : 0;
83}
84
85static int evdev_flush(struct file * file)
86{
87 struct evdev_list *list = file->private_data;
88 if (!list->evdev->exist) return -ENODEV;
89 return input_flush_device(&list->evdev->handle, file);
90}
91
92static void evdev_free(struct evdev *evdev)
93{
94 evdev_table[evdev->minor] = NULL;
95 kfree(evdev);
96}
97
98static int evdev_release(struct inode * inode, struct file * file)
99{
100 struct evdev_list *list = file->private_data;
101
102 if (list->evdev->grab == list) {
103 input_release_device(&list->evdev->handle);
104 list->evdev->grab = NULL;
105 }
106
107 evdev_fasync(-1, file, 0);
108 list_del(&list->node);
109
110 if (!--list->evdev->open) {
111 if (list->evdev->exist)
112 input_close_device(&list->evdev->handle);
113 else
114 evdev_free(list->evdev);
115 }
116
117 kfree(list);
118 return 0;
119}
120
121static int evdev_open(struct inode * inode, struct file * file)
122{
123 struct evdev_list *list;
124 int i = iminor(inode) - EVDEV_MINOR_BASE;
125 int accept_err;
126
127 if (i >= EVDEV_MINORS || !evdev_table[i] || !evdev_table[i]->exist)
128 return -ENODEV;
129
130 if ((accept_err = input_accept_process(&(evdev_table[i]->handle), file)))
131 return accept_err;
132
133 if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL)))
134 return -ENOMEM;
135 memset(list, 0, sizeof(struct evdev_list));
136
137 list->evdev = evdev_table[i];
138 list_add_tail(&list->node, &evdev_table[i]->list);
139 file->private_data = list;
140
141 if (!list->evdev->open++)
142 if (list->evdev->exist)
143 input_open_device(&list->evdev->handle);
144
145 return 0;
146}
147
148static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
149{
150 struct evdev_list *list = file->private_data;
151 struct input_event event;
152 int retval = 0;
153
154 if (!list->evdev->exist) return -ENODEV;
155
156 while (retval < count) {
157
158 if (copy_from_user(&event, buffer + retval, sizeof(struct input_event)))
159 return -EFAULT;
160 input_event(list->evdev->handle.dev, event.type, event.code, event.value);
161 retval += sizeof(struct input_event);
162 }
163
164 return retval;
165}
166
167static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
168{
169 struct evdev_list *list = file->private_data;
170 int retval;
171
172 if (count < sizeof(struct input_event))
173 return -EINVAL;
174
175 if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK))
176 return -EAGAIN;
177
178 retval = wait_event_interruptible(list->evdev->wait,
179 list->head != list->tail || (!list->evdev->exist));
180
181 if (retval)
182 return retval;
183
184 if (!list->evdev->exist)
185 return -ENODEV;
186
187 while (list->head != list->tail && retval + sizeof(struct input_event) <= count) {
188 if (copy_to_user(buffer + retval, list->buffer + list->tail,
189 sizeof(struct input_event))) return -EFAULT;
190 list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
191 retval += sizeof(struct input_event);
192 }
193
194 return retval;
195}
196
197/* No kernel lock - fine */
198static unsigned int evdev_poll(struct file *file, poll_table *wait)
199{
200 struct evdev_list *list = file->private_data;
201 poll_wait(file, &list->evdev->wait, wait);
202 return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) |
203 (list->evdev->exist ? 0 : (POLLHUP | POLLERR));
204}
205
206static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
207{
208 struct evdev_list *list = file->private_data;
209 struct evdev *evdev = list->evdev;
210 struct input_dev *dev = evdev->handle.dev;
211 struct input_absinfo abs;
212 void __user *p = (void __user *)arg;
213 int __user *ip = (int __user *)arg;
214 int i, t, u, v;
215
216 if (!evdev->exist) return -ENODEV;
217
218 switch (cmd) {
219
220 case EVIOCGVERSION:
221 return put_user(EV_VERSION, ip);
222
223 case EVIOCGID:
224 return copy_to_user(p, &dev->id, sizeof(struct input_id)) ? -EFAULT : 0;
225
226 case EVIOCGKEYCODE:
227 if (get_user(t, ip)) return -EFAULT;
228 if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL;
229 if (put_user(INPUT_KEYCODE(dev, t), ip + 1)) return -EFAULT;
230 return 0;
231
232 case EVIOCSKEYCODE:
233 if (get_user(t, ip)) return -EFAULT;
234 if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL;
235 if (get_user(v, ip + 1)) return -EFAULT;
236 if (v < 0 || v > KEY_MAX) return -EINVAL;
237 u = SET_INPUT_KEYCODE(dev, t, v);
238 clear_bit(u, dev->keybit);
239 set_bit(v, dev->keybit);
240 for (i = 0; i < dev->keycodemax; i++)
241 if (INPUT_KEYCODE(dev,i) == u)
242 set_bit(u, dev->keybit);
243 return 0;
244
245 case EVIOCSFF:
246 if (dev->upload_effect) {
247 struct ff_effect effect;
248 int err;
249
250 if (copy_from_user(&effect, p, sizeof(effect)))
251 return -EFAULT;
252 err = dev->upload_effect(dev, &effect);
253 if (put_user(effect.id, &(((struct ff_effect __user *)arg)->id)))
254 return -EFAULT;
255 return err;
256 }
257 else return -ENOSYS;
258
259 case EVIOCRMFF:
260 if (dev->erase_effect) {
261 return dev->erase_effect(dev, (int)arg);
262 }
263 else return -ENOSYS;
264
265 case EVIOCGEFFECTS:
266 if (put_user(dev->ff_effects_max, ip))
267 return -EFAULT;
268 return 0;
269
270 case EVIOCGRAB:
271 if (arg) {
272 if (evdev->grab)
273 return -EBUSY;
274 if (input_grab_device(&evdev->handle))
275 return -EBUSY;
276 evdev->grab = list;
277 return 0;
278 } else {
279 if (evdev->grab != list)
280 return -EINVAL;
281 input_release_device(&evdev->handle);
282 evdev->grab = NULL;
283 return 0;
284 }
285
286 default:
287
288 if (_IOC_TYPE(cmd) != 'E' || _IOC_DIR(cmd) != _IOC_READ)
289 return -EINVAL;
290
291 if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) {
292
293 long *bits;
294 int len;
295
296 switch (_IOC_NR(cmd) & EV_MAX) {
297 case 0: bits = dev->evbit; len = EV_MAX; break;
298 case EV_KEY: bits = dev->keybit; len = KEY_MAX; break;
299 case EV_REL: bits = dev->relbit; len = REL_MAX; break;
300 case EV_ABS: bits = dev->absbit; len = ABS_MAX; break;
301 case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break;
302 case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
303 case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
304 case EV_FF: bits = dev->ffbit; len = FF_MAX; break;
305 default: return -EINVAL;
306 }
307 len = NBITS(len) * sizeof(long);
308 if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
309 return copy_to_user(p, bits, len) ? -EFAULT : len;
310 }
311
312 if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) {
313 int len;
314 len = NBITS(KEY_MAX) * sizeof(long);
315 if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
316 return copy_to_user(p, dev->key, len) ? -EFAULT : len;
317 }
318
319 if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) {
320 int len;
321 len = NBITS(LED_MAX) * sizeof(long);
322 if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
323 return copy_to_user(p, dev->led, len) ? -EFAULT : len;
324 }
325
326 if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) {
327 int len;
328 len = NBITS(SND_MAX) * sizeof(long);
329 if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
330 return copy_to_user(p, dev->snd, len) ? -EFAULT : len;
331 }
332
333 if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
334 int len;
335 if (!dev->name) return -ENOENT;
336 len = strlen(dev->name) + 1;
337 if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
338 return copy_to_user(p, dev->name, len) ? -EFAULT : len;
339 }
340
341 if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) {
342 int len;
343 if (!dev->phys) return -ENOENT;
344 len = strlen(dev->phys) + 1;
345 if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
346 return copy_to_user(p, dev->phys, len) ? -EFAULT : len;
347 }
348
349 if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) {
350 int len;
351 if (!dev->uniq) return -ENOENT;
352 len = strlen(dev->uniq) + 1;
353 if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
354 return copy_to_user(p, dev->uniq, len) ? -EFAULT : len;
355 }
356
357 if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
358
359 int t = _IOC_NR(cmd) & ABS_MAX;
360
361 abs.value = dev->abs[t];
362 abs.minimum = dev->absmin[t];
363 abs.maximum = dev->absmax[t];
364 abs.fuzz = dev->absfuzz[t];
365 abs.flat = dev->absflat[t];
366
367 if (copy_to_user(p, &abs, sizeof(struct input_absinfo)))
368 return -EFAULT;
369
370 return 0;
371 }
372
373 if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
374
375 int t = _IOC_NR(cmd) & ABS_MAX;
376
377 if (copy_from_user(&abs, p, sizeof(struct input_absinfo)))
378 return -EFAULT;
379
380 dev->abs[t] = abs.value;
381 dev->absmin[t] = abs.minimum;
382 dev->absmax[t] = abs.maximum;
383 dev->absfuzz[t] = abs.fuzz;
384 dev->absflat[t] = abs.flat;
385
386 return 0;
387 }
388 }
389 return -EINVAL;
390}
391
392static struct file_operations evdev_fops = {
393 .owner = THIS_MODULE,
394 .read = evdev_read,
395 .write = evdev_write,
396 .poll = evdev_poll,
397 .open = evdev_open,
398 .release = evdev_release,
399 .ioctl = evdev_ioctl,
400 .fasync = evdev_fasync,
401 .flush = evdev_flush
402};
403
404static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
405{
406 struct evdev *evdev;
407 int minor;
408
409 for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++);
410 if (minor == EVDEV_MINORS) {
411 printk(KERN_ERR "evdev: no more free evdev devices\n");
412 return NULL;
413 }
414
415 if (!(evdev = kmalloc(sizeof(struct evdev), GFP_KERNEL)))
416 return NULL;
417 memset(evdev, 0, sizeof(struct evdev));
418
419 INIT_LIST_HEAD(&evdev->list);
420 init_waitqueue_head(&evdev->wait);
421
422 evdev->exist = 1;
423 evdev->minor = minor;
424 evdev->handle.dev = dev;
425 evdev->handle.name = evdev->name;
426 evdev->handle.handler = handler;
427 evdev->handle.private = evdev;
428 sprintf(evdev->name, "event%d", minor);
429
430 evdev_table[minor] = evdev;
431
432 devfs_mk_cdev(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
433 S_IFCHR|S_IRUGO|S_IWUSR, "input/event%d", minor);
434 class_simple_device_add(input_class,
435 MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
436 dev->dev, "event%d", minor);
437
438 return &evdev->handle;
439}
440
441static void evdev_disconnect(struct input_handle *handle)
442{
443 struct evdev *evdev = handle->private;
444 struct evdev_list *list;
445
446 class_simple_device_remove(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
447 devfs_remove("input/event%d", evdev->minor);
448 evdev->exist = 0;
449
450 if (evdev->open) {
451 input_close_device(handle);
452 wake_up_interruptible(&evdev->wait);
453 list_for_each_entry(list, &evdev->list, node)
454 kill_fasync(&list->fasync, SIGIO, POLL_HUP);
455 } else
456 evdev_free(evdev);
457}
458
459static struct input_device_id evdev_ids[] = {
460 { .driver_info = 1 }, /* Matches all devices */
461 { }, /* Terminating zero entry */
462};
463
464MODULE_DEVICE_TABLE(input, evdev_ids);
465
466static struct input_handler evdev_handler = {
467 .event = evdev_event,
468 .connect = evdev_connect,
469 .disconnect = evdev_disconnect,
470 .fops = &evdev_fops,
471 .minor = EVDEV_MINOR_BASE,
472 .name = "evdev",
473 .id_table = evdev_ids,
474};
475
476static int __init evdev_init(void)
477{
478 input_register_handler(&evdev_handler);
479 return 0;
480}
481
482static void __exit evdev_exit(void)
483{
484 input_unregister_handler(&evdev_handler);
485}
486
487module_init(evdev_init);
488module_exit(evdev_exit);
489
490MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
491MODULE_DESCRIPTION("Input driver event char devices");
492MODULE_LICENSE("GPL");
diff --git a/drivers/input/gameport/Kconfig b/drivers/input/gameport/Kconfig
new file mode 100644
index 000000000000..6282f460aba0
--- /dev/null
+++ b/drivers/input/gameport/Kconfig
@@ -0,0 +1,90 @@
1#
2# Gameport configuration
3#
4config GAMEPORT
5 tristate "Gameport support"
6 ---help---
7 Gameport support is for the standard 15-pin PC gameport. If you
8 have a joystick, gamepad, gameport card, a soundcard with a gameport
9 or anything else that uses the gameport, say Y or M here and also to
10 at least one of the hardware specific drivers.
11
12 For Ensoniq AudioPCI (ES1370), AudioPCI 97 (ES1371), ESS Solo1,
13 S3 SonicVibes, Trident 4DWave, SiS7018, and ALi 5451 gameport
14 support is provided by the sound drivers, so you won't need any
15 from the below listed modules. You still need to say Y here.
16
17 If unsure, say Y.
18
19 To compile this driver as a module, choose M here: the
20 module will be called gameport.
21
22if GAMEPORT
23
24config GAMEPORT_NS558
25 tristate "Classic ISA and PnP gameport support"
26 help
27 Say Y here if you have an ISA or PnP gameport.
28
29 If unsure, say Y.
30
31 To compile this driver as a module, choose M here: the
32 module will be called ns558.
33
34config GAMEPORT_L4
35 tristate "PDPI Lightning 4 gamecard support"
36 help
37 Say Y here if you have a PDPI Lightning 4 gamecard.
38
39 To compile this driver as a module, choose M here: the
40 module will be called lightning.
41
42config GAMEPORT_EMU10K1
43 tristate "SB Live and Audigy gameport support"
44 depends on PCI
45 help
46 Say Y here if you have a SoundBlaster Live! or SoundBlaster
47 Audigy card and want to use its gameport.
48
49 To compile this driver as a module, choose M here: the
50 module will be called emu10k1-gp.
51
52config GAMEPORT_VORTEX
53 tristate "Aureal Vortex, Vortex 2 gameport support"
54 depends on PCI
55 help
56 Say Y here if you have an Aureal Vortex 1 or 2 card and want
57 to use its gameport.
58
59 To compile this driver as a module, choose M here: the
60 module will be called vortex.
61
62config GAMEPORT_FM801
63 tristate "ForteMedia FM801 gameport support"
64 depends on PCI
65
66config GAMEPORT_CS461X
67 tristate "Crystal SoundFusion gameport support"
68 depends on PCI
69
70endif
71
72# Yes, SOUND_GAMEPORT looks a bit odd. Yes, it ends up being turned on
73# in every .config. Please don't touch it. It is here to handle an
74# unusual dependency between GAMEPORT and sound drivers.
75#
76# Some sound drivers call gameport functions. If GAMEPORT is
77# not selected, empty stubs are provided for the functions and all is
78# well.
79# If GAMEPORT is built in, everything is fine.
80# If GAMEPORT is a module, however, it would need to be loaded for the
81# sound driver to be able to link properly. Therefore, the sound
82# driver must be a module as well in that case. Since there's no way
83# to express that directly in Kconfig, we use SOUND_GAMEPORT to
84# express it. SOUND_GAMEPORT boils down to "if GAMEPORT is 'm',
85# anything that depends on SOUND_GAMEPORT must be 'm' as well. if
86# GAMEPORT is 'y' or 'n', it can be anything".
87config SOUND_GAMEPORT
88 tristate
89 default m if GAMEPORT=m
90 default y
diff --git a/drivers/input/gameport/Makefile b/drivers/input/gameport/Makefile
new file mode 100644
index 000000000000..5367b4267adf
--- /dev/null
+++ b/drivers/input/gameport/Makefile
@@ -0,0 +1,13 @@
1#
2# Makefile for the gameport drivers.
3#
4
5# Each configuration option enables a list of files.
6
7obj-$(CONFIG_GAMEPORT) += gameport.o
8obj-$(CONFIG_GAMEPORT_CS461X) += cs461x.o
9obj-$(CONFIG_GAMEPORT_EMU10K1) += emu10k1-gp.o
10obj-$(CONFIG_GAMEPORT_FM801) += fm801-gp.o
11obj-$(CONFIG_GAMEPORT_L4) += lightning.o
12obj-$(CONFIG_GAMEPORT_NS558) += ns558.o
13obj-$(CONFIG_GAMEPORT_VORTEX) += vortex.o
diff --git a/drivers/input/gameport/cs461x.c b/drivers/input/gameport/cs461x.c
new file mode 100644
index 000000000000..d4013ff98623
--- /dev/null
+++ b/drivers/input/gameport/cs461x.c
@@ -0,0 +1,322 @@
1/*
2 The all defines and part of code (such as cs461x_*) are
3 contributed from ALSA 0.5.8 sources.
4 See http://www.alsa-project.org/ for sources
5
6 Tested on Linux 686 2.4.0-test9, ALSA 0.5.8a and CS4610
7*/
8
9#include <asm/io.h>
10
11#include <linux/module.h>
12#include <linux/ioport.h>
13#include <linux/config.h>
14#include <linux/init.h>
15#include <linux/gameport.h>
16#include <linux/slab.h>
17#include <linux/pci.h>
18
19MODULE_AUTHOR("Victor Krapivin");
20MODULE_LICENSE("GPL");
21
22/*
23 These options are experimental
24
25#define CS461X_FULL_MAP
26*/
27
28
29#ifndef PCI_VENDOR_ID_CIRRUS
30#define PCI_VENDOR_ID_CIRRUS 0x1013
31#endif
32#ifndef PCI_DEVICE_ID_CIRRUS_4610
33#define PCI_DEVICE_ID_CIRRUS_4610 0x6001
34#endif
35#ifndef PCI_DEVICE_ID_CIRRUS_4612
36#define PCI_DEVICE_ID_CIRRUS_4612 0x6003
37#endif
38#ifndef PCI_DEVICE_ID_CIRRUS_4615
39#define PCI_DEVICE_ID_CIRRUS_4615 0x6004
40#endif
41
42/* Registers */
43
44#define BA0_JSPT 0x00000480
45#define BA0_JSCTL 0x00000484
46#define BA0_JSC1 0x00000488
47#define BA0_JSC2 0x0000048C
48#define BA0_JSIO 0x000004A0
49
50/* Bits for JSPT */
51
52#define JSPT_CAX 0x00000001
53#define JSPT_CAY 0x00000002
54#define JSPT_CBX 0x00000004
55#define JSPT_CBY 0x00000008
56#define JSPT_BA1 0x00000010
57#define JSPT_BA2 0x00000020
58#define JSPT_BB1 0x00000040
59#define JSPT_BB2 0x00000080
60
61/* Bits for JSCTL */
62
63#define JSCTL_SP_MASK 0x00000003
64#define JSCTL_SP_SLOW 0x00000000
65#define JSCTL_SP_MEDIUM_SLOW 0x00000001
66#define JSCTL_SP_MEDIUM_FAST 0x00000002
67#define JSCTL_SP_FAST 0x00000003
68#define JSCTL_ARE 0x00000004
69
70/* Data register pairs masks */
71
72#define JSC1_Y1V_MASK 0x0000FFFF
73#define JSC1_X1V_MASK 0xFFFF0000
74#define JSC1_Y1V_SHIFT 0
75#define JSC1_X1V_SHIFT 16
76#define JSC2_Y2V_MASK 0x0000FFFF
77#define JSC2_X2V_MASK 0xFFFF0000
78#define JSC2_Y2V_SHIFT 0
79#define JSC2_X2V_SHIFT 16
80
81/* JS GPIO */
82
83#define JSIO_DAX 0x00000001
84#define JSIO_DAY 0x00000002
85#define JSIO_DBX 0x00000004
86#define JSIO_DBY 0x00000008
87#define JSIO_AXOE 0x00000010
88#define JSIO_AYOE 0x00000020
89#define JSIO_BXOE 0x00000040
90#define JSIO_BYOE 0x00000080
91
92/*
93 The card initialization code is obfuscated; the module cs461x
94 need to be loaded after ALSA modules initialized and something
95 played on the CS 4610 chip (see sources for details of CS4610
96 initialization code from ALSA)
97*/
98
99/* Card specific definitions */
100
101#define CS461X_BA0_SIZE 0x2000
102#define CS461X_BA1_DATA0_SIZE 0x3000
103#define CS461X_BA1_DATA1_SIZE 0x3800
104#define CS461X_BA1_PRG_SIZE 0x7000
105#define CS461X_BA1_REG_SIZE 0x0100
106
107#define BA1_SP_DMEM0 0x00000000
108#define BA1_SP_DMEM1 0x00010000
109#define BA1_SP_PMEM 0x00020000
110#define BA1_SP_REG 0x00030000
111
112#define BA1_DWORD_SIZE (13 * 1024 + 512)
113#define BA1_MEMORY_COUNT 3
114
115/*
116 Only one CS461x card is still suppoted; the code requires
117 redesign to avoid this limitatuion.
118*/
119
120static unsigned long ba0_addr;
121static unsigned int __iomem *ba0;
122
123#ifdef CS461X_FULL_MAP
124static unsigned long ba1_addr;
125static union ba1_t {
126 struct {
127 unsigned int __iomem *data0;
128 unsigned int __iomem *data1;
129 unsigned int __iomem *pmem;
130 unsigned int __iomem *reg;
131 } name;
132 unsigned int __iomem *idx[4];
133} ba1;
134
135static void cs461x_poke(unsigned long reg, unsigned int val)
136{
137 writel(val, &ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff]);
138}
139
140static unsigned int cs461x_peek(unsigned long reg)
141{
142 return readl(&ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff]);
143}
144
145#endif
146
147static void cs461x_pokeBA0(unsigned long reg, unsigned int val)
148{
149 writel(val, &ba0[reg >> 2]);
150}
151
152static unsigned int cs461x_peekBA0(unsigned long reg)
153{
154 return readl(&ba0[reg >> 2]);
155}
156
157static int cs461x_free(struct pci_dev *pdev)
158{
159 struct gameport *port = pci_get_drvdata(pdev);
160
161 if (port)
162 gameport_unregister_port(port);
163
164 if (ba0) iounmap(ba0);
165#ifdef CS461X_FULL_MAP
166 if (ba1.name.data0) iounmap(ba1.name.data0);
167 if (ba1.name.data1) iounmap(ba1.name.data1);
168 if (ba1.name.pmem) iounmap(ba1.name.pmem);
169 if (ba1.name.reg) iounmap(ba1.name.reg);
170#endif
171 return 0;
172}
173
174static void cs461x_gameport_trigger(struct gameport *gameport)
175{
176 cs461x_pokeBA0(BA0_JSPT, 0xFF); //outb(gameport->io, 0xFF);
177}
178
179static unsigned char cs461x_gameport_read(struct gameport *gameport)
180{
181 return cs461x_peekBA0(BA0_JSPT); //inb(gameport->io);
182}
183
184static int cs461x_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
185{
186 unsigned js1, js2, jst;
187
188 js1 = cs461x_peekBA0(BA0_JSC1);
189 js2 = cs461x_peekBA0(BA0_JSC2);
190 jst = cs461x_peekBA0(BA0_JSPT);
191
192 *buttons = (~jst >> 4) & 0x0F;
193
194 axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF;
195 axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF;
196 axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF;
197 axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF;
198
199 for(jst=0;jst<4;++jst)
200 if(axes[jst]==0xFFFF) axes[jst] = -1;
201 return 0;
202}
203
204static int cs461x_gameport_open(struct gameport *gameport, int mode)
205{
206 switch (mode) {
207 case GAMEPORT_MODE_COOKED:
208 case GAMEPORT_MODE_RAW:
209 return 0;
210 default:
211 return -1;
212 }
213 return 0;
214}
215
216static struct pci_device_id cs461x_pci_tbl[] = {
217 { PCI_VENDOR_ID_CIRRUS, 0x6001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4610 */
218 { PCI_VENDOR_ID_CIRRUS, 0x6003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4612 */
219 { PCI_VENDOR_ID_CIRRUS, 0x6005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4615 */
220 { 0, }
221};
222MODULE_DEVICE_TABLE(pci, cs461x_pci_tbl);
223
224static int __devinit cs461x_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
225{
226 int rc;
227 struct gameport* port;
228
229 rc = pci_enable_device(pdev);
230 if (rc) {
231 printk(KERN_ERR "cs461x: Cannot enable PCI gameport (bus %d, devfn %d) error=%d\n",
232 pdev->bus->number, pdev->devfn, rc);
233 return rc;
234 }
235
236 ba0_addr = pci_resource_start(pdev, 0);
237#ifdef CS461X_FULL_MAP
238 ba1_addr = pci_resource_start(pdev, 1);
239#endif
240 if (ba0_addr == 0 || ba0_addr == ~0
241#ifdef CS461X_FULL_MAP
242 || ba1_addr == 0 || ba1_addr == ~0
243#endif
244 ) {
245 printk(KERN_ERR "cs461x: wrong address - ba0 = 0x%lx\n", ba0_addr);
246#ifdef CS461X_FULL_MAP
247 printk(KERN_ERR "cs461x: wrong address - ba1 = 0x%lx\n", ba1_addr);
248#endif
249 cs461x_free(pdev);
250 return -ENOMEM;
251 }
252
253 ba0 = ioremap(ba0_addr, CS461X_BA0_SIZE);
254#ifdef CS461X_FULL_MAP
255 ba1.name.data0 = ioremap(ba1_addr + BA1_SP_DMEM0, CS461X_BA1_DATA0_SIZE);
256 ba1.name.data1 = ioremap(ba1_addr + BA1_SP_DMEM1, CS461X_BA1_DATA1_SIZE);
257 ba1.name.pmem = ioremap(ba1_addr + BA1_SP_PMEM, CS461X_BA1_PRG_SIZE);
258 ba1.name.reg = ioremap(ba1_addr + BA1_SP_REG, CS461X_BA1_REG_SIZE);
259
260 if (ba0 == NULL || ba1.name.data0 == NULL ||
261 ba1.name.data1 == NULL || ba1.name.pmem == NULL ||
262 ba1.name.reg == NULL) {
263 cs461x_free(pdev);
264 return -ENOMEM;
265 }
266#else
267 if (ba0 == NULL) {
268 cs461x_free(pdev);
269 return -ENOMEM;
270 }
271#endif
272
273 if (!(port = gameport_allocate_port())) {
274 printk(KERN_ERR "cs461x: Memory allocation failed\n");
275 cs461x_free(pdev);
276 return -ENOMEM;
277 }
278
279 pci_set_drvdata(pdev, port);
280
281 port->open = cs461x_gameport_open;
282 port->trigger = cs461x_gameport_trigger;
283 port->read = cs461x_gameport_read;
284 port->cooked_read = cs461x_gameport_cooked_read;
285
286 gameport_set_name(port, "CS416x");
287 gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev));
288 port->dev.parent = &pdev->dev;
289
290 cs461x_pokeBA0(BA0_JSIO, 0xFF); // ?
291 cs461x_pokeBA0(BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW);
292
293 gameport_register_port(port);
294
295 return 0;
296}
297
298static void __devexit cs461x_pci_remove(struct pci_dev *pdev)
299{
300 cs461x_free(pdev);
301}
302
303static struct pci_driver cs461x_pci_driver = {
304 .name = "CS461x_gameport",
305 .id_table = cs461x_pci_tbl,
306 .probe = cs461x_pci_probe,
307 .remove = __devexit_p(cs461x_pci_remove),
308};
309
310static int __init cs461x_init(void)
311{
312 return pci_register_driver(&cs461x_pci_driver);
313}
314
315static void __exit cs461x_exit(void)
316{
317 pci_unregister_driver(&cs461x_pci_driver);
318}
319
320module_init(cs461x_init);
321module_exit(cs461x_exit);
322
diff --git a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c
new file mode 100644
index 000000000000..a0118038330a
--- /dev/null
+++ b/drivers/input/gameport/emu10k1-gp.c
@@ -0,0 +1,132 @@
1/*
2 * $Id: emu10k1-gp.c,v 1.8 2002/01/22 20:40:46 vojtech Exp $
3 *
4 * Copyright (c) 2001 Vojtech Pavlik
5 */
6
7/*
8 * EMU10k1 - SB Live / Audigy - gameport driver for Linux
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <asm/io.h>
32
33#include <linux/module.h>
34#include <linux/ioport.h>
35#include <linux/config.h>
36#include <linux/init.h>
37#include <linux/gameport.h>
38#include <linux/slab.h>
39#include <linux/pci.h>
40
41MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
42MODULE_DESCRIPTION("EMU10k1 gameport driver");
43MODULE_LICENSE("GPL");
44
45struct emu {
46 struct pci_dev *dev;
47 struct gameport *gameport;
48 int io;
49 int size;
50};
51
52static struct pci_device_id emu_tbl[] = {
53
54 { 0x1102, 0x7002, PCI_ANY_ID, PCI_ANY_ID }, /* SB Live gameport */
55 { 0x1102, 0x7003, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy gameport */
56 { 0x1102, 0x7004, PCI_ANY_ID, PCI_ANY_ID }, /* Dell SB Live */
57 { 0x1102, 0x7005, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy LS gameport */
58 { 0, }
59};
60
61MODULE_DEVICE_TABLE(pci, emu_tbl);
62
63static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
64{
65 int ioport, iolen;
66 struct emu *emu;
67 struct gameport *port;
68
69 if (pci_enable_device(pdev))
70 return -EBUSY;
71
72 ioport = pci_resource_start(pdev, 0);
73 iolen = pci_resource_len(pdev, 0);
74
75 if (!request_region(ioport, iolen, "emu10k1-gp"))
76 return -EBUSY;
77
78 emu = kcalloc(1, sizeof(struct emu), GFP_KERNEL);
79 port = gameport_allocate_port();
80 if (!emu || !port) {
81 printk(KERN_ERR "emu10k1-gp: Memory allocation failed\n");
82 release_region(ioport, iolen);
83 kfree(emu);
84 gameport_free_port(port);
85 return -ENOMEM;
86 }
87
88 emu->io = ioport;
89 emu->size = iolen;
90 emu->dev = pdev;
91 emu->gameport = port;
92
93 gameport_set_name(port, "EMU10K1");
94 gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev));
95 port->dev.parent = &pdev->dev;
96 port->io = ioport;
97
98 pci_set_drvdata(pdev, emu);
99
100 gameport_register_port(port);
101
102 return 0;
103}
104
105static void __devexit emu_remove(struct pci_dev *pdev)
106{
107 struct emu *emu = pci_get_drvdata(pdev);
108
109 gameport_unregister_port(emu->gameport);
110 release_region(emu->io, emu->size);
111 kfree(emu);
112}
113
114static struct pci_driver emu_driver = {
115 .name = "Emu10k1_gameport",
116 .id_table = emu_tbl,
117 .probe = emu_probe,
118 .remove = __devexit_p(emu_remove),
119};
120
121static int __init emu_init(void)
122{
123 return pci_register_driver(&emu_driver);
124}
125
126static void __exit emu_exit(void)
127{
128 pci_unregister_driver(&emu_driver);
129}
130
131module_init(emu_init);
132module_exit(emu_exit);
diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c
new file mode 100644
index 000000000000..57615bc63906
--- /dev/null
+++ b/drivers/input/gameport/fm801-gp.c
@@ -0,0 +1,163 @@
1/*
2 * FM801 gameport driver for Linux
3 *
4 * Copyright (c) by Takashi Iwai <tiwai@suse.de>
5 *
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 */
22
23#include <asm/io.h>
24#include <linux/delay.h>
25#include <linux/errno.h>
26#include <linux/ioport.h>
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/pci.h>
30#include <linux/init.h>
31#include <linux/slab.h>
32#include <linux/gameport.h>
33
34#define PCI_VENDOR_ID_FORTEMEDIA 0x1319
35#define PCI_DEVICE_ID_FM801_GP 0x0802
36
37#define HAVE_COOKED
38
39struct fm801_gp {
40 struct gameport *gameport;
41 struct resource *res_port;
42};
43
44#ifdef HAVE_COOKED
45static int fm801_gp_cooked_read(struct gameport *gameport, int *axes, int *buttons)
46{
47 unsigned short w;
48
49 w = inw(gameport->io + 2);
50 *buttons = (~w >> 14) & 0x03;
51 axes[0] = (w == 0xffff) ? -1 : ((w & 0x1fff) << 5);
52 w = inw(gameport->io + 4);
53 axes[1] = (w == 0xffff) ? -1 : ((w & 0x1fff) << 5);
54 w = inw(gameport->io + 6);
55 *buttons |= ((~w >> 14) & 0x03) << 2;
56 axes[2] = (w == 0xffff) ? -1 : ((w & 0x1fff) << 5);
57 w = inw(gameport->io + 8);
58 axes[3] = (w == 0xffff) ? -1 : ((w & 0x1fff) << 5);
59 outw(0xff, gameport->io); /* reset */
60
61 return 0;
62}
63#endif
64
65static int fm801_gp_open(struct gameport *gameport, int mode)
66{
67 switch (mode) {
68#ifdef HAVE_COOKED
69 case GAMEPORT_MODE_COOKED:
70 return 0;
71#endif
72 case GAMEPORT_MODE_RAW:
73 return 0;
74 default:
75 return -1;
76 }
77
78 return 0;
79}
80
81static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device_id *id)
82{
83 struct fm801_gp *gp;
84 struct gameport *port;
85
86 gp = kcalloc(1, sizeof(struct fm801_gp), GFP_KERNEL);
87 port = gameport_allocate_port();
88 if (!gp || !port) {
89 printk(KERN_ERR "fm801-gp: Memory allocation failed\n");
90 kfree(gp);
91 gameport_free_port(port);
92 return -ENOMEM;
93 }
94
95 pci_enable_device(pci);
96
97 port->open = fm801_gp_open;
98#ifdef HAVE_COOKED
99 port->cooked_read = fm801_gp_cooked_read;
100#endif
101 gameport_set_name(port, "FM801");
102 gameport_set_phys(port, "pci%s/gameport0", pci_name(pci));
103 port->dev.parent = &pci->dev;
104 port->io = pci_resource_start(pci, 0);
105
106 gp->gameport = port;
107 gp->res_port = request_region(port->io, 0x10, "FM801 GP");
108 if (!gp->res_port) {
109 kfree(gp);
110 gameport_free_port(port);
111 printk(KERN_DEBUG "fm801-gp: unable to grab region 0x%x-0x%x\n",
112 port->io, port->io + 0x0f);
113 return -EBUSY;
114 }
115
116 pci_set_drvdata(pci, gp);
117
118 outb(0x60, port->io + 0x0d); /* enable joystick 1 and 2 */
119 gameport_register_port(port);
120
121 return 0;
122}
123
124static void __devexit fm801_gp_remove(struct pci_dev *pci)
125{
126 struct fm801_gp *gp = pci_get_drvdata(pci);
127
128 if (gp) {
129 gameport_unregister_port(gp->gameport);
130 release_resource(gp->res_port);
131 kfree(gp);
132 }
133}
134
135static struct pci_device_id fm801_gp_id_table[] = {
136 { PCI_VENDOR_ID_FORTEMEDIA, PCI_DEVICE_ID_FM801_GP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
137 { 0 }
138};
139
140static struct pci_driver fm801_gp_driver = {
141 .name = "FM801_gameport",
142 .id_table = fm801_gp_id_table,
143 .probe = fm801_gp_probe,
144 .remove = __devexit_p(fm801_gp_remove),
145};
146
147static int __init fm801_gp_init(void)
148{
149 return pci_register_driver(&fm801_gp_driver);
150}
151
152static void __exit fm801_gp_exit(void)
153{
154 pci_unregister_driver(&fm801_gp_driver);
155}
156
157module_init(fm801_gp_init);
158module_exit(fm801_gp_exit);
159
160MODULE_DEVICE_TABLE(pci, fm801_gp_id_table);
161
162MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
163MODULE_LICENSE("GPL");
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
new file mode 100644
index 000000000000..f20c3f23388b
--- /dev/null
+++ b/drivers/input/gameport/gameport.c
@@ -0,0 +1,797 @@
1/*
2 * Generic gameport layer
3 *
4 * Copyright (c) 1999-2002 Vojtech Pavlik
5 * Copyright (c) 2005 Dmitry Torokhov
6 */
7
8/*
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published by
11 * the Free Software Foundation.
12 */
13
14#include <linux/stddef.h>
15#include <linux/module.h>
16#include <linux/ioport.h>
17#include <linux/init.h>
18#include <linux/gameport.h>
19#include <linux/wait.h>
20#include <linux/completion.h>
21#include <linux/sched.h>
22#include <linux/smp_lock.h>
23#include <linux/slab.h>
24#include <linux/delay.h>
25
26/*#include <asm/io.h>*/
27
28MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
29MODULE_DESCRIPTION("Generic gameport layer");
30MODULE_LICENSE("GPL");
31
32EXPORT_SYMBOL(__gameport_register_port);
33EXPORT_SYMBOL(gameport_unregister_port);
34EXPORT_SYMBOL(__gameport_register_driver);
35EXPORT_SYMBOL(gameport_unregister_driver);
36EXPORT_SYMBOL(gameport_open);
37EXPORT_SYMBOL(gameport_close);
38EXPORT_SYMBOL(gameport_rescan);
39EXPORT_SYMBOL(gameport_cooked_read);
40EXPORT_SYMBOL(gameport_set_name);
41EXPORT_SYMBOL(gameport_set_phys);
42EXPORT_SYMBOL(gameport_start_polling);
43EXPORT_SYMBOL(gameport_stop_polling);
44
45/*
46 * gameport_sem protects entire gameport subsystem and is taken
47 * every time gameport port or driver registrered or unregistered.
48 */
49static DECLARE_MUTEX(gameport_sem);
50
51static LIST_HEAD(gameport_list);
52
53static struct bus_type gameport_bus = {
54 .name = "gameport",
55};
56
57static void gameport_add_port(struct gameport *gameport);
58static void gameport_destroy_port(struct gameport *gameport);
59static void gameport_reconnect_port(struct gameport *gameport);
60static void gameport_disconnect_port(struct gameport *gameport);
61
62#if defined(__i386__)
63
64#define DELTA(x,y) ((y)-(x)+((y)<(x)?1193182/HZ:0))
65#define GET_TIME(x) do { x = get_time_pit(); } while (0)
66
67static unsigned int get_time_pit(void)
68{
69 extern spinlock_t i8253_lock;
70 unsigned long flags;
71 unsigned int count;
72
73 spin_lock_irqsave(&i8253_lock, flags);
74 outb_p(0x00, 0x43);
75 count = inb_p(0x40);
76 count |= inb_p(0x40) << 8;
77 spin_unlock_irqrestore(&i8253_lock, flags);
78
79 return count;
80}
81
82#endif
83
84
85
86/*
87 * gameport_measure_speed() measures the gameport i/o speed.
88 */
89
90static int gameport_measure_speed(struct gameport *gameport)
91{
92#if defined(__i386__)
93
94 unsigned int i, t, t1, t2, t3, tx;
95 unsigned long flags;
96
97 if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW))
98 return 0;
99
100 tx = 1 << 30;
101
102 for(i = 0; i < 50; i++) {
103 local_irq_save(flags);
104 GET_TIME(t1);
105 for (t = 0; t < 50; t++) gameport_read(gameport);
106 GET_TIME(t2);
107 GET_TIME(t3);
108 local_irq_restore(flags);
109 udelay(i * 10);
110 if ((t = DELTA(t2,t1) - DELTA(t3,t2)) < tx) tx = t;
111 }
112
113 gameport_close(gameport);
114 return 59659 / (tx < 1 ? 1 : tx);
115
116#elif defined (__x86_64__)
117
118 unsigned int i, t;
119 unsigned long tx, t1, t2, flags;
120
121 if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW))
122 return 0;
123
124 tx = 1 << 30;
125
126 for(i = 0; i < 50; i++) {
127 local_irq_save(flags);
128 rdtscl(t1);
129 for (t = 0; t < 50; t++) gameport_read(gameport);
130 rdtscl(t2);
131 local_irq_restore(flags);
132 udelay(i * 10);
133 if (t2 - t1 < tx) tx = t2 - t1;
134 }
135
136 gameport_close(gameport);
137 return (cpu_data[_smp_processor_id()].loops_per_jiffy * (unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx);
138
139#else
140
141 unsigned int j, t = 0;
142
143 if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW))
144 return 0;
145
146 j = jiffies; while (j == jiffies);
147 j = jiffies; while (j == jiffies) { t++; gameport_read(gameport); }
148
149 gameport_close(gameport);
150 return t * HZ / 1000;
151
152#endif
153}
154
155void gameport_start_polling(struct gameport *gameport)
156{
157 spin_lock(&gameport->timer_lock);
158
159 if (!gameport->poll_cnt++) {
160 BUG_ON(!gameport->poll_handler);
161 BUG_ON(!gameport->poll_interval);
162 mod_timer(&gameport->poll_timer, jiffies + msecs_to_jiffies(gameport->poll_interval));
163 }
164
165 spin_unlock(&gameport->timer_lock);
166}
167
168void gameport_stop_polling(struct gameport *gameport)
169{
170 spin_lock(&gameport->timer_lock);
171
172 if (!--gameport->poll_cnt)
173 del_timer(&gameport->poll_timer);
174
175 spin_unlock(&gameport->timer_lock);
176}
177
178static void gameport_run_poll_handler(unsigned long d)
179{
180 struct gameport *gameport = (struct gameport *)d;
181
182 gameport->poll_handler(gameport);
183 if (gameport->poll_cnt)
184 mod_timer(&gameport->poll_timer, jiffies + msecs_to_jiffies(gameport->poll_interval));
185}
186
187/*
188 * Basic gameport -> driver core mappings
189 */
190
191static void gameport_bind_driver(struct gameport *gameport, struct gameport_driver *drv)
192{
193 down_write(&gameport_bus.subsys.rwsem);
194
195 gameport->dev.driver = &drv->driver;
196 if (drv->connect(gameport, drv)) {
197 gameport->dev.driver = NULL;
198 goto out;
199 }
200 device_bind_driver(&gameport->dev);
201out:
202 up_write(&gameport_bus.subsys.rwsem);
203}
204
205static void gameport_release_driver(struct gameport *gameport)
206{
207 down_write(&gameport_bus.subsys.rwsem);
208 device_release_driver(&gameport->dev);
209 up_write(&gameport_bus.subsys.rwsem);
210}
211
212static void gameport_find_driver(struct gameport *gameport)
213{
214 down_write(&gameport_bus.subsys.rwsem);
215 device_attach(&gameport->dev);
216 up_write(&gameport_bus.subsys.rwsem);
217}
218
219
220/*
221 * Gameport event processing.
222 */
223
224enum gameport_event_type {
225 GAMEPORT_RESCAN,
226 GAMEPORT_RECONNECT,
227 GAMEPORT_REGISTER_PORT,
228 GAMEPORT_REGISTER_DRIVER,
229};
230
231struct gameport_event {
232 enum gameport_event_type type;
233 void *object;
234 struct module *owner;
235 struct list_head node;
236};
237
238static DEFINE_SPINLOCK(gameport_event_lock); /* protects gameport_event_list */
239static LIST_HEAD(gameport_event_list);
240static DECLARE_WAIT_QUEUE_HEAD(gameport_wait);
241static DECLARE_COMPLETION(gameport_exited);
242static int gameport_pid;
243
244static void gameport_queue_event(void *object, struct module *owner,
245 enum gameport_event_type event_type)
246{
247 unsigned long flags;
248 struct gameport_event *event;
249
250 spin_lock_irqsave(&gameport_event_lock, flags);
251
252 /*
253 * Scan event list for the other events for the same gameport port,
254 * starting with the most recent one. If event is the same we
255 * do not need add new one. If event is of different type we
256 * need to add this event and should not look further because
257 * we need to preseve sequence of distinct events.
258 */
259 list_for_each_entry_reverse(event, &gameport_event_list, node) {
260 if (event->object == object) {
261 if (event->type == event_type)
262 goto out;
263 break;
264 }
265 }
266
267 if ((event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC))) {
268 if (!try_module_get(owner)) {
269 printk(KERN_WARNING "gameport: Can't get module reference, dropping event %d\n", event_type);
270 goto out;
271 }
272
273 event->type = event_type;
274 event->object = object;
275 event->owner = owner;
276
277 list_add_tail(&event->node, &gameport_event_list);
278 wake_up(&gameport_wait);
279 } else {
280 printk(KERN_ERR "gameport: Not enough memory to queue event %d\n", event_type);
281 }
282out:
283 spin_unlock_irqrestore(&gameport_event_lock, flags);
284}
285
286static void gameport_free_event(struct gameport_event *event)
287{
288 module_put(event->owner);
289 kfree(event);
290}
291
292static void gameport_remove_duplicate_events(struct gameport_event *event)
293{
294 struct list_head *node, *next;
295 struct gameport_event *e;
296 unsigned long flags;
297
298 spin_lock_irqsave(&gameport_event_lock, flags);
299
300 list_for_each_safe(node, next, &gameport_event_list) {
301 e = list_entry(node, struct gameport_event, node);
302 if (event->object == e->object) {
303 /*
304 * If this event is of different type we should not
305 * look further - we only suppress duplicate events
306 * that were sent back-to-back.
307 */
308 if (event->type != e->type)
309 break;
310
311 list_del_init(node);
312 gameport_free_event(e);
313 }
314 }
315
316 spin_unlock_irqrestore(&gameport_event_lock, flags);
317}
318
319
320static struct gameport_event *gameport_get_event(void)
321{
322 struct gameport_event *event;
323 struct list_head *node;
324 unsigned long flags;
325
326 spin_lock_irqsave(&gameport_event_lock, flags);
327
328 if (list_empty(&gameport_event_list)) {
329 spin_unlock_irqrestore(&gameport_event_lock, flags);
330 return NULL;
331 }
332
333 node = gameport_event_list.next;
334 event = list_entry(node, struct gameport_event, node);
335 list_del_init(node);
336
337 spin_unlock_irqrestore(&gameport_event_lock, flags);
338
339 return event;
340}
341
342static void gameport_handle_events(void)
343{
344 struct gameport_event *event;
345 struct gameport_driver *gameport_drv;
346
347 down(&gameport_sem);
348
349 while ((event = gameport_get_event())) {
350
351 switch (event->type) {
352 case GAMEPORT_REGISTER_PORT:
353 gameport_add_port(event->object);
354 break;
355
356 case GAMEPORT_RECONNECT:
357 gameport_reconnect_port(event->object);
358 break;
359
360 case GAMEPORT_RESCAN:
361 gameport_disconnect_port(event->object);
362 gameport_find_driver(event->object);
363 break;
364
365 case GAMEPORT_REGISTER_DRIVER:
366 gameport_drv = event->object;
367 driver_register(&gameport_drv->driver);
368 break;
369
370 default:
371 break;
372 }
373
374 gameport_remove_duplicate_events(event);
375 gameport_free_event(event);
376 }
377
378 up(&gameport_sem);
379}
380
381/*
382 * Remove all events that have been submitted for a given gameport port.
383 */
384static void gameport_remove_pending_events(struct gameport *gameport)
385{
386 struct list_head *node, *next;
387 struct gameport_event *event;
388 unsigned long flags;
389
390 spin_lock_irqsave(&gameport_event_lock, flags);
391
392 list_for_each_safe(node, next, &gameport_event_list) {
393 event = list_entry(node, struct gameport_event, node);
394 if (event->object == gameport) {
395 list_del_init(node);
396 gameport_free_event(event);
397 }
398 }
399
400 spin_unlock_irqrestore(&gameport_event_lock, flags);
401}
402
403/*
404 * Destroy child gameport port (if any) that has not been fully registered yet.
405 *
406 * Note that we rely on the fact that port can have only one child and therefore
407 * only one child registration request can be pending. Additionally, children
408 * are registered by driver's connect() handler so there can't be a grandchild
409 * pending registration together with a child.
410 */
411static struct gameport *gameport_get_pending_child(struct gameport *parent)
412{
413 struct gameport_event *event;
414 struct gameport *gameport, *child = NULL;
415 unsigned long flags;
416
417 spin_lock_irqsave(&gameport_event_lock, flags);
418
419 list_for_each_entry(event, &gameport_event_list, node) {
420 if (event->type == GAMEPORT_REGISTER_PORT) {
421 gameport = event->object;
422 if (gameport->parent == parent) {
423 child = gameport;
424 break;
425 }
426 }
427 }
428
429 spin_unlock_irqrestore(&gameport_event_lock, flags);
430 return child;
431}
432
433static int gameport_thread(void *nothing)
434{
435 lock_kernel();
436 daemonize("kgameportd");
437 allow_signal(SIGTERM);
438
439 do {
440 gameport_handle_events();
441 wait_event_interruptible(gameport_wait, !list_empty(&gameport_event_list));
442 try_to_freeze(PF_FREEZE);
443 } while (!signal_pending(current));
444
445 printk(KERN_DEBUG "gameport: kgameportd exiting\n");
446
447 unlock_kernel();
448 complete_and_exit(&gameport_exited, 0);
449}
450
451
452/*
453 * Gameport port operations
454 */
455
456static ssize_t gameport_show_description(struct device *dev, char *buf)
457{
458 struct gameport *gameport = to_gameport_port(dev);
459 return sprintf(buf, "%s\n", gameport->name);
460}
461
462static ssize_t gameport_rebind_driver(struct device *dev, const char *buf, size_t count)
463{
464 struct gameport *gameport = to_gameport_port(dev);
465 struct device_driver *drv;
466 int retval;
467
468 retval = down_interruptible(&gameport_sem);
469 if (retval)
470 return retval;
471
472 retval = count;
473 if (!strncmp(buf, "none", count)) {
474 gameport_disconnect_port(gameport);
475 } else if (!strncmp(buf, "reconnect", count)) {
476 gameport_reconnect_port(gameport);
477 } else if (!strncmp(buf, "rescan", count)) {
478 gameport_disconnect_port(gameport);
479 gameport_find_driver(gameport);
480 } else if ((drv = driver_find(buf, &gameport_bus)) != NULL) {
481 gameport_disconnect_port(gameport);
482 gameport_bind_driver(gameport, to_gameport_driver(drv));
483 put_driver(drv);
484 } else {
485 retval = -EINVAL;
486 }
487
488 up(&gameport_sem);
489
490 return retval;
491}
492
493static struct device_attribute gameport_device_attrs[] = {
494 __ATTR(description, S_IRUGO, gameport_show_description, NULL),
495 __ATTR(drvctl, S_IWUSR, NULL, gameport_rebind_driver),
496 __ATTR_NULL
497};
498
499static void gameport_release_port(struct device *dev)
500{
501 struct gameport *gameport = to_gameport_port(dev);
502
503 kfree(gameport);
504 module_put(THIS_MODULE);
505}
506
507void gameport_set_phys(struct gameport *gameport, const char *fmt, ...)
508{
509 va_list args;
510
511 va_start(args, fmt);
512 vsnprintf(gameport->phys, sizeof(gameport->phys), fmt, args);
513 va_end(args);
514}
515
516/*
517 * Prepare gameport port for registration.
518 */
519static void gameport_init_port(struct gameport *gameport)
520{
521 static atomic_t gameport_no = ATOMIC_INIT(0);
522
523 __module_get(THIS_MODULE);
524
525 init_MUTEX(&gameport->drv_sem);
526 device_initialize(&gameport->dev);
527 snprintf(gameport->dev.bus_id, sizeof(gameport->dev.bus_id),
528 "gameport%lu", (unsigned long)atomic_inc_return(&gameport_no) - 1);
529 gameport->dev.bus = &gameport_bus;
530 gameport->dev.release = gameport_release_port;
531 if (gameport->parent)
532 gameport->dev.parent = &gameport->parent->dev;
533
534 spin_lock_init(&gameport->timer_lock);
535 init_timer(&gameport->poll_timer);
536 gameport->poll_timer.function = gameport_run_poll_handler;
537 gameport->poll_timer.data = (unsigned long)gameport;
538}
539
540/*
541 * Complete gameport port registration.
542 * Driver core will attempt to find appropriate driver for the port.
543 */
544static void gameport_add_port(struct gameport *gameport)
545{
546 if (gameport->parent)
547 gameport->parent->child = gameport;
548
549 gameport->speed = gameport_measure_speed(gameport);
550
551 list_add_tail(&gameport->node, &gameport_list);
552
553 if (gameport->io)
554 printk(KERN_INFO "gameport: %s is %s, io %#x, speed %dkHz\n",
555 gameport->name, gameport->phys, gameport->io, gameport->speed);
556 else
557 printk(KERN_INFO "gameport: %s is %s, speed %dkHz\n",
558 gameport->name, gameport->phys, gameport->speed);
559
560 device_add(&gameport->dev);
561 gameport->registered = 1;
562}
563
564/*
565 * gameport_destroy_port() completes deregistration process and removes
566 * port from the system
567 */
568static void gameport_destroy_port(struct gameport *gameport)
569{
570 struct gameport *child;
571
572 child = gameport_get_pending_child(gameport);
573 if (child) {
574 gameport_remove_pending_events(child);
575 put_device(&child->dev);
576 }
577
578 if (gameport->parent) {
579 gameport->parent->child = NULL;
580 gameport->parent = NULL;
581 }
582
583 if (gameport->registered) {
584 device_del(&gameport->dev);
585 list_del_init(&gameport->node);
586 gameport->registered = 0;
587 }
588
589 gameport_remove_pending_events(gameport);
590 put_device(&gameport->dev);
591}
592
593/*
594 * Reconnect gameport port and all its children (re-initialize attached devices)
595 */
596static void gameport_reconnect_port(struct gameport *gameport)
597{
598 do {
599 if (!gameport->drv || !gameport->drv->reconnect || gameport->drv->reconnect(gameport)) {
600 gameport_disconnect_port(gameport);
601 gameport_find_driver(gameport);
602 /* Ok, old children are now gone, we are done */
603 break;
604 }
605 gameport = gameport->child;
606 } while (gameport);
607}
608
609/*
610 * gameport_disconnect_port() unbinds a port from its driver. As a side effect
611 * all child ports are unbound and destroyed.
612 */
613static void gameport_disconnect_port(struct gameport *gameport)
614{
615 struct gameport *s, *parent;
616
617 if (gameport->child) {
618 /*
619 * Children ports should be disconnected and destroyed
620 * first, staring with the leaf one, since we don't want
621 * to do recursion
622 */
623 for (s = gameport; s->child; s = s->child)
624 /* empty */;
625
626 do {
627 parent = s->parent;
628
629 gameport_release_driver(s);
630 gameport_destroy_port(s);
631 } while ((s = parent) != gameport);
632 }
633
634 /*
635 * Ok, no children left, now disconnect this port
636 */
637 gameport_release_driver(gameport);
638}
639
640void gameport_rescan(struct gameport *gameport)
641{
642 gameport_queue_event(gameport, NULL, GAMEPORT_RESCAN);
643}
644
645void gameport_reconnect(struct gameport *gameport)
646{
647 gameport_queue_event(gameport, NULL, GAMEPORT_RECONNECT);
648}
649
650/*
651 * Submits register request to kgameportd for subsequent execution.
652 * Note that port registration is always asynchronous.
653 */
654void __gameport_register_port(struct gameport *gameport, struct module *owner)
655{
656 gameport_init_port(gameport);
657 gameport_queue_event(gameport, owner, GAMEPORT_REGISTER_PORT);
658}
659
660/*
661 * Synchronously unregisters gameport port.
662 */
663void gameport_unregister_port(struct gameport *gameport)
664{
665 down(&gameport_sem);
666 gameport_disconnect_port(gameport);
667 gameport_destroy_port(gameport);
668 up(&gameport_sem);
669}
670
671
672/*
673 * Gameport driver operations
674 */
675
676static ssize_t gameport_driver_show_description(struct device_driver *drv, char *buf)
677{
678 struct gameport_driver *driver = to_gameport_driver(drv);
679 return sprintf(buf, "%s\n", driver->description ? driver->description : "(none)");
680}
681
682static struct driver_attribute gameport_driver_attrs[] = {
683 __ATTR(description, S_IRUGO, gameport_driver_show_description, NULL),
684 __ATTR_NULL
685};
686
687static int gameport_driver_probe(struct device *dev)
688{
689 struct gameport *gameport = to_gameport_port(dev);
690 struct gameport_driver *drv = to_gameport_driver(dev->driver);
691
692 drv->connect(gameport, drv);
693 return gameport->drv ? 0 : -ENODEV;
694}
695
696static int gameport_driver_remove(struct device *dev)
697{
698 struct gameport *gameport = to_gameport_port(dev);
699 struct gameport_driver *drv = to_gameport_driver(dev->driver);
700
701 drv->disconnect(gameport);
702 return 0;
703}
704
705void __gameport_register_driver(struct gameport_driver *drv, struct module *owner)
706{
707 drv->driver.bus = &gameport_bus;
708 drv->driver.probe = gameport_driver_probe;
709 drv->driver.remove = gameport_driver_remove;
710 gameport_queue_event(drv, owner, GAMEPORT_REGISTER_DRIVER);
711}
712
713void gameport_unregister_driver(struct gameport_driver *drv)
714{
715 struct gameport *gameport;
716
717 down(&gameport_sem);
718 drv->ignore = 1; /* so gameport_find_driver ignores it */
719
720start_over:
721 list_for_each_entry(gameport, &gameport_list, node) {
722 if (gameport->drv == drv) {
723 gameport_disconnect_port(gameport);
724 gameport_find_driver(gameport);
725 /* we could've deleted some ports, restart */
726 goto start_over;
727 }
728 }
729
730 driver_unregister(&drv->driver);
731 up(&gameport_sem);
732}
733
734static int gameport_bus_match(struct device *dev, struct device_driver *drv)
735{
736 struct gameport_driver *gameport_drv = to_gameport_driver(drv);
737
738 return !gameport_drv->ignore;
739}
740
741static void gameport_set_drv(struct gameport *gameport, struct gameport_driver *drv)
742{
743 down(&gameport->drv_sem);
744 gameport->drv = drv;
745 up(&gameport->drv_sem);
746}
747
748int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode)
749{
750
751 if (gameport->open) {
752 if (gameport->open(gameport, mode)) {
753 return -1;
754 }
755 } else {
756 if (mode != GAMEPORT_MODE_RAW)
757 return -1;
758 }
759
760 gameport_set_drv(gameport, drv);
761 return 0;
762}
763
764void gameport_close(struct gameport *gameport)
765{
766 del_timer_sync(&gameport->poll_timer);
767 gameport->poll_handler = NULL;
768 gameport->poll_interval = 0;
769 gameport_set_drv(gameport, NULL);
770 if (gameport->close)
771 gameport->close(gameport);
772}
773
774static int __init gameport_init(void)
775{
776 if (!(gameport_pid = kernel_thread(gameport_thread, NULL, CLONE_KERNEL))) {
777 printk(KERN_ERR "gameport: Failed to start kgameportd\n");
778 return -1;
779 }
780
781 gameport_bus.dev_attrs = gameport_device_attrs;
782 gameport_bus.drv_attrs = gameport_driver_attrs;
783 gameport_bus.match = gameport_bus_match;
784 bus_register(&gameport_bus);
785
786 return 0;
787}
788
789static void __exit gameport_exit(void)
790{
791 bus_unregister(&gameport_bus);
792 kill_proc(gameport_pid, SIGTERM, 1);
793 wait_for_completion(&gameport_exited);
794}
795
796module_init(gameport_init);
797module_exit(gameport_exit);
diff --git a/drivers/input/gameport/lightning.c b/drivers/input/gameport/lightning.c
new file mode 100644
index 000000000000..d65d81080257
--- /dev/null
+++ b/drivers/input/gameport/lightning.c
@@ -0,0 +1,344 @@
1/*
2 * $Id: lightning.c,v 1.20 2002/01/22 20:41:31 vojtech Exp $
3 *
4 * Copyright (c) 1998-2001 Vojtech Pavlik
5 */
6
7/*
8 * PDPI Lightning 4 gamecard driver for Linux.
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <asm/io.h>
32#include <linux/delay.h>
33#include <linux/errno.h>
34#include <linux/ioport.h>
35#include <linux/kernel.h>
36#include <linux/module.h>
37#include <linux/init.h>
38#include <linux/gameport.h>
39#include <linux/slab.h>
40
41#define L4_PORT 0x201
42#define L4_SELECT_ANALOG 0xa4
43#define L4_SELECT_DIGITAL 0xa5
44#define L4_SELECT_SECONDARY 0xa6
45#define L4_CMD_ID 0x80
46#define L4_CMD_GETCAL 0x92
47#define L4_CMD_SETCAL 0x93
48#define L4_ID 0x04
49#define L4_BUSY 0x01
50#define L4_TIMEOUT 80 /* 80 us */
51
52MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
53MODULE_DESCRIPTION("PDPI Lightning 4 gamecard driver");
54MODULE_LICENSE("GPL");
55
56struct l4 {
57 struct gameport *gameport;
58 unsigned char port;
59};
60
61static struct l4 l4_ports[8];
62
63/*
64 * l4_wait_ready() waits for the L4 to become ready.
65 */
66
67static int l4_wait_ready(void)
68{
69 unsigned int t = L4_TIMEOUT;
70
71 while ((inb(L4_PORT) & L4_BUSY) && t > 0) t--;
72 return -(t <= 0);
73}
74
75/*
76 * l4_cooked_read() reads data from the Lightning 4.
77 */
78
79static int l4_cooked_read(struct gameport *gameport, int *axes, int *buttons)
80{
81 struct l4 *l4 = gameport->port_data;
82 unsigned char status;
83 int i, result = -1;
84
85 outb(L4_SELECT_ANALOG, L4_PORT);
86 outb(L4_SELECT_DIGITAL + (l4->port >> 2), L4_PORT);
87
88 if (inb(L4_PORT) & L4_BUSY) goto fail;
89 outb(l4->port & 3, L4_PORT);
90
91 if (l4_wait_ready()) goto fail;
92 status = inb(L4_PORT);
93
94 for (i = 0; i < 4; i++)
95 if (status & (1 << i)) {
96 if (l4_wait_ready()) goto fail;
97 axes[i] = inb(L4_PORT);
98 if (axes[i] > 252) axes[i] = -1;
99 }
100
101 if (status & 0x10) {
102 if (l4_wait_ready()) goto fail;
103 *buttons = inb(L4_PORT) & 0x0f;
104 }
105
106 result = 0;
107
108fail: outb(L4_SELECT_ANALOG, L4_PORT);
109 return result;
110}
111
112static int l4_open(struct gameport *gameport, int mode)
113{
114 struct l4 *l4 = gameport->port_data;
115
116 if (l4->port != 0 && mode != GAMEPORT_MODE_COOKED)
117 return -1;
118 outb(L4_SELECT_ANALOG, L4_PORT);
119 return 0;
120}
121
122/*
123 * l4_getcal() reads the L4 with calibration values.
124 */
125
126static int l4_getcal(int port, int *cal)
127{
128 int i, result = -1;
129
130 outb(L4_SELECT_ANALOG, L4_PORT);
131 outb(L4_SELECT_DIGITAL + (port >> 2), L4_PORT);
132 if (inb(L4_PORT) & L4_BUSY)
133 goto out;
134
135 outb(L4_CMD_GETCAL, L4_PORT);
136 if (l4_wait_ready())
137 goto out;
138
139 if (inb(L4_PORT) != L4_SELECT_DIGITAL + (port >> 2))
140 goto out;
141
142 if (l4_wait_ready())
143 goto out;
144 outb(port & 3, L4_PORT);
145
146 for (i = 0; i < 4; i++) {
147 if (l4_wait_ready())
148 goto out;
149 cal[i] = inb(L4_PORT);
150 }
151
152 result = 0;
153
154out: outb(L4_SELECT_ANALOG, L4_PORT);
155 return result;
156}
157
158/*
159 * l4_setcal() programs the L4 with calibration values.
160 */
161
162static int l4_setcal(int port, int *cal)
163{
164 int i, result = -1;
165
166 outb(L4_SELECT_ANALOG, L4_PORT);
167 outb(L4_SELECT_DIGITAL + (port >> 2), L4_PORT);
168 if (inb(L4_PORT) & L4_BUSY)
169 goto out;
170
171 outb(L4_CMD_SETCAL, L4_PORT);
172 if (l4_wait_ready())
173 goto out;
174
175 if (inb(L4_PORT) != L4_SELECT_DIGITAL + (port >> 2))
176 goto out;
177
178 if (l4_wait_ready())
179 goto out;
180 outb(port & 3, L4_PORT);
181
182 for (i = 0; i < 4; i++) {
183 if (l4_wait_ready())
184 goto out;
185 outb(cal[i], L4_PORT);
186 }
187
188 result = 0;
189
190out: outb(L4_SELECT_ANALOG, L4_PORT);
191 return result;
192}
193
194/*
195 * l4_calibrate() calibrates the L4 for the attached device, so
196 * that the device's resistance fits into the L4's 8-bit range.
197 */
198
199static int l4_calibrate(struct gameport *gameport, int *axes, int *max)
200{
201 int i, t;
202 int cal[4];
203 struct l4 *l4 = gameport->port_data;
204
205 if (l4_getcal(l4->port, cal))
206 return -1;
207
208 for (i = 0; i < 4; i++) {
209 t = (max[i] * cal[i]) / 200;
210 t = (t < 1) ? 1 : ((t > 255) ? 255 : t);
211 axes[i] = (axes[i] < 0) ? -1 : (axes[i] * cal[i]) / t;
212 axes[i] = (axes[i] > 252) ? 252 : axes[i];
213 cal[i] = t;
214 }
215
216 if (l4_setcal(l4->port, cal))
217 return -1;
218
219 return 0;
220}
221
222static int __init l4_create_ports(int card_no)
223{
224 struct l4 *l4;
225 struct gameport *port;
226 int i, idx;
227
228 for (i = 0; i < 4; i++) {
229
230 idx = card_no * 4 + i;
231 l4 = &l4_ports[idx];
232
233 if (!(l4->gameport = port = gameport_allocate_port())) {
234 printk(KERN_ERR "lightning: Memory allocation failed\n");
235 while (--i >= 0) {
236 gameport_free_port(l4->gameport);
237 l4->gameport = NULL;
238 }
239 return -ENOMEM;
240 }
241 l4->port = idx;
242
243 port->port_data = l4;
244 port->open = l4_open;
245 port->cooked_read = l4_cooked_read;
246 port->calibrate = l4_calibrate;
247
248 gameport_set_name(port, "PDPI Lightning 4");
249 gameport_set_phys(port, "isa%04x/gameport%d", L4_PORT, idx);
250
251 if (idx == 0)
252 port->io = L4_PORT;
253 }
254
255 return 0;
256}
257
258static int __init l4_add_card(int card_no)
259{
260 int cal[4] = { 255, 255, 255, 255 };
261 int i, rev, result;
262 struct l4 *l4;
263
264 outb(L4_SELECT_ANALOG, L4_PORT);
265 outb(L4_SELECT_DIGITAL + card_no, L4_PORT);
266
267 if (inb(L4_PORT) & L4_BUSY)
268 return -1;
269 outb(L4_CMD_ID, L4_PORT);
270
271 if (l4_wait_ready())
272 return -1;
273
274 if (inb(L4_PORT) != L4_SELECT_DIGITAL + card_no)
275 return -1;
276
277 if (l4_wait_ready())
278 return -1;
279 if (inb(L4_PORT) != L4_ID)
280 return -1;
281
282 if (l4_wait_ready())
283 return -1;
284 rev = inb(L4_PORT);
285
286 if (!rev)
287 return -1;
288
289 result = l4_create_ports(card_no);
290 if (result)
291 return result;
292
293 printk(KERN_INFO "gameport: PDPI Lightning 4 %s card v%d.%d at %#x\n",
294 card_no ? "secondary" : "primary", rev >> 4, rev, L4_PORT);
295
296 for (i = 0; i < 4; i++) {
297 l4 = &l4_ports[card_no * 4 + i];
298
299 if (rev > 0x28) /* on 2.9+ the setcal command works correctly */
300 l4_setcal(l4->port, cal);
301 gameport_register_port(l4->gameport);
302 }
303
304 return 0;
305}
306
307static int __init l4_init(void)
308{
309 int i, cards = 0;
310
311 if (!request_region(L4_PORT, 1, "lightning"))
312 return -1;
313
314 for (i = 0; i < 2; i++)
315 if (l4_add_card(i) == 0)
316 cards++;
317
318 outb(L4_SELECT_ANALOG, L4_PORT);
319
320 if (!cards) {
321 release_region(L4_PORT, 1);
322 return -1;
323 }
324
325 return 0;
326}
327
328static void __exit l4_exit(void)
329{
330 int i;
331 int cal[4] = { 59, 59, 59, 59 };
332
333 for (i = 0; i < 8; i++)
334 if (l4_ports[i].gameport) {
335 l4_setcal(l4_ports[i].port, cal);
336 gameport_unregister_port(l4_ports[i].gameport);
337 }
338
339 outb(L4_SELECT_ANALOG, L4_PORT);
340 release_region(L4_PORT, 1);
341}
342
343module_init(l4_init);
344module_exit(l4_exit);
diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c
new file mode 100644
index 000000000000..7c5c6318eeb9
--- /dev/null
+++ b/drivers/input/gameport/ns558.c
@@ -0,0 +1,291 @@
1/*
2 * $Id: ns558.c,v 1.43 2002/01/24 19:23:21 vojtech Exp $
3 *
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 * Copyright (c) 1999 Brian Gerst
6 */
7
8/*
9 * NS558 based standard IBM game port driver for Linux
10 */
11
12/*
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27 * Should you need to contact me, the author, you can do so either by
28 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
29 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
30 */
31
32#include <asm/io.h>
33
34#include <linux/module.h>
35#include <linux/ioport.h>
36#include <linux/config.h>
37#include <linux/init.h>
38#include <linux/delay.h>
39#include <linux/gameport.h>
40#include <linux/slab.h>
41#include <linux/pnp.h>
42
43MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
44MODULE_DESCRIPTION("Classic gameport (ISA/PnP) driver");
45MODULE_LICENSE("GPL");
46
47static int ns558_isa_portlist[] = { 0x201, 0x200, 0x202, 0x203, 0x204, 0x205, 0x207, 0x209,
48 0x20b, 0x20c, 0x20e, 0x20f, 0x211, 0x219, 0x101, 0 };
49
50struct ns558 {
51 int type;
52 int io;
53 int size;
54 struct pnp_dev *dev;
55 struct gameport *gameport;
56 struct list_head node;
57};
58
59static LIST_HEAD(ns558_list);
60
61/*
62 * ns558_isa_probe() tries to find an isa gameport at the
63 * specified address, and also checks for mirrors.
64 * A joystick must be attached for this to work.
65 */
66
67static int ns558_isa_probe(int io)
68{
69 int i, j, b;
70 unsigned char c, u, v;
71 struct ns558 *ns558;
72 struct gameport *port;
73
74/*
75 * No one should be using this address.
76 */
77
78 if (!request_region(io, 1, "ns558-isa"))
79 return -EBUSY;
80
81/*
82 * We must not be able to write arbitrary values to the port.
83 * The lower two axis bits must be 1 after a write.
84 */
85
86 c = inb(io);
87 outb(~c & ~3, io);
88 if (~(u = v = inb(io)) & 3) {
89 outb(c, io);
90 release_region(io, 1);
91 return -ENODEV;
92 }
93/*
94 * After a trigger, there must be at least some bits changing.
95 */
96
97 for (i = 0; i < 1000; i++) v &= inb(io);
98
99 if (u == v) {
100 outb(c, io);
101 release_region(io, 1);
102 return -ENODEV;
103 }
104 msleep(3);
105/*
106 * After some time (4ms) the axes shouldn't change anymore.
107 */
108
109 u = inb(io);
110 for (i = 0; i < 1000; i++)
111 if ((u ^ inb(io)) & 0xf) {
112 outb(c, io);
113 release_region(io, 1);
114 return -ENODEV;
115 }
116/*
117 * And now find the number of mirrors of the port.
118 */
119
120 for (i = 1; i < 5; i++) {
121
122 release_region(io & (-1 << (i - 1)), (1 << (i - 1)));
123
124 if (!request_region(io & (-1 << i), (1 << i), "ns558-isa"))
125 break; /* Don't disturb anyone */
126
127 outb(0xff, io & (-1 << i));
128 for (j = b = 0; j < 1000; j++)
129 if (inb(io & (-1 << i)) != inb((io & (-1 << i)) + (1 << i) - 1)) b++;
130 msleep(3);
131
132 if (b > 300) { /* We allow 30% difference */
133 release_region(io & (-1 << i), (1 << i));
134 break;
135 }
136 }
137
138 i--;
139
140 if (i != 4) {
141 if (!request_region(io & (-1 << i), (1 << i), "ns558-isa"))
142 return -EBUSY;
143 }
144
145 ns558 = kcalloc(1, sizeof(struct ns558), GFP_KERNEL);
146 port = gameport_allocate_port();
147 if (!ns558 || !port) {
148 printk(KERN_ERR "ns558: Memory allocation failed.\n");
149 release_region(io & (-1 << i), (1 << i));
150 kfree(ns558);
151 gameport_free_port(port);
152 return -ENOMEM;
153 }
154
155 memset(ns558, 0, sizeof(struct ns558));
156 ns558->io = io;
157 ns558->size = 1 << i;
158 ns558->gameport = port;
159
160 port->io = io;
161 gameport_set_name(port, "NS558 ISA Gameport");
162 gameport_set_phys(port, "isa%04x/gameport0", io & (-1 << i));
163
164 gameport_register_port(port);
165
166 list_add(&ns558->node, &ns558_list);
167
168 return 0;
169}
170
171#ifdef CONFIG_PNP
172
173static struct pnp_device_id pnp_devids[] = {
174 { .id = "@P@0001", .driver_data = 0 }, /* ALS 100 */
175 { .id = "@P@0020", .driver_data = 0 }, /* ALS 200 */
176 { .id = "@P@1001", .driver_data = 0 }, /* ALS 100+ */
177 { .id = "@P@2001", .driver_data = 0 }, /* ALS 120 */
178 { .id = "ASB16fd", .driver_data = 0 }, /* AdLib NSC16 */
179 { .id = "AZT3001", .driver_data = 0 }, /* AZT1008 */
180 { .id = "CDC0001", .driver_data = 0 }, /* Opl3-SAx */
181 { .id = "CSC0001", .driver_data = 0 }, /* CS4232 */
182 { .id = "CSC000f", .driver_data = 0 }, /* CS4236 */
183 { .id = "CSC0101", .driver_data = 0 }, /* CS4327 */
184 { .id = "CTL7001", .driver_data = 0 }, /* SB16 */
185 { .id = "CTL7002", .driver_data = 0 }, /* AWE64 */
186 { .id = "CTL7005", .driver_data = 0 }, /* Vibra16 */
187 { .id = "ENS2020", .driver_data = 0 }, /* SoundscapeVIVO */
188 { .id = "ESS0001", .driver_data = 0 }, /* ES1869 */
189 { .id = "ESS0005", .driver_data = 0 }, /* ES1878 */
190 { .id = "ESS6880", .driver_data = 0 }, /* ES688 */
191 { .id = "IBM0012", .driver_data = 0 }, /* CS4232 */
192 { .id = "OPT0001", .driver_data = 0 }, /* OPTi Audio16 */
193 { .id = "YMH0006", .driver_data = 0 }, /* Opl3-SA */
194 { .id = "YMH0022", .driver_data = 0 }, /* Opl3-SAx */
195 { .id = "PNPb02f", .driver_data = 0 }, /* Generic */
196 { .id = "", },
197};
198
199MODULE_DEVICE_TABLE(pnp, pnp_devids);
200
201static int ns558_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *did)
202{
203 int ioport, iolen;
204 struct ns558 *ns558;
205 struct gameport *port;
206
207 if (!pnp_port_valid(dev, 0)) {
208 printk(KERN_WARNING "ns558: No i/o ports on a gameport? Weird\n");
209 return -ENODEV;
210 }
211
212 ioport = pnp_port_start(dev, 0);
213 iolen = pnp_port_len(dev, 0);
214
215 if (!request_region(ioport, iolen, "ns558-pnp"))
216 return -EBUSY;
217
218 ns558 = kcalloc(1, sizeof(struct ns558), GFP_KERNEL);
219 port = gameport_allocate_port();
220 if (!ns558 || !port) {
221 printk(KERN_ERR "ns558: Memory allocation failed\n");
222 kfree(ns558);
223 gameport_free_port(port);
224 return -ENOMEM;
225 }
226
227 ns558->io = ioport;
228 ns558->size = iolen;
229 ns558->dev = dev;
230 ns558->gameport = port;
231
232 gameport_set_name(port, "NS558 PnP Gameport");
233 gameport_set_phys(port, "pnp%s/gameport0", dev->dev.bus_id);
234 port->dev.parent = &dev->dev;
235 port->io = ioport;
236
237 gameport_register_port(port);
238
239 list_add_tail(&ns558->node, &ns558_list);
240 return 0;
241}
242
243static struct pnp_driver ns558_pnp_driver = {
244 .name = "ns558",
245 .id_table = pnp_devids,
246 .probe = ns558_pnp_probe,
247};
248
249#else
250
251static struct pnp_driver ns558_pnp_driver;
252
253#endif
254
255static int pnp_registered = 0;
256
257static int __init ns558_init(void)
258{
259 int i = 0;
260
261/*
262 * Probe ISA ports first so that PnP gets to choose free port addresses
263 * not occupied by the ISA ports.
264 */
265
266 while (ns558_isa_portlist[i])
267 ns558_isa_probe(ns558_isa_portlist[i++]);
268
269 if (pnp_register_driver(&ns558_pnp_driver) >= 0)
270 pnp_registered = 1;
271
272
273 return (list_empty(&ns558_list) && !pnp_registered) ? -ENODEV : 0;
274}
275
276static void __exit ns558_exit(void)
277{
278 struct ns558 *ns558;
279
280 list_for_each_entry(ns558, &ns558_list, node) {
281 gameport_unregister_port(ns558->gameport);
282 release_region(ns558->io & ~(ns558->size - 1), ns558->size);
283 kfree(ns558);
284 }
285
286 if (pnp_registered)
287 pnp_unregister_driver(&ns558_pnp_driver);
288}
289
290module_init(ns558_init);
291module_exit(ns558_exit);
diff --git a/drivers/input/gameport/vortex.c b/drivers/input/gameport/vortex.c
new file mode 100644
index 000000000000..36b0309c8bf6
--- /dev/null
+++ b/drivers/input/gameport/vortex.c
@@ -0,0 +1,186 @@
1/*
2 * $Id: vortex.c,v 1.5 2002/07/01 15:39:30 vojtech Exp $
3 *
4 * Copyright (c) 2000-2001 Vojtech Pavlik
5 *
6 * Based on the work of:
7 * Raymond Ingles
8 */
9
10/*
11 * Trident 4DWave and Aureal Vortex gameport driver for Linux
12 */
13
14/*
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 * Should you need to contact me, the author, you can do so either by
30 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
31 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
32 */
33
34#include <asm/io.h>
35#include <linux/delay.h>
36#include <linux/errno.h>
37#include <linux/ioport.h>
38#include <linux/kernel.h>
39#include <linux/module.h>
40#include <linux/pci.h>
41#include <linux/init.h>
42#include <linux/slab.h>
43#include <linux/delay.h>
44#include <linux/gameport.h>
45
46MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
47MODULE_DESCRIPTION("Aureal Vortex and Vortex2 gameport driver");
48MODULE_LICENSE("GPL");
49
50#define VORTEX_GCR 0x0c /* Gameport control register */
51#define VORTEX_LEG 0x08 /* Legacy port location */
52#define VORTEX_AXD 0x10 /* Axes start */
53#define VORTEX_DATA_WAIT 20 /* 20 ms */
54
55struct vortex {
56 struct gameport *gameport;
57 struct pci_dev *dev;
58 unsigned char __iomem *base;
59 unsigned char __iomem *io;
60};
61
62static unsigned char vortex_read(struct gameport *gameport)
63{
64 struct vortex *vortex = gameport->port_data;
65 return readb(vortex->io + VORTEX_LEG);
66}
67
68static void vortex_trigger(struct gameport *gameport)
69{
70 struct vortex *vortex = gameport->port_data;
71 writeb(0xff, vortex->io + VORTEX_LEG);
72}
73
74static int vortex_cooked_read(struct gameport *gameport, int *axes, int *buttons)
75{
76 struct vortex *vortex = gameport->port_data;
77 int i;
78
79 *buttons = (~readb(vortex->base + VORTEX_LEG) >> 4) & 0xf;
80
81 for (i = 0; i < 4; i++) {
82 axes[i] = readw(vortex->io + VORTEX_AXD + i * sizeof(u32));
83 if (axes[i] == 0x1fff) axes[i] = -1;
84 }
85
86 return 0;
87}
88
89static int vortex_open(struct gameport *gameport, int mode)
90{
91 struct vortex *vortex = gameport->port_data;
92
93 switch (mode) {
94 case GAMEPORT_MODE_COOKED:
95 writeb(0x40, vortex->io + VORTEX_GCR);
96 msleep(VORTEX_DATA_WAIT);
97 return 0;
98 case GAMEPORT_MODE_RAW:
99 writeb(0x00, vortex->io + VORTEX_GCR);
100 return 0;
101 default:
102 return -1;
103 }
104
105 return 0;
106}
107
108static int __devinit vortex_probe(struct pci_dev *dev, const struct pci_device_id *id)
109{
110 struct vortex *vortex;
111 struct gameport *port;
112 int i;
113
114 vortex = kcalloc(1, sizeof(struct vortex), GFP_KERNEL);
115 port = gameport_allocate_port();
116 if (!vortex || !port) {
117 printk(KERN_ERR "vortex: Memory allocation failed.\n");
118 kfree(vortex);
119 gameport_free_port(port);
120 return -ENOMEM;
121 }
122
123 for (i = 0; i < 6; i++)
124 if (~pci_resource_flags(dev, i) & IORESOURCE_IO)
125 break;
126
127 pci_enable_device(dev);
128
129 vortex->dev = dev;
130 vortex->gameport = port;
131 vortex->base = ioremap(pci_resource_start(vortex->dev, i),
132 pci_resource_len(vortex->dev, i));
133 vortex->io = vortex->base + id->driver_data;
134
135 pci_set_drvdata(dev, vortex);
136
137 port->port_data = vortex;
138 port->fuzz = 64;
139
140 gameport_set_name(port, "AU88x0");
141 gameport_set_phys(port, "pci%s/gameport0", pci_name(dev));
142 port->dev.parent = &dev->dev;
143 port->read = vortex_read;
144 port->trigger = vortex_trigger;
145 port->cooked_read = vortex_cooked_read;
146 port->open = vortex_open;
147
148 gameport_register_port(port);
149
150 return 0;
151}
152
153static void __devexit vortex_remove(struct pci_dev *dev)
154{
155 struct vortex *vortex = pci_get_drvdata(dev);
156
157 gameport_unregister_port(vortex->gameport);
158 iounmap(vortex->base);
159 kfree(vortex);
160}
161
162static struct pci_device_id vortex_id_table[] = {
163 { 0x12eb, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x11000 },
164 { 0x12eb, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x28800 },
165 { 0 }
166};
167
168static struct pci_driver vortex_driver = {
169 .name = "vortex_gameport",
170 .id_table = vortex_id_table,
171 .probe = vortex_probe,
172 .remove = __devexit_p(vortex_remove),
173};
174
175static int __init vortex_init(void)
176{
177 return pci_register_driver(&vortex_driver);
178}
179
180static void __exit vortex_exit(void)
181{
182 pci_unregister_driver(&vortex_driver);
183}
184
185module_init(vortex_init);
186module_exit(vortex_exit);
diff --git a/drivers/input/input.c b/drivers/input/input.c
new file mode 100644
index 000000000000..3385dd03abfc
--- /dev/null
+++ b/drivers/input/input.c
@@ -0,0 +1,748 @@
1/*
2 * The input core
3 *
4 * Copyright (c) 1999-2002 Vojtech Pavlik
5 */
6
7/*
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 */
12
13#include <linux/init.h>
14#include <linux/sched.h>
15#include <linux/smp_lock.h>
16#include <linux/input.h>
17#include <linux/module.h>
18#include <linux/random.h>
19#include <linux/major.h>
20#include <linux/proc_fs.h>
21#include <linux/kobject_uevent.h>
22#include <linux/interrupt.h>
23#include <linux/poll.h>
24#include <linux/device.h>
25#include <linux/devfs_fs_kernel.h>
26
27MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
28MODULE_DESCRIPTION("Input core");
29MODULE_LICENSE("GPL");
30
31EXPORT_SYMBOL(input_register_device);
32EXPORT_SYMBOL(input_unregister_device);
33EXPORT_SYMBOL(input_register_handler);
34EXPORT_SYMBOL(input_unregister_handler);
35EXPORT_SYMBOL(input_grab_device);
36EXPORT_SYMBOL(input_release_device);
37EXPORT_SYMBOL(input_open_device);
38EXPORT_SYMBOL(input_close_device);
39EXPORT_SYMBOL(input_accept_process);
40EXPORT_SYMBOL(input_flush_device);
41EXPORT_SYMBOL(input_event);
42EXPORT_SYMBOL(input_class);
43
44#define INPUT_DEVICES 256
45
46static LIST_HEAD(input_dev_list);
47static LIST_HEAD(input_handler_list);
48
49static struct input_handler *input_table[8];
50
51#ifdef CONFIG_PROC_FS
52static struct proc_dir_entry *proc_bus_input_dir;
53static DECLARE_WAIT_QUEUE_HEAD(input_devices_poll_wait);
54static int input_devices_state;
55#endif
56
57void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
58{
59 struct input_handle *handle;
60
61 if (type > EV_MAX || !test_bit(type, dev->evbit))
62 return;
63
64 add_input_randomness(type, code, value);
65
66 switch (type) {
67
68 case EV_SYN:
69 switch (code) {
70 case SYN_CONFIG:
71 if (dev->event) dev->event(dev, type, code, value);
72 break;
73
74 case SYN_REPORT:
75 if (dev->sync) return;
76 dev->sync = 1;
77 break;
78 }
79 break;
80
81 case EV_KEY:
82
83 if (code > KEY_MAX || !test_bit(code, dev->keybit) || !!test_bit(code, dev->key) == value)
84 return;
85
86 if (value == 2)
87 break;
88
89 change_bit(code, dev->key);
90
91 if (test_bit(EV_REP, dev->evbit) && dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] && dev->timer.data && value) {
92 dev->repeat_key = code;
93 mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]));
94 }
95
96 break;
97
98 case EV_ABS:
99
100 if (code > ABS_MAX || !test_bit(code, dev->absbit))
101 return;
102
103 if (dev->absfuzz[code]) {
104 if ((value > dev->abs[code] - (dev->absfuzz[code] >> 1)) &&
105 (value < dev->abs[code] + (dev->absfuzz[code] >> 1)))
106 return;
107
108 if ((value > dev->abs[code] - dev->absfuzz[code]) &&
109 (value < dev->abs[code] + dev->absfuzz[code]))
110 value = (dev->abs[code] * 3 + value) >> 2;
111
112 if ((value > dev->abs[code] - (dev->absfuzz[code] << 1)) &&
113 (value < dev->abs[code] + (dev->absfuzz[code] << 1)))
114 value = (dev->abs[code] + value) >> 1;
115 }
116
117 if (dev->abs[code] == value)
118 return;
119
120 dev->abs[code] = value;
121 break;
122
123 case EV_REL:
124
125 if (code > REL_MAX || !test_bit(code, dev->relbit) || (value == 0))
126 return;
127
128 break;
129
130 case EV_MSC:
131
132 if (code > MSC_MAX || !test_bit(code, dev->mscbit))
133 return;
134
135 if (dev->event) dev->event(dev, type, code, value);
136
137 break;
138
139 case EV_LED:
140
141 if (code > LED_MAX || !test_bit(code, dev->ledbit) || !!test_bit(code, dev->led) == value)
142 return;
143
144 change_bit(code, dev->led);
145 if (dev->event) dev->event(dev, type, code, value);
146
147 break;
148
149 case EV_SND:
150
151 if (code > SND_MAX || !test_bit(code, dev->sndbit))
152 return;
153
154 if (dev->event) dev->event(dev, type, code, value);
155
156 break;
157
158 case EV_REP:
159
160 if (code > REP_MAX || value < 0 || dev->rep[code] == value) return;
161
162 dev->rep[code] = value;
163 if (dev->event) dev->event(dev, type, code, value);
164
165 break;
166
167 case EV_FF:
168 if (dev->event) dev->event(dev, type, code, value);
169 break;
170 }
171
172 if (type != EV_SYN)
173 dev->sync = 0;
174
175 if (dev->grab)
176 dev->grab->handler->event(dev->grab, type, code, value);
177 else
178 list_for_each_entry(handle, &dev->h_list, d_node)
179 if (handle->open)
180 handle->handler->event(handle, type, code, value);
181}
182
183static void input_repeat_key(unsigned long data)
184{
185 struct input_dev *dev = (void *) data;
186
187 if (!test_bit(dev->repeat_key, dev->key))
188 return;
189
190 input_event(dev, EV_KEY, dev->repeat_key, 2);
191 input_sync(dev);
192
193 if (dev->rep[REP_PERIOD])
194 mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_PERIOD]));
195}
196
197int input_accept_process(struct input_handle *handle, struct file *file)
198{
199 if (handle->dev->accept)
200 return handle->dev->accept(handle->dev, file);
201
202 return 0;
203}
204
205int input_grab_device(struct input_handle *handle)
206{
207 if (handle->dev->grab)
208 return -EBUSY;
209
210 handle->dev->grab = handle;
211 return 0;
212}
213
214void input_release_device(struct input_handle *handle)
215{
216 if (handle->dev->grab == handle)
217 handle->dev->grab = NULL;
218}
219
220int input_open_device(struct input_handle *handle)
221{
222 handle->open++;
223 if (handle->dev->open)
224 return handle->dev->open(handle->dev);
225 return 0;
226}
227
228int input_flush_device(struct input_handle* handle, struct file* file)
229{
230 if (handle->dev->flush)
231 return handle->dev->flush(handle->dev, file);
232
233 return 0;
234}
235
236void input_close_device(struct input_handle *handle)
237{
238 input_release_device(handle);
239 if (handle->dev->close)
240 handle->dev->close(handle->dev);
241 handle->open--;
242}
243
244static void input_link_handle(struct input_handle *handle)
245{
246 list_add_tail(&handle->d_node, &handle->dev->h_list);
247 list_add_tail(&handle->h_node, &handle->handler->h_list);
248}
249
250#define MATCH_BIT(bit, max) \
251 for (i = 0; i < NBITS(max); i++) \
252 if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
253 break; \
254 if (i != NBITS(max)) \
255 continue;
256
257static struct input_device_id *input_match_device(struct input_device_id *id, struct input_dev *dev)
258{
259 int i;
260
261 for (; id->flags || id->driver_info; id++) {
262
263 if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
264 if (id->id.bustype != dev->id.bustype)
265 continue;
266
267 if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)
268 if (id->id.vendor != dev->id.vendor)
269 continue;
270
271 if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)
272 if (id->id.product != dev->id.product)
273 continue;
274
275 if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION)
276 if (id->id.version != dev->id.version)
277 continue;
278
279 MATCH_BIT(evbit, EV_MAX);
280 MATCH_BIT(keybit, KEY_MAX);
281 MATCH_BIT(relbit, REL_MAX);
282 MATCH_BIT(absbit, ABS_MAX);
283 MATCH_BIT(mscbit, MSC_MAX);
284 MATCH_BIT(ledbit, LED_MAX);
285 MATCH_BIT(sndbit, SND_MAX);
286 MATCH_BIT(ffbit, FF_MAX);
287
288 return id;
289 }
290
291 return NULL;
292}
293
294/*
295 * Input hotplugging interface - loading event handlers based on
296 * device bitfields.
297 */
298
299#ifdef CONFIG_HOTPLUG
300
301/*
302 * Input hotplugging invokes what /proc/sys/kernel/hotplug says
303 * (normally /sbin/hotplug) when input devices get added or removed.
304 *
305 * This invokes a user mode policy agent, typically helping to load driver
306 * or other modules, configure the device, and more. Drivers can provide
307 * a MODULE_DEVICE_TABLE to help with module loading subtasks.
308 *
309 */
310
311#define SPRINTF_BIT_A(bit, name, max) \
312 do { \
313 envp[i++] = scratch; \
314 scratch += sprintf(scratch, name); \
315 for (j = NBITS(max) - 1; j >= 0; j--) \
316 if (dev->bit[j]) break; \
317 for (; j >= 0; j--) \
318 scratch += sprintf(scratch, "%lx ", dev->bit[j]); \
319 scratch++; \
320 } while (0)
321
322#define SPRINTF_BIT_A2(bit, name, max, ev) \
323 do { \
324 if (test_bit(ev, dev->evbit)) \
325 SPRINTF_BIT_A(bit, name, max); \
326 } while (0)
327
328static void input_call_hotplug(char *verb, struct input_dev *dev)
329{
330 char *argv[3], **envp, *buf, *scratch;
331 int i = 0, j, value;
332
333 if (!hotplug_path[0]) {
334 printk(KERN_ERR "input.c: calling hotplug without a hotplug agent defined\n");
335 return;
336 }
337 if (in_interrupt()) {
338 printk(KERN_ERR "input.c: calling hotplug from interrupt\n");
339 return;
340 }
341 if (!current->fs->root) {
342 printk(KERN_WARNING "input.c: calling hotplug without valid filesystem\n");
343 return;
344 }
345 if (!(envp = (char **) kmalloc(20 * sizeof(char *), GFP_KERNEL))) {
346 printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
347 return;
348 }
349 if (!(buf = kmalloc(1024, GFP_KERNEL))) {
350 kfree (envp);
351 printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
352 return;
353 }
354
355 argv[0] = hotplug_path;
356 argv[1] = "input";
357 argv[2] = NULL;
358
359 envp[i++] = "HOME=/";
360 envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
361
362 scratch = buf;
363
364 envp[i++] = scratch;
365 scratch += sprintf(scratch, "ACTION=%s", verb) + 1;
366
367 envp[i++] = scratch;
368 scratch += sprintf(scratch, "PRODUCT=%x/%x/%x/%x",
369 dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version) + 1;
370
371 if (dev->name) {
372 envp[i++] = scratch;
373 scratch += sprintf(scratch, "NAME=%s", dev->name) + 1;
374 }
375
376 if (dev->phys) {
377 envp[i++] = scratch;
378 scratch += sprintf(scratch, "PHYS=%s", dev->phys) + 1;
379 }
380
381 SPRINTF_BIT_A(evbit, "EV=", EV_MAX);
382 SPRINTF_BIT_A2(keybit, "KEY=", KEY_MAX, EV_KEY);
383 SPRINTF_BIT_A2(relbit, "REL=", REL_MAX, EV_REL);
384 SPRINTF_BIT_A2(absbit, "ABS=", ABS_MAX, EV_ABS);
385 SPRINTF_BIT_A2(mscbit, "MSC=", MSC_MAX, EV_MSC);
386 SPRINTF_BIT_A2(ledbit, "LED=", LED_MAX, EV_LED);
387 SPRINTF_BIT_A2(sndbit, "SND=", SND_MAX, EV_SND);
388 SPRINTF_BIT_A2(ffbit, "FF=", FF_MAX, EV_FF);
389
390 envp[i++] = NULL;
391
392#ifdef INPUT_DEBUG
393 printk(KERN_DEBUG "input.c: calling %s %s [%s %s %s %s %s]\n",
394 argv[0], argv[1], envp[0], envp[1], envp[2], envp[3], envp[4]);
395#endif
396
397 value = call_usermodehelper(argv [0], argv, envp, 0);
398
399 kfree(buf);
400 kfree(envp);
401
402#ifdef INPUT_DEBUG
403 if (value != 0)
404 printk(KERN_DEBUG "input.c: hotplug returned %d\n", value);
405#endif
406}
407
408#endif
409
410void input_register_device(struct input_dev *dev)
411{
412 struct input_handle *handle;
413 struct input_handler *handler;
414 struct input_device_id *id;
415
416 set_bit(EV_SYN, dev->evbit);
417
418 /*
419 * If delay and period are pre-set by the driver, then autorepeating
420 * is handled by the driver itself and we don't do it in input.c.
421 */
422
423 init_timer(&dev->timer);
424 if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
425 dev->timer.data = (long) dev;
426 dev->timer.function = input_repeat_key;
427 dev->rep[REP_DELAY] = 250;
428 dev->rep[REP_PERIOD] = 33;
429 }
430
431 INIT_LIST_HEAD(&dev->h_list);
432 list_add_tail(&dev->node, &input_dev_list);
433
434 list_for_each_entry(handler, &input_handler_list, node)
435 if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
436 if ((id = input_match_device(handler->id_table, dev)))
437 if ((handle = handler->connect(handler, dev, id)))
438 input_link_handle(handle);
439
440#ifdef CONFIG_HOTPLUG
441 input_call_hotplug("add", dev);
442#endif
443
444#ifdef CONFIG_PROC_FS
445 input_devices_state++;
446 wake_up(&input_devices_poll_wait);
447#endif
448}
449
450void input_unregister_device(struct input_dev *dev)
451{
452 struct list_head * node, * next;
453
454 if (!dev) return;
455
456 del_timer_sync(&dev->timer);
457
458 list_for_each_safe(node, next, &dev->h_list) {
459 struct input_handle * handle = to_handle(node);
460 list_del_init(&handle->d_node);
461 list_del_init(&handle->h_node);
462 handle->handler->disconnect(handle);
463 }
464
465#ifdef CONFIG_HOTPLUG
466 input_call_hotplug("remove", dev);
467#endif
468
469 list_del_init(&dev->node);
470
471#ifdef CONFIG_PROC_FS
472 input_devices_state++;
473 wake_up(&input_devices_poll_wait);
474#endif
475}
476
477void input_register_handler(struct input_handler *handler)
478{
479 struct input_dev *dev;
480 struct input_handle *handle;
481 struct input_device_id *id;
482
483 if (!handler) return;
484
485 INIT_LIST_HEAD(&handler->h_list);
486
487 if (handler->fops != NULL)
488 input_table[handler->minor >> 5] = handler;
489
490 list_add_tail(&handler->node, &input_handler_list);
491
492 list_for_each_entry(dev, &input_dev_list, node)
493 if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
494 if ((id = input_match_device(handler->id_table, dev)))
495 if ((handle = handler->connect(handler, dev, id)))
496 input_link_handle(handle);
497
498#ifdef CONFIG_PROC_FS
499 input_devices_state++;
500 wake_up(&input_devices_poll_wait);
501#endif
502}
503
504void input_unregister_handler(struct input_handler *handler)
505{
506 struct list_head * node, * next;
507
508 list_for_each_safe(node, next, &handler->h_list) {
509 struct input_handle * handle = to_handle_h(node);
510 list_del_init(&handle->h_node);
511 list_del_init(&handle->d_node);
512 handler->disconnect(handle);
513 }
514
515 list_del_init(&handler->node);
516
517 if (handler->fops != NULL)
518 input_table[handler->minor >> 5] = NULL;
519
520#ifdef CONFIG_PROC_FS
521 input_devices_state++;
522 wake_up(&input_devices_poll_wait);
523#endif
524}
525
526static int input_open_file(struct inode *inode, struct file *file)
527{
528 struct input_handler *handler = input_table[iminor(inode) >> 5];
529 struct file_operations *old_fops, *new_fops = NULL;
530 int err;
531
532 /* No load-on-demand here? */
533 if (!handler || !(new_fops = fops_get(handler->fops)))
534 return -ENODEV;
535
536 /*
537 * That's _really_ odd. Usually NULL ->open means "nothing special",
538 * not "no device". Oh, well...
539 */
540 if (!new_fops->open) {
541 fops_put(new_fops);
542 return -ENODEV;
543 }
544 old_fops = file->f_op;
545 file->f_op = new_fops;
546
547 err = new_fops->open(inode, file);
548
549 if (err) {
550 fops_put(file->f_op);
551 file->f_op = fops_get(old_fops);
552 }
553 fops_put(old_fops);
554 return err;
555}
556
557static struct file_operations input_fops = {
558 .owner = THIS_MODULE,
559 .open = input_open_file,
560};
561
562#ifdef CONFIG_PROC_FS
563
564#define SPRINTF_BIT_B(bit, name, max) \
565 do { \
566 len += sprintf(buf + len, "B: %s", name); \
567 for (i = NBITS(max) - 1; i >= 0; i--) \
568 if (dev->bit[i]) break; \
569 for (; i >= 0; i--) \
570 len += sprintf(buf + len, "%lx ", dev->bit[i]); \
571 len += sprintf(buf + len, "\n"); \
572 } while (0)
573
574#define SPRINTF_BIT_B2(bit, name, max, ev) \
575 do { \
576 if (test_bit(ev, dev->evbit)) \
577 SPRINTF_BIT_B(bit, name, max); \
578 } while (0)
579
580
581static unsigned int input_devices_poll(struct file *file, poll_table *wait)
582{
583 int state = input_devices_state;
584 poll_wait(file, &input_devices_poll_wait, wait);
585 if (state != input_devices_state)
586 return POLLIN | POLLRDNORM;
587 return 0;
588}
589
590static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
591{
592 struct input_dev *dev;
593 struct input_handle *handle;
594
595 off_t at = 0;
596 int i, len, cnt = 0;
597
598 list_for_each_entry(dev, &input_dev_list, node) {
599
600 len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
601 dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version);
602
603 len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : "");
604 len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : "");
605 len += sprintf(buf + len, "H: Handlers=");
606
607 list_for_each_entry(handle, &dev->h_list, d_node)
608 len += sprintf(buf + len, "%s ", handle->name);
609
610 len += sprintf(buf + len, "\n");
611
612 SPRINTF_BIT_B(evbit, "EV=", EV_MAX);
613 SPRINTF_BIT_B2(keybit, "KEY=", KEY_MAX, EV_KEY);
614 SPRINTF_BIT_B2(relbit, "REL=", REL_MAX, EV_REL);
615 SPRINTF_BIT_B2(absbit, "ABS=", ABS_MAX, EV_ABS);
616 SPRINTF_BIT_B2(mscbit, "MSC=", MSC_MAX, EV_MSC);
617 SPRINTF_BIT_B2(ledbit, "LED=", LED_MAX, EV_LED);
618 SPRINTF_BIT_B2(sndbit, "SND=", SND_MAX, EV_SND);
619 SPRINTF_BIT_B2(ffbit, "FF=", FF_MAX, EV_FF);
620
621 len += sprintf(buf + len, "\n");
622
623 at += len;
624
625 if (at >= pos) {
626 if (!*start) {
627 *start = buf + (pos - (at - len));
628 cnt = at - pos;
629 } else cnt += len;
630 buf += len;
631 if (cnt >= count)
632 break;
633 }
634 }
635
636 if (&dev->node == &input_dev_list)
637 *eof = 1;
638
639 return (count > cnt) ? cnt : count;
640}
641
642static int input_handlers_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
643{
644 struct input_handler *handler;
645
646 off_t at = 0;
647 int len = 0, cnt = 0;
648 int i = 0;
649
650 list_for_each_entry(handler, &input_handler_list, node) {
651
652 if (handler->fops)
653 len = sprintf(buf, "N: Number=%d Name=%s Minor=%d\n",
654 i++, handler->name, handler->minor);
655 else
656 len = sprintf(buf, "N: Number=%d Name=%s\n",
657 i++, handler->name);
658
659 at += len;
660
661 if (at >= pos) {
662 if (!*start) {
663 *start = buf + (pos - (at - len));
664 cnt = at - pos;
665 } else cnt += len;
666 buf += len;
667 if (cnt >= count)
668 break;
669 }
670 }
671 if (&handler->node == &input_handler_list)
672 *eof = 1;
673
674 return (count > cnt) ? cnt : count;
675}
676
677static int __init input_proc_init(void)
678{
679 struct proc_dir_entry *entry;
680
681 proc_bus_input_dir = proc_mkdir("input", proc_bus);
682 if (proc_bus_input_dir == NULL)
683 return -ENOMEM;
684 proc_bus_input_dir->owner = THIS_MODULE;
685 entry = create_proc_read_entry("devices", 0, proc_bus_input_dir, input_devices_read, NULL);
686 if (entry == NULL) {
687 remove_proc_entry("input", proc_bus);
688 return -ENOMEM;
689 }
690 entry->owner = THIS_MODULE;
691 entry->proc_fops->poll = input_devices_poll;
692 entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL);
693 if (entry == NULL) {
694 remove_proc_entry("devices", proc_bus_input_dir);
695 remove_proc_entry("input", proc_bus);
696 return -ENOMEM;
697 }
698 entry->owner = THIS_MODULE;
699 return 0;
700}
701#else /* !CONFIG_PROC_FS */
702static inline int input_proc_init(void) { return 0; }
703#endif
704
705struct class_simple *input_class;
706
707static int __init input_init(void)
708{
709 int retval = -ENOMEM;
710
711 input_class = class_simple_create(THIS_MODULE, "input");
712 if (IS_ERR(input_class))
713 return PTR_ERR(input_class);
714 input_proc_init();
715 retval = register_chrdev(INPUT_MAJOR, "input", &input_fops);
716 if (retval) {
717 printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
718 remove_proc_entry("devices", proc_bus_input_dir);
719 remove_proc_entry("handlers", proc_bus_input_dir);
720 remove_proc_entry("input", proc_bus);
721 class_simple_destroy(input_class);
722 return retval;
723 }
724
725 retval = devfs_mk_dir("input");
726 if (retval) {
727 remove_proc_entry("devices", proc_bus_input_dir);
728 remove_proc_entry("handlers", proc_bus_input_dir);
729 remove_proc_entry("input", proc_bus);
730 unregister_chrdev(INPUT_MAJOR, "input");
731 class_simple_destroy(input_class);
732 }
733 return retval;
734}
735
736static void __exit input_exit(void)
737{
738 remove_proc_entry("devices", proc_bus_input_dir);
739 remove_proc_entry("handlers", proc_bus_input_dir);
740 remove_proc_entry("input", proc_bus);
741
742 devfs_remove("input");
743 unregister_chrdev(INPUT_MAJOR, "input");
744 class_simple_destroy(input_class);
745}
746
747subsys_initcall(input_init);
748module_exit(input_exit);
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
new file mode 100644
index 000000000000..7d7527f8b02d
--- /dev/null
+++ b/drivers/input/joydev.c
@@ -0,0 +1,533 @@
1/*
2 * Joystick device driver for the input driver suite.
3 *
4 * Copyright (c) 1999-2002 Vojtech Pavlik
5 * Copyright (c) 1999 Colin Van Dyke
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <asm/io.h>
14#include <asm/system.h>
15#include <linux/delay.h>
16#include <linux/errno.h>
17#include <linux/joystick.h>
18#include <linux/input.h>
19#include <linux/kernel.h>
20#include <linux/major.h>
21#include <linux/slab.h>
22#include <linux/mm.h>
23#include <linux/miscdevice.h>
24#include <linux/module.h>
25#include <linux/poll.h>
26#include <linux/init.h>
27#include <linux/smp_lock.h>
28#include <linux/device.h>
29#include <linux/devfs_fs_kernel.h>
30
31MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
32MODULE_DESCRIPTION("Joystick device interfaces");
33MODULE_SUPPORTED_DEVICE("input/js");
34MODULE_LICENSE("GPL");
35
36#define JOYDEV_MINOR_BASE 0
37#define JOYDEV_MINORS 16
38#define JOYDEV_BUFFER_SIZE 64
39
40#define MSECS(t) (1000 * ((t) / HZ) + 1000 * ((t) % HZ) / HZ)
41
42struct joydev {
43 int exist;
44 int open;
45 int minor;
46 char name[16];
47 struct input_handle handle;
48 wait_queue_head_t wait;
49 struct list_head list;
50 struct js_corr corr[ABS_MAX + 1];
51 struct JS_DATA_SAVE_TYPE glue;
52 int nabs;
53 int nkey;
54 __u16 keymap[KEY_MAX - BTN_MISC + 1];
55 __u16 keypam[KEY_MAX - BTN_MISC + 1];
56 __u8 absmap[ABS_MAX + 1];
57 __u8 abspam[ABS_MAX + 1];
58 __s16 abs[ABS_MAX + 1];
59};
60
61struct joydev_list {
62 struct js_event buffer[JOYDEV_BUFFER_SIZE];
63 int head;
64 int tail;
65 int startup;
66 struct fasync_struct *fasync;
67 struct joydev *joydev;
68 struct list_head node;
69};
70
71static struct joydev *joydev_table[JOYDEV_MINORS];
72
73static int joydev_correct(int value, struct js_corr *corr)
74{
75 switch (corr->type) {
76 case JS_CORR_NONE:
77 break;
78 case JS_CORR_BROKEN:
79 value = value > corr->coef[0] ? (value < corr->coef[1] ? 0 :
80 ((corr->coef[3] * (value - corr->coef[1])) >> 14)) :
81 ((corr->coef[2] * (value - corr->coef[0])) >> 14);
82 break;
83 default:
84 return 0;
85 }
86
87 if (value < -32767) return -32767;
88 if (value > 32767) return 32767;
89
90 return value;
91}
92
93static void joydev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
94{
95 struct joydev *joydev = handle->private;
96 struct joydev_list *list;
97 struct js_event event;
98
99 switch (type) {
100
101 case EV_KEY:
102 if (code < BTN_MISC || value == 2) return;
103 event.type = JS_EVENT_BUTTON;
104 event.number = joydev->keymap[code - BTN_MISC];
105 event.value = value;
106 break;
107
108 case EV_ABS:
109 event.type = JS_EVENT_AXIS;
110 event.number = joydev->absmap[code];
111 event.value = joydev_correct(value, joydev->corr + event.number);
112 if (event.value == joydev->abs[event.number]) return;
113 joydev->abs[event.number] = event.value;
114 break;
115
116 default:
117 return;
118 }
119
120 event.time = MSECS(jiffies);
121
122 list_for_each_entry(list, &joydev->list, node) {
123
124 memcpy(list->buffer + list->head, &event, sizeof(struct js_event));
125
126 if (list->startup == joydev->nabs + joydev->nkey)
127 if (list->tail == (list->head = (list->head + 1) & (JOYDEV_BUFFER_SIZE - 1)))
128 list->startup = 0;
129
130 kill_fasync(&list->fasync, SIGIO, POLL_IN);
131 }
132
133 wake_up_interruptible(&joydev->wait);
134}
135
136static int joydev_fasync(int fd, struct file *file, int on)
137{
138 int retval;
139 struct joydev_list *list = file->private_data;
140 retval = fasync_helper(fd, file, on, &list->fasync);
141 return retval < 0 ? retval : 0;
142}
143
144static void joydev_free(struct joydev *joydev)
145{
146 joydev_table[joydev->minor] = NULL;
147 kfree(joydev);
148}
149
150static int joydev_release(struct inode * inode, struct file * file)
151{
152 struct joydev_list *list = file->private_data;
153
154 joydev_fasync(-1, file, 0);
155
156 list_del(&list->node);
157
158 if (!--list->joydev->open) {
159 if (list->joydev->exist)
160 input_close_device(&list->joydev->handle);
161 else
162 joydev_free(list->joydev);
163 }
164
165 kfree(list);
166 return 0;
167}
168
169static int joydev_open(struct inode *inode, struct file *file)
170{
171 struct joydev_list *list;
172 int i = iminor(inode) - JOYDEV_MINOR_BASE;
173
174 if (i >= JOYDEV_MINORS || !joydev_table[i])
175 return -ENODEV;
176
177 if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL)))
178 return -ENOMEM;
179 memset(list, 0, sizeof(struct joydev_list));
180
181 list->joydev = joydev_table[i];
182 list_add_tail(&list->node, &joydev_table[i]->list);
183 file->private_data = list;
184
185 if (!list->joydev->open++)
186 if (list->joydev->exist)
187 input_open_device(&list->joydev->handle);
188
189 return 0;
190}
191
192static ssize_t joydev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
193{
194 return -EINVAL;
195}
196
197static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
198{
199 struct joydev_list *list = file->private_data;
200 struct joydev *joydev = list->joydev;
201 struct input_dev *input = joydev->handle.dev;
202 int retval = 0;
203
204 if (!list->joydev->exist)
205 return -ENODEV;
206
207 if (count < sizeof(struct js_event))
208 return -EINVAL;
209
210 if (count == sizeof(struct JS_DATA_TYPE)) {
211
212 struct JS_DATA_TYPE data;
213 int i;
214
215 for (data.buttons = i = 0; i < 32 && i < joydev->nkey; i++)
216 data.buttons |= test_bit(joydev->keypam[i], input->key) ? (1 << i) : 0;
217 data.x = (joydev->abs[0] / 256 + 128) >> joydev->glue.JS_CORR.x;
218 data.y = (joydev->abs[1] / 256 + 128) >> joydev->glue.JS_CORR.y;
219
220 if (copy_to_user(buf, &data, sizeof(struct JS_DATA_TYPE)))
221 return -EFAULT;
222
223 list->startup = 0;
224 list->tail = list->head;
225
226 return sizeof(struct JS_DATA_TYPE);
227 }
228
229 if (list->startup == joydev->nabs + joydev->nkey
230 && list->head == list->tail && (file->f_flags & O_NONBLOCK))
231 return -EAGAIN;
232
233 retval = wait_event_interruptible(list->joydev->wait,
234 !list->joydev->exist ||
235 list->startup < joydev->nabs + joydev->nkey ||
236 list->head != list->tail);
237
238 if (retval)
239 return retval;
240
241 if (!list->joydev->exist)
242 return -ENODEV;
243
244 while (list->startup < joydev->nabs + joydev->nkey && retval + sizeof(struct js_event) <= count) {
245
246 struct js_event event;
247
248 event.time = MSECS(jiffies);
249
250 if (list->startup < joydev->nkey) {
251 event.type = JS_EVENT_BUTTON | JS_EVENT_INIT;
252 event.number = list->startup;
253 event.value = !!test_bit(joydev->keypam[event.number], input->key);
254 } else {
255 event.type = JS_EVENT_AXIS | JS_EVENT_INIT;
256 event.number = list->startup - joydev->nkey;
257 event.value = joydev->abs[event.number];
258 }
259
260 if (copy_to_user(buf + retval, &event, sizeof(struct js_event)))
261 return -EFAULT;
262
263 list->startup++;
264 retval += sizeof(struct js_event);
265 }
266
267 while (list->head != list->tail && retval + sizeof(struct js_event) <= count) {
268
269 if (copy_to_user(buf + retval, list->buffer + list->tail, sizeof(struct js_event)))
270 return -EFAULT;
271
272 list->tail = (list->tail + 1) & (JOYDEV_BUFFER_SIZE - 1);
273 retval += sizeof(struct js_event);
274 }
275
276 return retval;
277}
278
279/* No kernel lock - fine */
280static unsigned int joydev_poll(struct file *file, poll_table *wait)
281{
282 struct joydev_list *list = file->private_data;
283 poll_wait(file, &list->joydev->wait, wait);
284 return ((list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey) ?
285 (POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR));
286}
287
288static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
289{
290 struct joydev_list *list = file->private_data;
291 struct joydev *joydev = list->joydev;
292 struct input_dev *dev = joydev->handle.dev;
293 void __user *argp = (void __user *)arg;
294 int i, j;
295
296 if (!joydev->exist) return -ENODEV;
297
298 switch (cmd) {
299
300 case JS_SET_CAL:
301 return copy_from_user(&joydev->glue.JS_CORR, argp,
302 sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0;
303 case JS_GET_CAL:
304 return copy_to_user(argp, &joydev->glue.JS_CORR,
305 sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0;
306 case JS_SET_TIMEOUT:
307 return get_user(joydev->glue.JS_TIMEOUT, (int __user *) arg);
308 case JS_GET_TIMEOUT:
309 return put_user(joydev->glue.JS_TIMEOUT, (int __user *) arg);
310 case JS_SET_TIMELIMIT:
311 return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg);
312 case JS_GET_TIMELIMIT:
313 return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg);
314 case JS_SET_ALL:
315 return copy_from_user(&joydev->glue, argp,
316 sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0;
317 case JS_GET_ALL:
318 return copy_to_user(argp, &joydev->glue,
319 sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0;
320
321 case JSIOCGVERSION:
322 return put_user(JS_VERSION, (__u32 __user *) arg);
323 case JSIOCGAXES:
324 return put_user(joydev->nabs, (__u8 __user *) arg);
325 case JSIOCGBUTTONS:
326 return put_user(joydev->nkey, (__u8 __user *) arg);
327 case JSIOCSCORR:
328 if (copy_from_user(joydev->corr, argp,
329 sizeof(struct js_corr) * joydev->nabs))
330 return -EFAULT;
331 for (i = 0; i < joydev->nabs; i++) {
332 j = joydev->abspam[i];
333 joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
334 }
335 return 0;
336 case JSIOCGCORR:
337 return copy_to_user(argp, joydev->corr,
338 sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0;
339 case JSIOCSAXMAP:
340 if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1)))
341 return -EFAULT;
342 for (i = 0; i < joydev->nabs; i++) {
343 if (joydev->abspam[i] > ABS_MAX) return -EINVAL;
344 joydev->absmap[joydev->abspam[i]] = i;
345 }
346 return 0;
347 case JSIOCGAXMAP:
348 return copy_to_user(argp, joydev->abspam,
349 sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0;
350 case JSIOCSBTNMAP:
351 if (copy_from_user(joydev->keypam, argp, sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)))
352 return -EFAULT;
353 for (i = 0; i < joydev->nkey; i++) {
354 if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC) return -EINVAL;
355 joydev->keymap[joydev->keypam[i] - BTN_MISC] = i;
356 }
357 return 0;
358 case JSIOCGBTNMAP:
359 return copy_to_user(argp, joydev->keypam,
360 sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0;
361 default:
362 if ((cmd & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) == JSIOCGNAME(0)) {
363 int len;
364 if (!dev->name) return 0;
365 len = strlen(dev->name) + 1;
366 if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
367 if (copy_to_user(argp, dev->name, len)) return -EFAULT;
368 return len;
369 }
370 }
371 return -EINVAL;
372}
373
374static struct file_operations joydev_fops = {
375 .owner = THIS_MODULE,
376 .read = joydev_read,
377 .write = joydev_write,
378 .poll = joydev_poll,
379 .open = joydev_open,
380 .release = joydev_release,
381 .ioctl = joydev_ioctl,
382 .fasync = joydev_fasync,
383};
384
385static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
386{
387 struct joydev *joydev;
388 int i, j, t, minor;
389
390 for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
391 if (minor == JOYDEV_MINORS) {
392 printk(KERN_ERR "joydev: no more free joydev devices\n");
393 return NULL;
394 }
395
396 if (!(joydev = kmalloc(sizeof(struct joydev), GFP_KERNEL)))
397 return NULL;
398 memset(joydev, 0, sizeof(struct joydev));
399
400 INIT_LIST_HEAD(&joydev->list);
401 init_waitqueue_head(&joydev->wait);
402
403 joydev->minor = minor;
404 joydev->exist = 1;
405 joydev->handle.dev = dev;
406 joydev->handle.name = joydev->name;
407 joydev->handle.handler = handler;
408 joydev->handle.private = joydev;
409 sprintf(joydev->name, "js%d", minor);
410
411 for (i = 0; i < ABS_MAX + 1; i++)
412 if (test_bit(i, dev->absbit)) {
413 joydev->absmap[i] = joydev->nabs;
414 joydev->abspam[joydev->nabs] = i;
415 joydev->nabs++;
416 }
417
418 for (i = BTN_JOYSTICK - BTN_MISC; i < KEY_MAX - BTN_MISC + 1; i++)
419 if (test_bit(i + BTN_MISC, dev->keybit)) {
420 joydev->keymap[i] = joydev->nkey;
421 joydev->keypam[joydev->nkey] = i + BTN_MISC;
422 joydev->nkey++;
423 }
424
425 for (i = 0; i < BTN_JOYSTICK - BTN_MISC + 1; i++)
426 if (test_bit(i + BTN_MISC, dev->keybit)) {
427 joydev->keymap[i] = joydev->nkey;
428 joydev->keypam[joydev->nkey] = i + BTN_MISC;
429 joydev->nkey++;
430 }
431
432 for (i = 0; i < joydev->nabs; i++) {
433 j = joydev->abspam[i];
434 if (dev->absmax[j] == dev->absmin[j]) {
435 joydev->corr[i].type = JS_CORR_NONE;
436 joydev->abs[i] = dev->abs[j];
437 continue;
438 }
439 joydev->corr[i].type = JS_CORR_BROKEN;
440 joydev->corr[i].prec = dev->absfuzz[j];
441 joydev->corr[i].coef[0] = (dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j];
442 joydev->corr[i].coef[1] = (dev->absmax[j] + dev->absmin[j]) / 2 + dev->absflat[j];
443 if (!(t = ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j])))
444 continue;
445 joydev->corr[i].coef[2] = (1 << 29) / t;
446 joydev->corr[i].coef[3] = (1 << 29) / t;
447
448 joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
449 }
450
451 joydev_table[minor] = joydev;
452
453 devfs_mk_cdev(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
454 S_IFCHR|S_IRUGO|S_IWUSR, "input/js%d", minor);
455 class_simple_device_add(input_class,
456 MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
457 dev->dev, "js%d", minor);
458
459 return &joydev->handle;
460}
461
462static void joydev_disconnect(struct input_handle *handle)
463{
464 struct joydev *joydev = handle->private;
465 struct joydev_list *list;
466
467 class_simple_device_remove(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
468 devfs_remove("input/js%d", joydev->minor);
469 joydev->exist = 0;
470
471 if (joydev->open) {
472 input_close_device(handle);
473 wake_up_interruptible(&joydev->wait);
474 list_for_each_entry(list, &joydev->list, node)
475 kill_fasync(&list->fasync, SIGIO, POLL_HUP);
476 } else
477 joydev_free(joydev);
478}
479
480static struct input_device_id joydev_blacklist[] = {
481 {
482 .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
483 .evbit = { BIT(EV_KEY) },
484 .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
485 }, /* Avoid itouchpads, touchscreens and tablets */
486 { }, /* Terminating entry */
487};
488
489static struct input_device_id joydev_ids[] = {
490 {
491 .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
492 .evbit = { BIT(EV_ABS) },
493 .absbit = { BIT(ABS_X) },
494 },
495 {
496 .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
497 .evbit = { BIT(EV_ABS) },
498 .absbit = { BIT(ABS_WHEEL) },
499 },
500 {
501 .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
502 .evbit = { BIT(EV_ABS) },
503 .absbit = { BIT(ABS_THROTTLE) },
504 },
505 { }, /* Terminating entry */
506};
507
508MODULE_DEVICE_TABLE(input, joydev_ids);
509
510static struct input_handler joydev_handler = {
511 .event = joydev_event,
512 .connect = joydev_connect,
513 .disconnect = joydev_disconnect,
514 .fops = &joydev_fops,
515 .minor = JOYDEV_MINOR_BASE,
516 .name = "joydev",
517 .id_table = joydev_ids,
518 .blacklist = joydev_blacklist,
519};
520
521static int __init joydev_init(void)
522{
523 input_register_handler(&joydev_handler);
524 return 0;
525}
526
527static void __exit joydev_exit(void)
528{
529 input_unregister_handler(&joydev_handler);
530}
531
532module_init(joydev_init);
533module_exit(joydev_exit);
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
new file mode 100644
index 000000000000..67519ef0ef95
--- /dev/null
+++ b/drivers/input/joystick/Kconfig
@@ -0,0 +1,256 @@
1#
2# Joystick driver configuration
3#
4menuconfig INPUT_JOYSTICK
5 bool "Joysticks"
6 help
7 If you have a joystick, 6dof controller, gamepad, steering wheel,
8 weapon control system or something like that you can say Y here
9 and the list of supported devices will be displayed. This option
10 doesn't affect the kernel.
11
12 Please read the file <file:Documentation/input/joystick.txt> which
13 contains more information.
14
15if INPUT_JOYSTICK
16
17config JOYSTICK_ANALOG
18 tristate "Classic PC analog joysticks and gamepads"
19 select GAMEPORT
20 ---help---
21 Say Y here if you have a joystick that connects to the PC
22 gameport. In addition to the usual PC analog joystick, this driver
23 supports many extensions, including joysticks with throttle control,
24 with rudders, additional hats and buttons compatible with CH
25 Flightstick Pro, ThrustMaster FCS, 6 and 8 button gamepads, or
26 Saitek Cyborg joysticks.
27
28 Please read the file <file:Documentation/input/joystick.txt> which
29 contains more information.
30
31 To compile this driver as a module, choose M here: the
32 module will be called analog.
33
34config JOYSTICK_A3D
35 tristate "Assasin 3D and MadCatz Panther devices"
36 select GAMEPORT
37 help
38 Say Y here if you have an FPGaming or MadCatz controller using the
39 A3D protocol over the PC gameport.
40
41 To compile this driver as a module, choose M here: the
42 module will be called a3d.
43
44config JOYSTICK_ADI
45 tristate "Logitech ADI digital joysticks and gamepads"
46 select GAMEPORT
47 help
48 Say Y here if you have a Logitech controller using the ADI
49 protocol over the PC gameport.
50
51 To compile this driver as a module, choose M here: the
52 module will be called adi.
53
54config JOYSTICK_COBRA
55 tristate "Creative Labs Blaster Cobra gamepad"
56 select GAMEPORT
57 help
58 Say Y here if you have a Creative Labs Blaster Cobra gamepad.
59
60 To compile this driver as a module, choose M here: the
61 module will be called cobra.
62
63config JOYSTICK_GF2K
64 tristate "Genius Flight2000 Digital joysticks and gamepads"
65 select GAMEPORT
66 help
67 Say Y here if you have a Genius Flight2000 or MaxFighter digitally
68 communicating joystick or gamepad.
69
70 To compile this driver as a module, choose M here: the
71 module will be called gf2k.
72
73config JOYSTICK_GRIP
74 tristate "Gravis GrIP joysticks and gamepads"
75 select GAMEPORT
76 help
77 Say Y here if you have a Gravis controller using the GrIP protocol
78 over the PC gameport.
79
80 To compile this driver as a module, choose M here: the
81 module will be called grip.
82
83config JOYSTICK_GRIP_MP
84 tristate "Gravis GrIP MultiPort"
85 select GAMEPORT
86 help
87 Say Y here if you have the original Gravis GrIP MultiPort, a hub
88 that connects to the gameport and you connect gamepads to it.
89
90 To compile this driver as a module, choose M here: the
91 module will be called grip_mp.
92
93config JOYSTICK_GUILLEMOT
94 tristate "Guillemot joysticks and gamepads"
95 select GAMEPORT
96 help
97 Say Y here if you have a Guillemot joystick using a digital
98 protocol over the PC gameport.
99
100 To compile this driver as a module, choose M here: the
101 module will be called guillemot.
102
103config JOYSTICK_INTERACT
104 tristate "InterAct digital joysticks and gamepads"
105 select GAMEPORT
106 help
107 Say Y here if you have an InterAct gameport or joystick
108 communicating digitally over the gameport.
109
110 To compile this driver as a module, choose M here: the
111 module will be called interact.
112
113config JOYSTICK_SIDEWINDER
114 tristate "Microsoft SideWinder digital joysticks and gamepads"
115 select GAMEPORT
116 help
117 Say Y here if you have a Microsoft controller using the Digital
118 Overdrive protocol over PC gameport.
119
120 To compile this driver as a module, choose M here: the
121 module will be called sidewinder.
122
123config JOYSTICK_TMDC
124 tristate "ThrustMaster DirectConnect joysticks and gamepads"
125 select GAMEPORT
126 help
127 Say Y here if you have a ThrustMaster controller using the
128 DirectConnect (BSP) protocol over the PC gameport.
129
130 To compile this driver as a module, choose M here: the
131 module will be called tmdc.
132
133source "drivers/input/joystick/iforce/Kconfig"
134
135config JOYSTICK_WARRIOR
136 tristate "Logitech WingMan Warrior joystick"
137 select SERIO
138 help
139 Say Y here if you have a Logitech WingMan Warrior joystick connected
140 to your computer's serial port.
141
142 To compile this driver as a module, choose M here: the
143 module will be called warrior.
144
145config JOYSTICK_MAGELLAN
146 tristate "LogiCad3d Magellan/SpaceMouse 6dof controllers"
147 select SERIO
148 help
149 Say Y here if you have a Magellan or Space Mouse 6DOF controller
150 connected to your computer's serial port.
151
152 To compile this driver as a module, choose M here: the
153 module will be called magellan.
154
155config JOYSTICK_SPACEORB
156 tristate "SpaceTec SpaceOrb/Avenger 6dof controllers"
157 select SERIO
158 help
159 Say Y here if you have a SpaceOrb 360 or SpaceBall Avenger 6DOF
160 controller connected to your computer's serial port.
161
162 To compile this driver as a module, choose M here: the
163 module will be called spaceorb.
164
165config JOYSTICK_SPACEBALL
166 tristate "SpaceTec SpaceBall 6dof controllers"
167 select SERIO
168 help
169 Say Y here if you have a SpaceTec SpaceBall 2003/3003/4000 FLX
170 controller connected to your computer's serial port. For the
171 SpaceBall 4000 USB model, use the USB HID driver.
172
173 To compile this driver as a module, choose M here: the
174 module will be called spaceball.
175
176config JOYSTICK_STINGER
177 tristate "Gravis Stinger gamepad"
178 select SERIO
179 help
180 Say Y here if you have a Gravis Stinger connected to one of your
181 serial ports.
182
183 To compile this driver as a module, choose M here: the
184 module will be called stinger.
185
186config JOYSTICK_TWIDJOY
187 tristate "Twiddler as a joystick"
188 select SERIO
189 help
190 Say Y here if you have a Handykey Twiddler connected to your
191 computer's serial port and want to use it as a joystick.
192
193 To compile this driver as a module, choose M here: the
194 module will be called twidjoy.
195
196config JOYSTICK_DB9
197 tristate "Multisystem, Sega Genesis, Saturn joysticks and gamepads"
198 depends on PARPORT
199 ---help---
200 Say Y here if you have a Sega Master System gamepad, Sega Genesis
201 gamepad, Sega Saturn gamepad, or a Multisystem -- Atari, Amiga,
202 Commodore, Amstrad CPC joystick connected to your parallel port.
203 For more information on how to use the driver please read
204 <file:Documentation/input/joystick-parport.txt>.
205
206 To compile this driver as a module, choose M here: the
207 module will be called db9.
208
209config JOYSTICK_GAMECON
210 tristate "Multisystem, NES, SNES, N64, PSX joysticks and gamepads"
211 depends on PARPORT
212 ---help---
213 Say Y here if you have a Nintendo Entertainment System gamepad,
214 Super Nintendo Entertainment System gamepad, Nintendo 64 gamepad,
215 Sony PlayStation gamepad or a Multisystem -- Atari, Amiga,
216 Commodore, Amstrad CPC joystick connected to your parallel port.
217 For more information on how to use the driver please read
218 <file:Documentation/input/joystick-parport.txt>.
219
220 To compile this driver as a module, choose M here: the
221 module will be called gamecon.
222
223config JOYSTICK_TURBOGRAFX
224 tristate "Multisystem joysticks via TurboGraFX device"
225 depends on PARPORT
226 help
227 Say Y here if you have the TurboGraFX interface by Steffen Schwenke,
228 and want to use it with Multisystem -- Atari, Amiga, Commodore,
229 Amstrad CPC joystick. For more information on how to use the driver
230 please read <file:Documentation/input/joystick-parport.txt>.
231
232 To compile this driver as a module, choose M here: the
233 module will be called turbografx.
234
235config JOYSTICK_AMIGA
236 tristate "Amiga joysticks"
237 depends on AMIGA
238 help
239 Say Y here if you have an Amiga with a digital joystick connected
240 to it.
241
242 To compile this driver as a module, choose M here: the
243 module will be called amijoy.
244
245config JOYSTICK_JOYDUMP
246 tristate "Gameport data dumper"
247 select GAMEPORT
248 help
249 Say Y here if you want to dump data from your joystick into the system
250 log for debugging purposes. Say N if you are making a production
251 configuration or aren't sure.
252
253 To compile this driver as a module, choose M here: the
254 module will be called joydump.
255
256endif
diff --git a/drivers/input/joystick/Makefile b/drivers/input/joystick/Makefile
new file mode 100644
index 000000000000..5231f6ff75b8
--- /dev/null
+++ b/drivers/input/joystick/Makefile
@@ -0,0 +1,30 @@
1#
2# Makefile for the input core drivers.
3#
4
5# Each configuration option enables a list of files.
6
7obj-$(CONFIG_JOYSTICK_A3D) += a3d.o
8obj-$(CONFIG_JOYSTICK_ADI) += adi.o
9obj-$(CONFIG_JOYSTICK_AMIGA) += amijoy.o
10obj-$(CONFIG_JOYSTICK_ANALOG) += analog.o
11obj-$(CONFIG_JOYSTICK_COBRA) += cobra.o
12obj-$(CONFIG_JOYSTICK_DB9) += db9.o
13obj-$(CONFIG_JOYSTICK_GAMECON) += gamecon.o
14obj-$(CONFIG_JOYSTICK_GF2K) += gf2k.o
15obj-$(CONFIG_JOYSTICK_GRIP) += grip.o
16obj-$(CONFIG_JOYSTICK_GRIP_MP) += grip_mp.o
17obj-$(CONFIG_JOYSTICK_GUILLEMOT) += guillemot.o
18obj-$(CONFIG_JOYSTICK_INTERACT) += interact.o
19obj-$(CONFIG_JOYSTICK_JOYDUMP) += joydump.o
20obj-$(CONFIG_JOYSTICK_MAGELLAN) += magellan.o
21obj-$(CONFIG_JOYSTICK_SIDEWINDER) += sidewinder.o
22obj-$(CONFIG_JOYSTICK_SPACEBALL) += spaceball.o
23obj-$(CONFIG_JOYSTICK_SPACEORB) += spaceorb.o
24obj-$(CONFIG_JOYSTICK_STINGER) += stinger.o
25obj-$(CONFIG_JOYSTICK_TMDC) += tmdc.o
26obj-$(CONFIG_JOYSTICK_TURBOGRAFX) += turbografx.o
27obj-$(CONFIG_JOYSTICK_TWIDJOY) += twidjoy.o
28obj-$(CONFIG_JOYSTICK_WARRIOR) += warrior.o
29
30obj-$(CONFIG_JOYSTICK_IFORCE) += iforce/
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
new file mode 100644
index 000000000000..ad39fe4bf35f
--- /dev/null
+++ b/drivers/input/joystick/a3d.c
@@ -0,0 +1,417 @@
1/*
2 * $Id: a3d.c,v 1.21 2002/01/22 20:11:50 vojtech Exp $
3 *
4 * Copyright (c) 1998-2001 Vojtech Pavlik
5 */
6
7/*
8 * FP-Gaming Assasin 3D joystick driver for Linux
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/kernel.h>
32#include <linux/module.h>
33#include <linux/slab.h>
34#include <linux/init.h>
35#include <linux/gameport.h>
36#include <linux/input.h>
37
38#define DRIVER_DESC "FP-Gaming Assasin 3D joystick driver"
39
40MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
41MODULE_DESCRIPTION(DRIVER_DESC);
42MODULE_LICENSE("GPL");
43
44#define A3D_MAX_START 600 /* 600 us */
45#define A3D_MAX_STROBE 80 /* 80 us */
46#define A3D_MAX_LENGTH 40 /* 40*3 bits */
47
48#define A3D_MODE_A3D 1 /* Assassin 3D */
49#define A3D_MODE_PAN 2 /* Panther */
50#define A3D_MODE_OEM 3 /* Panther OEM version */
51#define A3D_MODE_PXL 4 /* Panther XL */
52
53static char *a3d_names[] = { NULL, "FP-Gaming Assassin 3D", "MadCatz Panther", "OEM Panther",
54 "MadCatz Panther XL", "MadCatz Panther XL w/ rudder" };
55
56struct a3d {
57 struct gameport *gameport;
58 struct gameport *adc;
59 struct input_dev dev;
60 int axes[4];
61 int buttons;
62 int mode;
63 int length;
64 int reads;
65 int bads;
66 char phys[32];
67};
68
69/*
70 * a3d_read_packet() reads an Assassin 3D packet.
71 */
72
73static int a3d_read_packet(struct gameport *gameport, int length, char *data)
74{
75 unsigned long flags;
76 unsigned char u, v;
77 unsigned int t, s;
78 int i;
79
80 i = 0;
81 t = gameport_time(gameport, A3D_MAX_START);
82 s = gameport_time(gameport, A3D_MAX_STROBE);
83
84 local_irq_save(flags);
85 gameport_trigger(gameport);
86 v = gameport_read(gameport);
87
88 while (t > 0 && i < length) {
89 t--;
90 u = v; v = gameport_read(gameport);
91 if (~v & u & 0x10) {
92 data[i++] = v >> 5;
93 t = s;
94 }
95 }
96
97 local_irq_restore(flags);
98
99 return i;
100}
101
102/*
103 * a3d_csum() computes checksum of triplet packet
104 */
105
106static int a3d_csum(char *data, int count)
107{
108 int i, csum = 0;
109
110 for (i = 0; i < count - 2; i++)
111 csum += data[i];
112 return (csum & 0x3f) != ((data[count - 2] << 3) | data[count - 1]);
113}
114
115static void a3d_read(struct a3d *a3d, unsigned char *data)
116{
117 struct input_dev *dev = &a3d->dev;
118
119 switch (a3d->mode) {
120
121 case A3D_MODE_A3D:
122 case A3D_MODE_OEM:
123 case A3D_MODE_PAN:
124
125 input_report_rel(dev, REL_X, ((data[5] << 6) | (data[6] << 3) | data[ 7]) - ((data[5] & 4) << 7));
126 input_report_rel(dev, REL_Y, ((data[8] << 6) | (data[9] << 3) | data[10]) - ((data[8] & 4) << 7));
127
128 input_report_key(dev, BTN_RIGHT, data[2] & 1);
129 input_report_key(dev, BTN_LEFT, data[3] & 2);
130 input_report_key(dev, BTN_MIDDLE, data[3] & 4);
131
132 input_sync(dev);
133
134 a3d->axes[0] = ((signed char)((data[11] << 6) | (data[12] << 3) | (data[13]))) + 128;
135 a3d->axes[1] = ((signed char)((data[14] << 6) | (data[15] << 3) | (data[16]))) + 128;
136 a3d->axes[2] = ((signed char)((data[17] << 6) | (data[18] << 3) | (data[19]))) + 128;
137 a3d->axes[3] = ((signed char)((data[20] << 6) | (data[21] << 3) | (data[22]))) + 128;
138
139 a3d->buttons = ((data[3] << 3) | data[4]) & 0xf;
140
141 break;
142
143 case A3D_MODE_PXL:
144
145 input_report_rel(dev, REL_X, ((data[ 9] << 6) | (data[10] << 3) | data[11]) - ((data[ 9] & 4) << 7));
146 input_report_rel(dev, REL_Y, ((data[12] << 6) | (data[13] << 3) | data[14]) - ((data[12] & 4) << 7));
147
148 input_report_key(dev, BTN_RIGHT, data[2] & 1);
149 input_report_key(dev, BTN_LEFT, data[3] & 2);
150 input_report_key(dev, BTN_MIDDLE, data[3] & 4);
151 input_report_key(dev, BTN_SIDE, data[7] & 2);
152 input_report_key(dev, BTN_EXTRA, data[7] & 4);
153
154 input_report_abs(dev, ABS_X, ((signed char)((data[15] << 6) | (data[16] << 3) | (data[17]))) + 128);
155 input_report_abs(dev, ABS_Y, ((signed char)((data[18] << 6) | (data[19] << 3) | (data[20]))) + 128);
156 input_report_abs(dev, ABS_RUDDER, ((signed char)((data[21] << 6) | (data[22] << 3) | (data[23]))) + 128);
157 input_report_abs(dev, ABS_THROTTLE, ((signed char)((data[24] << 6) | (data[25] << 3) | (data[26]))) + 128);
158
159 input_report_abs(dev, ABS_HAT0X, ( data[5] & 1) - ((data[5] >> 2) & 1));
160 input_report_abs(dev, ABS_HAT0Y, ((data[5] >> 1) & 1) - ((data[6] >> 2) & 1));
161 input_report_abs(dev, ABS_HAT1X, ((data[4] >> 1) & 1) - ( data[3] & 1));
162 input_report_abs(dev, ABS_HAT1Y, ((data[4] >> 2) & 1) - ( data[4] & 1));
163
164 input_report_key(dev, BTN_TRIGGER, data[8] & 1);
165 input_report_key(dev, BTN_THUMB, data[8] & 2);
166 input_report_key(dev, BTN_TOP, data[8] & 4);
167 input_report_key(dev, BTN_PINKIE, data[7] & 1);
168
169 input_sync(dev);
170
171 break;
172 }
173}
174
175
176/*
177 * a3d_poll() reads and analyzes A3D joystick data.
178 */
179
180static void a3d_poll(struct gameport *gameport)
181{
182 struct a3d *a3d = gameport_get_drvdata(gameport);
183 unsigned char data[A3D_MAX_LENGTH];
184
185 a3d->reads++;
186 if (a3d_read_packet(a3d->gameport, a3d->length, data) != a3d->length ||
187 data[0] != a3d->mode || a3d_csum(data, a3d->length))
188 a3d->bads++;
189 else
190 a3d_read(a3d, data);
191}
192
193/*
194 * a3d_adc_cooked_read() copies the acis and button data to the
195 * callers arrays. It could do the read itself, but the caller could
196 * call this more than 50 times a second, which would use too much CPU.
197 */
198
199static int a3d_adc_cooked_read(struct gameport *gameport, int *axes, int *buttons)
200{
201 struct a3d *a3d = gameport->port_data;
202 int i;
203
204 for (i = 0; i < 4; i++)
205 axes[i] = (a3d->axes[i] < 254) ? a3d->axes[i] : -1;
206 *buttons = a3d->buttons;
207 return 0;
208}
209
210/*
211 * a3d_adc_open() is the gameport open routine. It refuses to serve
212 * any but cooked data.
213 */
214
215static int a3d_adc_open(struct gameport *gameport, int mode)
216{
217 struct a3d *a3d = gameport->port_data;
218
219 if (mode != GAMEPORT_MODE_COOKED)
220 return -1;
221
222 gameport_start_polling(a3d->gameport);
223 return 0;
224}
225
226/*
227 * a3d_adc_close() is a callback from the input close routine.
228 */
229
230static void a3d_adc_close(struct gameport *gameport)
231{
232 struct a3d *a3d = gameport->port_data;
233
234 gameport_stop_polling(a3d->gameport);
235}
236
237/*
238 * a3d_open() is a callback from the input open routine.
239 */
240
241static int a3d_open(struct input_dev *dev)
242{
243 struct a3d *a3d = dev->private;
244
245 gameport_start_polling(a3d->gameport);
246 return 0;
247}
248
249/*
250 * a3d_close() is a callback from the input close routine.
251 */
252
253static void a3d_close(struct input_dev *dev)
254{
255 struct a3d *a3d = dev->private;
256
257 gameport_stop_polling(a3d->gameport);
258}
259
260/*
261 * a3d_connect() probes for A3D joysticks.
262 */
263
264static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
265{
266 struct a3d *a3d;
267 struct gameport *adc;
268 unsigned char data[A3D_MAX_LENGTH];
269 int i;
270 int err;
271
272 if (!(a3d = kcalloc(1, sizeof(struct a3d), GFP_KERNEL)))
273 return -ENOMEM;
274
275 a3d->gameport = gameport;
276
277 gameport_set_drvdata(gameport, a3d);
278
279 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
280 if (err)
281 goto fail1;
282
283 i = a3d_read_packet(gameport, A3D_MAX_LENGTH, data);
284
285 if (!i || a3d_csum(data, i)) {
286 err = -ENODEV;
287 goto fail2;
288 }
289
290 a3d->mode = data[0];
291
292 if (!a3d->mode || a3d->mode > 5) {
293 printk(KERN_WARNING "a3d.c: Unknown A3D device detected "
294 "(%s, id=%d), contact <vojtech@ucw.cz>\n", gameport->phys, a3d->mode);
295 err = -ENODEV;
296 goto fail2;
297 }
298
299 gameport_set_poll_handler(gameport, a3d_poll);
300 gameport_set_poll_interval(gameport, 20);
301
302 sprintf(a3d->phys, "%s/input0", gameport->phys);
303
304 if (a3d->mode == A3D_MODE_PXL) {
305
306 int axes[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER };
307
308 a3d->length = 33;
309
310 init_input_dev(&a3d->dev);
311
312 a3d->dev.evbit[0] |= BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
313 a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y);
314 a3d->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_RUDDER)
315 | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y) | BIT(ABS_HAT1X) | BIT(ABS_HAT1Y);
316
317 a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE)
318 | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
319
320 a3d->dev.keybit[LONG(BTN_JOYSTICK)] |= BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_PINKIE);
321
322 a3d_read(a3d, data);
323
324 for (i = 0; i < 4; i++) {
325 if (i < 2)
326 input_set_abs_params(&a3d->dev, axes[i], 48, a3d->dev.abs[axes[i]] * 2 - 48, 0, 8);
327 else
328 input_set_abs_params(&a3d->dev, axes[i], 2, 253, 0, 0);
329 input_set_abs_params(&a3d->dev, ABS_HAT0X + i, -1, 1, 0, 0);
330 }
331
332 } else {
333 a3d->length = 29;
334
335 init_input_dev(&a3d->dev);
336
337 a3d->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_REL);
338 a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y);
339 a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE);
340
341 a3d_read(a3d, data);
342
343 if (!(a3d->adc = adc = gameport_allocate_port()))
344 printk(KERN_ERR "a3d: Not enough memory for ADC port\n");
345 else {
346 adc->port_data = a3d;
347 adc->open = a3d_adc_open;
348 adc->close = a3d_adc_close;
349 adc->cooked_read = a3d_adc_cooked_read;
350 adc->fuzz = 1;
351
352 gameport_set_name(adc, a3d_names[a3d->mode]);
353 gameport_set_phys(adc, "%s/gameport0", gameport->phys);
354 adc->dev.parent = &gameport->dev;
355
356 gameport_register_port(adc);
357 }
358 }
359
360 a3d->dev.private = a3d;
361 a3d->dev.open = a3d_open;
362 a3d->dev.close = a3d_close;
363
364 a3d->dev.name = a3d_names[a3d->mode];
365 a3d->dev.phys = a3d->phys;
366 a3d->dev.id.bustype = BUS_GAMEPORT;
367 a3d->dev.id.vendor = GAMEPORT_ID_VENDOR_MADCATZ;
368 a3d->dev.id.product = a3d->mode;
369 a3d->dev.id.version = 0x0100;
370
371 input_register_device(&a3d->dev);
372 printk(KERN_INFO "input: %s on %s\n", a3d_names[a3d->mode], a3d->phys);
373
374 return 0;
375
376fail2: gameport_close(gameport);
377fail1: gameport_set_drvdata(gameport, NULL);
378 kfree(a3d);
379 return err;
380}
381
382static void a3d_disconnect(struct gameport *gameport)
383{
384 struct a3d *a3d = gameport_get_drvdata(gameport);
385
386 input_unregister_device(&a3d->dev);
387 if (a3d->adc) {
388 gameport_unregister_port(a3d->adc);
389 a3d->adc = NULL;
390 }
391 gameport_close(gameport);
392 gameport_set_drvdata(gameport, NULL);
393 kfree(a3d);
394}
395
396static struct gameport_driver a3d_drv = {
397 .driver = {
398 .name = "adc",
399 },
400 .description = DRIVER_DESC,
401 .connect = a3d_connect,
402 .disconnect = a3d_disconnect,
403};
404
405static int __init a3d_init(void)
406{
407 gameport_register_driver(&a3d_drv);
408 return 0;
409}
410
411static void __exit a3d_exit(void)
412{
413 gameport_unregister_driver(&a3d_drv);
414}
415
416module_init(a3d_init);
417module_exit(a3d_exit);
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c
new file mode 100644
index 000000000000..83f6dafc1716
--- /dev/null
+++ b/drivers/input/joystick/adi.c
@@ -0,0 +1,560 @@
1/*
2 * Copyright (c) 1998-2005 Vojtech Pavlik
3 */
4
5/*
6 * Logitech ADI joystick family driver for Linux
7 */
8
9/*
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * Should you need to contact me, the author, you can do so either by
25 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
26 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
27 */
28
29#include <linux/delay.h>
30#include <linux/kernel.h>
31#include <linux/module.h>
32#include <linux/string.h>
33#include <linux/slab.h>
34#include <linux/input.h>
35#include <linux/gameport.h>
36#include <linux/init.h>
37
38#define DRIVER_DESC "Logitech ADI joystick family driver"
39
40MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
41MODULE_DESCRIPTION(DRIVER_DESC);
42MODULE_LICENSE("GPL");
43
44/*
45 * Times, array sizes, flags, ids.
46 */
47
48#define ADI_MAX_START 200 /* Trigger to packet timeout [200us] */
49#define ADI_MAX_STROBE 40 /* Single bit timeout [40us] */
50#define ADI_INIT_DELAY 10 /* Delay after init packet [10ms] */
51#define ADI_DATA_DELAY 4 /* Delay after data packet [4ms] */
52
53#define ADI_MAX_LENGTH 256
54#define ADI_MIN_LENGTH 8
55#define ADI_MIN_LEN_LENGTH 10
56#define ADI_MIN_ID_LENGTH 66
57#define ADI_MAX_NAME_LENGTH 48
58#define ADI_MAX_CNAME_LENGTH 16
59#define ADI_MAX_PHYS_LENGTH 64
60
61#define ADI_FLAG_HAT 0x04
62#define ADI_FLAG_10BIT 0x08
63
64#define ADI_ID_TPD 0x01
65#define ADI_ID_WGP 0x06
66#define ADI_ID_WGPE 0x08
67#define ADI_ID_MAX 0x0a
68
69/*
70 * Names, buttons, axes ...
71 */
72
73static char *adi_names[] = { "WingMan Extreme Digital", "ThunderPad Digital", "SideCar", "CyberMan 2",
74 "WingMan Interceptor", "WingMan Formula", "WingMan GamePad",
75 "WingMan Extreme Digital 3D", "WingMan GamePad Extreme",
76 "WingMan GamePad USB", "Unknown Device %#x" };
77
78static char adi_wmgpe_abs[] = { ABS_X, ABS_Y, ABS_HAT0X, ABS_HAT0Y };
79static char adi_wmi_abs[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y };
80static char adi_wmed3d_abs[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RZ, ABS_HAT0X, ABS_HAT0Y };
81static char adi_cm2_abs[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
82static char adi_wmf_abs[] = { ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y };
83
84static short adi_wmgpe_key[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT };
85static short adi_wmi_key[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_EXTRA };
86static short adi_wmed3d_key[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2 };
87static short adi_cm2_key[] = { BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 };
88
89static char* adi_abs[] = { adi_wmi_abs, adi_wmgpe_abs, adi_wmf_abs, adi_cm2_abs, adi_wmi_abs, adi_wmf_abs,
90 adi_wmgpe_abs, adi_wmed3d_abs, adi_wmgpe_abs, adi_wmgpe_abs, adi_wmi_abs };
91
92static short* adi_key[] = { adi_wmi_key, adi_wmgpe_key, adi_cm2_key, adi_cm2_key, adi_wmi_key, adi_cm2_key,
93 adi_wmgpe_key, adi_wmed3d_key, adi_wmgpe_key, adi_wmgpe_key, adi_wmi_key };
94
95/*
96 * Hat to axis conversion arrays.
97 */
98
99static struct {
100 int x;
101 int y;
102} adi_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
103
104/*
105 * Per-port information.
106 */
107
108struct adi {
109 struct input_dev dev;
110 int length;
111 int ret;
112 int idx;
113 unsigned char id;
114 char buttons;
115 char axes10;
116 char axes8;
117 signed char pad;
118 char hats;
119 char *abs;
120 short *key;
121 char name[ADI_MAX_NAME_LENGTH];
122 char cname[ADI_MAX_CNAME_LENGTH];
123 char phys[ADI_MAX_PHYS_LENGTH];
124 unsigned char data[ADI_MAX_LENGTH];
125};
126
127struct adi_port {
128 struct gameport *gameport;
129 struct adi adi[2];
130 int bad;
131 int reads;
132};
133
134/*
135 * adi_read_packet() reads a Logitech ADI packet.
136 */
137
138static void adi_read_packet(struct adi_port *port)
139{
140 struct adi *adi = port->adi;
141 struct gameport *gameport = port->gameport;
142 unsigned char u, v, w, x, z;
143 int t[2], s[2], i;
144 unsigned long flags;
145
146 for (i = 0; i < 2; i++) {
147 adi[i].ret = -1;
148 t[i] = gameport_time(gameport, ADI_MAX_START);
149 s[i] = 0;
150 }
151
152 local_irq_save(flags);
153
154 gameport_trigger(gameport);
155 v = z = gameport_read(gameport);
156
157 do {
158 u = v;
159 w = u ^ (v = x = gameport_read(gameport));
160 for (i = 0; i < 2; i++, w >>= 2, x >>= 2) {
161 t[i]--;
162 if ((w & 0x30) && s[i]) {
163 if ((w & 0x30) < 0x30 && adi[i].ret < ADI_MAX_LENGTH && t[i] > 0) {
164 adi[i].data[++adi[i].ret] = w;
165 t[i] = gameport_time(gameport, ADI_MAX_STROBE);
166 } else t[i] = 0;
167 } else if (!(x & 0x30)) s[i] = 1;
168 }
169 } while (t[0] > 0 || t[1] > 0);
170
171 local_irq_restore(flags);
172
173 return;
174}
175
176/*
177 * adi_move_bits() detects a possible 2-stream mode, and moves
178 * the bits accordingly.
179 */
180
181static void adi_move_bits(struct adi_port *port, int length)
182{
183 int i;
184 struct adi *adi = port->adi;
185
186 adi[0].idx = adi[1].idx = 0;
187
188 if (adi[0].ret <= 0 || adi[1].ret <= 0) return;
189 if (adi[0].data[0] & 0x20 || ~adi[1].data[0] & 0x20) return;
190
191 for (i = 1; i <= adi[1].ret; i++)
192 adi[0].data[((length - 1) >> 1) + i + 1] = adi[1].data[i];
193
194 adi[0].ret += adi[1].ret;
195 adi[1].ret = -1;
196}
197
198/*
199 * adi_get_bits() gathers bits from the data packet.
200 */
201
202static inline int adi_get_bits(struct adi *adi, int count)
203{
204 int bits = 0;
205 int i;
206 if ((adi->idx += count) > adi->ret) return 0;
207 for (i = 0; i < count; i++)
208 bits |= ((adi->data[adi->idx - i] >> 5) & 1) << i;
209 return bits;
210}
211
212/*
213 * adi_decode() decodes Logitech joystick data into input events.
214 */
215
216static int adi_decode(struct adi *adi)
217{
218 struct input_dev *dev = &adi->dev;
219 char *abs = adi->abs;
220 short *key = adi->key;
221 int i, t;
222
223 if (adi->ret < adi->length || adi->id != (adi_get_bits(adi, 4) | (adi_get_bits(adi, 4) << 4)))
224 return -1;
225
226 for (i = 0; i < adi->axes10; i++)
227 input_report_abs(dev, *abs++, adi_get_bits(adi, 10));
228
229 for (i = 0; i < adi->axes8; i++)
230 input_report_abs(dev, *abs++, adi_get_bits(adi, 8));
231
232 for (i = 0; i < adi->buttons && i < 63; i++) {
233 if (i == adi->pad) {
234 t = adi_get_bits(adi, 4);
235 input_report_abs(dev, *abs++, ((t >> 2) & 1) - ( t & 1));
236 input_report_abs(dev, *abs++, ((t >> 1) & 1) - ((t >> 3) & 1));
237 }
238 input_report_key(dev, *key++, adi_get_bits(adi, 1));
239 }
240
241 for (i = 0; i < adi->hats; i++) {
242 if ((t = adi_get_bits(adi, 4)) > 8) t = 0;
243 input_report_abs(dev, *abs++, adi_hat_to_axis[t].x);
244 input_report_abs(dev, *abs++, adi_hat_to_axis[t].y);
245 }
246
247 for (i = 63; i < adi->buttons; i++)
248 input_report_key(dev, *key++, adi_get_bits(adi, 1));
249
250 input_sync(dev);
251
252 return 0;
253}
254
255/*
256 * adi_read() reads the data packet and decodes it.
257 */
258
259static int adi_read(struct adi_port *port)
260{
261 int i;
262 int result = 0;
263
264 adi_read_packet(port);
265 adi_move_bits(port, port->adi[0].length);
266
267 for (i = 0; i < 2; i++)
268 if (port->adi[i].length)
269 result |= adi_decode(port->adi + i);
270
271 return result;
272}
273
274/*
275 * adi_poll() repeatedly polls the Logitech joysticks.
276 */
277
278static void adi_poll(struct gameport *gameport)
279{
280 struct adi_port *port = gameport_get_drvdata(gameport);
281
282 port->bad -= adi_read(port);
283 port->reads++;
284}
285
286/*
287 * adi_open() is a callback from the input open routine.
288 */
289
290static int adi_open(struct input_dev *dev)
291{
292 struct adi_port *port = dev->private;
293
294 gameport_start_polling(port->gameport);
295 return 0;
296}
297
298/*
299 * adi_close() is a callback from the input close routine.
300 */
301
302static void adi_close(struct input_dev *dev)
303{
304 struct adi_port *port = dev->private;
305
306 gameport_stop_polling(port->gameport);
307}
308
309/*
310 * adi_init_digital() sends a trigger & delay sequence
311 * to reset and initialize a Logitech joystick into digital mode.
312 */
313
314static void adi_init_digital(struct gameport *gameport)
315{
316 int seq[] = { 4, -2, -3, 10, -6, -11, -7, -9, 11, 0 };
317 int i;
318
319 for (i = 0; seq[i]; i++) {
320 gameport_trigger(gameport);
321 if (seq[i] > 0) msleep(seq[i]);
322 if (seq[i] < 0) {
323 mdelay(-seq[i]);
324 udelay(-seq[i]*14); /* It looks like mdelay() is off by approx 1.4% */
325 }
326 }
327}
328
329static void adi_id_decode(struct adi *adi, struct adi_port *port)
330{
331 int i, t;
332
333 if (adi->ret < ADI_MIN_ID_LENGTH) /* Minimum ID packet length */
334 return;
335
336 if (adi->ret < (t = adi_get_bits(adi, 10))) {
337 printk(KERN_WARNING "adi: Short ID packet: reported: %d != read: %d\n", t, adi->ret);
338 return;
339 }
340
341 adi->id = adi_get_bits(adi, 4) | (adi_get_bits(adi, 4) << 4);
342
343 if ((t = adi_get_bits(adi, 4)) & ADI_FLAG_HAT) adi->hats++;
344
345 adi->length = adi_get_bits(adi, 10);
346
347 if (adi->length >= ADI_MAX_LENGTH || adi->length < ADI_MIN_LENGTH) {
348 printk(KERN_WARNING "adi: Bad data packet length (%d).\n", adi->length);
349 adi->length = 0;
350 return;
351 }
352
353 adi->axes8 = adi_get_bits(adi, 4);
354 adi->buttons = adi_get_bits(adi, 6);
355
356 if (adi_get_bits(adi, 6) != 8 && adi->hats) {
357 printk(KERN_WARNING "adi: Other than 8-dir POVs not supported yet.\n");
358 adi->length = 0;
359 return;
360 }
361
362 adi->buttons += adi_get_bits(adi, 6);
363 adi->hats += adi_get_bits(adi, 4);
364
365 i = adi_get_bits(adi, 4);
366
367 if (t & ADI_FLAG_10BIT) {
368 adi->axes10 = adi->axes8 - i;
369 adi->axes8 = i;
370 }
371
372 t = adi_get_bits(adi, 4);
373
374 for (i = 0; i < t; i++)
375 adi->cname[i] = adi_get_bits(adi, 8);
376 adi->cname[i] = 0;
377
378 t = 8 + adi->buttons + adi->axes10 * 10 + adi->axes8 * 8 + adi->hats * 4;
379 if (adi->length != t && adi->length != t + (t & 1)) {
380 printk(KERN_WARNING "adi: Expected length %d != data length %d\n", t, adi->length);
381 adi->length = 0;
382 return;
383 }
384
385 switch (adi->id) {
386 case ADI_ID_TPD:
387 adi->pad = 4;
388 adi->buttons -= 4;
389 break;
390 case ADI_ID_WGP:
391 adi->pad = 0;
392 adi->buttons -= 4;
393 break;
394 default:
395 adi->pad = -1;
396 break;
397 }
398}
399
400static void adi_init_input(struct adi *adi, struct adi_port *port, int half)
401{
402 int i, t;
403 char buf[ADI_MAX_NAME_LENGTH];
404
405 if (!adi->length) return;
406
407 init_input_dev(&adi->dev);
408
409 t = adi->id < ADI_ID_MAX ? adi->id : ADI_ID_MAX;
410
411 snprintf(buf, ADI_MAX_PHYS_LENGTH, adi_names[t], adi->id);
412 snprintf(adi->name, ADI_MAX_NAME_LENGTH, "Logitech %s", buf);
413 snprintf(adi->phys, ADI_MAX_PHYS_LENGTH, "%s/input%d", port->gameport->phys, half);
414
415 adi->abs = adi_abs[t];
416 adi->key = adi_key[t];
417
418 adi->dev.open = adi_open;
419 adi->dev.close = adi_close;
420
421 adi->dev.name = adi->name;
422 adi->dev.phys = adi->phys;
423 adi->dev.id.bustype = BUS_GAMEPORT;
424 adi->dev.id.vendor = GAMEPORT_ID_VENDOR_LOGITECH;
425 adi->dev.id.product = adi->id;
426 adi->dev.id.version = 0x0100;
427
428 adi->dev.private = port;
429 adi->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
430
431 for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++)
432 set_bit(adi->abs[i], adi->dev.absbit);
433
434 for (i = 0; i < adi->buttons; i++)
435 set_bit(adi->key[i], adi->dev.keybit);
436}
437
438static void adi_init_center(struct adi *adi)
439{
440 int i, t, x;
441
442 if (!adi->length)
443 return;
444
445 for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++) {
446
447 t = adi->abs[i];
448 x = adi->dev.abs[t];
449
450 if (t == ABS_THROTTLE || t == ABS_RUDDER || adi->id == ADI_ID_WGPE)
451 x = i < adi->axes10 ? 512 : 128;
452
453 if (i < adi->axes10)
454 input_set_abs_params(&adi->dev, t, 64, x * 2 - 64, 2, 16);
455 else if (i < adi->axes10 + adi->axes8)
456 input_set_abs_params(&adi->dev, t, 48, x * 2 - 48, 1, 16);
457 else
458 input_set_abs_params(&adi->dev, t, -1, 1, 0, 0);
459 }
460}
461
462/*
463 * adi_connect() probes for Logitech ADI joysticks.
464 */
465
466static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
467{
468 struct adi_port *port;
469 int i;
470 int err;
471
472 if (!(port = kcalloc(1, sizeof(struct adi_port), GFP_KERNEL)))
473 return -ENOMEM;
474
475 port->gameport = gameport;
476
477 gameport_set_drvdata(gameport, port);
478
479 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
480 if (err) {
481 kfree(port);
482 return err;
483 }
484
485 adi_init_digital(gameport);
486 adi_read_packet(port);
487
488 if (port->adi[0].ret >= ADI_MIN_LEN_LENGTH)
489 adi_move_bits(port, adi_get_bits(port->adi, 10));
490
491 for (i = 0; i < 2; i++) {
492 adi_id_decode(port->adi + i, port);
493 adi_init_input(port->adi + i, port, i);
494 }
495
496 if (!port->adi[0].length && !port->adi[1].length) {
497 gameport_close(gameport);
498 kfree(port);
499 return -ENODEV;
500 }
501
502 gameport_set_poll_handler(gameport, adi_poll);
503 gameport_set_poll_interval(gameport, 20);
504
505 msleep(ADI_INIT_DELAY);
506 if (adi_read(port)) {
507 msleep(ADI_DATA_DELAY);
508 adi_read(port);
509 }
510
511 for (i = 0; i < 2; i++)
512 if (port->adi[i].length > 0) {
513 adi_init_center(port->adi + i);
514 input_register_device(&port->adi[i].dev);
515 printk(KERN_INFO "input: %s [%s] on %s\n",
516 port->adi[i].name, port->adi[i].cname, gameport->phys);
517 }
518
519 return 0;
520}
521
522static void adi_disconnect(struct gameport *gameport)
523{
524 int i;
525 struct adi_port *port = gameport_get_drvdata(gameport);
526
527 for (i = 0; i < 2; i++)
528 if (port->adi[i].length > 0)
529 input_unregister_device(&port->adi[i].dev);
530 gameport_close(gameport);
531 gameport_set_drvdata(gameport, NULL);
532 kfree(port);
533}
534
535/*
536 * The gameport device structure.
537 */
538
539static struct gameport_driver adi_drv = {
540 .driver = {
541 .name = "adi",
542 },
543 .description = DRIVER_DESC,
544 .connect = adi_connect,
545 .disconnect = adi_disconnect,
546};
547
548static int __init adi_init(void)
549{
550 gameport_register_driver(&adi_drv);
551 return 0;
552}
553
554static void __exit adi_exit(void)
555{
556 gameport_unregister_driver(&adi_drv);
557}
558
559module_init(adi_init);
560module_exit(adi_exit);
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c
new file mode 100644
index 000000000000..cf36ca9b92f3
--- /dev/null
+++ b/drivers/input/joystick/amijoy.c
@@ -0,0 +1,161 @@
1/*
2 * $Id: amijoy.c,v 1.13 2002/01/22 20:26:32 vojtech Exp $
3 *
4 * Copyright (c) 1998-2001 Vojtech Pavlik
5 */
6
7/*
8 * Driver for Amiga joysticks for Linux/m68k
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/types.h>
32#include <linux/errno.h>
33#include <linux/kernel.h>
34#include <linux/module.h>
35#include <linux/moduleparam.h>
36#include <linux/init.h>
37#include <linux/input.h>
38#include <linux/interrupt.h>
39
40#include <asm/system.h>
41#include <asm/amigahw.h>
42#include <asm/amigaints.h>
43
44MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
45MODULE_DESCRIPTION("Driver for Amiga joysticks");
46MODULE_LICENSE("GPL");
47
48static int amijoy[2] = { 0, 1 };
49module_param_array_named(map, amijoy, uint, NULL, 0);
50MODULE_PARM_DESC(map, "Map of attached joysticks in form of <a>,<b> (default is 0,1)");
51
52__obsolete_setup("amijoy=");
53
54static int amijoy_used[2] = { 0, 0 };
55static struct input_dev amijoy_dev[2];
56static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" };
57
58static char *amijoy_name = "Amiga joystick";
59
60static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp)
61{
62 int i, data = 0, button = 0;
63
64 for (i = 0; i < 2; i++)
65 if (amijoy[i]) {
66
67 switch (i) {
68 case 0: data = ~custom.joy0dat; button = (~ciaa.pra >> 6) & 1; break;
69 case 1: data = ~custom.joy1dat; button = (~ciaa.pra >> 7) & 1; break;
70 }
71
72 input_regs(amijoy_dev + i, fp);
73
74 input_report_key(amijoy_dev + i, BTN_TRIGGER, button);
75
76 input_report_abs(amijoy_dev + i, ABS_X, ((data >> 1) & 1) - ((data >> 9) & 1));
77 data = ~(data ^ (data << 1));
78 input_report_abs(amijoy_dev + i, ABS_Y, ((data >> 1) & 1) - ((data >> 9) & 1));
79
80 input_sync(amijoy_dev + i);
81 }
82 return IRQ_HANDLED;
83}
84
85static int amijoy_open(struct input_dev *dev)
86{
87 int *used = dev->private;
88
89 if ((*used)++)
90 return 0;
91
92 if (request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", amijoy_interrupt)) {
93 (*used)--;
94 printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB);
95 return -EBUSY;
96 }
97
98 return 0;
99}
100
101static void amijoy_close(struct input_dev *dev)
102{
103 int *used = dev->private;
104
105 if (!--(*used))
106 free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt);
107}
108
109static int __init amijoy_init(void)
110{
111 int i, j;
112
113 for (i = 0; i < 2; i++)
114 if (amijoy[i]) {
115 if (!request_mem_region(CUSTOM_PHYSADDR+10+i*2, 2,
116 "amijoy [Denise]")) {
117 if (i == 1 && amijoy[0]) {
118 input_unregister_device(amijoy_dev);
119 release_mem_region(CUSTOM_PHYSADDR+10, 2);
120 }
121 return -EBUSY;
122 }
123
124 amijoy_dev[i].open = amijoy_open;
125 amijoy_dev[i].close = amijoy_close;
126 amijoy_dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
127 amijoy_dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
128 amijoy_dev[i].keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
129 for (j = 0; j < 2; j++) {
130 amijoy_dev[i].absmin[ABS_X + j] = -1;
131 amijoy_dev[i].absmax[ABS_X + j] = 1;
132 }
133
134 amijoy_dev[i].name = amijoy_name;
135 amijoy_dev[i].phys = amijoy_phys[i];
136 amijoy_dev[i].id.bustype = BUS_AMIGA;
137 amijoy_dev[i].id.vendor = 0x0001;
138 amijoy_dev[i].id.product = 0x0003;
139 amijoy_dev[i].id.version = 0x0100;
140
141 amijoy_dev[i].private = amijoy_used + i;
142
143 input_register_device(amijoy_dev + i);
144 printk(KERN_INFO "input: %s at joy%ddat\n", amijoy_name, i);
145 }
146 return 0;
147}
148
149static void __exit amijoy_exit(void)
150{
151 int i;
152
153 for (i = 0; i < 2; i++)
154 if (amijoy[i]) {
155 input_unregister_device(amijoy_dev + i);
156 release_mem_region(CUSTOM_PHYSADDR+10+i*2, 2);
157 }
158}
159
160module_init(amijoy_init);
161module_exit(amijoy_exit);
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
new file mode 100644
index 000000000000..504b7d550567
--- /dev/null
+++ b/drivers/input/joystick/analog.c
@@ -0,0 +1,772 @@
1/*
2 * $Id: analog.c,v 1.68 2002/01/22 20:18:32 vojtech Exp $
3 *
4 * Copyright (c) 1996-2001 Vojtech Pavlik
5 */
6
7/*
8 * Analog joystick and gamepad driver for Linux
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/config.h>
32#include <linux/delay.h>
33#include <linux/kernel.h>
34#include <linux/module.h>
35#include <linux/moduleparam.h>
36#include <linux/slab.h>
37#include <linux/bitops.h>
38#include <linux/init.h>
39#include <linux/input.h>
40#include <linux/gameport.h>
41#include <asm/timex.h>
42
43#define DRIVER_DESC "Analog joystick and gamepad driver"
44
45MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
46MODULE_DESCRIPTION(DRIVER_DESC);
47MODULE_LICENSE("GPL");
48
49/*
50 * Option parsing.
51 */
52
53#define ANALOG_PORTS 16
54
55static char *js[ANALOG_PORTS];
56static int js_nargs;
57static int analog_options[ANALOG_PORTS];
58module_param_array_named(map, js, charp, &js_nargs, 0);
59MODULE_PARM_DESC(map, "Describes analog joysticks type/capabilities");
60
61__obsolete_setup("js=");
62
63/*
64 * Times, feature definitions.
65 */
66
67#define ANALOG_RUDDER 0x00004
68#define ANALOG_THROTTLE 0x00008
69#define ANALOG_AXES_STD 0x0000f
70#define ANALOG_BTNS_STD 0x000f0
71
72#define ANALOG_BTNS_CHF 0x00100
73#define ANALOG_HAT1_CHF 0x00200
74#define ANALOG_HAT2_CHF 0x00400
75#define ANALOG_HAT_FCS 0x00800
76#define ANALOG_HATS_ALL 0x00e00
77#define ANALOG_BTN_TL 0x01000
78#define ANALOG_BTN_TR 0x02000
79#define ANALOG_BTN_TL2 0x04000
80#define ANALOG_BTN_TR2 0x08000
81#define ANALOG_BTNS_TLR 0x03000
82#define ANALOG_BTNS_TLR2 0x0c000
83#define ANALOG_BTNS_GAMEPAD 0x0f000
84
85#define ANALOG_HBTN_CHF 0x10000
86#define ANALOG_ANY_CHF 0x10700
87#define ANALOG_SAITEK 0x20000
88#define ANALOG_EXTENSIONS 0x7ff00
89#define ANALOG_GAMEPAD 0x80000
90
91#define ANALOG_MAX_TIME 3 /* 3 ms */
92#define ANALOG_LOOP_TIME 2000 /* 2 * loop */
93#define ANALOG_SAITEK_DELAY 200 /* 200 us */
94#define ANALOG_SAITEK_TIME 2000 /* 2000 us */
95#define ANALOG_AXIS_TIME 2 /* 2 * refresh */
96#define ANALOG_INIT_RETRIES 8 /* 8 times */
97#define ANALOG_FUZZ_BITS 2 /* 2 bit more */
98#define ANALOG_FUZZ_MAGIC 36 /* 36 u*ms/loop */
99
100#define ANALOG_MAX_NAME_LENGTH 128
101#define ANALOG_MAX_PHYS_LENGTH 32
102
103static short analog_axes[] = { ABS_X, ABS_Y, ABS_RUDDER, ABS_THROTTLE };
104static short analog_hats[] = { ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y };
105static short analog_pads[] = { BTN_Y, BTN_Z, BTN_TL, BTN_TR };
106static short analog_exts[] = { ANALOG_HAT1_CHF, ANALOG_HAT2_CHF, ANALOG_HAT_FCS };
107static short analog_pad_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_TL2, BTN_TR2, BTN_SELECT, BTN_START, BTN_MODE, BTN_BASE };
108static short analog_joy_btn[] = { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2,
109 BTN_BASE3, BTN_BASE4, BTN_BASE5, BTN_BASE6 };
110
111static unsigned char analog_chf[] = { 0xf, 0x0, 0x1, 0x9, 0x2, 0x4, 0xc, 0x8, 0x3, 0x5, 0xb, 0x7, 0xd, 0xe, 0xa, 0x6 };
112
113struct analog {
114 struct input_dev dev;
115 int mask;
116 short *buttons;
117 char name[ANALOG_MAX_NAME_LENGTH];
118 char phys[ANALOG_MAX_PHYS_LENGTH];
119};
120
121struct analog_port {
122 struct gameport *gameport;
123 struct analog analog[2];
124 unsigned char mask;
125 char saitek;
126 char cooked;
127 int bads;
128 int reads;
129 int speed;
130 int loop;
131 int fuzz;
132 int axes[4];
133 int buttons;
134 int initial[4];
135 int axtime;
136};
137
138/*
139 * Time macros.
140 */
141
142#ifdef __i386__
143#define GET_TIME(x) do { if (cpu_has_tsc) rdtscl(x); else x = get_time_pit(); } while (0)
144#define DELTA(x,y) (cpu_has_tsc ? ((y) - (x)) : ((x) - (y) + ((x) < (y) ? CLOCK_TICK_RATE / HZ : 0)))
145#define TIME_NAME (cpu_has_tsc?"TSC":"PIT")
146static unsigned int get_time_pit(void)
147{
148 extern spinlock_t i8253_lock;
149 unsigned long flags;
150 unsigned int count;
151
152 spin_lock_irqsave(&i8253_lock, flags);
153 outb_p(0x00, 0x43);
154 count = inb_p(0x40);
155 count |= inb_p(0x40) << 8;
156 spin_unlock_irqrestore(&i8253_lock, flags);
157
158 return count;
159}
160#elif defined(__x86_64__)
161#define GET_TIME(x) rdtscl(x)
162#define DELTA(x,y) ((y)-(x))
163#define TIME_NAME "TSC"
164#elif defined(__alpha__)
165#define GET_TIME(x) do { x = get_cycles(); } while (0)
166#define DELTA(x,y) ((y)-(x))
167#define TIME_NAME "PCC"
168#else
169#define FAKE_TIME
170static unsigned long analog_faketime = 0;
171#define GET_TIME(x) do { x = analog_faketime++; } while(0)
172#define DELTA(x,y) ((y)-(x))
173#define TIME_NAME "Unreliable"
174#warning Precise timer not defined for this architecture.
175#endif
176
177/*
178 * analog_decode() decodes analog joystick data and reports input events.
179 */
180
181static void analog_decode(struct analog *analog, int *axes, int *initial, int buttons)
182{
183 struct input_dev *dev = &analog->dev;
184 int i, j;
185
186 if (analog->mask & ANALOG_HAT_FCS)
187 for (i = 0; i < 4; i++)
188 if (axes[3] < ((initial[3] * ((i << 1) + 1)) >> 3)) {
189 buttons |= 1 << (i + 14);
190 break;
191 }
192
193 for (i = j = 0; i < 6; i++)
194 if (analog->mask & (0x10 << i))
195 input_report_key(dev, analog->buttons[j++], (buttons >> i) & 1);
196
197 if (analog->mask & ANALOG_HBTN_CHF)
198 for (i = 0; i < 4; i++)
199 input_report_key(dev, analog->buttons[j++], (buttons >> (i + 10)) & 1);
200
201 if (analog->mask & ANALOG_BTN_TL)
202 input_report_key(dev, analog_pads[0], axes[2] < (initial[2] >> 1));
203 if (analog->mask & ANALOG_BTN_TR)
204 input_report_key(dev, analog_pads[1], axes[3] < (initial[3] >> 1));
205 if (analog->mask & ANALOG_BTN_TL2)
206 input_report_key(dev, analog_pads[2], axes[2] > (initial[2] + (initial[2] >> 1)));
207 if (analog->mask & ANALOG_BTN_TR2)
208 input_report_key(dev, analog_pads[3], axes[3] > (initial[3] + (initial[3] >> 1)));
209
210 for (i = j = 0; i < 4; i++)
211 if (analog->mask & (1 << i))
212 input_report_abs(dev, analog_axes[j++], axes[i]);
213
214 for (i = j = 0; i < 3; i++)
215 if (analog->mask & analog_exts[i]) {
216 input_report_abs(dev, analog_hats[j++],
217 ((buttons >> ((i << 2) + 7)) & 1) - ((buttons >> ((i << 2) + 9)) & 1));
218 input_report_abs(dev, analog_hats[j++],
219 ((buttons >> ((i << 2) + 8)) & 1) - ((buttons >> ((i << 2) + 6)) & 1));
220 }
221
222 input_sync(dev);
223}
224
225/*
226 * analog_cooked_read() reads analog joystick data.
227 */
228
229static int analog_cooked_read(struct analog_port *port)
230{
231 struct gameport *gameport = port->gameport;
232 unsigned int time[4], start, loop, now, loopout, timeout;
233 unsigned char data[4], this, last;
234 unsigned long flags;
235 int i, j;
236
237 loopout = (ANALOG_LOOP_TIME * port->loop) / 1000;
238 timeout = ANALOG_MAX_TIME * port->speed;
239
240 local_irq_save(flags);
241 gameport_trigger(gameport);
242 GET_TIME(now);
243 local_irq_restore(flags);
244
245 start = now;
246 this = port->mask;
247 i = 0;
248
249 do {
250 loop = now;
251 last = this;
252
253 local_irq_disable();
254 this = gameport_read(gameport) & port->mask;
255 GET_TIME(now);
256 local_irq_restore(flags);
257
258 if ((last ^ this) && (DELTA(loop, now) < loopout)) {
259 data[i] = last ^ this;
260 time[i] = now;
261 i++;
262 }
263
264 } while (this && (i < 4) && (DELTA(start, now) < timeout));
265
266 this <<= 4;
267
268 for (--i; i >= 0; i--) {
269 this |= data[i];
270 for (j = 0; j < 4; j++)
271 if (data[i] & (1 << j))
272 port->axes[j] = (DELTA(start, time[i]) << ANALOG_FUZZ_BITS) / port->loop;
273 }
274
275 return -(this != port->mask);
276}
277
278static int analog_button_read(struct analog_port *port, char saitek, char chf)
279{
280 unsigned char u;
281 int t = 1, i = 0;
282 int strobe = gameport_time(port->gameport, ANALOG_SAITEK_TIME);
283
284 u = gameport_read(port->gameport);
285
286 if (!chf) {
287 port->buttons = (~u >> 4) & 0xf;
288 return 0;
289 }
290
291 port->buttons = 0;
292
293 while ((~u & 0xf0) && (i < 16) && t) {
294 port->buttons |= 1 << analog_chf[(~u >> 4) & 0xf];
295 if (!saitek) return 0;
296 udelay(ANALOG_SAITEK_DELAY);
297 t = strobe;
298 gameport_trigger(port->gameport);
299 while (((u = gameport_read(port->gameport)) & port->mask) && t) t--;
300 i++;
301 }
302
303 return -(!t || (i == 16));
304}
305
306/*
307 * analog_poll() repeatedly polls the Analog joysticks.
308 */
309
310static void analog_poll(struct gameport *gameport)
311{
312 struct analog_port *port = gameport_get_drvdata(gameport);
313 int i;
314
315 char saitek = !!(port->analog[0].mask & ANALOG_SAITEK);
316 char chf = !!(port->analog[0].mask & ANALOG_ANY_CHF);
317
318 if (port->cooked) {
319 port->bads -= gameport_cooked_read(port->gameport, port->axes, &port->buttons);
320 if (chf)
321 port->buttons = port->buttons ? (1 << analog_chf[port->buttons]) : 0;
322 port->reads++;
323 } else {
324 if (!port->axtime--) {
325 port->bads -= analog_cooked_read(port);
326 port->bads -= analog_button_read(port, saitek, chf);
327 port->reads++;
328 port->axtime = ANALOG_AXIS_TIME - 1;
329 } else {
330 if (!saitek)
331 analog_button_read(port, saitek, chf);
332 }
333 }
334
335 for (i = 0; i < 2; i++)
336 if (port->analog[i].mask)
337 analog_decode(port->analog + i, port->axes, port->initial, port->buttons);
338}
339
340/*
341 * analog_open() is a callback from the input open routine.
342 */
343
344static int analog_open(struct input_dev *dev)
345{
346 struct analog_port *port = dev->private;
347
348 gameport_start_polling(port->gameport);
349 return 0;
350}
351
352/*
353 * analog_close() is a callback from the input close routine.
354 */
355
356static void analog_close(struct input_dev *dev)
357{
358 struct analog_port *port = dev->private;
359
360 gameport_stop_polling(port->gameport);
361}
362
363/*
364 * analog_calibrate_timer() calibrates the timer and computes loop
365 * and timeout values for a joystick port.
366 */
367
368static void analog_calibrate_timer(struct analog_port *port)
369{
370 struct gameport *gameport = port->gameport;
371 unsigned int i, t, tx, t1, t2, t3;
372 unsigned long flags;
373
374 local_irq_save(flags);
375 GET_TIME(t1);
376#ifdef FAKE_TIME
377 analog_faketime += 830;
378#endif
379 mdelay(1);
380 GET_TIME(t2);
381 GET_TIME(t3);
382 local_irq_restore(flags);
383
384 port->speed = DELTA(t1, t2) - DELTA(t2, t3);
385
386 tx = ~0;
387
388 for (i = 0; i < 50; i++) {
389 local_irq_save(flags);
390 GET_TIME(t1);
391 for (t = 0; t < 50; t++) { gameport_read(gameport); GET_TIME(t2); }
392 GET_TIME(t3);
393 local_irq_restore(flags);
394 udelay(i);
395 t = DELTA(t1, t2) - DELTA(t2, t3);
396 if (t < tx) tx = t;
397 }
398
399 port->loop = tx / 50;
400}
401
402/*
403 * analog_name() constructs a name for an analog joystick.
404 */
405
406static void analog_name(struct analog *analog)
407{
408 sprintf(analog->name, "Analog %d-axis %d-button",
409 hweight8(analog->mask & ANALOG_AXES_STD),
410 hweight8(analog->mask & ANALOG_BTNS_STD) + !!(analog->mask & ANALOG_BTNS_CHF) * 2 +
411 hweight16(analog->mask & ANALOG_BTNS_GAMEPAD) + !!(analog->mask & ANALOG_HBTN_CHF) * 4);
412
413 if (analog->mask & ANALOG_HATS_ALL)
414 sprintf(analog->name, "%s %d-hat",
415 analog->name, hweight16(analog->mask & ANALOG_HATS_ALL));
416
417 if (analog->mask & ANALOG_HAT_FCS)
418 strcat(analog->name, " FCS");
419 if (analog->mask & ANALOG_ANY_CHF)
420 strcat(analog->name, (analog->mask & ANALOG_SAITEK) ? " Saitek" : " CHF");
421
422 strcat(analog->name, (analog->mask & ANALOG_GAMEPAD) ? " gamepad": " joystick");
423}
424
425/*
426 * analog_init_device()
427 */
428
429static void analog_init_device(struct analog_port *port, struct analog *analog, int index)
430{
431 int i, j, t, v, w, x, y, z;
432
433 analog_name(analog);
434 sprintf(analog->phys, "%s/input%d", port->gameport->phys, index);
435 analog->buttons = (analog->mask & ANALOG_GAMEPAD) ? analog_pad_btn : analog_joy_btn;
436
437 init_input_dev(&analog->dev);
438
439 analog->dev.name = analog->name;
440 analog->dev.phys = analog->phys;
441 analog->dev.id.bustype = BUS_GAMEPORT;
442 analog->dev.id.vendor = GAMEPORT_ID_VENDOR_ANALOG;
443 analog->dev.id.product = analog->mask >> 4;
444 analog->dev.id.version = 0x0100;
445
446 analog->dev.open = analog_open;
447 analog->dev.close = analog_close;
448 analog->dev.private = port;
449 analog->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
450
451 for (i = j = 0; i < 4; i++)
452 if (analog->mask & (1 << i)) {
453
454 t = analog_axes[j];
455 x = port->axes[i];
456 y = (port->axes[0] + port->axes[1]) >> 1;
457 z = y - port->axes[i];
458 z = z > 0 ? z : -z;
459 v = (x >> 3);
460 w = (x >> 3);
461
462 set_bit(t, analog->dev.absbit);
463
464 if ((i == 2 || i == 3) && (j == 2 || j == 3) && (z > (y >> 3)))
465 x = y;
466
467 if (analog->mask & ANALOG_SAITEK) {
468 if (i == 2) x = port->axes[i];
469 v = x - (x >> 2);
470 w = (x >> 4);
471 }
472
473 analog->dev.absmax[t] = (x << 1) - v;
474 analog->dev.absmin[t] = v;
475 analog->dev.absfuzz[t] = port->fuzz;
476 analog->dev.absflat[t] = w;
477
478 j++;
479 }
480
481 for (i = j = 0; i < 3; i++)
482 if (analog->mask & analog_exts[i])
483 for (x = 0; x < 2; x++) {
484 t = analog_hats[j++];
485 set_bit(t, analog->dev.absbit);
486 analog->dev.absmax[t] = 1;
487 analog->dev.absmin[t] = -1;
488 }
489
490 for (i = j = 0; i < 4; i++)
491 if (analog->mask & (0x10 << i))
492 set_bit(analog->buttons[j++], analog->dev.keybit);
493
494 if (analog->mask & ANALOG_BTNS_CHF)
495 for (i = 0; i < 2; i++)
496 set_bit(analog->buttons[j++], analog->dev.keybit);
497
498 if (analog->mask & ANALOG_HBTN_CHF)
499 for (i = 0; i < 4; i++)
500 set_bit(analog->buttons[j++], analog->dev.keybit);
501
502 for (i = 0; i < 4; i++)
503 if (analog->mask & (ANALOG_BTN_TL << i))
504 set_bit(analog_pads[i], analog->dev.keybit);
505
506 analog_decode(analog, port->axes, port->initial, port->buttons);
507
508 input_register_device(&analog->dev);
509
510 printk(KERN_INFO "input: %s at %s", analog->name, port->gameport->phys);
511
512 if (port->cooked)
513 printk(" [ADC port]\n");
514 else
515 printk(" [%s timer, %d %sHz clock, %d ns res]\n", TIME_NAME,
516 port->speed > 10000 ? (port->speed + 800) / 1000 : port->speed,
517 port->speed > 10000 ? "M" : "k",
518 port->speed > 10000 ? (port->loop * 1000) / (port->speed / 1000)
519 : (port->loop * 1000000) / port->speed);
520}
521
522/*
523 * analog_init_devices() sets up device-specific values and registers the input devices.
524 */
525
526static int analog_init_masks(struct analog_port *port)
527{
528 int i;
529 struct analog *analog = port->analog;
530 int max[4];
531
532 if (!port->mask)
533 return -1;
534
535 if ((port->mask & 3) != 3 && port->mask != 0xc) {
536 printk(KERN_WARNING "analog.c: Unknown joystick device found "
537 "(data=%#x, %s), probably not analog joystick.\n",
538 port->mask, port->gameport->phys);
539 return -1;
540 }
541
542
543 i = analog_options[0]; /* FIXME !!! - need to specify options for different ports */
544
545 analog[0].mask = i & 0xfffff;
546
547 analog[0].mask &= ~(ANALOG_AXES_STD | ANALOG_HAT_FCS | ANALOG_BTNS_GAMEPAD)
548 | port->mask | ((port->mask << 8) & ANALOG_HAT_FCS)
549 | ((port->mask << 10) & ANALOG_BTNS_TLR) | ((port->mask << 12) & ANALOG_BTNS_TLR2);
550
551 analog[0].mask &= ~(ANALOG_HAT2_CHF)
552 | ((analog[0].mask & ANALOG_HBTN_CHF) ? 0 : ANALOG_HAT2_CHF);
553
554 analog[0].mask &= ~(ANALOG_THROTTLE | ANALOG_BTN_TR | ANALOG_BTN_TR2)
555 | ((~analog[0].mask & ANALOG_HAT_FCS) >> 8)
556 | ((~analog[0].mask & ANALOG_HAT_FCS) << 2)
557 | ((~analog[0].mask & ANALOG_HAT_FCS) << 4);
558
559 analog[0].mask &= ~(ANALOG_THROTTLE | ANALOG_RUDDER)
560 | (((~analog[0].mask & ANALOG_BTNS_TLR ) >> 10)
561 & ((~analog[0].mask & ANALOG_BTNS_TLR2) >> 12));
562
563 analog[1].mask = ((i >> 20) & 0xff) | ((i >> 12) & 0xf0000);
564
565 analog[1].mask &= (analog[0].mask & ANALOG_EXTENSIONS) ? ANALOG_GAMEPAD
566 : (((ANALOG_BTNS_STD | port->mask) & ~analog[0].mask) | ANALOG_GAMEPAD);
567
568 if (port->cooked) {
569
570 for (i = 0; i < 4; i++) max[i] = port->axes[i] << 1;
571
572 if ((analog[0].mask & 0x7) == 0x7) max[2] = (max[0] + max[1]) >> 1;
573 if ((analog[0].mask & 0xb) == 0xb) max[3] = (max[0] + max[1]) >> 1;
574 if ((analog[0].mask & ANALOG_BTN_TL) && !(analog[0].mask & ANALOG_BTN_TL2)) max[2] >>= 1;
575 if ((analog[0].mask & ANALOG_BTN_TR) && !(analog[0].mask & ANALOG_BTN_TR2)) max[3] >>= 1;
576 if ((analog[0].mask & ANALOG_HAT_FCS)) max[3] >>= 1;
577
578 gameport_calibrate(port->gameport, port->axes, max);
579 }
580
581 for (i = 0; i < 4; i++)
582 port->initial[i] = port->axes[i];
583
584 return -!(analog[0].mask || analog[1].mask);
585}
586
587static int analog_init_port(struct gameport *gameport, struct gameport_driver *drv, struct analog_port *port)
588{
589 int i, t, u, v;
590
591 port->gameport = gameport;
592
593 gameport_set_drvdata(gameport, port);
594
595 if (!gameport_open(gameport, drv, GAMEPORT_MODE_RAW)) {
596
597 analog_calibrate_timer(port);
598
599 gameport_trigger(gameport);
600 t = gameport_read(gameport);
601 msleep(ANALOG_MAX_TIME);
602 port->mask = (gameport_read(gameport) ^ t) & t & 0xf;
603 port->fuzz = (port->speed * ANALOG_FUZZ_MAGIC) / port->loop / 1000 + ANALOG_FUZZ_BITS;
604
605 for (i = 0; i < ANALOG_INIT_RETRIES; i++) {
606 if (!analog_cooked_read(port))
607 break;
608 msleep(ANALOG_MAX_TIME);
609 }
610
611 u = v = 0;
612
613 msleep(ANALOG_MAX_TIME);
614 t = gameport_time(gameport, ANALOG_MAX_TIME * 1000);
615 gameport_trigger(gameport);
616 while ((gameport_read(port->gameport) & port->mask) && (u < t))
617 u++;
618 udelay(ANALOG_SAITEK_DELAY);
619 t = gameport_time(gameport, ANALOG_SAITEK_TIME);
620 gameport_trigger(gameport);
621 while ((gameport_read(port->gameport) & port->mask) && (v < t))
622 v++;
623
624 if (v < (u >> 1)) { /* FIXME - more than one port */
625 analog_options[0] |= /* FIXME - more than one port */
626 ANALOG_SAITEK | ANALOG_BTNS_CHF | ANALOG_HBTN_CHF | ANALOG_HAT1_CHF;
627 return 0;
628 }
629
630 gameport_close(gameport);
631 }
632
633 if (!gameport_open(gameport, drv, GAMEPORT_MODE_COOKED)) {
634
635 for (i = 0; i < ANALOG_INIT_RETRIES; i++)
636 if (!gameport_cooked_read(gameport, port->axes, &port->buttons))
637 break;
638 for (i = 0; i < 4; i++)
639 if (port->axes[i] != -1)
640 port->mask |= 1 << i;
641
642 port->fuzz = gameport->fuzz;
643 port->cooked = 1;
644 return 0;
645 }
646
647 return gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
648}
649
650static int analog_connect(struct gameport *gameport, struct gameport_driver *drv)
651{
652 struct analog_port *port;
653 int i;
654 int err;
655
656 if (!(port = kcalloc(1, sizeof(struct analog_port), GFP_KERNEL)))
657 return - ENOMEM;
658
659 err = analog_init_port(gameport, drv, port);
660 if (err) {
661 kfree(port);
662 return err;
663 }
664
665 err = analog_init_masks(port);
666 if (err) {
667 gameport_close(gameport);
668 gameport_set_drvdata(gameport, NULL);
669 kfree(port);
670 return err;
671 }
672
673 gameport_set_poll_handler(gameport, analog_poll);
674 gameport_set_poll_interval(gameport, 10);
675
676 for (i = 0; i < 2; i++)
677 if (port->analog[i].mask)
678 analog_init_device(port, port->analog + i, i);
679
680 return 0;
681}
682
683static void analog_disconnect(struct gameport *gameport)
684{
685 int i;
686 struct analog_port *port = gameport_get_drvdata(gameport);
687
688 for (i = 0; i < 2; i++)
689 if (port->analog[i].mask)
690 input_unregister_device(&port->analog[i].dev);
691 gameport_close(gameport);
692 gameport_set_drvdata(gameport, NULL);
693 printk(KERN_INFO "analog.c: %d out of %d reads (%d%%) on %s failed\n",
694 port->bads, port->reads, port->reads ? (port->bads * 100 / port->reads) : 0,
695 port->gameport->phys);
696 kfree(port);
697}
698
699struct analog_types {
700 char *name;
701 int value;
702};
703
704static struct analog_types analog_types[] = {
705 { "none", 0x00000000 },
706 { "auto", 0x000000ff },
707 { "2btn", 0x0000003f },
708 { "y-joy", 0x0cc00033 },
709 { "y-pad", 0x8cc80033 },
710 { "fcs", 0x000008f7 },
711 { "chf", 0x000002ff },
712 { "fullchf", 0x000007ff },
713 { "gamepad", 0x000830f3 },
714 { "gamepad8", 0x0008f0f3 },
715 { NULL, 0 }
716};
717
718static void analog_parse_options(void)
719{
720 int i, j;
721 char *end;
722
723 for (i = 0; i < js_nargs; i++) {
724
725 for (j = 0; analog_types[j].name; j++)
726 if (!strcmp(analog_types[j].name, js[i])) {
727 analog_options[i] = analog_types[j].value;
728 break;
729 }
730 if (analog_types[j].name) continue;
731
732 analog_options[i] = simple_strtoul(js[i], &end, 0);
733 if (end != js[i]) continue;
734
735 analog_options[i] = 0xff;
736 if (!strlen(js[i])) continue;
737
738 printk(KERN_WARNING "analog.c: Bad config for port %d - \"%s\"\n", i, js[i]);
739 }
740
741 for (; i < ANALOG_PORTS; i++)
742 analog_options[i] = 0xff;
743}
744
745/*
746 * The gameport device structure.
747 */
748
749static struct gameport_driver analog_drv = {
750 .driver = {
751 .name = "analog",
752 },
753 .description = DRIVER_DESC,
754 .connect = analog_connect,
755 .disconnect = analog_disconnect,
756};
757
758static int __init analog_init(void)
759{
760 analog_parse_options();
761 gameport_register_driver(&analog_drv);
762
763 return 0;
764}
765
766static void __exit analog_exit(void)
767{
768 gameport_unregister_driver(&analog_drv);
769}
770
771module_init(analog_init);
772module_exit(analog_exit);
diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c
new file mode 100644
index 000000000000..a6002205328f
--- /dev/null
+++ b/drivers/input/joystick/cobra.c
@@ -0,0 +1,264 @@
1/*
2 * $Id: cobra.c,v 1.19 2002/01/22 20:26:52 vojtech Exp $
3 *
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 */
6
7/*
8 * Creative Labs Blaster GamePad Cobra driver for Linux
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/kernel.h>
32#include <linux/module.h>
33#include <linux/slab.h>
34#include <linux/init.h>
35#include <linux/gameport.h>
36#include <linux/input.h>
37
38#define DRIVER_DESC "Creative Labs Blaster GamePad Cobra driver"
39
40MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
41MODULE_DESCRIPTION(DRIVER_DESC);
42MODULE_LICENSE("GPL");
43
44#define COBRA_MAX_STROBE 45 /* 45 us max wait for first strobe */
45#define COBRA_LENGTH 36
46
47static char* cobra_name = "Creative Labs Blaster GamePad Cobra";
48
49static int cobra_btn[] = { BTN_START, BTN_SELECT, BTN_TL, BTN_TR, BTN_X, BTN_Y, BTN_Z, BTN_A, BTN_B, BTN_C, BTN_TL2, BTN_TR2, 0 };
50
51struct cobra {
52 struct gameport *gameport;
53 struct input_dev dev[2];
54 int reads;
55 int bads;
56 unsigned char exists;
57 char phys[2][32];
58};
59
60static unsigned char cobra_read_packet(struct gameport *gameport, unsigned int *data)
61{
62 unsigned long flags;
63 unsigned char u, v, w;
64 __u64 buf[2];
65 int r[2], t[2];
66 int i, j, ret;
67
68 int strobe = gameport_time(gameport, COBRA_MAX_STROBE);
69
70 for (i = 0; i < 2; i++) {
71 r[i] = buf[i] = 0;
72 t[i] = COBRA_MAX_STROBE;
73 }
74
75 local_irq_save(flags);
76
77 u = gameport_read(gameport);
78
79 do {
80 t[0]--; t[1]--;
81 v = gameport_read(gameport);
82 for (i = 0, w = u ^ v; i < 2 && w; i++, w >>= 2)
83 if (w & 0x30) {
84 if ((w & 0x30) < 0x30 && r[i] < COBRA_LENGTH && t[i] > 0) {
85 buf[i] |= (__u64)((w >> 5) & 1) << r[i]++;
86 t[i] = strobe;
87 u = v;
88 } else t[i] = 0;
89 }
90 } while (t[0] > 0 || t[1] > 0);
91
92 local_irq_restore(flags);
93
94 ret = 0;
95
96 for (i = 0; i < 2; i++) {
97
98 if (r[i] != COBRA_LENGTH) continue;
99
100 for (j = 0; j < COBRA_LENGTH && (buf[i] & 0x04104107f) ^ 0x041041040; j++)
101 buf[i] = (buf[i] >> 1) | ((__u64)(buf[i] & 1) << (COBRA_LENGTH - 1));
102
103 if (j < COBRA_LENGTH) ret |= (1 << i);
104
105 data[i] = ((buf[i] >> 7) & 0x000001f) | ((buf[i] >> 8) & 0x00003e0)
106 | ((buf[i] >> 9) & 0x0007c00) | ((buf[i] >> 10) & 0x00f8000)
107 | ((buf[i] >> 11) & 0x1f00000);
108
109 }
110
111 return ret;
112}
113
114static void cobra_poll(struct gameport *gameport)
115{
116 struct cobra *cobra = gameport_get_drvdata(gameport);
117 struct input_dev *dev;
118 unsigned int data[2];
119 int i, j, r;
120
121 cobra->reads++;
122
123 if ((r = cobra_read_packet(gameport, data)) != cobra->exists) {
124 cobra->bads++;
125 return;
126 }
127
128 for (i = 0; i < 2; i++)
129 if (cobra->exists & r & (1 << i)) {
130
131 dev = cobra->dev + i;
132
133 input_report_abs(dev, ABS_X, ((data[i] >> 4) & 1) - ((data[i] >> 3) & 1));
134 input_report_abs(dev, ABS_Y, ((data[i] >> 2) & 1) - ((data[i] >> 1) & 1));
135
136 for (j = 0; cobra_btn[j]; j++)
137 input_report_key(dev, cobra_btn[j], data[i] & (0x20 << j));
138
139 input_sync(dev);
140
141 }
142}
143
144static int cobra_open(struct input_dev *dev)
145{
146 struct cobra *cobra = dev->private;
147
148 gameport_start_polling(cobra->gameport);
149 return 0;
150}
151
152static void cobra_close(struct input_dev *dev)
153{
154 struct cobra *cobra = dev->private;
155
156 gameport_stop_polling(cobra->gameport);
157}
158
159static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv)
160{
161 struct cobra *cobra;
162 unsigned int data[2];
163 int i, j;
164 int err;
165
166 if (!(cobra = kcalloc(1, sizeof(struct cobra), GFP_KERNEL)))
167 return -ENOMEM;
168
169 cobra->gameport = gameport;
170
171 gameport_set_drvdata(gameport, cobra);
172
173 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
174 if (err)
175 goto fail1;
176
177 cobra->exists = cobra_read_packet(gameport, data);
178
179 for (i = 0; i < 2; i++)
180 if ((cobra->exists >> i) & data[i] & 1) {
181 printk(KERN_WARNING "cobra.c: Device %d on %s has the Ext bit set. ID is: %d"
182 " Contact vojtech@ucw.cz\n", i, gameport->phys, (data[i] >> 2) & 7);
183 cobra->exists &= ~(1 << i);
184 }
185
186 if (!cobra->exists) {
187 err = -ENODEV;
188 goto fail2;
189 }
190
191 gameport_set_poll_handler(gameport, cobra_poll);
192 gameport_set_poll_interval(gameport, 20);
193
194 for (i = 0; i < 2; i++)
195 if ((cobra->exists >> i) & 1) {
196
197 sprintf(cobra->phys[i], "%s/input%d", gameport->phys, i);
198
199 cobra->dev[i].private = cobra;
200 cobra->dev[i].open = cobra_open;
201 cobra->dev[i].close = cobra_close;
202
203 cobra->dev[i].name = cobra_name;
204 cobra->dev[i].phys = cobra->phys[i];
205 cobra->dev[i].id.bustype = BUS_GAMEPORT;
206 cobra->dev[i].id.vendor = GAMEPORT_ID_VENDOR_CREATIVE;
207 cobra->dev[i].id.product = 0x0008;
208 cobra->dev[i].id.version = 0x0100;
209
210 cobra->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
211
212 input_set_abs_params(&cobra->dev[i], ABS_X, -1, 1, 0, 0);
213 input_set_abs_params(&cobra->dev[i], ABS_Y, -1, 1, 0, 0);
214
215 for (j = 0; cobra_btn[j]; j++)
216 set_bit(cobra_btn[j], cobra->dev[i].keybit);
217
218 input_register_device(&cobra->dev[i]);
219 printk(KERN_INFO "input: %s on %s\n", cobra_name, gameport->phys);
220 }
221
222 return 0;
223
224fail2: gameport_close(gameport);
225fail1: gameport_set_drvdata(gameport, NULL);
226 kfree(cobra);
227 return err;
228}
229
230static void cobra_disconnect(struct gameport *gameport)
231{
232 struct cobra *cobra = gameport_get_drvdata(gameport);
233 int i;
234
235 for (i = 0; i < 2; i++)
236 if ((cobra->exists >> i) & 1)
237 input_unregister_device(cobra->dev + i);
238 gameport_close(gameport);
239 gameport_set_drvdata(gameport, NULL);
240 kfree(cobra);
241}
242
243static struct gameport_driver cobra_drv = {
244 .driver = {
245 .name = "cobra",
246 },
247 .description = DRIVER_DESC,
248 .connect = cobra_connect,
249 .disconnect = cobra_disconnect,
250};
251
252static int __init cobra_init(void)
253{
254 gameport_register_driver(&cobra_drv);
255 return 0;
256}
257
258static void __exit cobra_exit(void)
259{
260 gameport_unregister_driver(&cobra_drv);
261}
262
263module_init(cobra_init);
264module_exit(cobra_exit);
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
new file mode 100644
index 000000000000..cfdd3acf06a1
--- /dev/null
+++ b/drivers/input/joystick/db9.c
@@ -0,0 +1,647 @@
1/*
2 * $Id: db9.c,v 1.13 2002/04/07 20:13:37 vojtech Exp $
3 *
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 *
6 * Based on the work of:
7 * Andree Borrmann Mats Sjövall
8 */
9
10/*
11 * Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver for Linux
12 */
13
14/*
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 * Should you need to contact me, the author, you can do so either by
30 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
31 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
32 */
33
34#include <linux/kernel.h>
35#include <linux/module.h>
36#include <linux/moduleparam.h>
37#include <linux/delay.h>
38#include <linux/init.h>
39#include <linux/parport.h>
40#include <linux/input.h>
41
42MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
43MODULE_DESCRIPTION("Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver");
44MODULE_LICENSE("GPL");
45
46static int db9[] __initdata = { -1, 0 };
47static int db9_nargs __initdata = 0;
48module_param_array_named(dev, db9, int, &db9_nargs, 0);
49MODULE_PARM_DESC(dev, "Describes first attached device (<parport#>,<type>)");
50
51static int db9_2[] __initdata = { -1, 0 };
52static int db9_nargs_2 __initdata = 0;
53module_param_array_named(dev2, db9_2, int, &db9_nargs_2, 0);
54MODULE_PARM_DESC(dev2, "Describes second attached device (<parport#>,<type>)");
55
56static int db9_3[] __initdata = { -1, 0 };
57static int db9_nargs_3 __initdata = 0;
58module_param_array_named(dev3, db9_3, int, &db9_nargs_3, 0);
59MODULE_PARM_DESC(dev3, "Describes third attached device (<parport#>,<type>)");
60
61__obsolete_setup("db9=");
62__obsolete_setup("db9_2=");
63__obsolete_setup("db9_3=");
64
65#define DB9_MULTI_STICK 0x01
66#define DB9_MULTI2_STICK 0x02
67#define DB9_GENESIS_PAD 0x03
68#define DB9_GENESIS5_PAD 0x05
69#define DB9_GENESIS6_PAD 0x06
70#define DB9_SATURN_PAD 0x07
71#define DB9_MULTI_0802 0x08
72#define DB9_MULTI_0802_2 0x09
73#define DB9_CD32_PAD 0x0A
74#define DB9_SATURN_DPP 0x0B
75#define DB9_SATURN_DPP_2 0x0C
76#define DB9_MAX_PAD 0x0D
77
78#define DB9_UP 0x01
79#define DB9_DOWN 0x02
80#define DB9_LEFT 0x04
81#define DB9_RIGHT 0x08
82#define DB9_FIRE1 0x10
83#define DB9_FIRE2 0x20
84#define DB9_FIRE3 0x40
85#define DB9_FIRE4 0x80
86
87#define DB9_NORMAL 0x0a
88#define DB9_NOSELECT 0x08
89
90#define DB9_MAX_DEVICES 2
91
92#define DB9_GENESIS6_DELAY 14
93#define DB9_REFRESH_TIME HZ/100
94
95struct db9 {
96 struct input_dev dev[DB9_MAX_DEVICES];
97 struct timer_list timer;
98 struct pardevice *pd;
99 int mode;
100 int used;
101 char phys[2][32];
102};
103
104static struct db9 *db9_base[3];
105
106static short db9_multi_btn[] = { BTN_TRIGGER, BTN_THUMB };
107static short db9_genesis_btn[] = { BTN_START, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_MODE };
108static short db9_cd32_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START };
109
110static char db9_buttons[DB9_MAX_PAD] = { 0, 1, 2, 4, 0, 6, 8, 9, 1, 1, 7, 9, 9 };
111static short *db9_btn[DB9_MAX_PAD] = { NULL, db9_multi_btn, db9_multi_btn, db9_genesis_btn, NULL, db9_genesis_btn,
112 db9_genesis_btn, db9_cd32_btn, db9_multi_btn, db9_multi_btn, db9_cd32_btn,
113 db9_cd32_btn, db9_cd32_btn };
114static char *db9_name[DB9_MAX_PAD] = { NULL, "Multisystem joystick", "Multisystem joystick (2 fire)", "Genesis pad",
115 NULL, "Genesis 5 pad", "Genesis 6 pad", "Saturn pad", "Multisystem (0.8.0.2) joystick",
116 "Multisystem (0.8.0.2-dual) joystick", "Amiga CD-32 pad", "Saturn dpp", "Saturn dpp dual" };
117
118static const int db9_max_pads[DB9_MAX_PAD] = { 0, 1, 1, 1, 0, 1, 1, 6, 1, 2, 1, 6, 12 };
119static const int db9_num_axis[DB9_MAX_PAD] = { 0, 2, 2, 2, 0, 2, 2, 7, 2, 2, 2 ,7, 7 };
120static const short db9_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_RZ, ABS_Z, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y };
121static const int db9_bidirectional[DB9_MAX_PAD] = { 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0 };
122static const int db9_reverse[DB9_MAX_PAD] = { 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0 };
123
124/*
125 * Saturn controllers
126 */
127#define DB9_SATURN_DELAY 300
128static const int db9_saturn_byte[] = { 1, 1, 1, 2, 2, 2, 2, 2, 1 };
129static const unsigned char db9_saturn_mask[] = { 0x04, 0x01, 0x02, 0x40, 0x20, 0x10, 0x08, 0x80, 0x08 };
130
131/*
132 * db9_saturn_write_sub() writes 2 bit data.
133 */
134static void db9_saturn_write_sub(struct parport *port, int type, unsigned char data, int powered, int pwr_sub)
135{
136 unsigned char c;
137
138 switch (type) {
139 case 1: /* DPP1 */
140 c = 0x80 | 0x30 | (powered ? 0x08 : 0) | (pwr_sub ? 0x04 : 0) | data;
141 parport_write_data(port, c);
142 break;
143 case 2: /* DPP2 */
144 c = 0x40 | data << 4 | (powered ? 0x08 : 0) | (pwr_sub ? 0x04 : 0) | 0x03;
145 parport_write_data(port, c);
146 break;
147 case 0: /* DB9 */
148 c = ((((data & 2) ? 2 : 0) | ((data & 1) ? 4 : 0)) ^ 0x02) | !powered;
149 parport_write_control(port, c);
150 break;
151 }
152}
153
154/*
155 * gc_saturn_read_sub() reads 4 bit data.
156 */
157static unsigned char db9_saturn_read_sub(struct parport *port, int type)
158{
159 unsigned char data;
160
161 if (type) {
162 /* DPP */
163 data = parport_read_status(port) ^ 0x80;
164 return (data & 0x80 ? 1 : 0) | (data & 0x40 ? 2 : 0)
165 | (data & 0x20 ? 4 : 0) | (data & 0x10 ? 8 : 0);
166 } else {
167 /* DB9 */
168 data = parport_read_data(port) & 0x0f;
169 return (data & 0x8 ? 1 : 0) | (data & 0x4 ? 2 : 0)
170 | (data & 0x2 ? 4 : 0) | (data & 0x1 ? 8 : 0);
171 }
172}
173
174/*
175 * db9_saturn_read_analog() sends clock and reads 8 bit data.
176 */
177static unsigned char db9_saturn_read_analog(struct parport *port, int type, int powered)
178{
179 unsigned char data;
180
181 db9_saturn_write_sub(port, type, 0, powered, 0);
182 udelay(DB9_SATURN_DELAY);
183 data = db9_saturn_read_sub(port, type) << 4;
184 db9_saturn_write_sub(port, type, 2, powered, 0);
185 udelay(DB9_SATURN_DELAY);
186 data |= db9_saturn_read_sub(port, type);
187 return data;
188}
189
190/*
191 * db9_saturn_read_packet() reads whole saturn packet at connector
192 * and returns device identifier code.
193 */
194static unsigned char db9_saturn_read_packet(struct parport *port, unsigned char *data, int type, int powered)
195{
196 int i, j;
197 unsigned char tmp;
198
199 db9_saturn_write_sub(port, type, 3, powered, 0);
200 data[0] = db9_saturn_read_sub(port, type);
201 switch (data[0] & 0x0f) {
202 case 0xf:
203 /* 1111 no pad */
204 return data[0] = 0xff;
205 case 0x4: case 0x4 | 0x8:
206 /* ?100 : digital controller */
207 db9_saturn_write_sub(port, type, 0, powered, 1);
208 data[2] = db9_saturn_read_sub(port, type) << 4;
209 db9_saturn_write_sub(port, type, 2, powered, 1);
210 data[1] = db9_saturn_read_sub(port, type) << 4;
211 db9_saturn_write_sub(port, type, 1, powered, 1);
212 data[1] |= db9_saturn_read_sub(port, type);
213 db9_saturn_write_sub(port, type, 3, powered, 1);
214 /* data[2] |= db9_saturn_read_sub(port, type); */
215 data[2] |= data[0];
216 return data[0] = 0x02;
217 case 0x1:
218 /* 0001 : analog controller or multitap */
219 db9_saturn_write_sub(port, type, 2, powered, 0);
220 udelay(DB9_SATURN_DELAY);
221 data[0] = db9_saturn_read_analog(port, type, powered);
222 if (data[0] != 0x41) {
223 /* read analog controller */
224 for (i = 0; i < (data[0] & 0x0f); i++)
225 data[i + 1] = db9_saturn_read_analog(port, type, powered);
226 db9_saturn_write_sub(port, type, 3, powered, 0);
227 return data[0];
228 } else {
229 /* read multitap */
230 if (db9_saturn_read_analog(port, type, powered) != 0x60)
231 return data[0] = 0xff;
232 for (i = 0; i < 60; i += 10) {
233 data[i] = db9_saturn_read_analog(port, type, powered);
234 if (data[i] != 0xff)
235 /* read each pad */
236 for (j = 0; j < (data[i] & 0x0f); j++)
237 data[i + j + 1] = db9_saturn_read_analog(port, type, powered);
238 }
239 db9_saturn_write_sub(port, type, 3, powered, 0);
240 return 0x41;
241 }
242 case 0x0:
243 /* 0000 : mouse */
244 db9_saturn_write_sub(port, type, 2, powered, 0);
245 udelay(DB9_SATURN_DELAY);
246 tmp = db9_saturn_read_analog(port, type, powered);
247 if (tmp == 0xff) {
248 for (i = 0; i < 3; i++)
249 data[i + 1] = db9_saturn_read_analog(port, type, powered);
250 db9_saturn_write_sub(port, type, 3, powered, 0);
251 return data[0] = 0xe3;
252 }
253 default:
254 return data[0];
255 }
256}
257
258/*
259 * db9_saturn_report() analyzes packet and reports.
260 */
261static int db9_saturn_report(unsigned char id, unsigned char data[60], struct input_dev *dev, int n, int max_pads)
262{
263 int tmp, i, j;
264
265 tmp = (id == 0x41) ? 60 : 10;
266 for (j = 0; (j < tmp) && (n < max_pads); j += 10, n++) {
267 switch (data[j]) {
268 case 0x16: /* multi controller (analog 4 axis) */
269 input_report_abs(dev + n, db9_abs[5], data[j + 6]);
270 case 0x15: /* mission stick (analog 3 axis) */
271 input_report_abs(dev + n, db9_abs[3], data[j + 4]);
272 input_report_abs(dev + n, db9_abs[4], data[j + 5]);
273 case 0x13: /* racing controller (analog 1 axis) */
274 input_report_abs(dev + n, db9_abs[2], data[j + 3]);
275 case 0x34: /* saturn keyboard (udlr ZXC ASD QE Esc) */
276 case 0x02: /* digital pad (digital 2 axis + buttons) */
277 input_report_abs(dev + n, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64));
278 input_report_abs(dev + n, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16));
279 for (i = 0; i < 9; i++)
280 input_report_key(dev + n, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]);
281 break;
282 case 0x19: /* mission stick x2 (analog 6 axis + buttons) */
283 input_report_abs(dev + n, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64));
284 input_report_abs(dev + n, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16));
285 for (i = 0; i < 9; i++)
286 input_report_key(dev + n, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]);
287 input_report_abs(dev + n, db9_abs[2], data[j + 3]);
288 input_report_abs(dev + n, db9_abs[3], data[j + 4]);
289 input_report_abs(dev + n, db9_abs[4], data[j + 5]);
290 /*
291 input_report_abs(dev + n, db9_abs[8], (data[j + 6] & 128 ? 0 : 1) - (data[j + 6] & 64 ? 0 : 1));
292 input_report_abs(dev + n, db9_abs[9], (data[j + 6] & 32 ? 0 : 1) - (data[j + 6] & 16 ? 0 : 1));
293 */
294 input_report_abs(dev + n, db9_abs[6], data[j + 7]);
295 input_report_abs(dev + n, db9_abs[7], data[j + 8]);
296 input_report_abs(dev + n, db9_abs[5], data[j + 9]);
297 break;
298 case 0xd3: /* sankyo ff (analog 1 axis + stop btn) */
299 input_report_key(dev + n, BTN_A, data[j + 3] & 0x80);
300 input_report_abs(dev + n, db9_abs[2], data[j + 3] & 0x7f);
301 break;
302 case 0xe3: /* shuttle mouse (analog 2 axis + buttons. signed value) */
303 input_report_key(dev + n, BTN_START, data[j + 1] & 0x08);
304 input_report_key(dev + n, BTN_A, data[j + 1] & 0x04);
305 input_report_key(dev + n, BTN_C, data[j + 1] & 0x02);
306 input_report_key(dev + n, BTN_B, data[j + 1] & 0x01);
307 input_report_abs(dev + n, db9_abs[2], data[j + 2] ^ 0x80);
308 input_report_abs(dev + n, db9_abs[3], (0xff-(data[j + 3] ^ 0x80))+1); /* */
309 break;
310 case 0xff:
311 default: /* no pad */
312 input_report_abs(dev + n, db9_abs[0], 0);
313 input_report_abs(dev + n, db9_abs[1], 0);
314 for (i = 0; i < 9; i++)
315 input_report_key(dev + n, db9_cd32_btn[i], 0);
316 break;
317 }
318 }
319 return n;
320}
321
322static int db9_saturn(int mode, struct parport *port, struct input_dev *dev)
323{
324 unsigned char id, data[60];
325 int type, n, max_pads;
326 int tmp, i;
327
328 switch (mode) {
329 case DB9_SATURN_PAD:
330 type = 0;
331 n = 1;
332 break;
333 case DB9_SATURN_DPP:
334 type = 1;
335 n = 1;
336 break;
337 case DB9_SATURN_DPP_2:
338 type = 1;
339 n = 2;
340 break;
341 default:
342 return -1;
343 }
344 max_pads = min(db9_max_pads[mode], DB9_MAX_DEVICES);
345 for (tmp = 0, i = 0; i < n; i++) {
346 id = db9_saturn_read_packet(port, data, type + i, 1);
347 tmp = db9_saturn_report(id, data, dev, tmp, max_pads);
348 }
349 return 0;
350}
351
352static void db9_timer(unsigned long private)
353{
354 struct db9 *db9 = (void *) private;
355 struct parport *port = db9->pd->port;
356 struct input_dev *dev = db9->dev;
357 int data, i;
358
359 switch(db9->mode) {
360 case DB9_MULTI_0802_2:
361
362 data = parport_read_data(port) >> 3;
363
364 input_report_abs(dev + 1, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
365 input_report_abs(dev + 1, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
366 input_report_key(dev + 1, BTN_TRIGGER, ~data & DB9_FIRE1);
367
368 case DB9_MULTI_0802:
369
370 data = parport_read_status(port) >> 3;
371
372 input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
373 input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
374 input_report_key(dev, BTN_TRIGGER, data & DB9_FIRE1);
375 break;
376
377 case DB9_MULTI_STICK:
378
379 data = parport_read_data(port);
380
381 input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
382 input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
383 input_report_key(dev, BTN_TRIGGER, ~data & DB9_FIRE1);
384 break;
385
386 case DB9_MULTI2_STICK:
387
388 data = parport_read_data(port);
389
390 input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
391 input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
392 input_report_key(dev, BTN_TRIGGER, ~data & DB9_FIRE1);
393 input_report_key(dev, BTN_THUMB, ~data & DB9_FIRE2);
394 break;
395
396 case DB9_GENESIS_PAD:
397
398 parport_write_control(port, DB9_NOSELECT);
399 data = parport_read_data(port);
400
401 input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
402 input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
403 input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
404 input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
405
406 parport_write_control(port, DB9_NORMAL);
407 data=parport_read_data(port);
408
409 input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
410 input_report_key(dev, BTN_START, ~data & DB9_FIRE2);
411 break;
412
413 case DB9_GENESIS5_PAD:
414
415 parport_write_control(port, DB9_NOSELECT);
416 data=parport_read_data(port);
417
418 input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
419 input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
420 input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
421 input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
422
423 parport_write_control(port, DB9_NORMAL);
424 data=parport_read_data(port);
425
426 input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
427 input_report_key(dev, BTN_X, ~data & DB9_FIRE2);
428 input_report_key(dev, BTN_Y, ~data & DB9_LEFT);
429 input_report_key(dev, BTN_START, ~data & DB9_RIGHT);
430 break;
431
432 case DB9_GENESIS6_PAD:
433
434 parport_write_control(port, DB9_NOSELECT); /* 1 */
435 udelay(DB9_GENESIS6_DELAY);
436 data=parport_read_data(port);
437
438 input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
439 input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
440 input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
441 input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
442
443 parport_write_control(port, DB9_NORMAL);
444 udelay(DB9_GENESIS6_DELAY);
445 data=parport_read_data(port);
446
447 input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
448 input_report_key(dev, BTN_START, ~data & DB9_FIRE2);
449
450 parport_write_control(port, DB9_NOSELECT); /* 2 */
451 udelay(DB9_GENESIS6_DELAY);
452 parport_write_control(port, DB9_NORMAL);
453 udelay(DB9_GENESIS6_DELAY);
454 parport_write_control(port, DB9_NOSELECT); /* 3 */
455 udelay(DB9_GENESIS6_DELAY);
456 data=parport_read_data(port);
457
458 input_report_key(dev, BTN_X, ~data & DB9_LEFT);
459 input_report_key(dev, BTN_Y, ~data & DB9_DOWN);
460 input_report_key(dev, BTN_Z, ~data & DB9_UP);
461 input_report_key(dev, BTN_MODE, ~data & DB9_RIGHT);
462
463 parport_write_control(port, DB9_NORMAL);
464 udelay(DB9_GENESIS6_DELAY);
465 parport_write_control(port, DB9_NOSELECT); /* 4 */
466 udelay(DB9_GENESIS6_DELAY);
467 parport_write_control(port, DB9_NORMAL);
468 break;
469
470 case DB9_SATURN_PAD:
471 case DB9_SATURN_DPP:
472 case DB9_SATURN_DPP_2:
473
474 db9_saturn(db9->mode, port, dev);
475 break;
476
477 case DB9_CD32_PAD:
478
479 data=parport_read_data(port);
480
481 input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
482 input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
483
484 parport_write_control(port, 0x0a);
485
486 for (i = 0; i < 7; i++) {
487 data = parport_read_data(port);
488 parport_write_control(port, 0x02);
489 parport_write_control(port, 0x0a);
490 input_report_key(dev, db9_cd32_btn[i], ~data & DB9_FIRE2);
491 }
492
493 parport_write_control(port, 0x00);
494 break;
495 }
496
497 input_sync(dev);
498
499 mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME);
500}
501
502static int db9_open(struct input_dev *dev)
503{
504 struct db9 *db9 = dev->private;
505 struct parport *port = db9->pd->port;
506
507 if (!db9->used++) {
508 parport_claim(db9->pd);
509 parport_write_data(port, 0xff);
510 if (db9_reverse[db9->mode]) {
511 parport_data_reverse(port);
512 parport_write_control(port, DB9_NORMAL);
513 }
514 mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME);
515 }
516
517 return 0;
518}
519
520static void db9_close(struct input_dev *dev)
521{
522 struct db9 *db9 = dev->private;
523 struct parport *port = db9->pd->port;
524
525 if (!--db9->used) {
526 del_timer(&db9->timer);
527 parport_write_control(port, 0x00);
528 parport_data_forward(port);
529 parport_release(db9->pd);
530 }
531}
532
533static struct db9 __init *db9_probe(int *config, int nargs)
534{
535 struct db9 *db9;
536 struct parport *pp;
537 int i, j;
538
539 if (config[0] < 0)
540 return NULL;
541
542 if (nargs < 2) {
543 printk(KERN_ERR "db9.c: Device type must be specified.\n");
544 return NULL;
545 }
546
547 if (config[1] < 1 || config[1] >= DB9_MAX_PAD || !db9_buttons[config[1]]) {
548 printk(KERN_ERR "db9.c: bad config\n");
549 return NULL;
550 }
551
552 pp = parport_find_number(config[0]);
553 if (!pp) {
554 printk(KERN_ERR "db9.c: no such parport\n");
555 return NULL;
556 }
557
558 if (db9_bidirectional[config[1]]) {
559 if (!(pp->modes & PARPORT_MODE_TRISTATE)) {
560 printk(KERN_ERR "db9.c: specified parport is not bidirectional\n");
561 parport_put_port(pp);
562 return NULL;
563 }
564 }
565
566 if (!(db9 = kmalloc(sizeof(struct db9), GFP_KERNEL))) {
567 parport_put_port(pp);
568 return NULL;
569 }
570 memset(db9, 0, sizeof(struct db9));
571
572 db9->mode = config[1];
573 init_timer(&db9->timer);
574 db9->timer.data = (long) db9;
575 db9->timer.function = db9_timer;
576
577 db9->pd = parport_register_device(pp, "db9", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
578 parport_put_port(pp);
579
580 if (!db9->pd) {
581 printk(KERN_ERR "db9.c: parport busy already - lp.o loaded?\n");
582 kfree(db9);
583 return NULL;
584 }
585
586 for (i = 0; i < (min(db9_max_pads[db9->mode], DB9_MAX_DEVICES)); i++) {
587
588 sprintf(db9->phys[i], "%s/input%d", db9->pd->port->name, i);
589
590 db9->dev[i].private = db9;
591 db9->dev[i].open = db9_open;
592 db9->dev[i].close = db9_close;
593
594 db9->dev[i].name = db9_name[db9->mode];
595 db9->dev[i].phys = db9->phys[i];
596 db9->dev[i].id.bustype = BUS_PARPORT;
597 db9->dev[i].id.vendor = 0x0002;
598 db9->dev[i].id.product = config[1];
599 db9->dev[i].id.version = 0x0100;
600
601 db9->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
602 for (j = 0; j < db9_buttons[db9->mode]; j++)
603 set_bit(db9_btn[db9->mode][j], db9->dev[i].keybit);
604 for (j = 0; j < db9_num_axis[db9->mode]; j++) {
605 set_bit(db9_abs[j], db9->dev[i].absbit);
606 if (j < 2) {
607 db9->dev[i].absmin[db9_abs[j]] = -1;
608 db9->dev[i].absmax[db9_abs[j]] = 1;
609 } else {
610 db9->dev[i].absmin[db9_abs[j]] = 1;
611 db9->dev[i].absmax[db9_abs[j]] = 255;
612 db9->dev[i].absflat[db9_abs[j]] = 0;
613 }
614 }
615 input_register_device(db9->dev + i);
616 printk(KERN_INFO "input: %s on %s\n", db9->dev[i].name, db9->pd->port->name);
617 }
618
619 return db9;
620}
621
622static int __init db9_init(void)
623{
624 db9_base[0] = db9_probe(db9, db9_nargs);
625 db9_base[1] = db9_probe(db9_2, db9_nargs_2);
626 db9_base[2] = db9_probe(db9_3, db9_nargs_3);
627
628 if (db9_base[0] || db9_base[1] || db9_base[2])
629 return 0;
630
631 return -ENODEV;
632}
633
634static void __exit db9_exit(void)
635{
636 int i, j;
637
638 for (i = 0; i < 3; i++)
639 if (db9_base[i]) {
640 for (j = 0; j < min(db9_max_pads[db9_base[i]->mode], DB9_MAX_DEVICES); j++)
641 input_unregister_device(db9_base[i]->dev + j);
642 parport_unregister_device(db9_base[i]->pd);
643 }
644}
645
646module_init(db9_init);
647module_exit(db9_exit);
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
new file mode 100644
index 000000000000..8732f52bdd08
--- /dev/null
+++ b/drivers/input/joystick/gamecon.c
@@ -0,0 +1,697 @@
1/*
2 * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux
3 *
4 * Copyright (c) 1999-2004 Vojtech Pavlik <vojtech@suse.cz>
5 * Copyright (c) 2004 Peter Nelson <rufus-kernel@hackish.org>
6 *
7 * Based on the work of:
8 * Andree Borrmann John Dahlstrom
9 * David Kuder Nathan Hand
10 */
11
12/*
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27 * Should you need to contact me, the author, you can do so either by
28 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
29 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
30 */
31
32#include <linux/kernel.h>
33#include <linux/delay.h>
34#include <linux/module.h>
35#include <linux/moduleparam.h>
36#include <linux/init.h>
37#include <linux/parport.h>
38#include <linux/input.h>
39
40MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
41MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver");
42MODULE_LICENSE("GPL");
43
44static int gc[] __initdata = { -1, 0, 0, 0, 0, 0 };
45static int gc_nargs __initdata = 0;
46module_param_array_named(map, gc, int, &gc_nargs, 0);
47MODULE_PARM_DESC(map, "Describers first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)");
48
49static int gc_2[] __initdata = { -1, 0, 0, 0, 0, 0 };
50static int gc_nargs_2 __initdata = 0;
51module_param_array_named(map2, gc_2, int, &gc_nargs_2, 0);
52MODULE_PARM_DESC(map2, "Describers second set of devices");
53
54static int gc_3[] __initdata = { -1, 0, 0, 0, 0, 0 };
55static int gc_nargs_3 __initdata = 0;
56module_param_array_named(map3, gc_3, int, &gc_nargs_3, 0);
57MODULE_PARM_DESC(map3, "Describers third set of devices");
58
59__obsolete_setup("gc=");
60__obsolete_setup("gc_2=");
61__obsolete_setup("gc_3=");
62
63/* see also gs_psx_delay parameter in PSX support section */
64
65#define GC_SNES 1
66#define GC_NES 2
67#define GC_NES4 3
68#define GC_MULTI 4
69#define GC_MULTI2 5
70#define GC_N64 6
71#define GC_PSX 7
72#define GC_DDR 8
73
74#define GC_MAX 8
75
76#define GC_REFRESH_TIME HZ/100
77
78struct gc {
79 struct pardevice *pd;
80 struct input_dev dev[5];
81 struct timer_list timer;
82 unsigned char pads[GC_MAX + 1];
83 int used;
84 char phys[5][32];
85};
86
87static struct gc *gc_base[3];
88
89static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 };
90
91static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick",
92 "Multisystem 2-button joystick", "N64 controller", "PSX controller",
93 "PSX DDR controller" };
94/*
95 * N64 support.
96 */
97
98static unsigned char gc_n64_bytes[] = { 0, 1, 13, 15, 14, 12, 10, 11, 2, 3 };
99static short gc_n64_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_TRIGGER, BTN_START };
100
101#define GC_N64_LENGTH 32 /* N64 bit length, not including stop bit */
102#define GC_N64_REQUEST_LENGTH 37 /* transmit request sequence is 9 bits long */
103#define GC_N64_DELAY 133 /* delay between transmit request, and response ready (us) */
104#define GC_N64_REQUEST 0x1dd1111111ULL /* the request data command (encoded for 000000011) */
105#define GC_N64_DWS 3 /* delay between write segments (required for sound playback because of ISA DMA) */
106 /* GC_N64_DWS > 24 is known to fail */
107#define GC_N64_POWER_W 0xe2 /* power during write (transmit request) */
108#define GC_N64_POWER_R 0xfd /* power during read */
109#define GC_N64_OUT 0x1d /* output bits to the 4 pads */
110 /* Reading the main axes of any N64 pad is known to fail if the corresponding bit */
111 /* in GC_N64_OUT is pulled low on the output port (by any routine) for more */
112 /* than 123 us */
113#define GC_N64_CLOCK 0x02 /* clock bits for read */
114
115/*
116 * gc_n64_read_packet() reads an N64 packet.
117 * Each pad uses one bit per byte. So all pads connected to this port are read in parallel.
118 */
119
120static void gc_n64_read_packet(struct gc *gc, unsigned char *data)
121{
122 int i;
123 unsigned long flags;
124
125/*
126 * Request the pad to transmit data
127 */
128
129 local_irq_save(flags);
130 for (i = 0; i < GC_N64_REQUEST_LENGTH; i++) {
131 parport_write_data(gc->pd->port, GC_N64_POWER_W | ((GC_N64_REQUEST >> i) & 1 ? GC_N64_OUT : 0));
132 udelay(GC_N64_DWS);
133 }
134 local_irq_restore(flags);
135
136/*
137 * Wait for the pad response to be loaded into the 33-bit register of the adapter
138 */
139
140 udelay(GC_N64_DELAY);
141
142/*
143 * Grab data (ignoring the last bit, which is a stop bit)
144 */
145
146 for (i = 0; i < GC_N64_LENGTH; i++) {
147 parport_write_data(gc->pd->port, GC_N64_POWER_R);
148 data[i] = parport_read_status(gc->pd->port);
149 parport_write_data(gc->pd->port, GC_N64_POWER_R | GC_N64_CLOCK);
150 }
151
152/*
153 * We must wait 200 ms here for the controller to reinitialize before the next read request.
154 * No worries as long as gc_read is polled less frequently than this.
155 */
156
157}
158
159/*
160 * NES/SNES support.
161 */
162
163#define GC_NES_DELAY 6 /* Delay between bits - 6us */
164#define GC_NES_LENGTH 8 /* The NES pads use 8 bits of data */
165#define GC_SNES_LENGTH 12 /* The SNES true length is 16, but the last 4 bits are unused */
166
167#define GC_NES_POWER 0xfc
168#define GC_NES_CLOCK 0x01
169#define GC_NES_LATCH 0x02
170
171static unsigned char gc_nes_bytes[] = { 0, 1, 2, 3 };
172static unsigned char gc_snes_bytes[] = { 8, 0, 2, 3, 9, 1, 10, 11 };
173static short gc_snes_btn[] = { BTN_A, BTN_B, BTN_SELECT, BTN_START, BTN_X, BTN_Y, BTN_TL, BTN_TR };
174
175/*
176 * gc_nes_read_packet() reads a NES/SNES packet.
177 * Each pad uses one bit per byte. So all pads connected to
178 * this port are read in parallel.
179 */
180
181static void gc_nes_read_packet(struct gc *gc, int length, unsigned char *data)
182{
183 int i;
184
185 parport_write_data(gc->pd->port, GC_NES_POWER | GC_NES_CLOCK | GC_NES_LATCH);
186 udelay(GC_NES_DELAY * 2);
187 parport_write_data(gc->pd->port, GC_NES_POWER | GC_NES_CLOCK);
188
189 for (i = 0; i < length; i++) {
190 udelay(GC_NES_DELAY);
191 parport_write_data(gc->pd->port, GC_NES_POWER);
192 data[i] = parport_read_status(gc->pd->port) ^ 0x7f;
193 udelay(GC_NES_DELAY);
194 parport_write_data(gc->pd->port, GC_NES_POWER | GC_NES_CLOCK);
195 }
196}
197
198/*
199 * Multisystem joystick support
200 */
201
202#define GC_MULTI_LENGTH 5 /* Multi system joystick packet length is 5 */
203#define GC_MULTI2_LENGTH 6 /* One more bit for one more button */
204
205/*
206 * gc_multi_read_packet() reads a Multisystem joystick packet.
207 */
208
209static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data)
210{
211 int i;
212
213 for (i = 0; i < length; i++) {
214 parport_write_data(gc->pd->port, ~(1 << i));
215 data[i] = parport_read_status(gc->pd->port) ^ 0x7f;
216 }
217}
218
219/*
220 * PSX support
221 *
222 * See documentation at:
223 * http://www.dim.com/~mackys/psxmemcard/ps-eng2.txt
224 * http://www.gamesx.com/controldata/psxcont/psxcont.htm
225 * ftp://milano.usal.es/pablo/
226 *
227 */
228
229#define GC_PSX_DELAY 25 /* 25 usec */
230#define GC_PSX_LENGTH 8 /* talk to the controller in bits */
231#define GC_PSX_BYTES 6 /* the maximum number of bytes to read off the controller */
232
233#define GC_PSX_MOUSE 1 /* Mouse */
234#define GC_PSX_NEGCON 2 /* NegCon */
235#define GC_PSX_NORMAL 4 /* Digital / Analog or Rumble in Digital mode */
236#define GC_PSX_ANALOG 5 /* Analog in Analog mode / Rumble in Green mode */
237#define GC_PSX_RUMBLE 7 /* Rumble in Red mode */
238
239#define GC_PSX_CLOCK 0x04 /* Pin 4 */
240#define GC_PSX_COMMAND 0x01 /* Pin 2 */
241#define GC_PSX_POWER 0xf8 /* Pins 5-9 */
242#define GC_PSX_SELECT 0x02 /* Pin 3 */
243
244#define GC_PSX_ID(x) ((x) >> 4) /* High nibble is device type */
245#define GC_PSX_LEN(x) (((x) & 0xf) << 1) /* Low nibble is length in bytes/2 */
246
247static int gc_psx_delay = GC_PSX_DELAY;
248module_param_named(psx_delay, gc_psx_delay, uint, 0);
249MODULE_PARM_DESC(psx_delay, "Delay when accessing Sony PSX controller (usecs)");
250
251__obsolete_setup("gc_psx_delay=");
252
253static short gc_psx_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_HAT0X, ABS_HAT0Y };
254static short gc_psx_btn[] = { BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_A, BTN_B, BTN_X, BTN_Y,
255 BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR };
256static short gc_psx_ddr_btn[] = { BTN_0, BTN_1, BTN_2, BTN_3 };
257
258/*
259 * gc_psx_command() writes 8bit command and reads 8bit data from
260 * the psx pad.
261 */
262
263static void gc_psx_command(struct gc *gc, int b, unsigned char data[5])
264{
265 int i, j, cmd, read;
266 for (i = 0; i < 5; i++)
267 data[i] = 0;
268
269 for (i = 0; i < GC_PSX_LENGTH; i++, b >>= 1) {
270 cmd = (b & 1) ? GC_PSX_COMMAND : 0;
271 parport_write_data(gc->pd->port, cmd | GC_PSX_POWER);
272 udelay(gc_psx_delay);
273 read = parport_read_status(gc->pd->port) ^ 0x80;
274 for (j = 0; j < 5; j++)
275 data[j] |= (read & gc_status_bit[j] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) ? (1 << i) : 0;
276 parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER);
277 udelay(gc_psx_delay);
278 }
279}
280
281/*
282 * gc_psx_read_packet() reads a whole psx packet and returns
283 * device identifier code.
284 */
285
286static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES], unsigned char id[5])
287{
288 int i, j, max_len = 0;
289 unsigned long flags;
290 unsigned char data2[5];
291
292 parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); /* Select pad */
293 udelay(gc_psx_delay);
294 parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_POWER); /* Deselect, begin command */
295 udelay(gc_psx_delay);
296
297 local_irq_save(flags);
298
299 gc_psx_command(gc, 0x01, data2); /* Access pad */
300 gc_psx_command(gc, 0x42, id); /* Get device ids */
301 gc_psx_command(gc, 0, data2); /* Dump status */
302
303 for (i =0; i < 5; i++) /* Find the longest pad */
304 if((gc_status_bit[i] & (gc->pads[GC_PSX] | gc->pads[GC_DDR]))
305 && (GC_PSX_LEN(id[i]) > max_len)
306 && (GC_PSX_LEN(id[i]) <= GC_PSX_BYTES))
307 max_len = GC_PSX_LEN(id[i]);
308
309 for (i = 0; i < max_len; i++) { /* Read in all the data */
310 gc_psx_command(gc, 0, data2);
311 for (j = 0; j < 5; j++)
312 data[j][i] = data2[j];
313 }
314
315 local_irq_restore(flags);
316
317 parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);
318
319 for(i = 0; i < 5; i++) /* Set id's to the real value */
320 id[i] = GC_PSX_ID(id[i]);
321}
322
323/*
324 * gc_timer() reads and analyzes console pads data.
325 */
326
327#define GC_MAX_LENGTH GC_N64_LENGTH
328
329static void gc_timer(unsigned long private)
330{
331 struct gc *gc = (void *) private;
332 struct input_dev *dev = gc->dev;
333 unsigned char data[GC_MAX_LENGTH];
334 unsigned char data_psx[5][GC_PSX_BYTES];
335 int i, j, s;
336
337/*
338 * N64 pads - must be read first, any read confuses them for 200 us
339 */
340
341 if (gc->pads[GC_N64]) {
342
343 gc_n64_read_packet(gc, data);
344
345 for (i = 0; i < 5; i++) {
346
347 s = gc_status_bit[i];
348
349 if (s & gc->pads[GC_N64] & ~(data[8] | data[9])) {
350
351 signed char axes[2];
352 axes[0] = axes[1] = 0;
353
354 for (j = 0; j < 8; j++) {
355 if (data[23 - j] & s) axes[0] |= 1 << j;
356 if (data[31 - j] & s) axes[1] |= 1 << j;
357 }
358
359 input_report_abs(dev + i, ABS_X, axes[0]);
360 input_report_abs(dev + i, ABS_Y, -axes[1]);
361
362 input_report_abs(dev + i, ABS_HAT0X, !(s & data[6]) - !(s & data[7]));
363 input_report_abs(dev + i, ABS_HAT0Y, !(s & data[4]) - !(s & data[5]));
364
365 for (j = 0; j < 10; j++)
366 input_report_key(dev + i, gc_n64_btn[j], s & data[gc_n64_bytes[j]]);
367
368 input_sync(dev + i);
369 }
370 }
371 }
372
373/*
374 * NES and SNES pads
375 */
376
377 if (gc->pads[GC_NES] || gc->pads[GC_SNES]) {
378
379 gc_nes_read_packet(gc, gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH, data);
380
381 for (i = 0; i < 5; i++) {
382
383 s = gc_status_bit[i];
384
385 if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) {
386 input_report_abs(dev + i, ABS_X, !(s & data[6]) - !(s & data[7]));
387 input_report_abs(dev + i, ABS_Y, !(s & data[4]) - !(s & data[5]));
388 }
389
390 if (s & gc->pads[GC_NES])
391 for (j = 0; j < 4; j++)
392 input_report_key(dev + i, gc_snes_btn[j], s & data[gc_nes_bytes[j]]);
393
394 if (s & gc->pads[GC_SNES])
395 for (j = 0; j < 8; j++)
396 input_report_key(dev + i, gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
397
398 input_sync(dev + i);
399 }
400 }
401
402/*
403 * Multi and Multi2 joysticks
404 */
405
406 if (gc->pads[GC_MULTI] || gc->pads[GC_MULTI2]) {
407
408 gc_multi_read_packet(gc, gc->pads[GC_MULTI2] ? GC_MULTI2_LENGTH : GC_MULTI_LENGTH, data);
409
410 for (i = 0; i < 5; i++) {
411
412 s = gc_status_bit[i];
413
414 if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) {
415 input_report_abs(dev + i, ABS_X, !(s & data[2]) - !(s & data[3]));
416 input_report_abs(dev + i, ABS_Y, !(s & data[0]) - !(s & data[1]));
417 input_report_key(dev + i, BTN_TRIGGER, s & data[4]);
418 }
419
420 if (s & gc->pads[GC_MULTI2])
421 input_report_key(dev + i, BTN_THUMB, s & data[5]);
422
423 input_sync(dev + i);
424 }
425 }
426
427/*
428 * PSX controllers
429 */
430
431 if (gc->pads[GC_PSX] || gc->pads[GC_DDR]) {
432
433 gc_psx_read_packet(gc, data_psx, data);
434
435 for (i = 0; i < 5; i++) {
436 switch (data[i]) {
437
438 case GC_PSX_RUMBLE:
439
440 input_report_key(dev + i, BTN_THUMBL, ~data_psx[i][0] & 0x04);
441 input_report_key(dev + i, BTN_THUMBR, ~data_psx[i][0] & 0x02);
442
443 case GC_PSX_NEGCON:
444 case GC_PSX_ANALOG:
445
446 if(gc->pads[GC_DDR] & gc_status_bit[i]) {
447 for(j = 0; j < 4; j++)
448 input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
449 } else {
450 for (j = 0; j < 4; j++)
451 input_report_abs(dev + i, gc_psx_abs[j+2], data_psx[i][j + 2]);
452
453 input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
454 input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
455 }
456
457 for (j = 0; j < 8; j++)
458 input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
459
460 input_report_key(dev + i, BTN_START, ~data_psx[i][0] & 0x08);
461 input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01);
462
463 input_sync(dev + i);
464
465 break;
466
467 case GC_PSX_NORMAL:
468 if(gc->pads[GC_DDR] & gc_status_bit[i]) {
469 for(j = 0; j < 4; j++)
470 input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
471 } else {
472 input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
473 input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
474
475 /* for some reason if the extra axes are left unset they drift */
476 /* for (j = 0; j < 4; j++)
477 input_report_abs(dev + i, gc_psx_abs[j+2], 128);
478 * This needs to be debugged properly,
479 * maybe fuzz processing needs to be done in input_sync()
480 * --vojtech
481 */
482 }
483
484 for (j = 0; j < 8; j++)
485 input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
486
487 input_report_key(dev + i, BTN_START, ~data_psx[i][0] & 0x08);
488 input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01);
489
490 input_sync(dev + i);
491
492 break;
493
494 case 0: /* not a pad, ignore */
495 break;
496 }
497 }
498 }
499
500 mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
501}
502
503static int gc_open(struct input_dev *dev)
504{
505 struct gc *gc = dev->private;
506 if (!gc->used++) {
507 parport_claim(gc->pd);
508 parport_write_control(gc->pd->port, 0x04);
509 mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
510 }
511 return 0;
512}
513
514static void gc_close(struct input_dev *dev)
515{
516 struct gc *gc = dev->private;
517 if (!--gc->used) {
518 del_timer(&gc->timer);
519 parport_write_control(gc->pd->port, 0x00);
520 parport_release(gc->pd);
521 }
522}
523
524static struct gc __init *gc_probe(int *config, int nargs)
525{
526 struct gc *gc;
527 struct parport *pp;
528 int i, j;
529
530 if (config[0] < 0)
531 return NULL;
532
533 if (nargs < 2) {
534 printk(KERN_ERR "gamecon.c: at least one device must be specified\n");
535 return NULL;
536 }
537
538 pp = parport_find_number(config[0]);
539
540 if (!pp) {
541 printk(KERN_ERR "gamecon.c: no such parport\n");
542 return NULL;
543 }
544
545 if (!(gc = kmalloc(sizeof(struct gc), GFP_KERNEL))) {
546 parport_put_port(pp);
547 return NULL;
548 }
549 memset(gc, 0, sizeof(struct gc));
550
551 gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
552
553 parport_put_port(pp);
554
555 if (!gc->pd) {
556 printk(KERN_ERR "gamecon.c: parport busy already - lp.o loaded?\n");
557 kfree(gc);
558 return NULL;
559 }
560
561 parport_claim(gc->pd);
562
563 init_timer(&gc->timer);
564 gc->timer.data = (long) gc;
565 gc->timer.function = gc_timer;
566
567 for (i = 0; i < nargs - 1; i++) {
568
569 if (!config[i + 1])
570 continue;
571
572 if (config[i + 1] < 1 || config[i + 1] > GC_MAX) {
573 printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", config[i + 1]);
574 continue;
575 }
576
577 gc->dev[i].private = gc;
578 gc->dev[i].open = gc_open;
579 gc->dev[i].close = gc_close;
580
581 gc->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
582
583 for (j = 0; j < 2; j++) {
584 set_bit(ABS_X + j, gc->dev[i].absbit);
585 gc->dev[i].absmin[ABS_X + j] = -1;
586 gc->dev[i].absmax[ABS_X + j] = 1;
587 }
588
589 gc->pads[0] |= gc_status_bit[i];
590 gc->pads[config[i + 1]] |= gc_status_bit[i];
591
592 switch(config[i + 1]) {
593
594 case GC_N64:
595 for (j = 0; j < 10; j++)
596 set_bit(gc_n64_btn[j], gc->dev[i].keybit);
597
598 for (j = 0; j < 2; j++) {
599 set_bit(ABS_X + j, gc->dev[i].absbit);
600 gc->dev[i].absmin[ABS_X + j] = -127;
601 gc->dev[i].absmax[ABS_X + j] = 126;
602 gc->dev[i].absflat[ABS_X + j] = 2;
603 set_bit(ABS_HAT0X + j, gc->dev[i].absbit);
604 gc->dev[i].absmin[ABS_HAT0X + j] = -1;
605 gc->dev[i].absmax[ABS_HAT0X + j] = 1;
606 }
607
608 break;
609
610 case GC_SNES:
611 for (j = 4; j < 8; j++)
612 set_bit(gc_snes_btn[j], gc->dev[i].keybit);
613 case GC_NES:
614 for (j = 0; j < 4; j++)
615 set_bit(gc_snes_btn[j], gc->dev[i].keybit);
616 break;
617
618 case GC_MULTI2:
619 set_bit(BTN_THUMB, gc->dev[i].keybit);
620 case GC_MULTI:
621 set_bit(BTN_TRIGGER, gc->dev[i].keybit);
622 break;
623
624 case GC_PSX:
625 case GC_DDR:
626 if(config[i + 1] == GC_DDR) {
627 for (j = 0; j < 4; j++)
628 set_bit(gc_psx_ddr_btn[j], gc->dev[i].keybit);
629 } else {
630 for (j = 0; j < 6; j++) {
631 set_bit(gc_psx_abs[j], gc->dev[i].absbit);
632 gc->dev[i].absmin[gc_psx_abs[j]] = 4;
633 gc->dev[i].absmax[gc_psx_abs[j]] = 252;
634 gc->dev[i].absflat[gc_psx_abs[j]] = 2;
635 }
636 }
637
638 for (j = 0; j < 12; j++)
639 set_bit(gc_psx_btn[j], gc->dev[i].keybit);
640
641 break;
642 }
643
644 sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i);
645
646 gc->dev[i].name = gc_names[config[i + 1]];
647 gc->dev[i].phys = gc->phys[i];
648 gc->dev[i].id.bustype = BUS_PARPORT;
649 gc->dev[i].id.vendor = 0x0001;
650 gc->dev[i].id.product = config[i + 1];
651 gc->dev[i].id.version = 0x0100;
652 }
653
654 parport_release(gc->pd);
655
656 if (!gc->pads[0]) {
657 parport_unregister_device(gc->pd);
658 kfree(gc);
659 return NULL;
660 }
661
662 for (i = 0; i < 5; i++)
663 if (gc->pads[0] & gc_status_bit[i]) {
664 input_register_device(gc->dev + i);
665 printk(KERN_INFO "input: %s on %s\n", gc->dev[i].name, gc->pd->port->name);
666 }
667
668 return gc;
669}
670
671static int __init gc_init(void)
672{
673 gc_base[0] = gc_probe(gc, gc_nargs);
674 gc_base[1] = gc_probe(gc_2, gc_nargs_2);
675 gc_base[2] = gc_probe(gc_3, gc_nargs_3);
676
677 if (gc_base[0] || gc_base[1] || gc_base[2])
678 return 0;
679
680 return -ENODEV;
681}
682
683static void __exit gc_exit(void)
684{
685 int i, j;
686
687 for (i = 0; i < 3; i++)
688 if (gc_base[i]) {
689 for (j = 0; j < 5; j++)
690 if (gc_base[i]->pads[0] & gc_status_bit[j])
691 input_unregister_device(gc_base[i]->dev + j);
692 parport_unregister_device(gc_base[i]->pd);
693 }
694}
695
696module_init(gc_init);
697module_exit(gc_exit);
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c
new file mode 100644
index 000000000000..ad13f09a4e71
--- /dev/null
+++ b/drivers/input/joystick/gf2k.c
@@ -0,0 +1,380 @@
1/*
2 * $Id: gf2k.c,v 1.19 2002/01/22 20:27:43 vojtech Exp $
3 *
4 * Copyright (c) 1998-2001 Vojtech Pavlik
5 */
6
7/*
8 * Genius Flight 2000 joystick driver for Linux
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/delay.h>
32#include <linux/kernel.h>
33#include <linux/slab.h>
34#include <linux/module.h>
35#include <linux/init.h>
36#include <linux/input.h>
37#include <linux/gameport.h>
38
39#define DRIVER_DESC "Genius Flight 2000 joystick driver"
40
41MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
42MODULE_DESCRIPTION(DRIVER_DESC);
43MODULE_LICENSE("GPL");
44
45#define GF2K_START 400 /* The time we wait for the first bit [400 us] */
46#define GF2K_STROBE 40 /* The time we wait for the first bit [40 us] */
47#define GF2K_TIMEOUT 4 /* Wait for everything to settle [4 ms] */
48#define GF2K_LENGTH 80 /* Max number of triplets in a packet */
49
50/*
51 * Genius joystick ids ...
52 */
53
54#define GF2K_ID_G09 1
55#define GF2K_ID_F30D 2
56#define GF2K_ID_F30 3
57#define GF2K_ID_F31D 4
58#define GF2K_ID_F305 5
59#define GF2K_ID_F23P 6
60#define GF2K_ID_F31 7
61#define GF2K_ID_MAX 7
62
63static char gf2k_length[] = { 40, 40, 40, 40, 40, 40, 40, 40 };
64static char gf2k_hat_to_axis[][2] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
65
66static char *gf2k_names[] = {"", "Genius G-09D", "Genius F-30D", "Genius F-30", "Genius MaxFighter F-31D",
67 "Genius F-30-5", "Genius Flight2000 F-23", "Genius F-31"};
68static unsigned char gf2k_hats[] = { 0, 2, 0, 0, 2, 0, 2, 0 };
69static unsigned char gf2k_axes[] = { 0, 2, 0, 0, 4, 0, 4, 0 };
70static unsigned char gf2k_joys[] = { 0, 0, 0, 0,10, 0, 8, 0 };
71static unsigned char gf2k_pads[] = { 0, 6, 0, 0, 0, 0, 0, 0 };
72static unsigned char gf2k_lens[] = { 0,18, 0, 0,18, 0,18, 0 };
73
74static unsigned char gf2k_abs[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, ABS_GAS, ABS_BRAKE };
75static short gf2k_btn_joy[] = { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4 };
76static short gf2k_btn_pad[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_START, BTN_SELECT };
77
78
79static short gf2k_seq_reset[] = { 240, 340, 0 };
80static short gf2k_seq_digital[] = { 590, 320, 860, 0 };
81
82struct gf2k {
83 struct gameport *gameport;
84 struct input_dev dev;
85 int reads;
86 int bads;
87 unsigned char id;
88 unsigned char length;
89 char phys[32];
90};
91
92/*
93 * gf2k_read_packet() reads a Genius Flight2000 packet.
94 */
95
96static int gf2k_read_packet(struct gameport *gameport, int length, char *data)
97{
98 unsigned char u, v;
99 int i;
100 unsigned int t, p;
101 unsigned long flags;
102
103 t = gameport_time(gameport, GF2K_START);
104 p = gameport_time(gameport, GF2K_STROBE);
105
106 i = 0;
107
108 local_irq_save(flags);
109
110 gameport_trigger(gameport);
111 v = gameport_read(gameport);
112
113 while (t > 0 && i < length) {
114 t--; u = v;
115 v = gameport_read(gameport);
116 if (v & ~u & 0x10) {
117 data[i++] = v >> 5;
118 t = p;
119 }
120 }
121
122 local_irq_restore(flags);
123
124 return i;
125}
126
127/*
128 * gf2k_trigger_seq() initializes a Genius Flight2000 joystick
129 * into digital mode.
130 */
131
132static void gf2k_trigger_seq(struct gameport *gameport, short *seq)
133{
134
135 unsigned long flags;
136 int i, t;
137
138 local_irq_save(flags);
139
140 i = 0;
141 do {
142 gameport_trigger(gameport);
143 t = gameport_time(gameport, GF2K_TIMEOUT * 1000);
144 while ((gameport_read(gameport) & 1) && t) t--;
145 udelay(seq[i]);
146 } while (seq[++i]);
147
148 gameport_trigger(gameport);
149
150 local_irq_restore(flags);
151}
152
153/*
154 * js_sw_get_bits() composes bits from the triplet buffer into a __u64.
155 * Parameter 'pos' is bit number inside packet where to start at, 'num' is number
156 * of bits to be read, 'shift' is offset in the resulting __u64 to start at, bits
157 * is number of bits per triplet.
158 */
159
160#define GB(p,n,s) gf2k_get_bits(data, p, n, s)
161
162static int gf2k_get_bits(unsigned char *buf, int pos, int num, int shift)
163{
164 __u64 data = 0;
165 int i;
166
167 for (i = 0; i < num / 3 + 2; i++)
168 data |= buf[pos / 3 + i] << (i * 3);
169 data >>= pos % 3;
170 data &= (1 << num) - 1;
171 data <<= shift;
172
173 return data;
174}
175
176static void gf2k_read(struct gf2k *gf2k, unsigned char *data)
177{
178 struct input_dev *dev = &gf2k->dev;
179 int i, t;
180
181 for (i = 0; i < 4 && i < gf2k_axes[gf2k->id]; i++)
182 input_report_abs(dev, gf2k_abs[i], GB(i<<3,8,0) | GB(i+46,1,8) | GB(i+50,1,9));
183
184 for (i = 0; i < 2 && i < gf2k_axes[gf2k->id] - 4; i++)
185 input_report_abs(dev, gf2k_abs[i], GB(i*9+60,8,0) | GB(i+54,1,9));
186
187 t = GB(40,4,0);
188
189 for (i = 0; i < gf2k_hats[gf2k->id]; i++)
190 input_report_abs(dev, ABS_HAT0X + i, gf2k_hat_to_axis[t][i]);
191
192 t = GB(44,2,0) | GB(32,8,2) | GB(78,2,10);
193
194 for (i = 0; i < gf2k_joys[gf2k->id]; i++)
195 input_report_key(dev, gf2k_btn_joy[i], (t >> i) & 1);
196
197 for (i = 0; i < gf2k_pads[gf2k->id]; i++)
198 input_report_key(dev, gf2k_btn_pad[i], (t >> i) & 1);
199
200 input_sync(dev);
201}
202
203/*
204 * gf2k_poll() reads and analyzes Genius joystick data.
205 */
206
207static void gf2k_poll(struct gameport *gameport)
208{
209 struct gf2k *gf2k = gameport_get_drvdata(gameport);
210 unsigned char data[GF2K_LENGTH];
211
212 gf2k->reads++;
213
214 if (gf2k_read_packet(gf2k->gameport, gf2k_length[gf2k->id], data) < gf2k_length[gf2k->id])
215 gf2k->bads++;
216 else
217 gf2k_read(gf2k, data);
218}
219
220static int gf2k_open(struct input_dev *dev)
221{
222 struct gf2k *gf2k = dev->private;
223
224 gameport_start_polling(gf2k->gameport);
225 return 0;
226}
227
228static void gf2k_close(struct input_dev *dev)
229{
230 struct gf2k *gf2k = dev->private;
231
232 gameport_stop_polling(gf2k->gameport);
233}
234
235/*
236 * gf2k_connect() probes for Genius id joysticks.
237 */
238
239static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
240{
241 struct gf2k *gf2k;
242 unsigned char data[GF2K_LENGTH];
243 int i, err;
244
245 if (!(gf2k = kcalloc(1, sizeof(struct gf2k), GFP_KERNEL)))
246 return -ENOMEM;
247
248 gf2k->gameport = gameport;
249
250 gameport_set_drvdata(gameport, gf2k);
251
252 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
253 if (err)
254 goto fail1;
255
256 gf2k_trigger_seq(gameport, gf2k_seq_reset);
257
258 msleep(GF2K_TIMEOUT);
259
260 gf2k_trigger_seq(gameport, gf2k_seq_digital);
261
262 msleep(GF2K_TIMEOUT);
263
264 if (gf2k_read_packet(gameport, GF2K_LENGTH, data) < 12) {
265 err = -ENODEV;
266 goto fail2;
267 }
268
269 if (!(gf2k->id = GB(7,2,0) | GB(3,3,2) | GB(0,3,5))) {
270 err = -ENODEV;
271 goto fail2;
272 }
273
274#ifdef RESET_WORKS
275 if ((gf2k->id != (GB(19,2,0) | GB(15,3,2) | GB(12,3,5))) ||
276 (gf2k->id != (GB(31,2,0) | GB(27,3,2) | GB(24,3,5)))) {
277 err = -ENODEV;
278 goto fail2;
279 }
280#else
281 gf2k->id = 6;
282#endif
283
284 if (gf2k->id > GF2K_ID_MAX || !gf2k_axes[gf2k->id]) {
285 printk(KERN_WARNING "gf2k.c: Not yet supported joystick on %s. [id: %d type:%s]\n",
286 gameport->phys, gf2k->id, gf2k->id > GF2K_ID_MAX ? "Unknown" : gf2k_names[gf2k->id]);
287 err = -ENODEV;
288 goto fail2;
289 }
290
291 gameport_set_poll_handler(gameport, gf2k_poll);
292 gameport_set_poll_interval(gameport, 20);
293
294 sprintf(gf2k->phys, "%s/input0", gameport->phys);
295
296 gf2k->length = gf2k_lens[gf2k->id];
297
298 init_input_dev(&gf2k->dev);
299
300 gf2k->dev.private = gf2k;
301 gf2k->dev.open = gf2k_open;
302 gf2k->dev.close = gf2k_close;
303 gf2k->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
304
305 gf2k->dev.name = gf2k_names[gf2k->id];
306 gf2k->dev.phys = gf2k->phys;
307 gf2k->dev.id.bustype = BUS_GAMEPORT;
308 gf2k->dev.id.vendor = GAMEPORT_ID_VENDOR_GENIUS;
309 gf2k->dev.id.product = gf2k->id;
310 gf2k->dev.id.version = 0x0100;
311
312 for (i = 0; i < gf2k_axes[gf2k->id]; i++)
313 set_bit(gf2k_abs[i], gf2k->dev.absbit);
314
315 for (i = 0; i < gf2k_hats[gf2k->id]; i++) {
316 set_bit(ABS_HAT0X + i, gf2k->dev.absbit);
317 gf2k->dev.absmin[ABS_HAT0X + i] = -1;
318 gf2k->dev.absmax[ABS_HAT0X + i] = 1;
319 }
320
321 for (i = 0; i < gf2k_joys[gf2k->id]; i++)
322 set_bit(gf2k_btn_joy[i], gf2k->dev.keybit);
323
324 for (i = 0; i < gf2k_pads[gf2k->id]; i++)
325 set_bit(gf2k_btn_pad[i], gf2k->dev.keybit);
326
327 gf2k_read_packet(gameport, gf2k->length, data);
328 gf2k_read(gf2k, data);
329
330 for (i = 0; i < gf2k_axes[gf2k->id]; i++) {
331 gf2k->dev.absmax[gf2k_abs[i]] = (i < 2) ? gf2k->dev.abs[gf2k_abs[i]] * 2 - 32 :
332 gf2k->dev.abs[gf2k_abs[0]] + gf2k->dev.abs[gf2k_abs[1]] - 32;
333 gf2k->dev.absmin[gf2k_abs[i]] = 32;
334 gf2k->dev.absfuzz[gf2k_abs[i]] = 8;
335 gf2k->dev.absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0;
336 }
337
338 input_register_device(&gf2k->dev);
339 printk(KERN_INFO "input: %s on %s\n", gf2k_names[gf2k->id], gameport->phys);
340
341 return 0;
342
343fail2: gameport_close(gameport);
344fail1: gameport_set_drvdata(gameport, NULL);
345 kfree(gf2k);
346 return err;
347}
348
349static void gf2k_disconnect(struct gameport *gameport)
350{
351 struct gf2k *gf2k = gameport_get_drvdata(gameport);
352
353 input_unregister_device(&gf2k->dev);
354 gameport_close(gameport);
355 gameport_set_drvdata(gameport, NULL);
356 kfree(gf2k);
357}
358
359static struct gameport_driver gf2k_drv = {
360 .driver = {
361 .name = "gf2k",
362 },
363 .description = DRIVER_DESC,
364 .connect = gf2k_connect,
365 .disconnect = gf2k_disconnect,
366};
367
368static int __init gf2k_init(void)
369{
370 gameport_register_driver(&gf2k_drv);
371 return 0;
372}
373
374static void __exit gf2k_exit(void)
375{
376 gameport_unregister_driver(&gf2k_drv);
377}
378
379module_init(gf2k_init);
380module_exit(gf2k_exit);
diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c
new file mode 100644
index 000000000000..d1500d2562d6
--- /dev/null
+++ b/drivers/input/joystick/grip.c
@@ -0,0 +1,422 @@
1/*
2 * $Id: grip.c,v 1.21 2002/01/22 20:27:57 vojtech Exp $
3 *
4 * Copyright (c) 1998-2001 Vojtech Pavlik
5 */
6
7/*
8 * Gravis/Kensington GrIP protocol joystick and gamepad driver for Linux
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/kernel.h>
32#include <linux/module.h>
33#include <linux/init.h>
34#include <linux/slab.h>
35#include <linux/gameport.h>
36#include <linux/input.h>
37
38#define DRIVER_DESC "Gravis GrIP protocol joystick driver"
39
40MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
41MODULE_DESCRIPTION(DRIVER_DESC);
42MODULE_LICENSE("GPL");
43
44#define GRIP_MODE_GPP 1
45#define GRIP_MODE_BD 2
46#define GRIP_MODE_XT 3
47#define GRIP_MODE_DC 4
48
49#define GRIP_LENGTH_GPP 24
50#define GRIP_STROBE_GPP 200 /* 200 us */
51#define GRIP_LENGTH_XT 4
52#define GRIP_STROBE_XT 64 /* 64 us */
53#define GRIP_MAX_CHUNKS_XT 10
54#define GRIP_MAX_BITS_XT 30
55
56struct grip {
57 struct gameport *gameport;
58 struct input_dev dev[2];
59 unsigned char mode[2];
60 int reads;
61 int bads;
62 char phys[2][32];
63};
64
65static int grip_btn_gpp[] = { BTN_START, BTN_SELECT, BTN_TR2, BTN_Y, 0, BTN_TL2, BTN_A, BTN_B, BTN_X, 0, BTN_TL, BTN_TR, -1 };
66static int grip_btn_bd[] = { BTN_THUMB, BTN_THUMB2, BTN_TRIGGER, BTN_TOP, BTN_BASE, -1 };
67static int grip_btn_xt[] = { BTN_TRIGGER, BTN_THUMB, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_SELECT, BTN_START, BTN_MODE, -1 };
68static int grip_btn_dc[] = { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_BASE5, -1 };
69
70static int grip_abs_gpp[] = { ABS_X, ABS_Y, -1 };
71static int grip_abs_bd[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 };
72static int grip_abs_xt[] = { ABS_X, ABS_Y, ABS_BRAKE, ABS_GAS, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, -1 };
73static int grip_abs_dc[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 };
74
75static char *grip_name[] = { NULL, "Gravis GamePad Pro", "Gravis Blackhawk Digital",
76 "Gravis Xterminator Digital", "Gravis Xterminator DualControl" };
77static int *grip_abs[] = { NULL, grip_abs_gpp, grip_abs_bd, grip_abs_xt, grip_abs_dc };
78static int *grip_btn[] = { NULL, grip_btn_gpp, grip_btn_bd, grip_btn_xt, grip_btn_dc };
79static char grip_anx[] = { 0, 0, 3, 5, 5 };
80static char grip_cen[] = { 0, 0, 2, 2, 4 };
81
82/*
83 * grip_gpp_read_packet() reads a Gravis GamePad Pro packet.
84 */
85
86static int grip_gpp_read_packet(struct gameport *gameport, int shift, unsigned int *data)
87{
88 unsigned long flags;
89 unsigned char u, v;
90 unsigned int t;
91 int i;
92
93 int strobe = gameport_time(gameport, GRIP_STROBE_GPP);
94
95 data[0] = 0;
96 t = strobe;
97 i = 0;
98
99 local_irq_save(flags);
100
101 v = gameport_read(gameport) >> shift;
102
103 do {
104 t--;
105 u = v; v = (gameport_read(gameport) >> shift) & 3;
106 if (~v & u & 1) {
107 data[0] |= (v >> 1) << i++;
108 t = strobe;
109 }
110 } while (i < GRIP_LENGTH_GPP && t > 0);
111
112 local_irq_restore(flags);
113
114 if (i < GRIP_LENGTH_GPP) return -1;
115
116 for (i = 0; i < GRIP_LENGTH_GPP && (data[0] & 0xfe4210) ^ 0x7c0000; i++)
117 data[0] = data[0] >> 1 | (data[0] & 1) << (GRIP_LENGTH_GPP - 1);
118
119 return -(i == GRIP_LENGTH_GPP);
120}
121
122/*
123 * grip_xt_read_packet() reads a Gravis Xterminator packet.
124 */
125
126static int grip_xt_read_packet(struct gameport *gameport, int shift, unsigned int *data)
127{
128 unsigned int i, j, buf, crc;
129 unsigned char u, v, w;
130 unsigned long flags;
131 unsigned int t;
132 char status;
133
134 int strobe = gameport_time(gameport, GRIP_STROBE_XT);
135
136 data[0] = data[1] = data[2] = data[3] = 0;
137 status = buf = i = j = 0;
138 t = strobe;
139
140 local_irq_save(flags);
141
142 v = w = (gameport_read(gameport) >> shift) & 3;
143
144 do {
145 t--;
146 u = (gameport_read(gameport) >> shift) & 3;
147
148 if (u ^ v) {
149
150 if ((u ^ v) & 1) {
151 buf = (buf << 1) | (u >> 1);
152 t = strobe;
153 i++;
154 } else
155
156 if ((((u ^ v) & (v ^ w)) >> 1) & ~(u | v | w) & 1) {
157 if (i == 20) {
158 crc = buf ^ (buf >> 7) ^ (buf >> 14);
159 if (!((crc ^ (0x25cb9e70 >> ((crc >> 2) & 0x1c))) & 0xf)) {
160 data[buf >> 18] = buf >> 4;
161 status |= 1 << (buf >> 18);
162 }
163 j++;
164 }
165 t = strobe;
166 buf = 0;
167 i = 0;
168 }
169 w = v;
170 v = u;
171 }
172
173 } while (status != 0xf && i < GRIP_MAX_BITS_XT && j < GRIP_MAX_CHUNKS_XT && t > 0);
174
175 local_irq_restore(flags);
176
177 return -(status != 0xf);
178}
179
180/*
181 * grip_timer() repeatedly polls the joysticks and generates events.
182 */
183
184static void grip_poll(struct gameport *gameport)
185{
186 struct grip *grip = gameport_get_drvdata(gameport);
187 unsigned int data[GRIP_LENGTH_XT];
188 struct input_dev *dev;
189 int i, j;
190
191 for (i = 0; i < 2; i++) {
192
193 dev = grip->dev + i;
194 grip->reads++;
195
196 switch (grip->mode[i]) {
197
198 case GRIP_MODE_GPP:
199
200 if (grip_gpp_read_packet(grip->gameport, (i << 1) + 4, data)) {
201 grip->bads++;
202 break;
203 }
204
205 input_report_abs(dev, ABS_X, ((*data >> 15) & 1) - ((*data >> 16) & 1));
206 input_report_abs(dev, ABS_Y, ((*data >> 13) & 1) - ((*data >> 12) & 1));
207
208 for (j = 0; j < 12; j++)
209 if (grip_btn_gpp[j])
210 input_report_key(dev, grip_btn_gpp[j], (*data >> j) & 1);
211
212 break;
213
214 case GRIP_MODE_BD:
215
216 if (grip_xt_read_packet(grip->gameport, (i << 1) + 4, data)) {
217 grip->bads++;
218 break;
219 }
220
221 input_report_abs(dev, ABS_X, (data[0] >> 2) & 0x3f);
222 input_report_abs(dev, ABS_Y, 63 - ((data[0] >> 8) & 0x3f));
223 input_report_abs(dev, ABS_THROTTLE, (data[2] >> 8) & 0x3f);
224
225 input_report_abs(dev, ABS_HAT0X, ((data[2] >> 1) & 1) - ( data[2] & 1));
226 input_report_abs(dev, ABS_HAT0Y, ((data[2] >> 2) & 1) - ((data[2] >> 3) & 1));
227
228 for (j = 0; j < 5; j++)
229 input_report_key(dev, grip_btn_bd[j], (data[3] >> (j + 4)) & 1);
230
231 break;
232
233 case GRIP_MODE_XT:
234
235 if (grip_xt_read_packet(grip->gameport, (i << 1) + 4, data)) {
236 grip->bads++;
237 break;
238 }
239
240 input_report_abs(dev, ABS_X, (data[0] >> 2) & 0x3f);
241 input_report_abs(dev, ABS_Y, 63 - ((data[0] >> 8) & 0x3f));
242 input_report_abs(dev, ABS_BRAKE, (data[1] >> 2) & 0x3f);
243 input_report_abs(dev, ABS_GAS, (data[1] >> 8) & 0x3f);
244 input_report_abs(dev, ABS_THROTTLE, (data[2] >> 8) & 0x3f);
245
246 input_report_abs(dev, ABS_HAT0X, ((data[2] >> 1) & 1) - ( data[2] & 1));
247 input_report_abs(dev, ABS_HAT0Y, ((data[2] >> 2) & 1) - ((data[2] >> 3) & 1));
248 input_report_abs(dev, ABS_HAT1X, ((data[2] >> 5) & 1) - ((data[2] >> 4) & 1));
249 input_report_abs(dev, ABS_HAT1Y, ((data[2] >> 6) & 1) - ((data[2] >> 7) & 1));
250
251 for (j = 0; j < 11; j++)
252 input_report_key(dev, grip_btn_xt[j], (data[3] >> (j + 3)) & 1);
253 break;
254
255 case GRIP_MODE_DC:
256
257 if (grip_xt_read_packet(grip->gameport, (i << 1) + 4, data)) {
258 grip->bads++;
259 break;
260 }
261
262 input_report_abs(dev, ABS_X, (data[0] >> 2) & 0x3f);
263 input_report_abs(dev, ABS_Y, (data[0] >> 8) & 0x3f);
264 input_report_abs(dev, ABS_RX, (data[1] >> 2) & 0x3f);
265 input_report_abs(dev, ABS_RY, (data[1] >> 8) & 0x3f);
266 input_report_abs(dev, ABS_THROTTLE, (data[2] >> 8) & 0x3f);
267
268 input_report_abs(dev, ABS_HAT0X, ((data[2] >> 1) & 1) - ( data[2] & 1));
269 input_report_abs(dev, ABS_HAT0Y, ((data[2] >> 2) & 1) - ((data[2] >> 3) & 1));
270
271 for (j = 0; j < 9; j++)
272 input_report_key(dev, grip_btn_dc[j], (data[3] >> (j + 3)) & 1);
273 break;
274
275
276 }
277
278 input_sync(dev);
279 }
280}
281
282static int grip_open(struct input_dev *dev)
283{
284 struct grip *grip = dev->private;
285
286 gameport_start_polling(grip->gameport);
287 return 0;
288}
289
290static void grip_close(struct input_dev *dev)
291{
292 struct grip *grip = dev->private;
293
294 gameport_stop_polling(grip->gameport);
295}
296
297static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
298{
299 struct grip *grip;
300 unsigned int data[GRIP_LENGTH_XT];
301 int i, j, t;
302 int err;
303
304 if (!(grip = kcalloc(1, sizeof(struct grip), GFP_KERNEL)))
305 return -ENOMEM;
306
307 grip->gameport = gameport;
308
309 gameport_set_drvdata(gameport, grip);
310
311 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
312 if (err)
313 goto fail1;
314
315 for (i = 0; i < 2; i++) {
316 if (!grip_gpp_read_packet(gameport, (i << 1) + 4, data)) {
317 grip->mode[i] = GRIP_MODE_GPP;
318 continue;
319 }
320 if (!grip_xt_read_packet(gameport, (i << 1) + 4, data)) {
321 if (!(data[3] & 7)) {
322 grip->mode[i] = GRIP_MODE_BD;
323 continue;
324 }
325 if (!(data[2] & 0xf0)) {
326 grip->mode[i] = GRIP_MODE_XT;
327 continue;
328 }
329 grip->mode[i] = GRIP_MODE_DC;
330 continue;
331 }
332 }
333
334 if (!grip->mode[0] && !grip->mode[1]) {
335 err = -ENODEV;
336 goto fail2;
337 }
338
339 gameport_set_poll_handler(gameport, grip_poll);
340 gameport_set_poll_interval(gameport, 20);
341
342 for (i = 0; i < 2; i++)
343 if (grip->mode[i]) {
344
345 sprintf(grip->phys[i], "%s/input%d", gameport->phys, i);
346
347 grip->dev[i].private = grip;
348
349 grip->dev[i].open = grip_open;
350 grip->dev[i].close = grip_close;
351
352 grip->dev[i].name = grip_name[grip->mode[i]];
353 grip->dev[i].phys = grip->phys[i];
354 grip->dev[i].id.bustype = BUS_GAMEPORT;
355 grip->dev[i].id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
356 grip->dev[i].id.product = grip->mode[i];
357 grip->dev[i].id.version = 0x0100;
358
359 grip->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
360
361 for (j = 0; (t = grip_abs[grip->mode[i]][j]) >= 0; j++) {
362
363 if (j < grip_cen[grip->mode[i]])
364 input_set_abs_params(&grip->dev[i], t, 14, 52, 1, 2);
365 else if (j < grip_anx[grip->mode[i]])
366 input_set_abs_params(&grip->dev[i], t, 3, 57, 1, 0);
367 else
368 input_set_abs_params(&grip->dev[i], t, -1, 1, 0, 0);
369 }
370
371 for (j = 0; (t = grip_btn[grip->mode[i]][j]) >= 0; j++)
372 if (t > 0)
373 set_bit(t, grip->dev[i].keybit);
374
375 printk(KERN_INFO "input: %s on %s\n",
376 grip_name[grip->mode[i]], gameport->phys);
377 input_register_device(grip->dev + i);
378 }
379
380 return 0;
381
382fail2: gameport_close(gameport);
383fail1: gameport_set_drvdata(gameport, NULL);
384 kfree(grip);
385 return err;
386}
387
388static void grip_disconnect(struct gameport *gameport)
389{
390 struct grip *grip = gameport_get_drvdata(gameport);
391 int i;
392
393 for (i = 0; i < 2; i++)
394 if (grip->mode[i])
395 input_unregister_device(grip->dev + i);
396 gameport_close(gameport);
397 gameport_set_drvdata(gameport, NULL);
398 kfree(grip);
399}
400
401static struct gameport_driver grip_drv = {
402 .driver = {
403 .name = "grip",
404 },
405 .description = DRIVER_DESC,
406 .connect = grip_connect,
407 .disconnect = grip_disconnect,
408};
409
410static int __init grip_init(void)
411{
412 gameport_register_driver(&grip_drv);
413 return 0;
414}
415
416static void __exit grip_exit(void)
417{
418 gameport_unregister_driver(&grip_drv);
419}
420
421module_init(grip_init);
422module_exit(grip_exit);
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
new file mode 100644
index 000000000000..42e5005d621f
--- /dev/null
+++ b/drivers/input/joystick/grip_mp.c
@@ -0,0 +1,677 @@
1/*
2 * $Id: grip_mp.c,v 1.9 2002/07/20 19:28:45 bonnland Exp $
3 *
4 * Driver for the Gravis Grip Multiport, a gamepad "hub" that
5 * connects up to four 9-pin digital gamepads/joysticks.
6 * Driver tested on SMP and UP kernel versions 2.4.18-4 and 2.4.18-5.
7 *
8 * Thanks to Chris Gassib for helpful advice.
9 *
10 * Copyright (c) 2002 Brian Bonnlander, Bill Soudan
11 * Copyright (c) 1998-2000 Vojtech Pavlik
12 */
13
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/slab.h>
18#include <linux/gameport.h>
19#include <linux/input.h>
20#include <linux/delay.h>
21#include <linux/proc_fs.h>
22
23#define DRIVER_DESC "Gravis Grip Multiport driver"
24
25MODULE_AUTHOR("Brian Bonnlander");
26MODULE_DESCRIPTION(DRIVER_DESC);
27MODULE_LICENSE("GPL");
28
29#ifdef GRIP_DEBUG
30#define dbg(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" , ## arg)
31#else
32#define dbg(format, arg...) do {} while (0)
33#endif
34
35/*
36 * Grip multiport state
37 */
38
39struct grip_mp {
40 struct gameport *gameport;
41 struct input_dev dev[4];
42 int mode[4];
43 int registered[4];
44 int reads;
45 int bads;
46
47 /* individual gamepad states */
48 int buttons[4];
49 int xaxes[4];
50 int yaxes[4];
51 int dirty[4]; /* has the state been updated? */
52};
53
54/*
55 * Multiport packet interpretation
56 */
57
58#define PACKET_FULL 0x80000000 /* packet is full */
59#define PACKET_IO_FAST 0x40000000 /* 3 bits per gameport read */
60#define PACKET_IO_SLOW 0x20000000 /* 1 bit per gameport read */
61#define PACKET_MP_MORE 0x04000000 /* multiport wants to send more */
62#define PACKET_MP_DONE 0x02000000 /* multiport done sending */
63
64/*
65 * Packet status code interpretation
66 */
67
68#define IO_GOT_PACKET 0x0100 /* Got a packet */
69#define IO_MODE_FAST 0x0200 /* Used 3 data bits per gameport read */
70#define IO_SLOT_CHANGE 0x0800 /* Multiport physical slot status changed */
71#define IO_DONE 0x1000 /* Multiport is done sending packets */
72#define IO_RETRY 0x4000 /* Try again later to get packet */
73#define IO_RESET 0x8000 /* Force multiport to resend all packets */
74
75/*
76 * Gamepad configuration data. Other 9-pin digital joystick devices
77 * may work with the multiport, so this may not be an exhaustive list!
78 * Commodore 64 joystick remains untested.
79 */
80
81#define GRIP_INIT_DELAY 2000 /* 2 ms */
82
83#define GRIP_MODE_NONE 0
84#define GRIP_MODE_RESET 1
85#define GRIP_MODE_GP 2
86#define GRIP_MODE_C64 3
87
88static int grip_btn_gp[] = { BTN_TR, BTN_TL, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, -1 };
89static int grip_btn_c64[] = { BTN_JOYSTICK, -1 };
90
91static int grip_abs_gp[] = { ABS_X, ABS_Y, -1 };
92static int grip_abs_c64[] = { ABS_X, ABS_Y, -1 };
93
94static int *grip_abs[] = { NULL, NULL, grip_abs_gp, grip_abs_c64 };
95static int *grip_btn[] = { NULL, NULL, grip_btn_gp, grip_btn_c64 };
96
97static char *grip_name[] = { NULL, NULL, "Gravis Grip Pad", "Commodore 64 Joystick" };
98
99static const int init_seq[] = {
100 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1,
101 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1,
102 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1,
103 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1 };
104
105/* Maps multiport directional values to X,Y axis values (each axis encoded in 3 bits) */
106
107static int axis_map[] = { 5, 9, 1, 5, 6, 10, 2, 6, 4, 8, 0, 4, 5, 9, 1, 5 };
108
109static void register_slot(int i, struct grip_mp *grip);
110
111/*
112 * Returns whether an odd or even number of bits are on in pkt.
113 */
114
115static int bit_parity(u32 pkt)
116{
117 int x = pkt ^ (pkt >> 16);
118 x ^= x >> 8;
119 x ^= x >> 4;
120 x ^= x >> 2;
121 x ^= x >> 1;
122 return x & 1;
123}
124
125/*
126 * Poll gameport; return true if all bits set in 'onbits' are on and
127 * all bits set in 'offbits' are off.
128 */
129
130static inline int poll_until(u8 onbits, u8 offbits, int u_sec, struct gameport* gp, u8 *data)
131{
132 int i, nloops;
133
134 nloops = gameport_time(gp, u_sec);
135 for (i = 0; i < nloops; i++) {
136 *data = gameport_read(gp);
137 if ((*data & onbits) == onbits &&
138 (~(*data) & offbits) == offbits)
139 return 1;
140 }
141 dbg("gameport timed out after %d microseconds.\n", u_sec);
142 return 0;
143}
144
145/*
146 * Gets a 28-bit packet from the multiport.
147 *
148 * After getting a packet successfully, commands encoded by sendcode may
149 * be sent to the multiport.
150 *
151 * The multiport clock value is reflected in gameport bit B4.
152 *
153 * Returns a packet status code indicating whether packet is valid, the transfer
154 * mode, and any error conditions.
155 *
156 * sendflags: current I/O status
157 * sendcode: data to send to the multiport if sendflags is nonzero
158 */
159
160static int mp_io(struct gameport* gameport, int sendflags, int sendcode, u32 *packet)
161{
162 u8 raw_data; /* raw data from gameport */
163 u8 data_mask; /* packet data bits from raw_data */
164 u32 pkt; /* packet temporary storage */
165 int bits_per_read; /* num packet bits per gameport read */
166 int portvals = 0; /* used for port value sanity check */
167 int i;
168
169 /* Gameport bits B0, B4, B5 should first be off, then B4 should come on. */
170
171 *packet = 0;
172 raw_data = gameport_read(gameport);
173 if (raw_data & 1)
174 return IO_RETRY;
175
176 for (i = 0; i < 64; i++) {
177 raw_data = gameport_read(gameport);
178 portvals |= 1 << ((raw_data >> 4) & 3); /* Demux B4, B5 */
179 }
180
181 if (portvals == 1) { /* B4, B5 off */
182 raw_data = gameport_read(gameport);
183 portvals = raw_data & 0xf0;
184
185 if (raw_data & 0x31)
186 return IO_RESET;
187 gameport_trigger(gameport);
188
189 if (!poll_until(0x10, 0, 308, gameport, &raw_data))
190 return IO_RESET;
191 } else
192 return IO_RETRY;
193
194 /* Determine packet transfer mode and prepare for packet construction. */
195
196 if (raw_data & 0x20) { /* 3 data bits/read */
197 portvals |= raw_data >> 4; /* Compare B4-B7 before & after trigger */
198
199 if (portvals != 0xb)
200 return 0;
201 data_mask = 7;
202 bits_per_read = 3;
203 pkt = (PACKET_FULL | PACKET_IO_FAST) >> 28;
204 } else { /* 1 data bit/read */
205 data_mask = 1;
206 bits_per_read = 1;
207 pkt = (PACKET_FULL | PACKET_IO_SLOW) >> 28;
208 }
209
210 /* Construct a packet. Final data bits must be zero. */
211
212 while (1) {
213 if (!poll_until(0, 0x10, 77, gameport, &raw_data))
214 return IO_RESET;
215 raw_data = (raw_data >> 5) & data_mask;
216
217 if (pkt & PACKET_FULL)
218 break;
219 pkt = (pkt << bits_per_read) | raw_data;
220
221 if (!poll_until(0x10, 0, 77, gameport, &raw_data))
222 return IO_RESET;
223 }
224
225 if (raw_data)
226 return IO_RESET;
227
228 /* If 3 bits/read used, drop from 30 bits to 28. */
229
230 if (bits_per_read == 3) {
231 pkt = (pkt & 0xffff0000) | ((pkt << 1) & 0xffff);
232 pkt = (pkt >> 2) | 0xf0000000;
233 }
234
235 if (bit_parity(pkt) == 1)
236 return IO_RESET;
237
238 /* Acknowledge packet receipt */
239
240 if (!poll_until(0x30, 0, 77, gameport, &raw_data))
241 return IO_RESET;
242
243 raw_data = gameport_read(gameport);
244
245 if (raw_data & 1)
246 return IO_RESET;
247
248 gameport_trigger(gameport);
249
250 if (!poll_until(0, 0x20, 77, gameport, &raw_data))
251 return IO_RESET;
252
253 /* Return if we just wanted the packet or multiport wants to send more */
254
255 *packet = pkt;
256 if ((sendflags == 0) || ((sendflags & IO_RETRY) && !(pkt & PACKET_MP_DONE)))
257 return IO_GOT_PACKET;
258
259 if (pkt & PACKET_MP_MORE)
260 return IO_GOT_PACKET | IO_RETRY;
261
262 /* Multiport is done sending packets and is ready to receive data */
263
264 if (!poll_until(0x20, 0, 77, gameport, &raw_data))
265 return IO_GOT_PACKET | IO_RESET;
266
267 raw_data = gameport_read(gameport);
268 if (raw_data & 1)
269 return IO_GOT_PACKET | IO_RESET;
270
271 /* Trigger gameport based on bits in sendcode */
272
273 gameport_trigger(gameport);
274 do {
275 if (!poll_until(0x20, 0x10, 116, gameport, &raw_data))
276 return IO_GOT_PACKET | IO_RESET;
277
278 if (!poll_until(0x30, 0, 193, gameport, &raw_data))
279 return IO_GOT_PACKET | IO_RESET;
280
281 if (raw_data & 1)
282 return IO_GOT_PACKET | IO_RESET;
283
284 if (sendcode & 1)
285 gameport_trigger(gameport);
286
287 sendcode >>= 1;
288 } while (sendcode);
289
290 return IO_GOT_PACKET | IO_MODE_FAST;
291}
292
293/*
294 * Disables and restores interrupts for mp_io(), which does the actual I/O.
295 */
296
297static int multiport_io(struct gameport* gameport, int sendflags, int sendcode, u32 *packet)
298{
299 int status;
300 unsigned long flags;
301
302 local_irq_save(flags);
303 status = mp_io(gameport, sendflags, sendcode, packet);
304 local_irq_restore(flags);
305
306 return status;
307}
308
309/*
310 * Puts multiport into digital mode. Multiport LED turns green.
311 *
312 * Returns true if a valid digital packet was received, false otherwise.
313 */
314
315static int dig_mode_start(struct gameport *gameport, u32 *packet)
316{
317 int i, seq_len = sizeof(init_seq)/sizeof(int);
318 int flags, tries = 0, bads = 0;
319
320 for (i = 0; i < seq_len; i++) { /* Send magic sequence */
321 if (init_seq[i])
322 gameport_trigger(gameport);
323 udelay(GRIP_INIT_DELAY);
324 }
325
326 for (i = 0; i < 16; i++) /* Wait for multiport to settle */
327 udelay(GRIP_INIT_DELAY);
328
329 while (tries < 64 && bads < 8) { /* Reset multiport and try getting a packet */
330
331 flags = multiport_io(gameport, IO_RESET, 0x27, packet);
332
333 if (flags & IO_MODE_FAST)
334 return 1;
335
336 if (flags & IO_RETRY)
337 tries++;
338 else
339 bads++;
340 }
341 return 0;
342}
343
344/*
345 * Packet structure: B0-B15 => gamepad state
346 * B16-B20 => gamepad device type
347 * B21-B24 => multiport slot index (1-4)
348 *
349 * Known device types: 0x1f (grip pad), 0x0 (no device). Others may exist.
350 *
351 * Returns the packet status.
352 */
353
354static int get_and_decode_packet(struct grip_mp *grip, int flags)
355{
356 u32 packet;
357 int joytype = 0;
358 int slot = 0;
359
360 /* Get a packet and check for validity */
361
362 flags &= IO_RESET | IO_RETRY;
363 flags = multiport_io(grip->gameport, flags, 0, &packet);
364 grip->reads++;
365
366 if (packet & PACKET_MP_DONE)
367 flags |= IO_DONE;
368
369 if (flags && !(flags & IO_GOT_PACKET)) {
370 grip->bads++;
371 return flags;
372 }
373
374 /* Ignore non-gamepad packets, e.g. multiport hardware version */
375
376 slot = ((packet >> 21) & 0xf) - 1;
377 if ((slot < 0) || (slot > 3))
378 return flags;
379
380 /*
381 * Handle "reset" packets, which occur at startup, and when gamepads
382 * are removed or plugged in. May contain configuration of a new gamepad.
383 */
384
385 joytype = (packet >> 16) & 0x1f;
386 if (!joytype) {
387
388 if (grip->registered[slot]) {
389 printk(KERN_INFO "grip_mp: removing %s, slot %d\n",
390 grip_name[grip->mode[slot]], slot);
391 input_unregister_device(grip->dev + slot);
392 grip->registered[slot] = 0;
393 }
394 dbg("Reset: grip multiport slot %d\n", slot);
395 grip->mode[slot] = GRIP_MODE_RESET;
396 flags |= IO_SLOT_CHANGE;
397 return flags;
398 }
399
400 /* Interpret a grip pad packet */
401
402 if (joytype == 0x1f) {
403
404 int dir = (packet >> 8) & 0xf; /* eight way directional value */
405 grip->buttons[slot] = (~packet) & 0xff;
406 grip->yaxes[slot] = ((axis_map[dir] >> 2) & 3) - 1;
407 grip->xaxes[slot] = (axis_map[dir] & 3) - 1;
408 grip->dirty[slot] = 1;
409
410 if (grip->mode[slot] == GRIP_MODE_RESET)
411 flags |= IO_SLOT_CHANGE;
412
413 grip->mode[slot] = GRIP_MODE_GP;
414
415 if (!grip->registered[slot]) {
416 dbg("New Grip pad in multiport slot %d.\n", slot);
417 register_slot(slot, grip);
418 }
419 return flags;
420 }
421
422 /* Handle non-grip device codes. For now, just print diagnostics. */
423
424 {
425 static int strange_code = 0;
426 if (strange_code != joytype) {
427 printk(KERN_INFO "Possible non-grip pad/joystick detected.\n");
428 printk(KERN_INFO "Got joy type 0x%x and packet 0x%x.\n", joytype, packet);
429 strange_code = joytype;
430 }
431 }
432 return flags;
433}
434
435/*
436 * Returns true if all multiport slot states appear valid.
437 */
438
439static int slots_valid(struct grip_mp *grip)
440{
441 int flags, slot, invalid = 0, active = 0;
442
443 flags = get_and_decode_packet(grip, 0);
444 if (!(flags & IO_GOT_PACKET))
445 return 0;
446
447 for (slot = 0; slot < 4; slot++) {
448 if (grip->mode[slot] == GRIP_MODE_RESET)
449 invalid = 1;
450 if (grip->mode[slot] != GRIP_MODE_NONE)
451 active = 1;
452 }
453
454 /* Return true if no active slot but multiport sent all its data */
455 if (!active)
456 return (flags & IO_DONE) ? 1 : 0;
457
458 /* Return false if invalid device code received */
459 return invalid ? 0 : 1;
460}
461
462/*
463 * Returns whether the multiport was placed into digital mode and
464 * able to communicate its state successfully.
465 */
466
467static int multiport_init(struct grip_mp *grip)
468{
469 int dig_mode, initialized = 0, tries = 0;
470 u32 packet;
471
472 dig_mode = dig_mode_start(grip->gameport, &packet);
473 while (!dig_mode && tries < 4) {
474 dig_mode = dig_mode_start(grip->gameport, &packet);
475 tries++;
476 }
477
478 if (dig_mode)
479 dbg("multiport_init(): digital mode activated.\n");
480 else {
481 dbg("multiport_init(): unable to activate digital mode.\n");
482 return 0;
483 }
484
485 /* Get packets, store multiport state, and check state's validity */
486 for (tries = 0; tries < 4096; tries++) {
487 if ( slots_valid(grip) ) {
488 initialized = 1;
489 break;
490 }
491 }
492 dbg("multiport_init(): initialized == %d\n", initialized);
493 return initialized;
494}
495
496/*
497 * Reports joystick state to the linux input layer.
498 */
499
500static void report_slot(struct grip_mp *grip, int slot)
501{
502 struct input_dev *dev = &(grip->dev[slot]);
503 int i, buttons = grip->buttons[slot];
504
505 /* Store button states with linux input driver */
506
507 for (i = 0; i < 8; i++)
508 input_report_key(dev, grip_btn_gp[i], (buttons >> i) & 1);
509
510 /* Store axis states with linux driver */
511
512 input_report_abs(dev, ABS_X, grip->xaxes[slot]);
513 input_report_abs(dev, ABS_Y, grip->yaxes[slot]);
514
515 /* Tell the receiver of the events to process them */
516
517 input_sync(dev);
518
519 grip->dirty[slot] = 0;
520}
521
522/*
523 * Get the multiport state.
524 */
525
526static void grip_poll(struct gameport *gameport)
527{
528 struct grip_mp *grip = gameport_get_drvdata(gameport);
529 int i, npkts, flags;
530
531 for (npkts = 0; npkts < 4; npkts++) {
532 flags = IO_RETRY;
533 for (i = 0; i < 32; i++) {
534 flags = get_and_decode_packet(grip, flags);
535 if ((flags & IO_GOT_PACKET) || !(flags & IO_RETRY))
536 break;
537 }
538 if (flags & IO_DONE)
539 break;
540 }
541
542 for (i = 0; i < 4; i++)
543 if (grip->dirty[i])
544 report_slot(grip, i);
545}
546
547/*
548 * Called when a joystick device file is opened
549 */
550
551static int grip_open(struct input_dev *dev)
552{
553 struct grip_mp *grip = dev->private;
554
555 gameport_start_polling(grip->gameport);
556 return 0;
557}
558
559/*
560 * Called when a joystick device file is closed
561 */
562
563static void grip_close(struct input_dev *dev)
564{
565 struct grip_mp *grip = dev->private;
566
567 gameport_start_polling(grip->gameport);
568}
569
570/*
571 * Tell the linux input layer about a newly plugged-in gamepad.
572 */
573
574static void register_slot(int slot, struct grip_mp *grip)
575{
576 int j, t;
577
578 grip->dev[slot].private = grip;
579 grip->dev[slot].open = grip_open;
580 grip->dev[slot].close = grip_close;
581 grip->dev[slot].name = grip_name[grip->mode[slot]];
582 grip->dev[slot].id.bustype = BUS_GAMEPORT;
583 grip->dev[slot].id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
584 grip->dev[slot].id.product = 0x0100 + grip->mode[slot];
585 grip->dev[slot].id.version = 0x0100;
586 grip->dev[slot].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
587
588 for (j = 0; (t = grip_abs[grip->mode[slot]][j]) >= 0; j++)
589 input_set_abs_params(&grip->dev[slot], t, -1, 1, 0, 0);
590
591 for (j = 0; (t = grip_btn[grip->mode[slot]][j]) >= 0; j++)
592 if (t > 0)
593 set_bit(t, grip->dev[slot].keybit);
594
595 input_register_device(grip->dev + slot);
596 grip->registered[slot] = 1;
597
598 if (grip->dirty[slot]) /* report initial state, if any */
599 report_slot(grip, slot);
600
601 printk(KERN_INFO "grip_mp: added %s, slot %d\n",
602 grip_name[grip->mode[slot]], slot);
603}
604
605static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
606{
607 struct grip_mp *grip;
608 int err;
609
610 if (!(grip = kcalloc(1, sizeof(struct grip_mp), GFP_KERNEL)))
611 return -ENOMEM;
612
613 grip->gameport = gameport;
614
615 gameport_set_drvdata(gameport, grip);
616
617 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
618 if (err)
619 goto fail1;
620
621 gameport_set_poll_handler(gameport, grip_poll);
622 gameport_set_poll_interval(gameport, 20);
623
624 if (!multiport_init(grip)) {
625 err = -ENODEV;
626 goto fail2;
627 }
628
629 if (!grip->mode[0] && !grip->mode[1] && !grip->mode[2] && !grip->mode[3]) {
630 /* nothing plugged in */
631 err = -ENODEV;
632 goto fail2;
633 }
634
635 return 0;
636
637fail2: gameport_close(gameport);
638fail1: gameport_set_drvdata(gameport, NULL);
639 kfree(grip);
640 return err;
641}
642
643static void grip_disconnect(struct gameport *gameport)
644{
645 struct grip_mp *grip = gameport_get_drvdata(gameport);
646 int i;
647
648 for (i = 0; i < 4; i++)
649 if (grip->registered[i])
650 input_unregister_device(grip->dev + i);
651 gameport_close(gameport);
652 gameport_set_drvdata(gameport, NULL);
653 kfree(grip);
654}
655
656static struct gameport_driver grip_drv = {
657 .driver = {
658 .name = "grip_mp",
659 },
660 .description = DRIVER_DESC,
661 .connect = grip_connect,
662 .disconnect = grip_disconnect,
663};
664
665static int __init grip_init(void)
666{
667 gameport_register_driver(&grip_drv);
668 return 0;
669}
670
671static void __exit grip_exit(void)
672{
673 gameport_unregister_driver(&grip_drv);
674}
675
676module_init(grip_init);
677module_exit(grip_exit);
diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c
new file mode 100644
index 000000000000..f93da7bc082d
--- /dev/null
+++ b/drivers/input/joystick/guillemot.c
@@ -0,0 +1,289 @@
1/*
2 * $Id: guillemot.c,v 1.10 2002/01/22 20:28:12 vojtech Exp $
3 *
4 * Copyright (c) 2001 Vojtech Pavlik
5 */
6
7/*
8 * Guillemot Digital Interface Protocol driver for Linux
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/kernel.h>
32#include <linux/slab.h>
33#include <linux/module.h>
34#include <linux/delay.h>
35#include <linux/init.h>
36#include <linux/gameport.h>
37#include <linux/input.h>
38
39#define DRIVER_DESC "Guillemot Digital joystick driver"
40
41MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
42MODULE_DESCRIPTION(DRIVER_DESC);
43MODULE_LICENSE("GPL");
44
45#define GUILLEMOT_MAX_START 600 /* 600 us */
46#define GUILLEMOT_MAX_STROBE 60 /* 60 us */
47#define GUILLEMOT_MAX_LENGTH 17 /* 17 bytes */
48
49static short guillemot_abs_pad[] =
50 { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, -1 };
51
52static short guillemot_btn_pad[] =
53 { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_MODE, BTN_SELECT, -1 };
54
55static struct {
56 int x;
57 int y;
58} guillemot_hat_to_axis[16] = {{ 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
59
60struct guillemot_type {
61 unsigned char id;
62 short *abs;
63 short *btn;
64 int hat;
65 char *name;
66};
67
68struct guillemot {
69 struct gameport *gameport;
70 struct input_dev dev;
71 int bads;
72 int reads;
73 struct guillemot_type *type;
74 unsigned char length;
75 char phys[32];
76};
77
78static struct guillemot_type guillemot_type[] = {
79 { 0x00, guillemot_abs_pad, guillemot_btn_pad, 1, "Guillemot Pad" },
80 { 0 }};
81
82/*
83 * guillemot_read_packet() reads Guillemot joystick data.
84 */
85
86static int guillemot_read_packet(struct gameport *gameport, u8 *data)
87{
88 unsigned long flags;
89 unsigned char u, v;
90 unsigned int t, s;
91 int i;
92
93 for (i = 0; i < GUILLEMOT_MAX_LENGTH; i++)
94 data[i] = 0;
95
96 i = 0;
97 t = gameport_time(gameport, GUILLEMOT_MAX_START);
98 s = gameport_time(gameport, GUILLEMOT_MAX_STROBE);
99
100 local_irq_save(flags);
101 gameport_trigger(gameport);
102 v = gameport_read(gameport);
103
104 while (t > 0 && i < GUILLEMOT_MAX_LENGTH * 8) {
105 t--;
106 u = v; v = gameport_read(gameport);
107 if (v & ~u & 0x10) {
108 data[i >> 3] |= ((v >> 5) & 1) << (i & 7);
109 i++;
110 t = s;
111 }
112 }
113
114 local_irq_restore(flags);
115
116 return i;
117}
118
119/*
120 * guillemot_poll() reads and analyzes Guillemot joystick data.
121 */
122
123static void guillemot_poll(struct gameport *gameport)
124{
125 struct guillemot *guillemot = gameport_get_drvdata(gameport);
126 struct input_dev *dev = &guillemot->dev;
127 u8 data[GUILLEMOT_MAX_LENGTH];
128 int i;
129
130 guillemot->reads++;
131
132 if (guillemot_read_packet(guillemot->gameport, data) != GUILLEMOT_MAX_LENGTH * 8 ||
133 data[0] != 0x55 || data[16] != 0xaa) {
134 guillemot->bads++;
135 } else {
136
137 for (i = 0; i < 6 && guillemot->type->abs[i] >= 0; i++)
138 input_report_abs(dev, guillemot->type->abs[i], data[i + 5]);
139
140 if (guillemot->type->hat) {
141 input_report_abs(dev, ABS_HAT0X, guillemot_hat_to_axis[data[4] >> 4].x);
142 input_report_abs(dev, ABS_HAT0Y, guillemot_hat_to_axis[data[4] >> 4].y);
143 }
144
145 for (i = 0; i < 16 && guillemot->type->btn[i] >= 0; i++)
146 input_report_key(dev, guillemot->type->btn[i], (data[2 + (i >> 3)] >> (i & 7)) & 1);
147 }
148
149 input_sync(dev);
150}
151
152/*
153 * guillemot_open() is a callback from the input open routine.
154 */
155
156static int guillemot_open(struct input_dev *dev)
157{
158 struct guillemot *guillemot = dev->private;
159
160 gameport_start_polling(guillemot->gameport);
161 return 0;
162}
163
164/*
165 * guillemot_close() is a callback from the input close routine.
166 */
167
168static void guillemot_close(struct input_dev *dev)
169{
170 struct guillemot *guillemot = dev->private;
171
172 gameport_stop_polling(guillemot->gameport);
173}
174
175/*
176 * guillemot_connect() probes for Guillemot joysticks.
177 */
178
179static int guillemot_connect(struct gameport *gameport, struct gameport_driver *drv)
180{
181 struct guillemot *guillemot;
182 u8 data[GUILLEMOT_MAX_LENGTH];
183 int i, t;
184 int err;
185
186 if (!(guillemot = kcalloc(1, sizeof(struct guillemot), GFP_KERNEL)))
187 return -ENOMEM;
188
189 guillemot->gameport = gameport;
190
191 gameport_set_drvdata(gameport, guillemot);
192
193 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
194 if (err)
195 goto fail1;
196
197 i = guillemot_read_packet(gameport, data);
198
199 if (i != GUILLEMOT_MAX_LENGTH * 8 || data[0] != 0x55 || data[16] != 0xaa) {
200 err = -ENODEV;
201 goto fail2;
202 }
203
204 for (i = 0; guillemot_type[i].name; i++)
205 if (guillemot_type[i].id == data[11])
206 break;
207
208 if (!guillemot_type[i].name) {
209 printk(KERN_WARNING "guillemot.c: Unknown joystick on %s. [ %02x%02x:%04x, ver %d.%02d ]\n",
210 gameport->phys, data[12], data[13], data[11], data[14], data[15]);
211 err = -ENODEV;
212 goto fail2;
213 }
214
215 gameport_set_poll_handler(gameport, guillemot_poll);
216 gameport_set_poll_interval(gameport, 20);
217
218 sprintf(guillemot->phys, "%s/input0", gameport->phys);
219
220 guillemot->type = guillemot_type + i;
221
222 guillemot->dev.private = guillemot;
223 guillemot->dev.open = guillemot_open;
224 guillemot->dev.close = guillemot_close;
225
226 guillemot->dev.name = guillemot_type[i].name;
227 guillemot->dev.phys = guillemot->phys;
228 guillemot->dev.id.bustype = BUS_GAMEPORT;
229 guillemot->dev.id.vendor = GAMEPORT_ID_VENDOR_GUILLEMOT;
230 guillemot->dev.id.product = guillemot_type[i].id;
231 guillemot->dev.id.version = (int)data[14] << 8 | data[15];
232
233 guillemot->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
234
235 for (i = 0; (t = guillemot->type->abs[i]) >= 0; i++)
236 input_set_abs_params(&guillemot->dev, t, 0, 255, 0, 0);
237
238 if (guillemot->type->hat) {
239 input_set_abs_params(&guillemot->dev, ABS_HAT0X, -1, 1, 0, 0);
240 input_set_abs_params(&guillemot->dev, ABS_HAT0Y, -1, 1, 0, 0);
241 }
242
243 for (i = 0; (t = guillemot->type->btn[i]) >= 0; i++)
244 set_bit(t, guillemot->dev.keybit);
245
246 input_register_device(&guillemot->dev);
247 printk(KERN_INFO "input: %s ver %d.%02d on %s\n",
248 guillemot->type->name, data[14], data[15], gameport->phys);
249
250 return 0;
251
252fail2: gameport_close(gameport);
253fail1: gameport_set_drvdata(gameport, NULL);
254 kfree(guillemot);
255 return err;
256}
257
258static void guillemot_disconnect(struct gameport *gameport)
259{
260 struct guillemot *guillemot = gameport_get_drvdata(gameport);
261
262 printk(KERN_INFO "guillemot.c: Failed %d reads out of %d on %s\n", guillemot->reads, guillemot->bads, guillemot->phys);
263 input_unregister_device(&guillemot->dev);
264 gameport_close(gameport);
265 kfree(guillemot);
266}
267
268static struct gameport_driver guillemot_drv = {
269 .driver = {
270 .name = "guillemot",
271 },
272 .description = DRIVER_DESC,
273 .connect = guillemot_connect,
274 .disconnect = guillemot_disconnect,
275};
276
277static int __init guillemot_init(void)
278{
279 gameport_register_driver(&guillemot_drv);
280 return 0;
281}
282
283static void __exit guillemot_exit(void)
284{
285 gameport_unregister_driver(&guillemot_drv);
286}
287
288module_init(guillemot_init);
289module_exit(guillemot_exit);
diff --git a/drivers/input/joystick/iforce/Kconfig b/drivers/input/joystick/iforce/Kconfig
new file mode 100644
index 000000000000..8fde22a021b3
--- /dev/null
+++ b/drivers/input/joystick/iforce/Kconfig
@@ -0,0 +1,32 @@
1#
2# I-Force driver configuration
3#
4config JOYSTICK_IFORCE
5 tristate "I-Force devices"
6 depends on INPUT && INPUT_JOYSTICK
7 help
8 Say Y here if you have an I-Force joystick or steering wheel
9
10 You also must choose at least one of the two options below.
11
12 To compile this driver as a module, choose M here: the
13 module will be called iforce.
14
15config JOYSTICK_IFORCE_USB
16 bool "I-Force USB joysticks and wheels"
17 depends on JOYSTICK_IFORCE && (JOYSTICK_IFORCE=m || USB=y) && USB
18 help
19 Say Y here if you have an I-Force joystick or steering wheel
20 connected to your USB port.
21
22config JOYSTICK_IFORCE_232
23 bool "I-Force Serial joysticks and wheels"
24 depends on JOYSTICK_IFORCE && (JOYSTICK_IFORCE=m || SERIO=y) && SERIO
25 help
26 Say Y here if you have an I-Force joystick or steering wheel
27 connected to your serial (COM) port.
28
29 You will need an additional utility called inputattach, see
30 <file:Documentation/input/joystick.txt>
31 and <file:Documentation/input/ff.txt>.
32
diff --git a/drivers/input/joystick/iforce/Makefile b/drivers/input/joystick/iforce/Makefile
new file mode 100644
index 000000000000..17ae42bf9ffd
--- /dev/null
+++ b/drivers/input/joystick/iforce/Makefile
@@ -0,0 +1,20 @@
1#
2# Makefile for the I-Force driver
3#
4# By Johann Deneux <deneux@ifrance.com>
5#
6
7# Goal definition
8iforce-objs := iforce-ff.o iforce-main.o iforce-packets.o
9
10obj-$(CONFIG_JOYSTICK_IFORCE) += iforce.o
11
12ifeq ($(CONFIG_JOYSTICK_IFORCE_232),y)
13 iforce-objs += iforce-serio.o
14endif
15
16ifeq ($(CONFIG_JOYSTICK_IFORCE_USB),y)
17 iforce-objs += iforce-usb.o
18endif
19
20EXTRA_CFLAGS = -Werror-implicit-function-declaration
diff --git a/drivers/input/joystick/iforce/iforce-ff.c b/drivers/input/joystick/iforce/iforce-ff.c
new file mode 100644
index 000000000000..4678b6dab43b
--- /dev/null
+++ b/drivers/input/joystick/iforce/iforce-ff.c
@@ -0,0 +1,543 @@
1/*
2 * $Id: iforce-ff.c,v 1.9 2002/02/02 19:28:35 jdeneux Exp $
3 *
4 * Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
5 * Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
6 *
7 * USB/RS232 I-Force joysticks and wheels.
8 */
9
10/*
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 * Should you need to contact me, the author, you can do so either by
26 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
27 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
28 */
29
30#include "iforce.h"
31
32/*
33 * Set the magnitude of a constant force effect
34 * Return error code
35 *
36 * Note: caller must ensure exclusive access to device
37 */
38
39static int make_magnitude_modifier(struct iforce* iforce,
40 struct resource* mod_chunk, int no_alloc, __s16 level)
41{
42 unsigned char data[3];
43
44 if (!no_alloc) {
45 down(&iforce->mem_mutex);
46 if (allocate_resource(&(iforce->device_memory), mod_chunk, 2,
47 iforce->device_memory.start, iforce->device_memory.end, 2L,
48 NULL, NULL)) {
49 up(&iforce->mem_mutex);
50 return -ENOMEM;
51 }
52 up(&iforce->mem_mutex);
53 }
54
55 data[0] = LO(mod_chunk->start);
56 data[1] = HI(mod_chunk->start);
57 data[2] = HIFIX80(level);
58
59 iforce_send_packet(iforce, FF_CMD_MAGNITUDE, data);
60
61 iforce_dump_packet("magnitude: ", FF_CMD_MAGNITUDE, data);
62 return 0;
63}
64
65/*
66 * Upload the component of an effect dealing with the period, phase and magnitude
67 */
68
69static int make_period_modifier(struct iforce* iforce,
70 struct resource* mod_chunk, int no_alloc,
71 __s16 magnitude, __s16 offset, u16 period, u16 phase)
72{
73 unsigned char data[7];
74
75 period = TIME_SCALE(period);
76
77 if (!no_alloc) {
78 down(&iforce->mem_mutex);
79 if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0c,
80 iforce->device_memory.start, iforce->device_memory.end, 2L,
81 NULL, NULL)) {
82 up(&iforce->mem_mutex);
83 return -ENOMEM;
84 }
85 up(&iforce->mem_mutex);
86 }
87
88 data[0] = LO(mod_chunk->start);
89 data[1] = HI(mod_chunk->start);
90
91 data[2] = HIFIX80(magnitude);
92 data[3] = HIFIX80(offset);
93 data[4] = HI(phase);
94
95 data[5] = LO(period);
96 data[6] = HI(period);
97
98 iforce_send_packet(iforce, FF_CMD_PERIOD, data);
99
100 return 0;
101}
102
103/*
104 * Uploads the part of an effect setting the envelope of the force
105 */
106
107static int make_envelope_modifier(struct iforce* iforce,
108 struct resource* mod_chunk, int no_alloc,
109 u16 attack_duration, __s16 initial_level,
110 u16 fade_duration, __s16 final_level)
111{
112 unsigned char data[8];
113
114 attack_duration = TIME_SCALE(attack_duration);
115 fade_duration = TIME_SCALE(fade_duration);
116
117 if (!no_alloc) {
118 down(&iforce->mem_mutex);
119 if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0e,
120 iforce->device_memory.start, iforce->device_memory.end, 2L,
121 NULL, NULL)) {
122 up(&iforce->mem_mutex);
123 return -ENOMEM;
124 }
125 up(&iforce->mem_mutex);
126 }
127
128 data[0] = LO(mod_chunk->start);
129 data[1] = HI(mod_chunk->start);
130
131 data[2] = LO(attack_duration);
132 data[3] = HI(attack_duration);
133 data[4] = HI(initial_level);
134
135 data[5] = LO(fade_duration);
136 data[6] = HI(fade_duration);
137 data[7] = HI(final_level);
138
139 iforce_send_packet(iforce, FF_CMD_ENVELOPE, data);
140
141 return 0;
142}
143
144/*
145 * Component of spring, friction, inertia... effects
146 */
147
148static int make_condition_modifier(struct iforce* iforce,
149 struct resource* mod_chunk, int no_alloc,
150 __u16 rsat, __u16 lsat, __s16 rk, __s16 lk, u16 db, __s16 center)
151{
152 unsigned char data[10];
153
154 if (!no_alloc) {
155 down(&iforce->mem_mutex);
156 if (allocate_resource(&(iforce->device_memory), mod_chunk, 8,
157 iforce->device_memory.start, iforce->device_memory.end, 2L,
158 NULL, NULL)) {
159 up(&iforce->mem_mutex);
160 return -ENOMEM;
161 }
162 up(&iforce->mem_mutex);
163 }
164
165 data[0] = LO(mod_chunk->start);
166 data[1] = HI(mod_chunk->start);
167
168 data[2] = (100*rk)>>15; /* Dangerous: the sign is extended by gcc on plateforms providing an arith shift */
169 data[3] = (100*lk)>>15; /* This code is incorrect on cpus lacking arith shift */
170
171 center = (500*center)>>15;
172 data[4] = LO(center);
173 data[5] = HI(center);
174
175 db = (1000*db)>>16;
176 data[6] = LO(db);
177 data[7] = HI(db);
178
179 data[8] = (100*rsat)>>16;
180 data[9] = (100*lsat)>>16;
181
182 iforce_send_packet(iforce, FF_CMD_CONDITION, data);
183 iforce_dump_packet("condition", FF_CMD_CONDITION, data);
184
185 return 0;
186}
187
188static unsigned char find_button(struct iforce *iforce, signed short button)
189{
190 int i;
191 for (i = 1; iforce->type->btn[i] >= 0; i++)
192 if (iforce->type->btn[i] == button)
193 return i + 1;
194 return 0;
195}
196
197/*
198 * Analyse the changes in an effect, and tell if we need to send an condition
199 * parameter packet
200 */
201static int need_condition_modifier(struct iforce* iforce, struct ff_effect* new)
202{
203 int id = new->id;
204 struct ff_effect* old = &iforce->core_effects[id].effect;
205 int ret=0;
206 int i;
207
208 if (new->type != FF_SPRING && new->type != FF_FRICTION) {
209 printk(KERN_WARNING "iforce.c: bad effect type in need_condition_modifier\n");
210 return FALSE;
211 }
212
213 for(i=0; i<2; i++) {
214 ret |= old->u.condition[i].right_saturation != new->u.condition[i].right_saturation
215 || old->u.condition[i].left_saturation != new->u.condition[i].left_saturation
216 || old->u.condition[i].right_coeff != new->u.condition[i].right_coeff
217 || old->u.condition[i].left_coeff != new->u.condition[i].left_coeff
218 || old->u.condition[i].deadband != new->u.condition[i].deadband
219 || old->u.condition[i].center != new->u.condition[i].center;
220 }
221 return ret;
222}
223
224/*
225 * Analyse the changes in an effect, and tell if we need to send a magnitude
226 * parameter packet
227 */
228static int need_magnitude_modifier(struct iforce* iforce, struct ff_effect* effect)
229{
230 int id = effect->id;
231 struct ff_effect* old = &iforce->core_effects[id].effect;
232
233 if (effect->type != FF_CONSTANT) {
234 printk(KERN_WARNING "iforce.c: bad effect type in need_envelope_modifier\n");
235 return FALSE;
236 }
237
238 return (old->u.constant.level != effect->u.constant.level);
239}
240
241/*
242 * Analyse the changes in an effect, and tell if we need to send an envelope
243 * parameter packet
244 */
245static int need_envelope_modifier(struct iforce* iforce, struct ff_effect* effect)
246{
247 int id = effect->id;
248 struct ff_effect* old = &iforce->core_effects[id].effect;
249
250 switch (effect->type) {
251 case FF_CONSTANT:
252 if (old->u.constant.envelope.attack_length != effect->u.constant.envelope.attack_length
253 || old->u.constant.envelope.attack_level != effect->u.constant.envelope.attack_level
254 || old->u.constant.envelope.fade_length != effect->u.constant.envelope.fade_length
255 || old->u.constant.envelope.fade_level != effect->u.constant.envelope.fade_level)
256 return TRUE;
257 break;
258
259 case FF_PERIODIC:
260 if (old->u.periodic.envelope.attack_length != effect->u.periodic.envelope.attack_length
261 || old->u.periodic.envelope.attack_level != effect->u.periodic.envelope.attack_level
262 || old->u.periodic.envelope.fade_length != effect->u.periodic.envelope.fade_length
263 || old->u.periodic.envelope.fade_level != effect->u.periodic.envelope.fade_level)
264 return TRUE;
265 break;
266
267 default:
268 printk(KERN_WARNING "iforce.c: bad effect type in need_envelope_modifier\n");
269 }
270
271 return FALSE;
272}
273
274/*
275 * Analyse the changes in an effect, and tell if we need to send a periodic
276 * parameter effect
277 */
278static int need_period_modifier(struct iforce* iforce, struct ff_effect* new)
279{
280 int id = new->id;
281 struct ff_effect* old = &iforce->core_effects[id].effect;
282
283 if (new->type != FF_PERIODIC) {
284 printk(KERN_WARNING "iforce.c: bad effect type in need_periodic_modifier\n");
285 return FALSE;
286 }
287
288 return (old->u.periodic.period != new->u.periodic.period
289 || old->u.periodic.magnitude != new->u.periodic.magnitude
290 || old->u.periodic.offset != new->u.periodic.offset
291 || old->u.periodic.phase != new->u.periodic.phase);
292}
293
294/*
295 * Analyse the changes in an effect, and tell if we need to send an effect
296 * packet
297 */
298static int need_core(struct iforce* iforce, struct ff_effect* new)
299{
300 int id = new->id;
301 struct ff_effect* old = &iforce->core_effects[id].effect;
302
303 if (old->direction != new->direction
304 || old->trigger.button != new->trigger.button
305 || old->trigger.interval != new->trigger.interval
306 || old->replay.length != new->replay.length
307 || old->replay.delay != new->replay.delay)
308 return TRUE;
309
310 return FALSE;
311}
312/*
313 * Send the part common to all effects to the device
314 */
315static int make_core(struct iforce* iforce, u16 id, u16 mod_id1, u16 mod_id2,
316 u8 effect_type, u8 axes, u16 duration, u16 delay, u16 button,
317 u16 interval, u16 direction)
318{
319 unsigned char data[14];
320
321 duration = TIME_SCALE(duration);
322 delay = TIME_SCALE(delay);
323 interval = TIME_SCALE(interval);
324
325 data[0] = LO(id);
326 data[1] = effect_type;
327 data[2] = LO(axes) | find_button(iforce, button);
328
329 data[3] = LO(duration);
330 data[4] = HI(duration);
331
332 data[5] = HI(direction);
333
334 data[6] = LO(interval);
335 data[7] = HI(interval);
336
337 data[8] = LO(mod_id1);
338 data[9] = HI(mod_id1);
339 data[10] = LO(mod_id2);
340 data[11] = HI(mod_id2);
341
342 data[12] = LO(delay);
343 data[13] = HI(delay);
344
345 /* Stop effect */
346/* iforce_control_playback(iforce, id, 0);*/
347
348 iforce_send_packet(iforce, FF_CMD_EFFECT, data);
349
350 /* If needed, restart effect */
351 if (test_bit(FF_CORE_SHOULD_PLAY, iforce->core_effects[id].flags)) {
352 /* BUG: perhaps we should replay n times, instead of 1. But we do not know n */
353 iforce_control_playback(iforce, id, 1);
354 }
355
356 return 0;
357}
358
359/*
360 * Upload a periodic effect to the device
361 * See also iforce_upload_constant.
362 */
363int iforce_upload_periodic(struct iforce* iforce, struct ff_effect* effect, int is_update)
364{
365 u8 wave_code;
366 int core_id = effect->id;
367 struct iforce_core_effect* core_effect = iforce->core_effects + core_id;
368 struct resource* mod1_chunk = &(iforce->core_effects[core_id].mod1_chunk);
369 struct resource* mod2_chunk = &(iforce->core_effects[core_id].mod2_chunk);
370 int param1_err = 1;
371 int param2_err = 1;
372 int core_err = 0;
373
374 if (!is_update || need_period_modifier(iforce, effect)) {
375 param1_err = make_period_modifier(iforce, mod1_chunk,
376 is_update,
377 effect->u.periodic.magnitude, effect->u.periodic.offset,
378 effect->u.periodic.period, effect->u.periodic.phase);
379 if (param1_err) return param1_err;
380 set_bit(FF_MOD1_IS_USED, core_effect->flags);
381 }
382
383 if (!is_update || need_envelope_modifier(iforce, effect)) {
384 param2_err = make_envelope_modifier(iforce, mod2_chunk,
385 is_update,
386 effect->u.periodic.envelope.attack_length,
387 effect->u.periodic.envelope.attack_level,
388 effect->u.periodic.envelope.fade_length,
389 effect->u.periodic.envelope.fade_level);
390 if (param2_err) return param2_err;
391 set_bit(FF_MOD2_IS_USED, core_effect->flags);
392 }
393
394 switch (effect->u.periodic.waveform) {
395 case FF_SQUARE: wave_code = 0x20; break;
396 case FF_TRIANGLE: wave_code = 0x21; break;
397 case FF_SINE: wave_code = 0x22; break;
398 case FF_SAW_UP: wave_code = 0x23; break;
399 case FF_SAW_DOWN: wave_code = 0x24; break;
400 default: wave_code = 0x20; break;
401 }
402
403 if (!is_update || need_core(iforce, effect)) {
404 core_err = make_core(iforce, effect->id,
405 mod1_chunk->start,
406 mod2_chunk->start,
407 wave_code,
408 0x20,
409 effect->replay.length,
410 effect->replay.delay,
411 effect->trigger.button,
412 effect->trigger.interval,
413 effect->direction);
414 }
415
416 /* If one of the parameter creation failed, we already returned an
417 * error code.
418 * If the core creation failed, we return its error code.
419 * Else: if one parameter at least was created, we return 0
420 * else we return 1;
421 */
422 return core_err < 0 ? core_err : (param1_err && param2_err);
423}
424
425/*
426 * Upload a constant force effect
427 * Return value:
428 * <0 Error code
429 * 0 Ok, effect created or updated
430 * 1 effect did not change since last upload, and no packet was therefore sent
431 */
432int iforce_upload_constant(struct iforce* iforce, struct ff_effect* effect, int is_update)
433{
434 int core_id = effect->id;
435 struct iforce_core_effect* core_effect = iforce->core_effects + core_id;
436 struct resource* mod1_chunk = &(iforce->core_effects[core_id].mod1_chunk);
437 struct resource* mod2_chunk = &(iforce->core_effects[core_id].mod2_chunk);
438 int param1_err = 1;
439 int param2_err = 1;
440 int core_err = 0;
441
442 if (!is_update || need_magnitude_modifier(iforce, effect)) {
443 param1_err = make_magnitude_modifier(iforce, mod1_chunk,
444 is_update,
445 effect->u.constant.level);
446 if (param1_err) return param1_err;
447 set_bit(FF_MOD1_IS_USED, core_effect->flags);
448 }
449
450 if (!is_update || need_envelope_modifier(iforce, effect)) {
451 param2_err = make_envelope_modifier(iforce, mod2_chunk,
452 is_update,
453 effect->u.constant.envelope.attack_length,
454 effect->u.constant.envelope.attack_level,
455 effect->u.constant.envelope.fade_length,
456 effect->u.constant.envelope.fade_level);
457 if (param2_err) return param2_err;
458 set_bit(FF_MOD2_IS_USED, core_effect->flags);
459 }
460
461 if (!is_update || need_core(iforce, effect)) {
462 core_err = make_core(iforce, effect->id,
463 mod1_chunk->start,
464 mod2_chunk->start,
465 0x00,
466 0x20,
467 effect->replay.length,
468 effect->replay.delay,
469 effect->trigger.button,
470 effect->trigger.interval,
471 effect->direction);
472 }
473
474 /* If one of the parameter creation failed, we already returned an
475 * error code.
476 * If the core creation failed, we return its error code.
477 * Else: if one parameter at least was created, we return 0
478 * else we return 1;
479 */
480 return core_err < 0 ? core_err : (param1_err && param2_err);
481}
482
483/*
484 * Upload an condition effect. Those are for example friction, inertia, springs...
485 */
486int iforce_upload_condition(struct iforce* iforce, struct ff_effect* effect, int is_update)
487{
488 int core_id = effect->id;
489 struct iforce_core_effect* core_effect = iforce->core_effects + core_id;
490 struct resource* mod1_chunk = &(core_effect->mod1_chunk);
491 struct resource* mod2_chunk = &(core_effect->mod2_chunk);
492 u8 type;
493 int param_err = 1;
494 int core_err = 0;
495
496 switch (effect->type) {
497 case FF_SPRING: type = 0x40; break;
498 case FF_DAMPER: type = 0x41; break;
499 default: return -1;
500 }
501
502 if (!is_update || need_condition_modifier(iforce, effect)) {
503 param_err = make_condition_modifier(iforce, mod1_chunk,
504 is_update,
505 effect->u.condition[0].right_saturation,
506 effect->u.condition[0].left_saturation,
507 effect->u.condition[0].right_coeff,
508 effect->u.condition[0].left_coeff,
509 effect->u.condition[0].deadband,
510 effect->u.condition[0].center);
511 if (param_err) return param_err;
512 set_bit(FF_MOD1_IS_USED, core_effect->flags);
513
514 param_err = make_condition_modifier(iforce, mod2_chunk,
515 is_update,
516 effect->u.condition[1].right_saturation,
517 effect->u.condition[1].left_saturation,
518 effect->u.condition[1].right_coeff,
519 effect->u.condition[1].left_coeff,
520 effect->u.condition[1].deadband,
521 effect->u.condition[1].center);
522 if (param_err) return param_err;
523 set_bit(FF_MOD2_IS_USED, core_effect->flags);
524
525 }
526
527 if (!is_update || need_core(iforce, effect)) {
528 core_err = make_core(iforce, effect->id,
529 mod1_chunk->start, mod2_chunk->start,
530 type, 0xc0,
531 effect->replay.length, effect->replay.delay,
532 effect->trigger.button, effect->trigger.interval,
533 effect->direction);
534 }
535
536 /* If the parameter creation failed, we already returned an
537 * error code.
538 * If the core creation failed, we return its error code.
539 * Else: if a parameter was created, we return 0
540 * else we return 1;
541 */
542 return core_err < 0 ? core_err : param_err;
543}
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
new file mode 100644
index 000000000000..028f3513629a
--- /dev/null
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -0,0 +1,557 @@
1/*
2 * $Id: iforce-main.c,v 1.19 2002/07/07 10:22:50 jdeneux Exp $
3 *
4 * Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
5 * Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
6 *
7 * USB/RS232 I-Force joysticks and wheels.
8 */
9
10/*
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 * Should you need to contact me, the author, you can do so either by
26 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
27 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
28 */
29
30#include "iforce.h"
31
32MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>, Johann Deneux <deneux@ifrance.com>");
33MODULE_DESCRIPTION("USB/RS232 I-Force joysticks and wheels driver");
34MODULE_LICENSE("GPL");
35
36static signed short btn_joystick[] =
37{ BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE,
38 BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_BASE5, BTN_A, BTN_B, BTN_C, -1 };
39
40static signed short btn_avb_pegasus[] =
41{ BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE,
42 BTN_BASE2, BTN_BASE3, BTN_BASE4, -1 };
43
44static signed short btn_wheel[] =
45{ BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE,
46 BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_BASE5, BTN_A, BTN_B, BTN_C, -1 };
47
48static signed short btn_avb_tw[] =
49{ BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE,
50 BTN_BASE2, BTN_BASE3, BTN_BASE4, -1 };
51
52static signed short btn_avb_wheel[] =
53{ BTN_GEAR_DOWN, BTN_GEAR_UP, BTN_BASE, BTN_BASE2, BTN_BASE3,
54 BTN_BASE4, BTN_BASE5, BTN_BASE6, -1 };
55
56static signed short abs_joystick[] =
57{ ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 };
58
59static signed short abs_avb_pegasus[] =
60{ ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, ABS_HAT0X, ABS_HAT0Y,
61 ABS_HAT1X, ABS_HAT1Y, -1 };
62
63static signed short abs_wheel[] =
64{ ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, -1 };
65
66static signed short ff_iforce[] =
67{ FF_PERIODIC, FF_CONSTANT, FF_SPRING, FF_DAMPER,
68 FF_SQUARE, FF_TRIANGLE, FF_SINE, FF_SAW_UP, FF_SAW_DOWN, FF_GAIN,
69 FF_AUTOCENTER, -1 };
70
71static struct iforce_device iforce_device[] = {
72 { 0x044f, 0xa01c, "Thrustmaster Motor Sport GT", btn_wheel, abs_wheel, ff_iforce },
73 { 0x046d, 0xc281, "Logitech WingMan Force", btn_joystick, abs_joystick, ff_iforce },
74 { 0x046d, 0xc291, "Logitech WingMan Formula Force", btn_wheel, abs_wheel, ff_iforce },
75 { 0x05ef, 0x020a, "AVB Top Shot Pegasus", btn_avb_pegasus, abs_avb_pegasus, ff_iforce },
76 { 0x05ef, 0x8884, "AVB Mag Turbo Force", btn_avb_wheel, abs_wheel, ff_iforce },
77 { 0x05ef, 0x8888, "AVB Top Shot Force Feedback Racing Wheel", btn_avb_tw, abs_wheel, ff_iforce }, //?
78 { 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //?
79 { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //?
80 { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //?
81 { 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce }
82};
83
84
85
86static int iforce_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
87{
88 struct iforce* iforce = (struct iforce*)(dev->private);
89 unsigned char data[3];
90
91 if (type != EV_FF)
92 return -1;
93
94 switch (code) {
95
96 case FF_GAIN:
97
98 data[0] = value >> 9;
99 iforce_send_packet(iforce, FF_CMD_GAIN, data);
100
101 return 0;
102
103 case FF_AUTOCENTER:
104
105 data[0] = 0x03;
106 data[1] = value >> 9;
107 iforce_send_packet(iforce, FF_CMD_AUTOCENTER, data);
108
109 data[0] = 0x04;
110 data[1] = 0x01;
111 iforce_send_packet(iforce, FF_CMD_AUTOCENTER, data);
112
113 return 0;
114
115 default: /* Play or stop an effect */
116
117 if (!CHECK_OWNERSHIP(code, iforce)) {
118 return -1;
119 }
120 if (value > 0) {
121 set_bit(FF_CORE_SHOULD_PLAY, iforce->core_effects[code].flags);
122 }
123 else {
124 clear_bit(FF_CORE_SHOULD_PLAY, iforce->core_effects[code].flags);
125 }
126
127 iforce_control_playback(iforce, code, value);
128 return 0;
129 }
130
131 return -1;
132}
133
134/*
135 * Function called when an ioctl is performed on the event dev entry.
136 * It uploads an effect to the device
137 */
138static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect)
139{
140 struct iforce* iforce = (struct iforce*)(dev->private);
141 int id;
142 int ret;
143 int is_update;
144
145/* Check this effect type is supported by this device */
146 if (!test_bit(effect->type, iforce->dev.ffbit))
147 return -EINVAL;
148
149/*
150 * If we want to create a new effect, get a free id
151 */
152 if (effect->id == -1) {
153
154 for (id=0; id < FF_EFFECTS_MAX; ++id)
155 if (!test_and_set_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags)) break;
156
157 if ( id == FF_EFFECTS_MAX || id >= iforce->dev.ff_effects_max)
158 return -ENOMEM;
159
160 effect->id = id;
161 iforce->core_effects[id].owner = current->pid;
162 iforce->core_effects[id].flags[0] = (1<<FF_CORE_IS_USED); /* Only IS_USED bit must be set */
163
164 is_update = FALSE;
165 }
166 else {
167 /* We want to update an effect */
168 if (!CHECK_OWNERSHIP(effect->id, iforce)) return -EACCES;
169
170 /* Parameter type cannot be updated */
171 if (effect->type != iforce->core_effects[effect->id].effect.type)
172 return -EINVAL;
173
174 /* Check the effect is not already being updated */
175 if (test_bit(FF_CORE_UPDATE, iforce->core_effects[effect->id].flags)) {
176 return -EAGAIN;
177 }
178
179 is_update = TRUE;
180 }
181
182/*
183 * Upload the effect
184 */
185 switch (effect->type) {
186
187 case FF_PERIODIC:
188 ret = iforce_upload_periodic(iforce, effect, is_update);
189 break;
190
191 case FF_CONSTANT:
192 ret = iforce_upload_constant(iforce, effect, is_update);
193 break;
194
195 case FF_SPRING:
196 case FF_DAMPER:
197 ret = iforce_upload_condition(iforce, effect, is_update);
198 break;
199
200 default:
201 return -EINVAL;
202 }
203 if (ret == 0) {
204 /* A packet was sent, forbid new updates until we are notified
205 * that the packet was updated
206 */
207 set_bit(FF_CORE_UPDATE, iforce->core_effects[effect->id].flags);
208 }
209 iforce->core_effects[effect->id].effect = *effect;
210 return ret;
211}
212
213/*
214 * Erases an effect: it frees the effect id and mark as unused the memory
215 * allocated for the parameters
216 */
217static int iforce_erase_effect(struct input_dev *dev, int effect_id)
218{
219 struct iforce* iforce = (struct iforce*)(dev->private);
220 int err = 0;
221 struct iforce_core_effect* core_effect;
222
223 /* Check who is trying to erase this effect */
224 if (iforce->core_effects[effect_id].owner != current->pid) {
225 printk(KERN_WARNING "iforce-main.c: %d tried to erase an effect belonging to %d\n", current->pid, iforce->core_effects[effect_id].owner);
226 return -EACCES;
227 }
228
229 if (effect_id < 0 || effect_id >= FF_EFFECTS_MAX)
230 return -EINVAL;
231
232 core_effect = iforce->core_effects + effect_id;
233
234 if (test_bit(FF_MOD1_IS_USED, core_effect->flags))
235 err = release_resource(&(iforce->core_effects[effect_id].mod1_chunk));
236
237 if (!err && test_bit(FF_MOD2_IS_USED, core_effect->flags))
238 err = release_resource(&(iforce->core_effects[effect_id].mod2_chunk));
239
240 /*TODO: remember to change that if more FF_MOD* bits are added */
241 core_effect->flags[0] = 0;
242
243 return err;
244}
245
246static int iforce_open(struct input_dev *dev)
247{
248 struct iforce *iforce = dev->private;
249
250 switch (iforce->bus) {
251#ifdef CONFIG_JOYSTICK_IFORCE_USB
252 case IFORCE_USB:
253 iforce->irq->dev = iforce->usbdev;
254 if (usb_submit_urb(iforce->irq, GFP_KERNEL))
255 return -EIO;
256 break;
257#endif
258 }
259
260 /* Enable force feedback */
261 iforce_send_packet(iforce, FF_CMD_ENABLE, "\004");
262
263 return 0;
264}
265
266static int iforce_flush(struct input_dev *dev, struct file *file)
267{
268 struct iforce *iforce = dev->private;
269 int i;
270
271 /* Erase all effects this process owns */
272 for (i=0; i<dev->ff_effects_max; ++i) {
273
274 if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags) &&
275 current->pid == iforce->core_effects[i].owner) {
276
277 /* Stop effect */
278 input_report_ff(dev, i, 0);
279
280 /* Free ressources assigned to effect */
281 if (iforce_erase_effect(dev, i)) {
282 printk(KERN_WARNING "iforce_flush: erase effect %d failed\n", i);
283 }
284 }
285
286 }
287 return 0;
288}
289
290static void iforce_release(struct input_dev *dev)
291{
292 struct iforce *iforce = dev->private;
293 int i;
294
295 /* Check: no effect should be present in memory */
296 for (i=0; i<dev->ff_effects_max; ++i) {
297 if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags))
298 break;
299 }
300 if (i<dev->ff_effects_max) {
301 printk(KERN_WARNING "iforce_release: Device still owns effects\n");
302 }
303
304 /* Disable force feedback playback */
305 iforce_send_packet(iforce, FF_CMD_ENABLE, "\001");
306
307 switch (iforce->bus) {
308#ifdef CONFIG_JOYSTICK_IFORCE_USB
309 case IFORCE_USB:
310 usb_unlink_urb(iforce->irq);
311
312 /* The device was unplugged before the file
313 * was released */
314 if (iforce->usbdev == NULL) {
315 iforce_delete_device(iforce);
316 kfree(iforce);
317 }
318 break;
319#endif
320 }
321}
322
323void iforce_delete_device(struct iforce *iforce)
324{
325 switch (iforce->bus) {
326#ifdef CONFIG_JOYSTICK_IFORCE_USB
327 case IFORCE_USB:
328 iforce_usb_delete(iforce);
329 break;
330#endif
331#ifdef CONFIG_JOYSTICK_IFORCE_232
332 case IFORCE_232:
333 //TODO: Wait for the last packets to be sent
334 break;
335#endif
336 }
337}
338
339int iforce_init_device(struct iforce *iforce)
340{
341 unsigned char c[] = "CEOV";
342 int i;
343
344 init_waitqueue_head(&iforce->wait);
345 spin_lock_init(&iforce->xmit_lock);
346 init_MUTEX(&iforce->mem_mutex);
347 iforce->xmit.buf = iforce->xmit_data;
348
349 iforce->dev.ff_effects_max = 10;
350
351/*
352 * Input device fields.
353 */
354
355 switch (iforce->bus) {
356#ifdef CONFIG_JOYSTICK_IFORCE_USB
357 case IFORCE_USB:
358 iforce->dev.id.bustype = BUS_USB;
359 iforce->dev.dev = &iforce->usbdev->dev;
360 break;
361#endif
362#ifdef CONFIG_JOYSTICK_IFORCE_232
363 case IFORCE_232:
364 iforce->dev.id.bustype = BUS_RS232;
365 iforce->dev.dev = &iforce->serio->dev;
366 break;
367#endif
368 }
369
370 iforce->dev.private = iforce;
371 iforce->dev.name = "Unknown I-Force device";
372 iforce->dev.open = iforce_open;
373 iforce->dev.close = iforce_release;
374 iforce->dev.flush = iforce_flush;
375 iforce->dev.event = iforce_input_event;
376 iforce->dev.upload_effect = iforce_upload_effect;
377 iforce->dev.erase_effect = iforce_erase_effect;
378
379/*
380 * On-device memory allocation.
381 */
382
383 iforce->device_memory.name = "I-Force device effect memory";
384 iforce->device_memory.start = 0;
385 iforce->device_memory.end = 200;
386 iforce->device_memory.flags = IORESOURCE_MEM;
387 iforce->device_memory.parent = NULL;
388 iforce->device_memory.child = NULL;
389 iforce->device_memory.sibling = NULL;
390
391/*
392 * Wait until device ready - until it sends its first response.
393 */
394
395 for (i = 0; i < 20; i++)
396 if (!iforce_get_id_packet(iforce, "O"))
397 break;
398
399 if (i == 20) { /* 5 seconds */
400 printk(KERN_ERR "iforce-main.c: Timeout waiting for response from device.\n");
401 return -1;
402 }
403
404/*
405 * Get device info.
406 */
407
408 if (!iforce_get_id_packet(iforce, "M"))
409 iforce->dev.id.vendor = (iforce->edata[2] << 8) | iforce->edata[1];
410 else
411 printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet M\n");
412
413 if (!iforce_get_id_packet(iforce, "P"))
414 iforce->dev.id.product = (iforce->edata[2] << 8) | iforce->edata[1];
415 else
416 printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet P\n");
417
418 if (!iforce_get_id_packet(iforce, "B"))
419 iforce->device_memory.end = (iforce->edata[2] << 8) | iforce->edata[1];
420 else
421 printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet B\n");
422
423 if (!iforce_get_id_packet(iforce, "N"))
424 iforce->dev.ff_effects_max = iforce->edata[1];
425 else
426 printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet N\n");
427
428 /* Check if the device can store more effects than the driver can really handle */
429 if (iforce->dev.ff_effects_max > FF_EFFECTS_MAX) {
430 printk(KERN_WARNING "input??: Device can handle %d effects, but N_EFFECTS_MAX is set to %d in iforce.h\n",
431 iforce->dev.ff_effects_max, FF_EFFECTS_MAX);
432 iforce->dev.ff_effects_max = FF_EFFECTS_MAX;
433 }
434
435/*
436 * Display additional info.
437 */
438
439 for (i = 0; c[i]; i++)
440 if (!iforce_get_id_packet(iforce, c + i))
441 iforce_dump_packet("info", iforce->ecmd, iforce->edata);
442
443/*
444 * Disable spring, enable force feedback.
445 * FIXME: We should use iforce_set_autocenter() et al here.
446 */
447
448 iforce_send_packet(iforce, FF_CMD_AUTOCENTER, "\004\000");
449
450/*
451 * Find appropriate device entry
452 */
453
454 for (i = 0; iforce_device[i].idvendor; i++)
455 if (iforce_device[i].idvendor == iforce->dev.id.vendor &&
456 iforce_device[i].idproduct == iforce->dev.id.product)
457 break;
458
459 iforce->type = iforce_device + i;
460 iforce->dev.name = iforce->type->name;
461
462/*
463 * Set input device bitfields and ranges.
464 */
465
466 iforce->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_FF) | BIT(EV_FF_STATUS);
467
468 for (i = 0; iforce->type->btn[i] >= 0; i++) {
469 signed short t = iforce->type->btn[i];
470 set_bit(t, iforce->dev.keybit);
471 }
472 set_bit(BTN_DEAD, iforce->dev.keybit);
473
474 for (i = 0; iforce->type->abs[i] >= 0; i++) {
475
476 signed short t = iforce->type->abs[i];
477 set_bit(t, iforce->dev.absbit);
478
479 switch (t) {
480
481 case ABS_X:
482 case ABS_Y:
483 case ABS_WHEEL:
484
485 iforce->dev.absmax[t] = 1920;
486 iforce->dev.absmin[t] = -1920;
487 iforce->dev.absflat[t] = 128;
488 iforce->dev.absfuzz[t] = 16;
489
490 set_bit(t, iforce->dev.ffbit);
491 break;
492
493 case ABS_THROTTLE:
494 case ABS_GAS:
495 case ABS_BRAKE:
496
497 iforce->dev.absmax[t] = 255;
498 iforce->dev.absmin[t] = 0;
499 break;
500
501 case ABS_RUDDER:
502
503 iforce->dev.absmax[t] = 127;
504 iforce->dev.absmin[t] = -128;
505 break;
506
507 case ABS_HAT0X:
508 case ABS_HAT0Y:
509 case ABS_HAT1X:
510 case ABS_HAT1Y:
511 iforce->dev.absmax[t] = 1;
512 iforce->dev.absmin[t] = -1;
513 break;
514 }
515 }
516
517 for (i = 0; iforce->type->ff[i] >= 0; i++)
518 set_bit(iforce->type->ff[i], iforce->dev.ffbit);
519
520/*
521 * Register input device.
522 */
523
524 input_register_device(&iforce->dev);
525
526 printk(KERN_DEBUG "iforce->dev.open = %p\n", iforce->dev.open);
527
528 printk(KERN_INFO "input: %s [%d effects, %ld bytes memory]\n",
529 iforce->dev.name, iforce->dev.ff_effects_max,
530 iforce->device_memory.end);
531
532 return 0;
533}
534
535static int __init iforce_init(void)
536{
537#ifdef CONFIG_JOYSTICK_IFORCE_USB
538 usb_register(&iforce_usb_driver);
539#endif
540#ifdef CONFIG_JOYSTICK_IFORCE_232
541 serio_register_driver(&iforce_serio_drv);
542#endif
543 return 0;
544}
545
546static void __exit iforce_exit(void)
547{
548#ifdef CONFIG_JOYSTICK_IFORCE_USB
549 usb_deregister(&iforce_usb_driver);
550#endif
551#ifdef CONFIG_JOYSTICK_IFORCE_232
552 serio_unregister_driver(&iforce_serio_drv);
553#endif
554}
555
556module_init(iforce_init);
557module_exit(iforce_exit);
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
new file mode 100644
index 000000000000..58728ebaaf80
--- /dev/null
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -0,0 +1,319 @@
1/*
2 * $Id: iforce-packets.c,v 1.16 2002/07/07 10:22:50 jdeneux Exp $
3 *
4 * Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
5 * Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
6 *
7 * USB/RS232 I-Force joysticks and wheels.
8 */
9
10/*
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 * Should you need to contact me, the author, you can do so either by
26 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
27 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
28 */
29
30#include "iforce.h"
31
32static struct {
33 __s32 x;
34 __s32 y;
35} iforce_hat_to_axis[16] = {{ 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
36
37
38void iforce_dump_packet(char *msg, u16 cmd, unsigned char *data)
39{
40 int i;
41
42 printk(KERN_DEBUG "iforce.c: %s ( cmd = %04x, data = ", msg, cmd);
43 for (i = 0; i < LO(cmd); i++)
44 printk("%02x ", data[i]);
45 printk(")\n");
46}
47
48/*
49 * Send a packet of bytes to the device
50 */
51int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data)
52{
53 /* Copy data to buffer */
54 int n = LO(cmd);
55 int c;
56 int empty;
57 int head, tail;
58 unsigned long flags;
59
60/*
61 * Update head and tail of xmit buffer
62 */
63 spin_lock_irqsave(&iforce->xmit_lock, flags);
64
65 head = iforce->xmit.head;
66 tail = iforce->xmit.tail;
67
68 if (CIRC_SPACE(head, tail, XMIT_SIZE) < n+2) {
69 printk(KERN_WARNING "iforce.c: not enough space in xmit buffer to send new packet\n");
70 spin_unlock_irqrestore(&iforce->xmit_lock, flags);
71 return -1;
72 }
73
74 empty = head == tail;
75 XMIT_INC(iforce->xmit.head, n+2);
76
77/*
78 * Store packet in xmit buffer
79 */
80 iforce->xmit.buf[head] = HI(cmd);
81 XMIT_INC(head, 1);
82 iforce->xmit.buf[head] = LO(cmd);
83 XMIT_INC(head, 1);
84
85 c = CIRC_SPACE_TO_END(head, tail, XMIT_SIZE);
86 if (n < c) c=n;
87
88 memcpy(&iforce->xmit.buf[head],
89 data,
90 c);
91 if (n != c) {
92 memcpy(&iforce->xmit.buf[0],
93 data + c,
94 n - c);
95 }
96 XMIT_INC(head, n);
97
98 spin_unlock_irqrestore(&iforce->xmit_lock, flags);
99/*
100 * If necessary, start the transmission
101 */
102 switch (iforce->bus) {
103
104#ifdef CONFIG_JOYSTICK_IFORCE_232
105 case IFORCE_232:
106 if (empty)
107 iforce_serial_xmit(iforce);
108 break;
109#endif
110#ifdef CONFIG_JOYSTICK_IFORCE_USB
111 case IFORCE_USB:
112
113 if (iforce->usbdev && empty &&
114 !test_and_set_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags)) {
115
116 iforce_usb_xmit(iforce);
117 }
118 break;
119#endif
120 }
121 return 0;
122}
123
124/* Start or stop an effect */
125int iforce_control_playback(struct iforce* iforce, u16 id, unsigned int value)
126{
127 unsigned char data[3];
128
129printk(KERN_DEBUG "iforce-packets.c: control_playback %d %d\n", id, value);
130
131 data[0] = LO(id);
132 data[1] = (value > 0) ? ((value > 1) ? 0x41 : 0x01) : 0;
133 data[2] = LO(value);
134 return iforce_send_packet(iforce, FF_CMD_PLAY, data);
135}
136
137/* Mark an effect that was being updated as ready. That means it can be updated
138 * again */
139static int mark_core_as_ready(struct iforce *iforce, unsigned short addr)
140{
141 int i;
142 for (i=0; i<iforce->dev.ff_effects_max; ++i) {
143 if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags) &&
144 (iforce->core_effects[i].mod1_chunk.start == addr ||
145 iforce->core_effects[i].mod2_chunk.start == addr)) {
146 clear_bit(FF_CORE_UPDATE, iforce->core_effects[i].flags);
147 return 0;
148 }
149 }
150 printk(KERN_WARNING "iforce-packets.c: unused effect %04x updated !!!\n", addr);
151 return -1;
152}
153
154void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data, struct pt_regs *regs)
155{
156 struct input_dev *dev = &iforce->dev;
157 int i;
158 static int being_used = 0;
159
160 if (being_used)
161 printk(KERN_WARNING "iforce-packets.c: re-entrant call to iforce_process %d\n", being_used);
162 being_used++;
163
164#ifdef CONFIG_JOYSTICK_IFORCE_232
165 if (HI(iforce->expect_packet) == HI(cmd)) {
166 iforce->expect_packet = 0;
167 iforce->ecmd = cmd;
168 memcpy(iforce->edata, data, IFORCE_MAX_LENGTH);
169 wake_up(&iforce->wait);
170 }
171#endif
172
173 if (!iforce->type) {
174 being_used--;
175 return;
176 }
177
178 switch (HI(cmd)) {
179
180 case 0x01: /* joystick position data */
181 case 0x03: /* wheel position data */
182
183 input_regs(dev, regs);
184
185 if (HI(cmd) == 1) {
186 input_report_abs(dev, ABS_X, (__s16) (((__s16)data[1] << 8) | data[0]));
187 input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[3] << 8) | data[2]));
188 input_report_abs(dev, ABS_THROTTLE, 255 - data[4]);
189 if (LO(cmd) >= 8 && test_bit(ABS_RUDDER ,dev->absbit))
190 input_report_abs(dev, ABS_RUDDER, (__s8)data[7]);
191 } else {
192 input_report_abs(dev, ABS_WHEEL, (__s16) (((__s16)data[1] << 8) | data[0]));
193 input_report_abs(dev, ABS_GAS, 255 - data[2]);
194 input_report_abs(dev, ABS_BRAKE, 255 - data[3]);
195 }
196
197 input_report_abs(dev, ABS_HAT0X, iforce_hat_to_axis[data[6] >> 4].x);
198 input_report_abs(dev, ABS_HAT0Y, iforce_hat_to_axis[data[6] >> 4].y);
199
200 for (i = 0; iforce->type->btn[i] >= 0; i++)
201 input_report_key(dev, iforce->type->btn[i], data[(i >> 3) + 5] & (1 << (i & 7)));
202
203 /* If there are untouched bits left, interpret them as the second hat */
204 if (i <= 8) {
205 int btns = data[6];
206 if (test_bit(ABS_HAT1X, dev->absbit)) {
207 if (btns & 8) input_report_abs(dev, ABS_HAT1X, -1);
208 else if (btns & 2) input_report_abs(dev, ABS_HAT1X, 1);
209 else input_report_abs(dev, ABS_HAT1X, 0);
210 }
211 if (test_bit(ABS_HAT1Y, dev->absbit)) {
212 if (btns & 1) input_report_abs(dev, ABS_HAT1Y, -1);
213 else if (btns & 4) input_report_abs(dev, ABS_HAT1Y, 1);
214 else input_report_abs(dev, ABS_HAT1Y, 0);
215 }
216 }
217
218 input_sync(dev);
219
220 break;
221
222 case 0x02: /* status report */
223 input_regs(dev, regs);
224 input_report_key(dev, BTN_DEAD, data[0] & 0x02);
225 input_sync(dev);
226
227 /* Check if an effect was just started or stopped */
228 i = data[1] & 0x7f;
229 if (data[1] & 0x80) {
230 if (!test_and_set_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) {
231 /* Report play event */
232 input_report_ff_status(dev, i, FF_STATUS_PLAYING);
233 }
234 }
235 else if (test_and_clear_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) {
236 /* Report stop event */
237 input_report_ff_status(dev, i, FF_STATUS_STOPPED);
238 }
239 if (LO(cmd) > 3) {
240 int j;
241 for (j=3; j<LO(cmd); j+=2) {
242 mark_core_as_ready(iforce, data[j] | (data[j+1]<<8));
243 }
244 }
245 break;
246 }
247 being_used--;
248}
249
250int iforce_get_id_packet(struct iforce *iforce, char *packet)
251{
252 DECLARE_WAITQUEUE(wait, current);
253 int timeout = HZ; /* 1 second */
254
255 switch (iforce->bus) {
256
257 case IFORCE_USB:
258
259#ifdef CONFIG_JOYSTICK_IFORCE_USB
260 iforce->cr.bRequest = packet[0];
261 iforce->ctrl->dev = iforce->usbdev;
262
263 set_current_state(TASK_INTERRUPTIBLE);
264 add_wait_queue(&iforce->wait, &wait);
265
266 if (usb_submit_urb(iforce->ctrl, GFP_ATOMIC)) {
267 set_current_state(TASK_RUNNING);
268 remove_wait_queue(&iforce->wait, &wait);
269 return -1;
270 }
271
272 while (timeout && iforce->ctrl->status == -EINPROGRESS)
273 timeout = schedule_timeout(timeout);
274
275 set_current_state(TASK_RUNNING);
276 remove_wait_queue(&iforce->wait, &wait);
277
278 if (!timeout) {
279 usb_unlink_urb(iforce->ctrl);
280 return -1;
281 }
282#else
283 printk(KERN_ERR "iforce_get_id_packet: iforce->bus = USB!\n");
284#endif
285 break;
286
287 case IFORCE_232:
288
289#ifdef CONFIG_JOYSTICK_IFORCE_232
290 iforce->expect_packet = FF_CMD_QUERY;
291 iforce_send_packet(iforce, FF_CMD_QUERY, packet);
292
293 set_current_state(TASK_INTERRUPTIBLE);
294 add_wait_queue(&iforce->wait, &wait);
295
296 while (timeout && iforce->expect_packet)
297 timeout = schedule_timeout(timeout);
298
299 set_current_state(TASK_RUNNING);
300 remove_wait_queue(&iforce->wait, &wait);
301
302 if (!timeout) {
303 iforce->expect_packet = 0;
304 return -1;
305 }
306#else
307 printk(KERN_ERR "iforce_get_id_packet: iforce->bus = SERIO!\n");
308#endif
309 break;
310
311 default:
312 printk(KERN_ERR "iforce_get_id_packet: iforce->bus = %d\n",
313 iforce->bus);
314 break;
315 }
316
317 return -(iforce->edata[0] != packet[0]);
318}
319
diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c
new file mode 100644
index 000000000000..11f51905cba7
--- /dev/null
+++ b/drivers/input/joystick/iforce/iforce-serio.c
@@ -0,0 +1,193 @@
1/*
2 * $Id: iforce-serio.c,v 1.4 2002/01/28 22:45:00 jdeneux Exp $
3 *
4 * Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz>
5 * Copyright (c) 2001 Johann Deneux <deneux@ifrance.com>
6 *
7 * USB/RS232 I-Force joysticks and wheels.
8 */
9
10/*
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 * Should you need to contact me, the author, you can do so either by
26 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
27 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
28 */
29
30#include "iforce.h"
31
32void iforce_serial_xmit(struct iforce *iforce)
33{
34 unsigned char cs;
35 int i;
36 unsigned long flags;
37
38 if (test_and_set_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags)) {
39 set_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags);
40 return;
41 }
42
43 spin_lock_irqsave(&iforce->xmit_lock, flags);
44
45again:
46 if (iforce->xmit.head == iforce->xmit.tail) {
47 clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
48 spin_unlock_irqrestore(&iforce->xmit_lock, flags);
49 return;
50 }
51
52 cs = 0x2b;
53
54 serio_write(iforce->serio, 0x2b);
55
56 serio_write(iforce->serio, iforce->xmit.buf[iforce->xmit.tail]);
57 cs ^= iforce->xmit.buf[iforce->xmit.tail];
58 XMIT_INC(iforce->xmit.tail, 1);
59
60 for (i=iforce->xmit.buf[iforce->xmit.tail]; i >= 0; --i) {
61 serio_write(iforce->serio, iforce->xmit.buf[iforce->xmit.tail]);
62 cs ^= iforce->xmit.buf[iforce->xmit.tail];
63 XMIT_INC(iforce->xmit.tail, 1);
64 }
65
66 serio_write(iforce->serio, cs);
67
68 if (test_and_clear_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags))
69 goto again;
70
71 clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
72
73 spin_unlock_irqrestore(&iforce->xmit_lock, flags);
74}
75
76static void iforce_serio_write_wakeup(struct serio *serio)
77{
78 struct iforce *iforce = serio_get_drvdata(serio);
79
80 iforce_serial_xmit(iforce);
81}
82
83static irqreturn_t iforce_serio_irq(struct serio *serio,
84 unsigned char data, unsigned int flags, struct pt_regs *regs)
85{
86 struct iforce *iforce = serio_get_drvdata(serio);
87
88 if (!iforce->pkt) {
89 if (data == 0x2b)
90 iforce->pkt = 1;
91 goto out;
92 }
93
94 if (!iforce->id) {
95 if (data > 3 && data != 0xff)
96 iforce->pkt = 0;
97 else
98 iforce->id = data;
99 goto out;
100 }
101
102 if (!iforce->len) {
103 if (data > IFORCE_MAX_LENGTH) {
104 iforce->pkt = 0;
105 iforce->id = 0;
106 } else {
107 iforce->len = data;
108 }
109 goto out;
110 }
111
112 if (iforce->idx < iforce->len) {
113 iforce->csum += iforce->data[iforce->idx++] = data;
114 goto out;
115 }
116
117 if (iforce->idx == iforce->len) {
118 iforce_process_packet(iforce, (iforce->id << 8) | iforce->idx, iforce->data, regs);
119 iforce->pkt = 0;
120 iforce->id = 0;
121 iforce->len = 0;
122 iforce->idx = 0;
123 iforce->csum = 0;
124 }
125out:
126 return IRQ_HANDLED;
127}
128
129static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
130{
131 struct iforce *iforce;
132 int err;
133
134 if (!(iforce = kmalloc(sizeof(struct iforce), GFP_KERNEL)))
135 return -ENOMEM;
136
137 memset(iforce, 0, sizeof(struct iforce));
138
139 iforce->bus = IFORCE_232;
140 iforce->serio = serio;
141
142 serio_set_drvdata(serio, iforce);
143
144 err = serio_open(serio, drv);
145 if (err) {
146 serio_set_drvdata(serio, NULL);
147 kfree(iforce);
148 return err;
149 }
150
151 if (iforce_init_device(iforce)) {
152 serio_close(serio);
153 serio_set_drvdata(serio, NULL);
154 kfree(iforce);
155 return -ENODEV;
156 }
157
158 return 0;
159}
160
161static void iforce_serio_disconnect(struct serio *serio)
162{
163 struct iforce *iforce = serio_get_drvdata(serio);
164
165 input_unregister_device(&iforce->dev);
166 serio_close(serio);
167 serio_set_drvdata(serio, NULL);
168 kfree(iforce);
169}
170
171static struct serio_device_id iforce_serio_ids[] = {
172 {
173 .type = SERIO_RS232,
174 .proto = SERIO_IFORCE,
175 .id = SERIO_ANY,
176 .extra = SERIO_ANY,
177 },
178 { 0 }
179};
180
181MODULE_DEVICE_TABLE(serio, iforce_serio_ids);
182
183struct serio_driver iforce_serio_drv = {
184 .driver = {
185 .name = "iforce",
186 },
187 .description = "RS232 I-Force joysticks and wheels driver",
188 .id_table = iforce_serio_ids,
189 .write_wakeup = iforce_serio_write_wakeup,
190 .interrupt = iforce_serio_irq,
191 .connect = iforce_serio_connect,
192 .disconnect = iforce_serio_disconnect,
193};
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
new file mode 100644
index 000000000000..617c0b0e5a39
--- /dev/null
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -0,0 +1,243 @@
1 /*
2 * $Id: iforce-usb.c,v 1.16 2002/06/09 11:08:04 jdeneux Exp $
3 *
4 * Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
5 * Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
6 *
7 * USB/RS232 I-Force joysticks and wheels.
8 */
9
10/*
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 * Should you need to contact me, the author, you can do so either by
26 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
27 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
28 */
29
30#include "iforce.h"
31
32void iforce_usb_xmit(struct iforce *iforce)
33{
34 int n, c;
35 unsigned long flags;
36
37 spin_lock_irqsave(&iforce->xmit_lock, flags);
38
39 if (iforce->xmit.head == iforce->xmit.tail) {
40 clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
41 spin_unlock_irqrestore(&iforce->xmit_lock, flags);
42 return;
43 }
44
45 ((char *)iforce->out->transfer_buffer)[0] = iforce->xmit.buf[iforce->xmit.tail];
46 XMIT_INC(iforce->xmit.tail, 1);
47 n = iforce->xmit.buf[iforce->xmit.tail];
48 XMIT_INC(iforce->xmit.tail, 1);
49
50 iforce->out->transfer_buffer_length = n + 1;
51 iforce->out->dev = iforce->usbdev;
52
53 /* Copy rest of data then */
54 c = CIRC_CNT_TO_END(iforce->xmit.head, iforce->xmit.tail, XMIT_SIZE);
55 if (n < c) c=n;
56
57 memcpy(iforce->out->transfer_buffer + 1,
58 &iforce->xmit.buf[iforce->xmit.tail],
59 c);
60 if (n != c) {
61 memcpy(iforce->out->transfer_buffer + 1 + c,
62 &iforce->xmit.buf[0],
63 n-c);
64 }
65 XMIT_INC(iforce->xmit.tail, n);
66
67 if ( (n=usb_submit_urb(iforce->out, GFP_ATOMIC)) ) {
68 printk(KERN_WARNING "iforce-usb.c: iforce_usb_xmit: usb_submit_urb failed %d\n", n);
69 }
70
71 /* The IFORCE_XMIT_RUNNING bit is not cleared here. That's intended.
72 * As long as the urb completion handler is not called, the transmiting
73 * is considered to be running */
74 spin_unlock_irqrestore(&iforce->xmit_lock, flags);
75}
76
77static void iforce_usb_irq(struct urb *urb, struct pt_regs *regs)
78{
79 struct iforce *iforce = urb->context;
80 int status;
81
82 switch (urb->status) {
83 case 0:
84 /* success */
85 break;
86 case -ECONNRESET:
87 case -ENOENT:
88 case -ESHUTDOWN:
89 /* this urb is terminated, clean up */
90 dbg("%s - urb shutting down with status: %d",
91 __FUNCTION__, urb->status);
92 return;
93 default:
94 dbg("%s - urb has status of: %d", __FUNCTION__, urb->status);
95 goto exit;
96 }
97
98 iforce_process_packet(iforce,
99 (iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1, regs);
100
101exit:
102 status = usb_submit_urb (urb, GFP_ATOMIC);
103 if (status)
104 err ("%s - usb_submit_urb failed with result %d",
105 __FUNCTION__, status);
106}
107
108static void iforce_usb_out(struct urb *urb, struct pt_regs *regs)
109{
110 struct iforce *iforce = urb->context;
111
112 if (urb->status) {
113 printk(KERN_DEBUG "iforce_usb_out: urb->status %d, exiting", urb->status);
114 return;
115 }
116
117 iforce_usb_xmit(iforce);
118
119 wake_up(&iforce->wait);
120}
121
122static void iforce_usb_ctrl(struct urb *urb, struct pt_regs *regs)
123{
124 struct iforce *iforce = urb->context;
125 if (urb->status) return;
126 iforce->ecmd = 0xff00 | urb->actual_length;
127 wake_up(&iforce->wait);
128}
129
130static int iforce_usb_probe(struct usb_interface *intf,
131 const struct usb_device_id *id)
132{
133 struct usb_device *dev = interface_to_usbdev(intf);
134 struct usb_host_interface *interface;
135 struct usb_endpoint_descriptor *epirq, *epout;
136 struct iforce *iforce;
137
138 interface = intf->cur_altsetting;
139
140 epirq = &interface->endpoint[0].desc;
141 epout = &interface->endpoint[1].desc;
142
143 if (!(iforce = kmalloc(sizeof(struct iforce) + 32, GFP_KERNEL)))
144 goto fail;
145
146 memset(iforce, 0, sizeof(struct iforce));
147
148 if (!(iforce->irq = usb_alloc_urb(0, GFP_KERNEL))) {
149 goto fail;
150 }
151
152 if (!(iforce->out = usb_alloc_urb(0, GFP_KERNEL))) {
153 goto fail;
154 }
155
156 if (!(iforce->ctrl = usb_alloc_urb(0, GFP_KERNEL))) {
157 goto fail;
158 }
159
160 iforce->bus = IFORCE_USB;
161 iforce->usbdev = dev;
162
163 iforce->cr.bRequestType = USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_INTERFACE;
164 iforce->cr.wIndex = 0;
165 iforce->cr.wLength = 16;
166
167 usb_fill_int_urb(iforce->irq, dev, usb_rcvintpipe(dev, epirq->bEndpointAddress),
168 iforce->data, 16, iforce_usb_irq, iforce, epirq->bInterval);
169
170 usb_fill_bulk_urb(iforce->out, dev, usb_sndbulkpipe(dev, epout->bEndpointAddress),
171 iforce + 1, 32, iforce_usb_out, iforce);
172
173 usb_fill_control_urb(iforce->ctrl, dev, usb_rcvctrlpipe(dev, 0),
174 (void*) &iforce->cr, iforce->edata, 16, iforce_usb_ctrl, iforce);
175
176 if (iforce_init_device(iforce)) goto fail;
177
178 usb_set_intfdata(intf, iforce);
179 return 0;
180
181fail:
182 if (iforce) {
183 if (iforce->irq) usb_free_urb(iforce->irq);
184 if (iforce->out) usb_free_urb(iforce->out);
185 if (iforce->ctrl) usb_free_urb(iforce->ctrl);
186 kfree(iforce);
187 }
188
189 return -ENODEV;
190}
191
192/* Called by iforce_delete() */
193void iforce_usb_delete(struct iforce* iforce)
194{
195 usb_unlink_urb(iforce->irq);
196/* Is it ok to unlink those ? */
197 usb_unlink_urb(iforce->out);
198 usb_unlink_urb(iforce->ctrl);
199
200 usb_free_urb(iforce->irq);
201 usb_free_urb(iforce->out);
202 usb_free_urb(iforce->ctrl);
203}
204
205static void iforce_usb_disconnect(struct usb_interface *intf)
206{
207 struct iforce *iforce = usb_get_intfdata(intf);
208 int open = 0; /* FIXME! iforce->dev.handle->open; */
209
210 usb_set_intfdata(intf, NULL);
211 if (iforce) {
212 iforce->usbdev = NULL;
213 input_unregister_device(&iforce->dev);
214
215 if (!open) {
216 iforce_delete_device(iforce);
217 kfree(iforce);
218 }
219 }
220}
221
222static struct usb_device_id iforce_usb_ids [] = {
223 { USB_DEVICE(0x044f, 0xa01c) }, /* Thrustmaster Motor Sport GT */
224 { USB_DEVICE(0x046d, 0xc281) }, /* Logitech WingMan Force */
225 { USB_DEVICE(0x046d, 0xc291) }, /* Logitech WingMan Formula Force */
226 { USB_DEVICE(0x05ef, 0x020a) }, /* AVB Top Shot Pegasus */
227 { USB_DEVICE(0x05ef, 0x8884) }, /* AVB Mag Turbo Force */
228 { USB_DEVICE(0x05ef, 0x8888) }, /* AVB Top Shot FFB Racing Wheel */
229 { USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */
230 { USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */
231 { USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */
232 { } /* Terminating entry */
233};
234
235MODULE_DEVICE_TABLE (usb, iforce_usb_ids);
236
237struct usb_driver iforce_usb_driver = {
238 .owner = THIS_MODULE,
239 .name = "iforce",
240 .probe = iforce_usb_probe,
241 .disconnect = iforce_usb_disconnect,
242 .id_table = iforce_usb_ids,
243};
diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h
new file mode 100644
index 000000000000..bce247bc300b
--- /dev/null
+++ b/drivers/input/joystick/iforce/iforce.h
@@ -0,0 +1,191 @@
1/*
2 * $Id: iforce.h,v 1.13 2002/07/07 10:22:50 jdeneux Exp $
3 *
4 * Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
5 * Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
6 *
7 * USB/RS232 I-Force joysticks and wheels.
8 */
9
10/*
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 * Should you need to contact me, the author, you can do so either by
26 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
27 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
28 */
29
30#include <linux/kernel.h>
31#include <linux/slab.h>
32#include <linux/input.h>
33#include <linux/module.h>
34#include <linux/init.h>
35#include <linux/spinlock.h>
36#include <linux/usb.h>
37#include <linux/serio.h>
38#include <linux/config.h>
39#include <linux/circ_buf.h>
40#include <asm/semaphore.h>
41
42/* This module provides arbitrary resource management routines.
43 * I use it to manage the device's memory.
44 * Despite the name of this module, I am *not* going to access the ioports.
45 */
46#include <linux/ioport.h>
47
48#define IFORCE_MAX_LENGTH 16
49
50/* iforce::bus */
51#define IFORCE_232 1
52#define IFORCE_USB 2
53
54#define FALSE 0
55#define TRUE 1
56
57#define FF_EFFECTS_MAX 32
58
59/* Each force feedback effect is made of one core effect, which can be
60 * associated to at most to effect modifiers
61 */
62#define FF_MOD1_IS_USED 0
63#define FF_MOD2_IS_USED 1
64#define FF_CORE_IS_USED 2
65#define FF_CORE_IS_PLAYED 3 /* Effect is currently being played */
66#define FF_CORE_SHOULD_PLAY 4 /* User wants the effect to be played */
67#define FF_CORE_UPDATE 5 /* Effect is being updated */
68#define FF_MODCORE_MAX 5
69
70#define CHECK_OWNERSHIP(i, iforce) \
71 ((i) < FF_EFFECTS_MAX && i >= 0 && \
72 test_bit(FF_CORE_IS_USED, (iforce)->core_effects[(i)].flags) && \
73 (current->pid == 0 || \
74 (iforce)->core_effects[(i)].owner == current->pid))
75
76struct iforce_core_effect {
77 /* Information about where modifiers are stored in the device's memory */
78 struct resource mod1_chunk;
79 struct resource mod2_chunk;
80 unsigned long flags[NBITS(FF_MODCORE_MAX)];
81 pid_t owner;
82 /* Used to keep track of parameters of an effect. They are needed
83 * to know what parts of an effect changed in an update operation.
84 * We try to send only parameter packets if possible, as sending
85 * effect parameter requires the effect to be stoped and restarted
86 */
87 struct ff_effect effect;
88};
89
90#define FF_CMD_EFFECT 0x010e
91#define FF_CMD_ENVELOPE 0x0208
92#define FF_CMD_MAGNITUDE 0x0303
93#define FF_CMD_PERIOD 0x0407
94#define FF_CMD_CONDITION 0x050a
95
96#define FF_CMD_AUTOCENTER 0x4002
97#define FF_CMD_PLAY 0x4103
98#define FF_CMD_ENABLE 0x4201
99#define FF_CMD_GAIN 0x4301
100
101#define FF_CMD_QUERY 0xff01
102
103/* Buffer for async write */
104#define XMIT_SIZE 256
105#define XMIT_INC(var, n) (var)+=n; (var)&= XMIT_SIZE -1
106/* iforce::xmit_flags */
107#define IFORCE_XMIT_RUNNING 0
108#define IFORCE_XMIT_AGAIN 1
109
110struct iforce_device {
111 u16 idvendor;
112 u16 idproduct;
113 char *name;
114 signed short *btn;
115 signed short *abs;
116 signed short *ff;
117};
118
119struct iforce {
120 struct input_dev dev; /* Input device interface */
121 struct iforce_device *type;
122 int bus;
123
124 unsigned char data[IFORCE_MAX_LENGTH];
125 unsigned char edata[IFORCE_MAX_LENGTH];
126 u16 ecmd;
127 u16 expect_packet;
128
129#ifdef CONFIG_JOYSTICK_IFORCE_232
130 struct serio *serio; /* RS232 transfer */
131 int idx, pkt, len, id;
132 unsigned char csum;
133#endif
134#ifdef CONFIG_JOYSTICK_IFORCE_USB
135 struct usb_device *usbdev; /* USB transfer */
136 struct urb *irq, *out, *ctrl;
137 struct usb_ctrlrequest cr;
138#endif
139 spinlock_t xmit_lock;
140 /* Buffer used for asynchronous sending of bytes to the device */
141 struct circ_buf xmit;
142 unsigned char xmit_data[XMIT_SIZE];
143 long xmit_flags[1];
144
145 /* Force Feedback */
146 wait_queue_head_t wait;
147 struct resource device_memory;
148 struct iforce_core_effect core_effects[FF_EFFECTS_MAX];
149 struct semaphore mem_mutex;
150};
151
152/* Get hi and low bytes of a 16-bits int */
153#define HI(a) ((unsigned char)((a) >> 8))
154#define LO(a) ((unsigned char)((a) & 0xff))
155
156/* For many parameters, it seems that 0x80 is a special value that should
157 * be avoided. Instead, we replace this value by 0x7f
158 */
159#define HIFIX80(a) ((unsigned char)(((a)<0? (a)+255 : (a))>>8))
160
161/* Encode a time value */
162#define TIME_SCALE(a) (a)
163
164
165/* Public functions */
166/* iforce-serio.c */
167void iforce_serial_xmit(struct iforce *iforce);
168
169/* iforce-usb.c */
170void iforce_usb_xmit(struct iforce *iforce);
171void iforce_usb_delete(struct iforce *iforce);
172
173/* iforce-main.c */
174int iforce_init_device(struct iforce *iforce);
175void iforce_delete_device(struct iforce *iforce);
176
177/* iforce-packets.c */
178int iforce_control_playback(struct iforce*, u16 id, unsigned int);
179void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data, struct pt_regs *regs);
180int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data);
181void iforce_dump_packet(char *msg, u16 cmd, unsigned char *data) ;
182int iforce_get_id_packet(struct iforce *iforce, char *packet);
183
184/* iforce-ff.c */
185int iforce_upload_periodic(struct iforce*, struct ff_effect*, int is_update);
186int iforce_upload_constant(struct iforce*, struct ff_effect*, int is_update);
187int iforce_upload_condition(struct iforce*, struct ff_effect*, int is_update);
188
189/* Public variables */
190extern struct serio_driver iforce_serio_drv;
191extern struct usb_driver iforce_usb_driver;
diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c
new file mode 100644
index 000000000000..9d3f8c38cb09
--- /dev/null
+++ b/drivers/input/joystick/interact.c
@@ -0,0 +1,322 @@
1/*
2 * $Id: interact.c,v 1.16 2002/01/22 20:28:25 vojtech Exp $
3 *
4 * Copyright (c) 2001 Vojtech Pavlik
5 *
6 * Based on the work of:
7 * Toby Deshane
8 */
9
10/*
11 * InterAct digital gamepad/joystick driver for Linux
12 */
13
14/*
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 * Should you need to contact me, the author, you can do so either by
30 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
31 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
32 */
33
34#include <linux/kernel.h>
35#include <linux/slab.h>
36#include <linux/module.h>
37#include <linux/delay.h>
38#include <linux/init.h>
39#include <linux/gameport.h>
40#include <linux/input.h>
41
42#define DRIVER_DESC "InterAct digital joystick driver"
43
44MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
45MODULE_DESCRIPTION(DRIVER_DESC);
46MODULE_LICENSE("GPL");
47
48#define INTERACT_MAX_START 600 /* 400 us */
49#define INTERACT_MAX_STROBE 60 /* 40 us */
50#define INTERACT_MAX_LENGTH 32 /* 32 bits */
51
52#define INTERACT_TYPE_HHFX 0 /* HammerHead/FX */
53#define INTERACT_TYPE_PP8D 1 /* ProPad 8 */
54
55struct interact {
56 struct gameport *gameport;
57 struct input_dev dev;
58 int bads;
59 int reads;
60 unsigned char type;
61 unsigned char length;
62 char phys[32];
63};
64
65static short interact_abs_hhfx[] =
66 { ABS_RX, ABS_RY, ABS_X, ABS_Y, ABS_HAT0X, ABS_HAT0Y, -1 };
67static short interact_abs_pp8d[] =
68 { ABS_X, ABS_Y, -1 };
69
70static short interact_btn_hhfx[] =
71 { BTN_TR, BTN_X, BTN_Y, BTN_Z, BTN_A, BTN_B, BTN_C, BTN_TL, BTN_TL2, BTN_TR2, BTN_MODE, BTN_SELECT, -1 };
72static short interact_btn_pp8d[] =
73 { BTN_C, BTN_TL, BTN_TR, BTN_A, BTN_B, BTN_Y, BTN_Z, BTN_X, -1 };
74
75struct interact_type {
76 int id;
77 short *abs;
78 short *btn;
79 char *name;
80 unsigned char length;
81 unsigned char b8;
82};
83
84static struct interact_type interact_type[] = {
85 { 0x6202, interact_abs_hhfx, interact_btn_hhfx, "InterAct HammerHead/FX", 32, 4 },
86 { 0x53f8, interact_abs_pp8d, interact_btn_pp8d, "InterAct ProPad 8 Digital", 16, 0 },
87 { 0 }};
88
89/*
90 * interact_read_packet() reads and InterAct joystick data.
91 */
92
93static int interact_read_packet(struct gameport *gameport, int length, u32 *data)
94{
95 unsigned long flags;
96 unsigned char u, v;
97 unsigned int t, s;
98 int i;
99
100 i = 0;
101 data[0] = data[1] = data[2] = 0;
102 t = gameport_time(gameport, INTERACT_MAX_START);
103 s = gameport_time(gameport, INTERACT_MAX_STROBE);
104
105 local_irq_save(flags);
106 gameport_trigger(gameport);
107 v = gameport_read(gameport);
108
109 while (t > 0 && i < length) {
110 t--;
111 u = v; v = gameport_read(gameport);
112 if (v & ~u & 0x40) {
113 data[0] = (data[0] << 1) | ((v >> 4) & 1);
114 data[1] = (data[1] << 1) | ((v >> 5) & 1);
115 data[2] = (data[2] << 1) | ((v >> 7) & 1);
116 i++;
117 t = s;
118 }
119 }
120
121 local_irq_restore(flags);
122
123 return i;
124}
125
126/*
127 * interact_poll() reads and analyzes InterAct joystick data.
128 */
129
130static void interact_poll(struct gameport *gameport)
131{
132 struct interact *interact = gameport_get_drvdata(gameport);
133 struct input_dev *dev = &interact->dev;
134 u32 data[3];
135 int i;
136
137 interact->reads++;
138
139 if (interact_read_packet(interact->gameport, interact->length, data) < interact->length) {
140 interact->bads++;
141 } else {
142
143 for (i = 0; i < 3; i++)
144 data[i] <<= INTERACT_MAX_LENGTH - interact->length;
145
146 switch (interact->type) {
147
148 case INTERACT_TYPE_HHFX:
149
150 for (i = 0; i < 4; i++)
151 input_report_abs(dev, interact_abs_hhfx[i], (data[i & 1] >> ((i >> 1) << 3)) & 0xff);
152
153 for (i = 0; i < 2; i++)
154 input_report_abs(dev, ABS_HAT0Y - i,
155 ((data[1] >> ((i << 1) + 17)) & 1) - ((data[1] >> ((i << 1) + 16)) & 1));
156
157 for (i = 0; i < 8; i++)
158 input_report_key(dev, interact_btn_hhfx[i], (data[0] >> (i + 16)) & 1);
159
160 for (i = 0; i < 4; i++)
161 input_report_key(dev, interact_btn_hhfx[i + 8], (data[1] >> (i + 20)) & 1);
162
163 break;
164
165 case INTERACT_TYPE_PP8D:
166
167 for (i = 0; i < 2; i++)
168 input_report_abs(dev, interact_abs_pp8d[i],
169 ((data[0] >> ((i << 1) + 20)) & 1) - ((data[0] >> ((i << 1) + 21)) & 1));
170
171 for (i = 0; i < 8; i++)
172 input_report_key(dev, interact_btn_pp8d[i], (data[1] >> (i + 16)) & 1);
173
174 break;
175 }
176 }
177
178 input_sync(dev);
179}
180
181/*
182 * interact_open() is a callback from the input open routine.
183 */
184
185static int interact_open(struct input_dev *dev)
186{
187 struct interact *interact = dev->private;
188
189 gameport_start_polling(interact->gameport);
190 return 0;
191}
192
193/*
194 * interact_close() is a callback from the input close routine.
195 */
196
197static void interact_close(struct input_dev *dev)
198{
199 struct interact *interact = dev->private;
200
201 gameport_stop_polling(interact->gameport);
202}
203
204/*
205 * interact_connect() probes for InterAct joysticks.
206 */
207
208static int interact_connect(struct gameport *gameport, struct gameport_driver *drv)
209{
210 struct interact *interact;
211 __u32 data[3];
212 int i, t;
213 int err;
214
215 if (!(interact = kcalloc(1, sizeof(struct interact), GFP_KERNEL)))
216 return -ENOMEM;
217
218 interact->gameport = gameport;
219
220 gameport_set_drvdata(gameport, interact);
221
222 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
223 if (err)
224 goto fail1;
225
226 i = interact_read_packet(gameport, INTERACT_MAX_LENGTH * 2, data);
227
228 if (i != 32 || (data[0] >> 24) != 0x0c || (data[1] >> 24) != 0x02) {
229 err = -ENODEV;
230 goto fail2;
231 }
232
233 for (i = 0; interact_type[i].length; i++)
234 if (interact_type[i].id == (data[2] >> 16))
235 break;
236
237 if (!interact_type[i].length) {
238 printk(KERN_WARNING "interact.c: Unknown joystick on %s. [len %d d0 %08x d1 %08x i2 %08x]\n",
239 gameport->phys, i, data[0], data[1], data[2]);
240 err = -ENODEV;
241 goto fail2;
242 }
243
244 gameport_set_poll_handler(gameport, interact_poll);
245 gameport_set_poll_interval(gameport, 20);
246
247 sprintf(interact->phys, "%s/input0", gameport->phys);
248
249 interact->type = i;
250 interact->length = interact_type[i].length;
251
252 interact->dev.private = interact;
253 interact->dev.open = interact_open;
254 interact->dev.close = interact_close;
255
256 interact->dev.name = interact_type[i].name;
257 interact->dev.phys = interact->phys;
258 interact->dev.id.bustype = BUS_GAMEPORT;
259 interact->dev.id.vendor = GAMEPORT_ID_VENDOR_INTERACT;
260 interact->dev.id.product = interact_type[i].id;
261 interact->dev.id.version = 0x0100;
262
263 interact->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
264
265 for (i = 0; (t = interact_type[interact->type].abs[i]) >= 0; i++) {
266 set_bit(t, interact->dev.absbit);
267 if (i < interact_type[interact->type].b8) {
268 interact->dev.absmin[t] = 0;
269 interact->dev.absmax[t] = 255;
270 } else {
271 interact->dev.absmin[t] = -1;
272 interact->dev.absmax[t] = 1;
273 }
274 }
275
276 for (i = 0; (t = interact_type[interact->type].btn[i]) >= 0; i++)
277 set_bit(t, interact->dev.keybit);
278
279 input_register_device(&interact->dev);
280 printk(KERN_INFO "input: %s on %s\n",
281 interact_type[interact->type].name, gameport->phys);
282
283 return 0;
284
285fail2: gameport_close(gameport);
286fail1: gameport_set_drvdata(gameport, NULL);
287 kfree(interact);
288 return err;
289}
290
291static void interact_disconnect(struct gameport *gameport)
292{
293 struct interact *interact = gameport_get_drvdata(gameport);
294
295 input_unregister_device(&interact->dev);
296 gameport_close(gameport);
297 gameport_set_drvdata(gameport, NULL);
298 kfree(interact);
299}
300
301static struct gameport_driver interact_drv = {
302 .driver = {
303 .name = "interact",
304 },
305 .description = DRIVER_DESC,
306 .connect = interact_connect,
307 .disconnect = interact_disconnect,
308};
309
310static int __init interact_init(void)
311{
312 gameport_register_driver(&interact_drv);
313 return 0;
314}
315
316static void __exit interact_exit(void)
317{
318 gameport_unregister_driver(&interact_drv);
319}
320
321module_init(interact_init);
322module_exit(interact_exit);
diff --git a/drivers/input/joystick/joydump.c b/drivers/input/joystick/joydump.c
new file mode 100644
index 000000000000..4234ccaf9146
--- /dev/null
+++ b/drivers/input/joystick/joydump.c
@@ -0,0 +1,175 @@
1/*
2 * $Id: joydump.c,v 1.1 2002/01/23 06:56:16 jsimmons Exp $
3 *
4 * Copyright (c) 1996-2001 Vojtech Pavlik
5 */
6
7/*
8 * This is just a very simple driver that can dump the data
9 * out of the joystick port into the syslog ...
10 */
11
12/*
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27 * Should you need to contact me, the author, you can do so either by
28 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
29 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
30 */
31
32#include <linux/module.h>
33#include <linux/gameport.h>
34#include <linux/kernel.h>
35#include <linux/delay.h>
36#include <linux/init.h>
37
38#define DRIVER_DESC "Gameport data dumper module"
39
40MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
41MODULE_DESCRIPTION(DRIVER_DESC);
42MODULE_LICENSE("GPL");
43
44#define BUF_SIZE 256
45
46struct joydump {
47 unsigned int time;
48 unsigned char data;
49};
50
51static int joydump_connect(struct gameport *gameport, struct gameport_driver *drv)
52{
53 struct joydump *buf; /* all entries */
54 struct joydump *dump, *prev; /* one entry each */
55 int axes[4], buttons;
56 int i, j, t, timeout;
57 unsigned long flags;
58 unsigned char u;
59
60 printk(KERN_INFO "joydump: ,------------------ START ----------------.\n");
61 printk(KERN_INFO "joydump: | Dumping: %30s |\n", gameport->phys);
62 printk(KERN_INFO "joydump: | Speed: %28d kHz |\n", gameport->speed);
63
64 if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW)) {
65
66 printk(KERN_INFO "joydump: | Raw mode not available - trying cooked. |\n");
67
68 if (gameport_open(gameport, drv, GAMEPORT_MODE_COOKED)) {
69
70 printk(KERN_INFO "joydump: | Cooked not available either. Failing. |\n");
71 printk(KERN_INFO "joydump: `------------------- END -----------------'\n");
72 return -ENODEV;
73 }
74
75 gameport_cooked_read(gameport, axes, &buttons);
76
77 for (i = 0; i < 4; i++)
78 printk(KERN_INFO "joydump: | Axis %d: %4d. |\n", i, axes[i]);
79 printk(KERN_INFO "joydump: | Buttons %02x. |\n", buttons);
80 printk(KERN_INFO "joydump: `------------------- END -----------------'\n");
81 }
82
83 timeout = gameport_time(gameport, 10000); /* 10 ms */
84
85 buf = kmalloc(BUF_SIZE * sizeof(struct joydump), GFP_KERNEL);
86 if (!buf) {
87 printk(KERN_INFO "joydump: no memory for testing\n");
88 goto jd_end;
89 }
90 dump = buf;
91 t = 0;
92 i = 1;
93
94 local_irq_save(flags);
95
96 u = gameport_read(gameport);
97
98 dump->data = u;
99 dump->time = t;
100 dump++;
101
102 gameport_trigger(gameport);
103
104 while (i < BUF_SIZE && t < timeout) {
105
106 dump->data = gameport_read(gameport);
107
108 if (dump->data ^ u) {
109 u = dump->data;
110 dump->time = t;
111 i++;
112 dump++;
113 }
114 t++;
115 }
116
117 local_irq_restore(flags);
118
119/*
120 * Dump data.
121 */
122
123 t = i;
124 dump = buf;
125 prev = dump;
126
127 printk(KERN_INFO "joydump: >------------------ DATA -----------------<\n");
128 printk(KERN_INFO "joydump: | index: %3d delta: %3d us data: ", 0, 0);
129 for (j = 7; j >= 0; j--)
130 printk("%d", (dump->data >> j) & 1);
131 printk(" |\n");
132 dump++;
133
134 for (i = 1; i < t; i++, dump++, prev++) {
135 printk(KERN_INFO "joydump: | index: %3d delta: %3d us data: ",
136 i, dump->time - prev->time);
137 for (j = 7; j >= 0; j--)
138 printk("%d", (dump->data >> j) & 1);
139 printk(" |\n");
140 }
141 kfree(buf);
142
143jd_end:
144 printk(KERN_INFO "joydump: `------------------- END -----------------'\n");
145
146 return 0;
147}
148
149static void joydump_disconnect(struct gameport *gameport)
150{
151 gameport_close(gameport);
152}
153
154static struct gameport_driver joydump_drv = {
155 .driver = {
156 .name = "joydump",
157 },
158 .description = DRIVER_DESC,
159 .connect = joydump_connect,
160 .disconnect = joydump_disconnect,
161};
162
163static int __init joydump_init(void)
164{
165 gameport_register_driver(&joydump_drv);
166 return 0;
167}
168
169static void __exit joydump_exit(void)
170{
171 gameport_unregister_driver(&joydump_drv);
172}
173
174module_init(joydump_init);
175module_exit(joydump_exit);
diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c
new file mode 100644
index 000000000000..1ba503627242
--- /dev/null
+++ b/drivers/input/joystick/magellan.c
@@ -0,0 +1,247 @@
1/*
2 * $Id: magellan.c,v 1.16 2002/01/22 20:28:39 vojtech Exp $
3 *
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 */
6
7/*
8 * Magellan and Space Mouse 6dof controller driver for Linux
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/kernel.h>
32#include <linux/module.h>
33#include <linux/slab.h>
34#include <linux/input.h>
35#include <linux/serio.h>
36#include <linux/init.h>
37
38#define DRIVER_DESC "Magellan and SpaceMouse 6dof controller driver"
39
40MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
41MODULE_DESCRIPTION(DRIVER_DESC);
42MODULE_LICENSE("GPL");
43
44/*
45 * Definitions & global arrays.
46 */
47
48#define MAGELLAN_MAX_LENGTH 32
49
50static int magellan_buttons[] = { BTN_0, BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 };
51static int magellan_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
52static char *magellan_name = "LogiCad3D Magellan / SpaceMouse";
53
54/*
55 * Per-Magellan data.
56 */
57
58struct magellan {
59 struct input_dev dev;
60 int idx;
61 unsigned char data[MAGELLAN_MAX_LENGTH];
62 char phys[32];
63};
64
65/*
66 * magellan_crunch_nibbles() verifies that the bytes sent from the Magellan
67 * have correct upper nibbles for the lower ones, if not, the packet will
68 * be thrown away. It also strips these upper halves to simplify further
69 * processing.
70 */
71
72static int magellan_crunch_nibbles(unsigned char *data, int count)
73{
74 static unsigned char nibbles[16] = "0AB3D56GH9:K<MN?";
75
76 do {
77 if (data[count] == nibbles[data[count] & 0xf])
78 data[count] = data[count] & 0xf;
79 else
80 return -1;
81 } while (--count);
82
83 return 0;
84}
85
86static void magellan_process_packet(struct magellan* magellan, struct pt_regs *regs)
87{
88 struct input_dev *dev = &magellan->dev;
89 unsigned char *data = magellan->data;
90 int i, t;
91
92 if (!magellan->idx) return;
93
94 input_regs(dev, regs);
95
96 switch (magellan->data[0]) {
97
98 case 'd': /* Axis data */
99 if (magellan->idx != 25) return;
100 if (magellan_crunch_nibbles(data, 24)) return;
101 for (i = 0; i < 6; i++)
102 input_report_abs(dev, magellan_axes[i],
103 (data[(i << 2) + 1] << 12 | data[(i << 2) + 2] << 8 |
104 data[(i << 2) + 3] << 4 | data[(i << 2) + 4]) - 32768);
105 break;
106
107 case 'k': /* Button data */
108 if (magellan->idx != 4) return;
109 if (magellan_crunch_nibbles(data, 3)) return;
110 t = (data[1] << 1) | (data[2] << 5) | data[3];
111 for (i = 0; i < 9; i++) input_report_key(dev, magellan_buttons[i], (t >> i) & 1);
112 break;
113 }
114
115 input_sync(dev);
116}
117
118static irqreturn_t magellan_interrupt(struct serio *serio,
119 unsigned char data, unsigned int flags, struct pt_regs *regs)
120{
121 struct magellan* magellan = serio_get_drvdata(serio);
122
123 if (data == '\r') {
124 magellan_process_packet(magellan, regs);
125 magellan->idx = 0;
126 } else {
127 if (magellan->idx < MAGELLAN_MAX_LENGTH)
128 magellan->data[magellan->idx++] = data;
129 }
130 return IRQ_HANDLED;
131}
132
133/*
134 * magellan_disconnect() is the opposite of magellan_connect()
135 */
136
137static void magellan_disconnect(struct serio *serio)
138{
139 struct magellan* magellan = serio_get_drvdata(serio);
140
141 input_unregister_device(&magellan->dev);
142 serio_close(serio);
143 serio_set_drvdata(serio, NULL);
144 kfree(magellan);
145}
146
147/*
148 * magellan_connect() is the routine that is called when someone adds a
149 * new serio device that supports Magellan protocol and registers it as
150 * an input device.
151 */
152
153static int magellan_connect(struct serio *serio, struct serio_driver *drv)
154{
155 struct magellan *magellan;
156 int i, t;
157 int err;
158
159 if (!(magellan = kmalloc(sizeof(struct magellan), GFP_KERNEL)))
160 return -ENOMEM;
161
162 memset(magellan, 0, sizeof(struct magellan));
163
164 magellan->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
165
166 for (i = 0; i < 9; i++)
167 set_bit(magellan_buttons[i], magellan->dev.keybit);
168
169 for (i = 0; i < 6; i++) {
170 t = magellan_axes[i];
171 set_bit(t, magellan->dev.absbit);
172 magellan->dev.absmin[t] = -360;
173 magellan->dev.absmax[t] = 360;
174 }
175
176 sprintf(magellan->phys, "%s/input0", serio->phys);
177
178 init_input_dev(&magellan->dev);
179 magellan->dev.private = magellan;
180 magellan->dev.name = magellan_name;
181 magellan->dev.phys = magellan->phys;
182 magellan->dev.id.bustype = BUS_RS232;
183 magellan->dev.id.vendor = SERIO_MAGELLAN;
184 magellan->dev.id.product = 0x0001;
185 magellan->dev.id.version = 0x0100;
186 magellan->dev.dev = &serio->dev;
187
188 serio_set_drvdata(serio, magellan);
189
190 err = serio_open(serio, drv);
191 if (err) {
192 serio_set_drvdata(serio, NULL);
193 kfree(magellan);
194 return err;
195 }
196
197 input_register_device(&magellan->dev);
198
199 printk(KERN_INFO "input: %s on %s\n", magellan_name, serio->phys);
200
201 return 0;
202}
203
204/*
205 * The serio driver structure.
206 */
207
208static struct serio_device_id magellan_serio_ids[] = {
209 {
210 .type = SERIO_RS232,
211 .proto = SERIO_MAGELLAN,
212 .id = SERIO_ANY,
213 .extra = SERIO_ANY,
214 },
215 { 0 }
216};
217
218MODULE_DEVICE_TABLE(serio, magellan_serio_ids);
219
220static struct serio_driver magellan_drv = {
221 .driver = {
222 .name = "magellan",
223 },
224 .description = DRIVER_DESC,
225 .id_table = magellan_serio_ids,
226 .interrupt = magellan_interrupt,
227 .connect = magellan_connect,
228 .disconnect = magellan_disconnect,
229};
230
231/*
232 * The functions for inserting/removing us as a module.
233 */
234
235static int __init magellan_init(void)
236{
237 serio_register_driver(&magellan_drv);
238 return 0;
239}
240
241static void __exit magellan_exit(void)
242{
243 serio_unregister_driver(&magellan_drv);
244}
245
246module_init(magellan_init);
247module_exit(magellan_exit);
diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
new file mode 100644
index 000000000000..47144a7ed9e7
--- /dev/null
+++ b/drivers/input/joystick/sidewinder.c
@@ -0,0 +1,807 @@
1/*
2 * Copyright (c) 1998-2005 Vojtech Pavlik
3 */
4
5/*
6 * Microsoft SideWinder joystick family driver for Linux
7 */
8
9/*
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * Should you need to contact me, the author, you can do so either by
25 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
26 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
27 */
28
29#include <linux/delay.h>
30#include <linux/kernel.h>
31#include <linux/module.h>
32#include <linux/slab.h>
33#include <linux/init.h>
34#include <linux/input.h>
35#include <linux/gameport.h>
36
37#define DRIVER_DESC "Microsoft SideWinder joystick family driver"
38
39MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
40MODULE_DESCRIPTION(DRIVER_DESC);
41MODULE_LICENSE("GPL");
42
43/*
44 * These are really magic values. Changing them can make a problem go away,
45 * as well as break everything.
46 */
47
48#undef SW_DEBUG
49#undef SW_DEBUG_DATA
50
51#define SW_START 600 /* The time we wait for the first bit [600 us] */
52#define SW_STROBE 60 /* Max time per bit [60 us] */
53#define SW_TIMEOUT 6 /* Wait for everything to settle [6 ms] */
54#define SW_KICK 45 /* Wait after A0 fall till kick [45 us] */
55#define SW_END 8 /* Number of bits before end of packet to kick */
56#define SW_FAIL 16 /* Number of packet read errors to fail and reinitialize */
57#define SW_BAD 2 /* Number of packet read errors to switch off 3d Pro optimization */
58#define SW_OK 64 /* Number of packet read successes to switch optimization back on */
59#define SW_LENGTH 512 /* Max number of bits in a packet */
60
61#ifdef SW_DEBUG
62#define dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg)
63#else
64#define dbg(format, arg...) do {} while (0)
65#endif
66
67/*
68 * SideWinder joystick types ...
69 */
70
71#define SW_ID_3DP 0
72#define SW_ID_GP 1
73#define SW_ID_PP 2
74#define SW_ID_FFP 3
75#define SW_ID_FSP 4
76#define SW_ID_FFW 5
77
78/*
79 * Names, buttons, axes ...
80 */
81
82static char *sw_name[] = { "3D Pro", "GamePad", "Precision Pro", "Force Feedback Pro", "FreeStyle Pro",
83 "Force Feedback Wheel" };
84
85static char sw_abs[][7] = {
86 { ABS_X, ABS_Y, ABS_RZ, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y },
87 { ABS_X, ABS_Y },
88 { ABS_X, ABS_Y, ABS_RZ, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y },
89 { ABS_X, ABS_Y, ABS_RZ, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y },
90 { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y },
91 { ABS_RX, ABS_RUDDER, ABS_THROTTLE }};
92
93static char sw_bit[][7] = {
94 { 10, 10, 9, 10, 1, 1 },
95 { 1, 1 },
96 { 10, 10, 6, 7, 1, 1 },
97 { 10, 10, 6, 7, 1, 1 },
98 { 10, 10, 6, 1, 1 },
99 { 10, 7, 7, 1, 1 }};
100
101static short sw_btn[][12] = {
102 { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_THUMB2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_MODE },
103 { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE },
104 { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_SELECT },
105 { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_SELECT },
106 { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT },
107 { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_THUMB2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4 }};
108
109static struct {
110 int x;
111 int y;
112} sw_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
113
114struct sw {
115 struct gameport *gameport;
116 struct input_dev dev[4];
117 char name[64];
118 char phys[4][32];
119 int length;
120 int type;
121 int bits;
122 int number;
123 int fail;
124 int ok;
125 int reads;
126 int bads;
127};
128
129/*
130 * sw_read_packet() is a function which reads either a data packet, or an
131 * identification packet from a SideWinder joystick. The protocol is very,
132 * very, very braindamaged. Microsoft patented it in US patent #5628686.
133 */
134
135static int sw_read_packet(struct gameport *gameport, unsigned char *buf, int length, int id)
136{
137 unsigned long flags;
138 int timeout, bitout, sched, i, kick, start, strobe;
139 unsigned char pending, u, v;
140
141 i = -id; /* Don't care about data, only want ID */
142 timeout = id ? gameport_time(gameport, SW_TIMEOUT * 1000) : 0; /* Set up global timeout for ID packet */
143 kick = id ? gameport_time(gameport, SW_KICK) : 0; /* Set up kick timeout for ID packet */
144 start = gameport_time(gameport, SW_START);
145 strobe = gameport_time(gameport, SW_STROBE);
146 bitout = start;
147 pending = 0;
148 sched = 0;
149
150 local_irq_save(flags); /* Quiet, please */
151
152 gameport_trigger(gameport); /* Trigger */
153 v = gameport_read(gameport);
154
155 do {
156 bitout--;
157 u = v;
158 v = gameport_read(gameport);
159 } while (!(~v & u & 0x10) && (bitout > 0)); /* Wait for first falling edge on clock */
160
161 if (bitout > 0)
162 bitout = strobe; /* Extend time if not timed out */
163
164 while ((timeout > 0 || bitout > 0) && (i < length)) {
165
166 timeout--;
167 bitout--; /* Decrement timers */
168 sched--;
169
170 u = v;
171 v = gameport_read(gameport);
172
173 if ((~u & v & 0x10) && (bitout > 0)) { /* Rising edge on clock - data bit */
174 if (i >= 0) /* Want this data */
175 buf[i] = v >> 5; /* Store it */
176 i++; /* Advance index */
177 bitout = strobe; /* Extend timeout for next bit */
178 }
179
180 if (kick && (~v & u & 0x01)) { /* Falling edge on axis 0 */
181 sched = kick; /* Schedule second trigger */
182 kick = 0; /* Don't schedule next time on falling edge */
183 pending = 1; /* Mark schedule */
184 }
185
186 if (pending && sched < 0 && (i > -SW_END)) { /* Second trigger time */
187 gameport_trigger(gameport); /* Trigger */
188 bitout = start; /* Long bit timeout */
189 pending = 0; /* Unmark schedule */
190 timeout = 0; /* Switch from global to bit timeouts */
191 }
192 }
193
194 local_irq_restore(flags); /* Done - relax */
195
196#ifdef SW_DEBUG_DATA
197 {
198 int j;
199 printk(KERN_DEBUG "sidewinder.c: Read %d triplets. [", i);
200 for (j = 0; j < i; j++) printk("%d", buf[j]);
201 printk("]\n");
202 }
203#endif
204
205 return i;
206}
207
208/*
209 * sw_get_bits() and GB() compose bits from the triplet buffer into a __u64.
210 * Parameter 'pos' is bit number inside packet where to start at, 'num' is number
211 * of bits to be read, 'shift' is offset in the resulting __u64 to start at, bits
212 * is number of bits per triplet.
213 */
214
215#define GB(pos,num) sw_get_bits(buf, pos, num, sw->bits)
216
217static __u64 sw_get_bits(unsigned char *buf, int pos, int num, char bits)
218{
219 __u64 data = 0;
220 int tri = pos % bits; /* Start position */
221 int i = pos / bits;
222 int bit = 0;
223
224 while (num--) {
225 data |= (__u64)((buf[i] >> tri++) & 1) << bit++; /* Transfer bit */
226 if (tri == bits) {
227 i++; /* Next triplet */
228 tri = 0;
229 }
230 }
231
232 return data;
233}
234
235/*
236 * sw_init_digital() initializes a SideWinder 3D Pro joystick
237 * into digital mode.
238 */
239
240static void sw_init_digital(struct gameport *gameport)
241{
242 int seq[] = { 140, 140+725, 140+300, 0 };
243 unsigned long flags;
244 int i, t;
245
246 local_irq_save(flags);
247
248 i = 0;
249 do {
250 gameport_trigger(gameport); /* Trigger */
251 t = gameport_time(gameport, SW_TIMEOUT * 1000);
252 while ((gameport_read(gameport) & 1) && t) t--; /* Wait for axis to fall back to 0 */
253 udelay(seq[i]); /* Delay magic time */
254 } while (seq[++i]);
255
256 gameport_trigger(gameport); /* Last trigger */
257
258 local_irq_restore(flags);
259}
260
261/*
262 * sw_parity() computes parity of __u64
263 */
264
265static int sw_parity(__u64 t)
266{
267 int x = t ^ (t >> 32);
268
269 x ^= x >> 16;
270 x ^= x >> 8;
271 x ^= x >> 4;
272 x ^= x >> 2;
273 x ^= x >> 1;
274 return x & 1;
275}
276
277/*
278 * sw_ccheck() checks synchronization bits and computes checksum of nibbles.
279 */
280
281static int sw_check(__u64 t)
282{
283 unsigned char sum = 0;
284
285 if ((t & 0x8080808080808080ULL) ^ 0x80) /* Sync */
286 return -1;
287
288 while (t) { /* Sum */
289 sum += t & 0xf;
290 t >>= 4;
291 }
292
293 return sum & 0xf;
294}
295
296/*
297 * sw_parse() analyzes SideWinder joystick data, and writes the results into
298 * the axes and buttons arrays.
299 */
300
301static int sw_parse(unsigned char *buf, struct sw *sw)
302{
303 int hat, i, j;
304 struct input_dev *dev = sw->dev;
305
306 switch (sw->type) {
307
308 case SW_ID_3DP:
309
310 if (sw_check(GB(0,64)) || (hat = (GB(6,1) << 3) | GB(60,3)) > 8)
311 return -1;
312
313 input_report_abs(dev, ABS_X, (GB( 3,3) << 7) | GB(16,7));
314 input_report_abs(dev, ABS_Y, (GB( 0,3) << 7) | GB(24,7));
315 input_report_abs(dev, ABS_RZ, (GB(35,2) << 7) | GB(40,7));
316 input_report_abs(dev, ABS_THROTTLE, (GB(32,3) << 7) | GB(48,7));
317
318 input_report_abs(dev, ABS_HAT0X, sw_hat_to_axis[hat].x);
319 input_report_abs(dev, ABS_HAT0Y, sw_hat_to_axis[hat].y);
320
321 for (j = 0; j < 7; j++)
322 input_report_key(dev, sw_btn[SW_ID_3DP][j], !GB(j+8,1));
323
324 input_report_key(dev, BTN_BASE4, !GB(38,1));
325 input_report_key(dev, BTN_BASE5, !GB(37,1));
326
327 input_sync(dev);
328
329 return 0;
330
331 case SW_ID_GP:
332
333 for (i = 0; i < sw->number; i ++) {
334
335 if (sw_parity(GB(i*15,15)))
336 return -1;
337
338 input_report_abs(dev + i, ABS_X, GB(i*15+3,1) - GB(i*15+2,1));
339 input_report_abs(dev + i, ABS_Y, GB(i*15+0,1) - GB(i*15+1,1));
340
341 for (j = 0; j < 10; j++)
342 input_report_key(dev + i, sw_btn[SW_ID_GP][j], !GB(i*15+j+4,1));
343
344 input_sync(dev + i);
345 }
346
347 return 0;
348
349 case SW_ID_PP:
350 case SW_ID_FFP:
351
352 if (!sw_parity(GB(0,48)) || (hat = GB(42,4)) > 8)
353 return -1;
354
355 input_report_abs(dev, ABS_X, GB( 9,10));
356 input_report_abs(dev, ABS_Y, GB(19,10));
357 input_report_abs(dev, ABS_RZ, GB(36, 6));
358 input_report_abs(dev, ABS_THROTTLE, GB(29, 7));
359
360 input_report_abs(dev, ABS_HAT0X, sw_hat_to_axis[hat].x);
361 input_report_abs(dev, ABS_HAT0Y, sw_hat_to_axis[hat].y);
362
363 for (j = 0; j < 9; j++)
364 input_report_key(dev, sw_btn[SW_ID_PP][j], !GB(j,1));
365
366 input_sync(dev);
367
368 return 0;
369
370 case SW_ID_FSP:
371
372 if (!sw_parity(GB(0,43)) || (hat = GB(28,4)) > 8)
373 return -1;
374
375 input_report_abs(dev, ABS_X, GB( 0,10));
376 input_report_abs(dev, ABS_Y, GB(16,10));
377 input_report_abs(dev, ABS_THROTTLE, GB(32, 6));
378
379 input_report_abs(dev, ABS_HAT0X, sw_hat_to_axis[hat].x);
380 input_report_abs(dev, ABS_HAT0Y, sw_hat_to_axis[hat].y);
381
382 for (j = 0; j < 6; j++)
383 input_report_key(dev, sw_btn[SW_ID_FSP][j], !GB(j+10,1));
384
385 input_report_key(dev, BTN_TR, !GB(26,1));
386 input_report_key(dev, BTN_START, !GB(27,1));
387 input_report_key(dev, BTN_MODE, !GB(38,1));
388 input_report_key(dev, BTN_SELECT, !GB(39,1));
389
390 input_sync(dev);
391
392 return 0;
393
394 case SW_ID_FFW:
395
396 if (!sw_parity(GB(0,33)))
397 return -1;
398
399 input_report_abs(dev, ABS_RX, GB( 0,10));
400 input_report_abs(dev, ABS_RUDDER, GB(10, 6));
401 input_report_abs(dev, ABS_THROTTLE, GB(16, 6));
402
403 for (j = 0; j < 8; j++)
404 input_report_key(dev, sw_btn[SW_ID_FFW][j], !GB(j+22,1));
405
406 input_sync(dev);
407
408 return 0;
409 }
410
411 return -1;
412}
413
414/*
415 * sw_read() reads SideWinder joystick data, and reinitializes
416 * the joystick in case of persistent problems. This is the function that is
417 * called from the generic code to poll the joystick.
418 */
419
420static int sw_read(struct sw *sw)
421{
422 unsigned char buf[SW_LENGTH];
423 int i;
424
425 i = sw_read_packet(sw->gameport, buf, sw->length, 0);
426
427 if (sw->type == SW_ID_3DP && sw->length == 66 && i != 66) { /* Broken packet, try to fix */
428
429 if (i == 64 && !sw_check(sw_get_bits(buf,0,64,1))) { /* Last init failed, 1 bit mode */
430 printk(KERN_WARNING "sidewinder.c: Joystick in wrong mode on %s"
431 " - going to reinitialize.\n", sw->gameport->phys);
432 sw->fail = SW_FAIL; /* Reinitialize */
433 i = 128; /* Bogus value */
434 }
435
436 if (i < 66 && GB(0,64) == GB(i*3-66,64)) /* 1 == 3 */
437 i = 66; /* Everything is fine */
438
439 if (i < 66 && GB(0,64) == GB(66,64)) /* 1 == 2 */
440 i = 66; /* Everything is fine */
441
442 if (i < 66 && GB(i*3-132,64) == GB(i*3-66,64)) { /* 2 == 3 */
443 memmove(buf, buf + i - 22, 22); /* Move data */
444 i = 66; /* Carry on */
445 }
446 }
447
448 if (i == sw->length && !sw_parse(buf, sw)) { /* Parse data */
449
450 sw->fail = 0;
451 sw->ok++;
452
453 if (sw->type == SW_ID_3DP && sw->length == 66 /* Many packets OK */
454 && sw->ok > SW_OK) {
455
456 printk(KERN_INFO "sidewinder.c: No more trouble on %s"
457 " - enabling optimization again.\n", sw->gameport->phys);
458 sw->length = 22;
459 }
460
461 return 0;
462 }
463
464 sw->ok = 0;
465 sw->fail++;
466
467 if (sw->type == SW_ID_3DP && sw->length == 22 && sw->fail > SW_BAD) { /* Consecutive bad packets */
468
469 printk(KERN_INFO "sidewinder.c: Many bit errors on %s"
470 " - disabling optimization.\n", sw->gameport->phys);
471 sw->length = 66;
472 }
473
474 if (sw->fail < SW_FAIL)
475 return -1; /* Not enough, don't reinitialize yet */
476
477 printk(KERN_WARNING "sidewinder.c: Too many bit errors on %s"
478 " - reinitializing joystick.\n", sw->gameport->phys);
479
480 if (!i && sw->type == SW_ID_3DP) { /* 3D Pro can be in analog mode */
481 mdelay(3 * SW_TIMEOUT);
482 sw_init_digital(sw->gameport);
483 }
484
485 mdelay(SW_TIMEOUT);
486 i = sw_read_packet(sw->gameport, buf, SW_LENGTH, 0); /* Read normal data packet */
487 mdelay(SW_TIMEOUT);
488 sw_read_packet(sw->gameport, buf, SW_LENGTH, i); /* Read ID packet, this initializes the stick */
489
490 sw->fail = SW_FAIL;
491
492 return -1;
493}
494
495static void sw_poll(struct gameport *gameport)
496{
497 struct sw *sw = gameport_get_drvdata(gameport);
498
499 sw->reads++;
500 if (sw_read(sw))
501 sw->bads++;
502}
503
504static int sw_open(struct input_dev *dev)
505{
506 struct sw *sw = dev->private;
507
508 gameport_start_polling(sw->gameport);
509 return 0;
510}
511
512static void sw_close(struct input_dev *dev)
513{
514 struct sw *sw = dev->private;
515
516 gameport_stop_polling(sw->gameport);
517}
518
519/*
520 * sw_print_packet() prints the contents of a SideWinder packet.
521 */
522
523static void sw_print_packet(char *name, int length, unsigned char *buf, char bits)
524{
525 int i;
526
527 printk(KERN_INFO "sidewinder.c: %s packet, %d bits. [", name, length);
528 for (i = (((length + 3) >> 2) - 1); i >= 0; i--)
529 printk("%x", (int)sw_get_bits(buf, i << 2, 4, bits));
530 printk("]\n");
531}
532
533/*
534 * sw_3dp_id() translates the 3DP id into a human legible string.
535 * Unfortunately I don't know how to do this for the other SW types.
536 */
537
538static void sw_3dp_id(unsigned char *buf, char *comment)
539{
540 int i;
541 char pnp[8], rev[9];
542
543 for (i = 0; i < 7; i++) /* ASCII PnP ID */
544 pnp[i] = sw_get_bits(buf, 24+8*i, 8, 1);
545
546 for (i = 0; i < 8; i++) /* ASCII firmware revision */
547 rev[i] = sw_get_bits(buf, 88+8*i, 8, 1);
548
549 pnp[7] = rev[8] = 0;
550
551 sprintf(comment, " [PnP %d.%02d id %s rev %s]",
552 (int) ((sw_get_bits(buf, 8, 6, 1) << 6) | /* Two 6-bit values */
553 sw_get_bits(buf, 16, 6, 1)) / 100,
554 (int) ((sw_get_bits(buf, 8, 6, 1) << 6) |
555 sw_get_bits(buf, 16, 6, 1)) % 100,
556 pnp, rev);
557}
558
559/*
560 * sw_guess_mode() checks the upper two button bits for toggling -
561 * indication of that the joystick is in 3-bit mode. This is documented
562 * behavior for 3DP ID packet, and for example the FSP does this in
563 * normal packets instead. Fun ...
564 */
565
566static int sw_guess_mode(unsigned char *buf, int len)
567{
568 int i;
569 unsigned char xor = 0;
570
571 for (i = 1; i < len; i++)
572 xor |= (buf[i - 1] ^ buf[i]) & 6;
573
574 return !!xor * 2 + 1;
575}
576
577/*
578 * sw_connect() probes for SideWinder type joysticks.
579 */
580
581static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
582{
583 struct sw *sw;
584 int i, j, k, l;
585 int err;
586 unsigned char *buf = NULL; /* [SW_LENGTH] */
587 unsigned char *idbuf = NULL; /* [SW_LENGTH] */
588 unsigned char m = 1;
589 char comment[40];
590
591 comment[0] = 0;
592
593 sw = kcalloc(1, sizeof(struct sw), GFP_KERNEL);
594 buf = kmalloc(SW_LENGTH, GFP_KERNEL);
595 idbuf = kmalloc(SW_LENGTH, GFP_KERNEL);
596 if (!sw || !buf || !idbuf) {
597 err = -ENOMEM;
598 goto fail1;
599 }
600
601 sw->gameport = gameport;
602
603 gameport_set_drvdata(gameport, sw);
604
605 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
606 if (err)
607 goto fail1;
608
609 dbg("Init 0: Opened %s, io %#x, speed %d",
610 gameport->phys, gameport->io, gameport->speed);
611
612 i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Read normal packet */
613 msleep(SW_TIMEOUT);
614 dbg("Init 1: Mode %d. Length %d.", m , i);
615
616 if (!i) { /* No data. 3d Pro analog mode? */
617 sw_init_digital(gameport); /* Switch to digital */
618 msleep(SW_TIMEOUT);
619 i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Retry reading packet */
620 msleep(SW_TIMEOUT);
621 dbg("Init 1b: Length %d.", i);
622 if (!i) { /* No data -> FAIL */
623 err = -ENODEV;
624 goto fail2;
625 }
626 }
627
628 j = sw_read_packet(gameport, idbuf, SW_LENGTH, i); /* Read ID. This initializes the stick */
629 m |= sw_guess_mode(idbuf, j); /* ID packet should carry mode info [3DP] */
630 dbg("Init 2: Mode %d. ID Length %d.", m, j);
631
632 if (j <= 0) { /* Read ID failed. Happens in 1-bit mode on PP */
633 msleep(SW_TIMEOUT);
634 i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Retry reading packet */
635 m |= sw_guess_mode(buf, i);
636 dbg("Init 2b: Mode %d. Length %d.", m, i);
637 if (!i) {
638 err = -ENODEV;
639 goto fail2;
640 }
641 msleep(SW_TIMEOUT);
642 j = sw_read_packet(gameport, idbuf, SW_LENGTH, i); /* Retry reading ID */
643 dbg("Init 2c: ID Length %d.", j);
644 }
645
646 sw->type = -1;
647 k = SW_FAIL; /* Try SW_FAIL times */
648 l = 0;
649
650 do {
651 k--;
652 msleep(SW_TIMEOUT);
653 i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Read data packet */
654 dbg("Init 3: Mode %d. Length %d. Last %d. Tries %d.", m, i, l, k);
655
656 if (i > l) { /* Longer? As we can only lose bits, it makes */
657 /* no sense to try detection for a packet shorter */
658 l = i; /* than the previous one */
659
660 sw->number = 1;
661 sw->gameport = gameport;
662 sw->length = i;
663 sw->bits = m;
664
665 dbg("Init 3a: Case %d.\n", i * m);
666
667 switch (i * m) {
668 case 60:
669 sw->number++;
670 case 45: /* Ambiguous packet length */
671 if (j <= 40) { /* ID length less or eq 40 -> FSP */
672 case 43:
673 sw->type = SW_ID_FSP;
674 break;
675 }
676 sw->number++;
677 case 30:
678 sw->number++;
679 case 15:
680 sw->type = SW_ID_GP;
681 break;
682 case 33:
683 case 31:
684 sw->type = SW_ID_FFW;
685 break;
686 case 48: /* Ambiguous */
687 if (j == 14) { /* ID length 14*3 -> FFP */
688 sw->type = SW_ID_FFP;
689 sprintf(comment, " [AC %s]", sw_get_bits(idbuf,38,1,3) ? "off" : "on");
690 } else
691 sw->type = SW_ID_PP;
692 break;
693 case 66:
694 sw->bits = 3;
695 case 198:
696 sw->length = 22;
697 case 64:
698 sw->type = SW_ID_3DP;
699 if (j == 160) sw_3dp_id(idbuf, comment);
700 break;
701 }
702 }
703
704 } while (k && sw->type == -1);
705
706 if (sw->type == -1) {
707 printk(KERN_WARNING "sidewinder.c: unknown joystick device detected "
708 "on %s, contact <vojtech@ucw.cz>\n", gameport->phys);
709 sw_print_packet("ID", j * 3, idbuf, 3);
710 sw_print_packet("Data", i * m, buf, m);
711 err = -ENODEV;
712 goto fail2;
713 }
714
715#ifdef SW_DEBUG
716 sw_print_packet("ID", j * 3, idbuf, 3);
717 sw_print_packet("Data", i * m, buf, m);
718#endif
719
720 gameport_set_poll_handler(gameport, sw_poll);
721 gameport_set_poll_interval(gameport, 20);
722
723 k = i;
724 l = j;
725
726 for (i = 0; i < sw->number; i++) {
727 int bits, code;
728
729 sprintf(sw->name, "Microsoft SideWinder %s", sw_name[sw->type]);
730 sprintf(sw->phys[i], "%s/input%d", gameport->phys, i);
731
732 sw->dev[i].private = sw;
733
734 sw->dev[i].open = sw_open;
735 sw->dev[i].close = sw_close;
736
737 sw->dev[i].name = sw->name;
738 sw->dev[i].phys = sw->phys[i];
739 sw->dev[i].id.bustype = BUS_GAMEPORT;
740 sw->dev[i].id.vendor = GAMEPORT_ID_VENDOR_MICROSOFT;
741 sw->dev[i].id.product = sw->type;
742 sw->dev[i].id.version = 0x0100;
743
744 sw->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
745
746 for (j = 0; (bits = sw_bit[sw->type][j]); j++) {
747 code = sw_abs[sw->type][j];
748 set_bit(code, sw->dev[i].absbit);
749 sw->dev[i].absmax[code] = (1 << bits) - 1;
750 sw->dev[i].absmin[code] = (bits == 1) ? -1 : 0;
751 sw->dev[i].absfuzz[code] = ((bits >> 1) >= 2) ? (1 << ((bits >> 1) - 2)) : 0;
752 if (code != ABS_THROTTLE)
753 sw->dev[i].absflat[code] = (bits >= 5) ? (1 << (bits - 5)) : 0;
754 }
755
756 for (j = 0; (code = sw_btn[sw->type][j]); j++)
757 set_bit(code, sw->dev[i].keybit);
758
759 input_register_device(sw->dev + i);
760 printk(KERN_INFO "input: %s%s on %s [%d-bit id %d data %d]\n",
761 sw->name, comment, gameport->phys, m, l, k);
762 }
763
764 return 0;
765
766fail2: gameport_close(gameport);
767fail1: gameport_set_drvdata(gameport, NULL);
768 kfree(sw);
769 kfree(buf);
770 kfree(idbuf);
771 return err;
772}
773
774static void sw_disconnect(struct gameport *gameport)
775{
776 struct sw *sw = gameport_get_drvdata(gameport);
777 int i;
778
779 for (i = 0; i < sw->number; i++)
780 input_unregister_device(sw->dev + i);
781 gameport_close(gameport);
782 gameport_set_drvdata(gameport, NULL);
783 kfree(sw);
784}
785
786static struct gameport_driver sw_drv = {
787 .driver = {
788 .name = "sidewinder",
789 },
790 .description = DRIVER_DESC,
791 .connect = sw_connect,
792 .disconnect = sw_disconnect,
793};
794
795static int __init sw_init(void)
796{
797 gameport_register_driver(&sw_drv);
798 return 0;
799}
800
801static void __exit sw_exit(void)
802{
803 gameport_unregister_driver(&sw_drv);
804}
805
806module_init(sw_init);
807module_exit(sw_exit);
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
new file mode 100644
index 000000000000..ec0a2a64d49c
--- /dev/null
+++ b/drivers/input/joystick/spaceball.c
@@ -0,0 +1,319 @@
1/*
2 * $Id: spaceball.c,v 1.17 2002/01/22 20:29:03 vojtech Exp $
3 *
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 *
6 * Based on the work of:
7 * David Thompson
8 * Joseph Krahn
9 */
10
11/*
12 * SpaceTec SpaceBall 2003/3003/4000 FLX driver for Linux
13 */
14
15/*
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 * Should you need to contact me, the author, you can do so either by
31 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
32 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
33 */
34
35#include <linux/kernel.h>
36#include <linux/slab.h>
37#include <linux/module.h>
38#include <linux/init.h>
39#include <linux/input.h>
40#include <linux/serio.h>
41
42#define DRIVER_DESC "SpaceTec SpaceBall 2003/3003/4000 FLX driver"
43
44MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
45MODULE_DESCRIPTION(DRIVER_DESC);
46MODULE_LICENSE("GPL");
47
48/*
49 * Constants.
50 */
51
52#define SPACEBALL_MAX_LENGTH 128
53#define SPACEBALL_MAX_ID 8
54
55#define SPACEBALL_1003 1
56#define SPACEBALL_2003B 3
57#define SPACEBALL_2003C 4
58#define SPACEBALL_3003C 7
59#define SPACEBALL_4000FLX 8
60#define SPACEBALL_4000FLX_L 9
61
62static int spaceball_axes[] = { ABS_X, ABS_Z, ABS_Y, ABS_RX, ABS_RZ, ABS_RY };
63static char *spaceball_names[] = {
64 "?", "SpaceTec SpaceBall 1003", "SpaceTec SpaceBall 2003", "SpaceTec SpaceBall 2003B",
65 "SpaceTec SpaceBall 2003C", "SpaceTec SpaceBall 3003", "SpaceTec SpaceBall SpaceController",
66 "SpaceTec SpaceBall 3003C", "SpaceTec SpaceBall 4000FLX", "SpaceTec SpaceBall 4000FLX Lefty" };
67
68/*
69 * Per-Ball data.
70 */
71
72struct spaceball {
73 struct input_dev dev;
74 struct serio *serio;
75 int idx;
76 int escape;
77 unsigned char data[SPACEBALL_MAX_LENGTH];
78 char phys[32];
79};
80
81/*
82 * spaceball_process_packet() decodes packets the driver receives from the
83 * SpaceBall.
84 */
85
86static void spaceball_process_packet(struct spaceball* spaceball, struct pt_regs *regs)
87{
88 struct input_dev *dev = &spaceball->dev;
89 unsigned char *data = spaceball->data;
90 int i;
91
92 if (spaceball->idx < 2) return;
93
94 input_regs(dev, regs);
95
96 switch (spaceball->data[0]) {
97
98 case 'D': /* Ball data */
99 if (spaceball->idx != 15) return;
100 for (i = 0; i < 6; i++)
101 input_report_abs(dev, spaceball_axes[i],
102 (__s16)((data[2 * i + 3] << 8) | data[2 * i + 2]));
103 break;
104
105 case 'K': /* Button data */
106 if (spaceball->idx != 3) return;
107 input_report_key(dev, BTN_1, (data[2] & 0x01) || (data[2] & 0x20));
108 input_report_key(dev, BTN_2, data[2] & 0x02);
109 input_report_key(dev, BTN_3, data[2] & 0x04);
110 input_report_key(dev, BTN_4, data[2] & 0x08);
111 input_report_key(dev, BTN_5, data[1] & 0x01);
112 input_report_key(dev, BTN_6, data[1] & 0x02);
113 input_report_key(dev, BTN_7, data[1] & 0x04);
114 input_report_key(dev, BTN_8, data[1] & 0x10);
115 break;
116
117 case '.': /* Advanced button data */
118 if (spaceball->idx != 3) return;
119 input_report_key(dev, BTN_1, data[2] & 0x01);
120 input_report_key(dev, BTN_2, data[2] & 0x02);
121 input_report_key(dev, BTN_3, data[2] & 0x04);
122 input_report_key(dev, BTN_4, data[2] & 0x08);
123 input_report_key(dev, BTN_5, data[2] & 0x10);
124 input_report_key(dev, BTN_6, data[2] & 0x20);
125 input_report_key(dev, BTN_7, data[2] & 0x80);
126 input_report_key(dev, BTN_8, data[1] & 0x01);
127 input_report_key(dev, BTN_9, data[1] & 0x02);
128 input_report_key(dev, BTN_A, data[1] & 0x04);
129 input_report_key(dev, BTN_B, data[1] & 0x08);
130 input_report_key(dev, BTN_C, data[1] & 0x10);
131 input_report_key(dev, BTN_MODE, data[1] & 0x20);
132 break;
133
134 case 'E': /* Device error */
135 spaceball->data[spaceball->idx - 1] = 0;
136 printk(KERN_ERR "spaceball: Device error. [%s]\n", spaceball->data + 1);
137 break;
138
139 case '?': /* Bad command packet */
140 spaceball->data[spaceball->idx - 1] = 0;
141 printk(KERN_ERR "spaceball: Bad command. [%s]\n", spaceball->data + 1);
142 break;
143 }
144
145 input_sync(dev);
146}
147
148/*
149 * Spaceball 4000 FLX packets all start with a one letter packet-type decriptor,
150 * and end in 0x0d. It uses '^' as an escape for CR, XOFF and XON characters which
151 * can occur in the axis values.
152 */
153
154static irqreturn_t spaceball_interrupt(struct serio *serio,
155 unsigned char data, unsigned int flags, struct pt_regs *regs)
156{
157 struct spaceball *spaceball = serio_get_drvdata(serio);
158
159 switch (data) {
160 case 0xd:
161 spaceball_process_packet(spaceball, regs);
162 spaceball->idx = 0;
163 spaceball->escape = 0;
164 break;
165 case '^':
166 if (!spaceball->escape) {
167 spaceball->escape = 1;
168 break;
169 }
170 spaceball->escape = 0;
171 case 'M':
172 case 'Q':
173 case 'S':
174 if (spaceball->escape) {
175 spaceball->escape = 0;
176 data &= 0x1f;
177 }
178 default:
179 if (spaceball->escape)
180 spaceball->escape = 0;
181 if (spaceball->idx < SPACEBALL_MAX_LENGTH)
182 spaceball->data[spaceball->idx++] = data;
183 break;
184 }
185 return IRQ_HANDLED;
186}
187
188/*
189 * spaceball_disconnect() is the opposite of spaceball_connect()
190 */
191
192static void spaceball_disconnect(struct serio *serio)
193{
194 struct spaceball* spaceball = serio_get_drvdata(serio);
195
196 input_unregister_device(&spaceball->dev);
197 serio_close(serio);
198 serio_set_drvdata(serio, NULL);
199 kfree(spaceball);
200}
201
202/*
203 * spaceball_connect() is the routine that is called when someone adds a
204 * new serio device that supports Spaceball protocol and registers it as
205 * an input device.
206 */
207
208static int spaceball_connect(struct serio *serio, struct serio_driver *drv)
209{
210 struct spaceball *spaceball;
211 int i, t, id;
212 int err;
213
214 if ((id = serio->id.id) > SPACEBALL_MAX_ID)
215 return -ENODEV;
216
217 if (!(spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL)))
218 return - ENOMEM;
219
220 memset(spaceball, 0, sizeof(struct spaceball));
221
222 spaceball->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
223
224 switch (id) {
225 case SPACEBALL_4000FLX:
226 case SPACEBALL_4000FLX_L:
227 spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_9);
228 spaceball->dev.keybit[LONG(BTN_A)] |= BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_MODE);
229 default:
230 spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4)
231 | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7) | BIT(BTN_8);
232 case SPACEBALL_3003C:
233 spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_1) | BIT(BTN_8);
234 }
235
236 for (i = 0; i < 6; i++) {
237 t = spaceball_axes[i];
238 set_bit(t, spaceball->dev.absbit);
239 spaceball->dev.absmin[t] = i < 3 ? -8000 : -1600;
240 spaceball->dev.absmax[t] = i < 3 ? 8000 : 1600;
241 spaceball->dev.absflat[t] = i < 3 ? 40 : 8;
242 spaceball->dev.absfuzz[t] = i < 3 ? 8 : 2;
243 }
244
245 spaceball->serio = serio;
246 spaceball->dev.private = spaceball;
247
248 sprintf(spaceball->phys, "%s/input0", serio->phys);
249
250 init_input_dev(&spaceball->dev);
251 spaceball->dev.name = spaceball_names[id];
252 spaceball->dev.phys = spaceball->phys;
253 spaceball->dev.id.bustype = BUS_RS232;
254 spaceball->dev.id.vendor = SERIO_SPACEBALL;
255 spaceball->dev.id.product = id;
256 spaceball->dev.id.version = 0x0100;
257 spaceball->dev.dev = &serio->dev;
258
259 serio_set_drvdata(serio, spaceball);
260
261 err = serio_open(serio, drv);
262 if (err) {
263 serio_set_drvdata(serio, NULL);
264 kfree(spaceball);
265 return err;
266 }
267
268 input_register_device(&spaceball->dev);
269
270 printk(KERN_INFO "input: %s on serio%s\n",
271 spaceball_names[id], serio->phys);
272
273 return 0;
274}
275
276/*
277 * The serio driver structure.
278 */
279
280static struct serio_device_id spaceball_serio_ids[] = {
281 {
282 .type = SERIO_RS232,
283 .proto = SERIO_SPACEBALL,
284 .id = SERIO_ANY,
285 .extra = SERIO_ANY,
286 },
287 { 0 }
288};
289
290MODULE_DEVICE_TABLE(serio, spaceball_serio_ids);
291
292static struct serio_driver spaceball_drv = {
293 .driver = {
294 .name = "spaceball",
295 },
296 .description = DRIVER_DESC,
297 .id_table = spaceball_serio_ids,
298 .interrupt = spaceball_interrupt,
299 .connect = spaceball_connect,
300 .disconnect = spaceball_disconnect,
301};
302
303/*
304 * The functions for inserting/removing us as a module.
305 */
306
307static int __init spaceball_init(void)
308{
309 serio_register_driver(&spaceball_drv);
310 return 0;
311}
312
313static void __exit spaceball_exit(void)
314{
315 serio_unregister_driver(&spaceball_drv);
316}
317
318module_init(spaceball_init);
319module_exit(spaceball_exit);
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c
new file mode 100644
index 000000000000..c76cf8ff29c0
--- /dev/null
+++ b/drivers/input/joystick/spaceorb.c
@@ -0,0 +1,263 @@
1/*
2 * $Id: spaceorb.c,v 1.15 2002/01/22 20:29:19 vojtech Exp $
3 *
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 *
6 * Based on the work of:
7 * David Thompson
8 */
9
10/*
11 * SpaceTec SpaceOrb 360 and Avenger 6dof controller driver for Linux
12 */
13
14/*
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 * Should you need to contact me, the author, you can do so either by
30 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
31 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
32 */
33
34#include <linux/kernel.h>
35#include <linux/slab.h>
36#include <linux/module.h>
37#include <linux/init.h>
38#include <linux/input.h>
39#include <linux/serio.h>
40
41#define DRIVER_DESC "SpaceTec SpaceOrb 360 and Avenger 6dof controller driver"
42
43MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
44MODULE_DESCRIPTION(DRIVER_DESC);
45MODULE_LICENSE("GPL");
46
47/*
48 * Constants.
49 */
50
51#define SPACEORB_MAX_LENGTH 64
52
53static int spaceorb_buttons[] = { BTN_TL, BTN_TR, BTN_Y, BTN_X, BTN_B, BTN_A };
54static int spaceorb_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
55static char *spaceorb_name = "SpaceTec SpaceOrb 360 / Avenger";
56
57/*
58 * Per-Orb data.
59 */
60
61struct spaceorb {
62 struct input_dev dev;
63 struct serio *serio;
64 int idx;
65 unsigned char data[SPACEORB_MAX_LENGTH];
66 char phys[32];
67};
68
69static unsigned char spaceorb_xor[] = "SpaceWare";
70
71static unsigned char *spaceorb_errors[] = { "EEPROM storing 0 failed", "Receive queue overflow", "Transmit queue timeout",
72 "Bad packet", "Power brown-out", "EEPROM checksum error", "Hardware fault" };
73
74/*
75 * spaceorb_process_packet() decodes packets the driver receives from the
76 * SpaceOrb.
77 */
78
79static void spaceorb_process_packet(struct spaceorb *spaceorb, struct pt_regs *regs)
80{
81 struct input_dev *dev = &spaceorb->dev;
82 unsigned char *data = spaceorb->data;
83 unsigned char c = 0;
84 int axes[6];
85 int i;
86
87 if (spaceorb->idx < 2) return;
88 for (i = 0; i < spaceorb->idx; i++) c ^= data[i];
89 if (c) return;
90
91 input_regs(dev, regs);
92
93 switch (data[0]) {
94
95 case 'R': /* Reset packet */
96 spaceorb->data[spaceorb->idx - 1] = 0;
97 for (i = 1; i < spaceorb->idx && spaceorb->data[i] == ' '; i++);
98 printk(KERN_INFO "input: %s [%s] on %s\n",
99 spaceorb_name, spaceorb->data + i, spaceorb->serio->phys);
100 break;
101
102 case 'D': /* Ball + button data */
103 if (spaceorb->idx != 12) return;
104 for (i = 0; i < 9; i++) spaceorb->data[i+2] ^= spaceorb_xor[i];
105 axes[0] = ( data[2] << 3) | (data[ 3] >> 4);
106 axes[1] = ((data[3] & 0x0f) << 6) | (data[ 4] >> 1);
107 axes[2] = ((data[4] & 0x01) << 9) | (data[ 5] << 2) | (data[4] >> 5);
108 axes[3] = ((data[6] & 0x1f) << 5) | (data[ 7] >> 2);
109 axes[4] = ((data[7] & 0x03) << 8) | (data[ 8] << 1) | (data[7] >> 6);
110 axes[5] = ((data[9] & 0x3f) << 4) | (data[10] >> 3);
111 for (i = 0; i < 6; i++)
112 input_report_abs(dev, spaceorb_axes[i], axes[i] - ((axes[i] & 0x200) ? 1024 : 0));
113 for (i = 0; i < 6; i++)
114 input_report_key(dev, spaceorb_buttons[i], (data[1] >> i) & 1);
115 break;
116
117 case 'K': /* Button data */
118 if (spaceorb->idx != 5) return;
119 for (i = 0; i < 7; i++)
120 input_report_key(dev, spaceorb_buttons[i], (data[2] >> i) & 1);
121
122 break;
123
124 case 'E': /* Error packet */
125 if (spaceorb->idx != 4) return;
126 printk(KERN_ERR "joy-spaceorb: Device error. [ ");
127 for (i = 0; i < 7; i++) if (data[1] & (1 << i)) printk("%s ", spaceorb_errors[i]);
128 printk("]\n");
129 break;
130 }
131
132 input_sync(dev);
133}
134
135static irqreturn_t spaceorb_interrupt(struct serio *serio,
136 unsigned char data, unsigned int flags, struct pt_regs *regs)
137{
138 struct spaceorb* spaceorb = serio_get_drvdata(serio);
139
140 if (~data & 0x80) {
141 if (spaceorb->idx) spaceorb_process_packet(spaceorb, regs);
142 spaceorb->idx = 0;
143 }
144 if (spaceorb->idx < SPACEORB_MAX_LENGTH)
145 spaceorb->data[spaceorb->idx++] = data & 0x7f;
146 return IRQ_HANDLED;
147}
148
149/*
150 * spaceorb_disconnect() is the opposite of spaceorb_connect()
151 */
152
153static void spaceorb_disconnect(struct serio *serio)
154{
155 struct spaceorb* spaceorb = serio_get_drvdata(serio);
156
157 input_unregister_device(&spaceorb->dev);
158 serio_close(serio);
159 serio_set_drvdata(serio, NULL);
160 kfree(spaceorb);
161}
162
163/*
164 * spaceorb_connect() is the routine that is called when someone adds a
165 * new serio device that supports SpaceOrb/Avenger protocol and registers
166 * it as an input device.
167 */
168
169static int spaceorb_connect(struct serio *serio, struct serio_driver *drv)
170{
171 struct spaceorb *spaceorb;
172 int i, t;
173 int err;
174
175 if (!(spaceorb = kmalloc(sizeof(struct spaceorb), GFP_KERNEL)))
176 return -ENOMEM;
177
178 memset(spaceorb, 0, sizeof(struct spaceorb));
179
180 spaceorb->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
181
182 for (i = 0; i < 6; i++)
183 set_bit(spaceorb_buttons[i], spaceorb->dev.keybit);
184
185 for (i = 0; i < 6; i++) {
186 t = spaceorb_axes[i];
187 set_bit(t, spaceorb->dev.absbit);
188 spaceorb->dev.absmin[t] = -508;
189 spaceorb->dev.absmax[t] = 508;
190 }
191
192 spaceorb->serio = serio;
193 spaceorb->dev.private = spaceorb;
194
195 sprintf(spaceorb->phys, "%s/input0", serio->phys);
196
197 init_input_dev(&spaceorb->dev);
198 spaceorb->dev.name = spaceorb_name;
199 spaceorb->dev.phys = spaceorb->phys;
200 spaceorb->dev.id.bustype = BUS_RS232;
201 spaceorb->dev.id.vendor = SERIO_SPACEORB;
202 spaceorb->dev.id.product = 0x0001;
203 spaceorb->dev.id.version = 0x0100;
204 spaceorb->dev.dev = &serio->dev;
205
206 serio_set_drvdata(serio, spaceorb);
207
208 err = serio_open(serio, drv);
209 if (err) {
210 serio_set_drvdata(serio, NULL);
211 kfree(spaceorb);
212 return err;
213 }
214
215 input_register_device(&spaceorb->dev);
216
217 return 0;
218}
219
220/*
221 * The serio driver structure.
222 */
223
224static struct serio_device_id spaceorb_serio_ids[] = {
225 {
226 .type = SERIO_RS232,
227 .proto = SERIO_SPACEORB,
228 .id = SERIO_ANY,
229 .extra = SERIO_ANY,
230 },
231 { 0 }
232};
233
234MODULE_DEVICE_TABLE(serio, spaceorb_serio_ids);
235
236static struct serio_driver spaceorb_drv = {
237 .driver = {
238 .name = "spaceorb",
239 },
240 .description = DRIVER_DESC,
241 .id_table = spaceorb_serio_ids,
242 .interrupt = spaceorb_interrupt,
243 .connect = spaceorb_connect,
244 .disconnect = spaceorb_disconnect,
245};
246
247/*
248 * The functions for inserting/removing us as a module.
249 */
250
251static int __init spaceorb_init(void)
252{
253 serio_register_driver(&spaceorb_drv);
254 return 0;
255}
256
257static void __exit spaceorb_exit(void)
258{
259 serio_unregister_driver(&spaceorb_drv);
260}
261
262module_init(spaceorb_init);
263module_exit(spaceorb_exit);
diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c
new file mode 100644
index 000000000000..6f6e6753d590
--- /dev/null
+++ b/drivers/input/joystick/stinger.c
@@ -0,0 +1,236 @@
1/*
2 * $Id: stinger.c,v 1.10 2002/01/22 20:29:31 vojtech Exp $
3 *
4 * Copyright (c) 2000-2001 Vojtech Pavlik
5 * Copyright (c) 2000 Mark Fletcher
6 */
7
8/*
9 * Gravis Stinger gamepad driver for Linux
10 */
11
12/*
13 * This program is free warftware; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27 * Should you need to contact me, the author, you can do so either by
28 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
29 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
30 */
31
32#include <linux/kernel.h>
33#include <linux/module.h>
34#include <linux/slab.h>
35#include <linux/input.h>
36#include <linux/serio.h>
37#include <linux/init.h>
38
39#define DRIVER_DESC "Gravis Stinger gamepad driver"
40
41MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
42MODULE_DESCRIPTION(DRIVER_DESC);
43MODULE_LICENSE("GPL");
44
45/*
46 * Constants.
47 */
48
49#define STINGER_MAX_LENGTH 8
50
51static char *stinger_name = "Gravis Stinger";
52
53/*
54 * Per-Stinger data.
55 */
56
57struct stinger {
58 struct input_dev dev;
59 int idx;
60 unsigned char data[STINGER_MAX_LENGTH];
61 char phys[32];
62};
63
64/*
65 * stinger_process_packet() decodes packets the driver receives from the
66 * Stinger. It updates the data accordingly.
67 */
68
69static void stinger_process_packet(struct stinger *stinger, struct pt_regs *regs)
70{
71 struct input_dev *dev = &stinger->dev;
72 unsigned char *data = stinger->data;
73
74 if (!stinger->idx) return;
75
76 input_regs(dev, regs);
77
78 input_report_key(dev, BTN_A, ((data[0] & 0x20) >> 5));
79 input_report_key(dev, BTN_B, ((data[0] & 0x10) >> 4));
80 input_report_key(dev, BTN_C, ((data[0] & 0x08) >> 3));
81 input_report_key(dev, BTN_X, ((data[0] & 0x04) >> 2));
82 input_report_key(dev, BTN_Y, ((data[3] & 0x20) >> 5));
83 input_report_key(dev, BTN_Z, ((data[3] & 0x10) >> 4));
84 input_report_key(dev, BTN_TL, ((data[3] & 0x08) >> 3));
85 input_report_key(dev, BTN_TR, ((data[3] & 0x04) >> 2));
86 input_report_key(dev, BTN_SELECT, ((data[3] & 0x02) >> 1));
87 input_report_key(dev, BTN_START, (data[3] & 0x01));
88
89 input_report_abs(dev, ABS_X, (data[1] & 0x3F) - ((data[0] & 0x01) << 6));
90 input_report_abs(dev, ABS_Y, ((data[0] & 0x02) << 5) - (data[2] & 0x3F));
91
92 input_sync(dev);
93
94 return;
95}
96
97/*
98 * stinger_interrupt() is called by the low level driver when characters
99 * are ready for us. We then buffer them for further processing, or call the
100 * packet processing routine.
101 */
102
103static irqreturn_t stinger_interrupt(struct serio *serio,
104 unsigned char data, unsigned int flags, struct pt_regs *regs)
105{
106 struct stinger *stinger = serio_get_drvdata(serio);
107
108 /* All Stinger packets are 4 bytes */
109
110 if (stinger->idx < STINGER_MAX_LENGTH)
111 stinger->data[stinger->idx++] = data;
112
113 if (stinger->idx == 4) {
114 stinger_process_packet(stinger, regs);
115 stinger->idx = 0;
116 }
117
118 return IRQ_HANDLED;
119}
120
121/*
122 * stinger_disconnect() is the opposite of stinger_connect()
123 */
124
125static void stinger_disconnect(struct serio *serio)
126{
127 struct stinger *stinger = serio_get_drvdata(serio);
128
129 input_unregister_device(&stinger->dev);
130 serio_close(serio);
131 serio_set_drvdata(serio, NULL);
132 kfree(stinger);
133}
134
135/*
136 * stinger_connect() is the routine that is called when someone adds a
137 * new serio device that supports Stinger protocol and registers it as
138 * an input device.
139 */
140
141static int stinger_connect(struct serio *serio, struct serio_driver *drv)
142{
143 struct stinger *stinger;
144 int i;
145 int err;
146
147 if (!(stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL)))
148 return -ENOMEM;
149
150 memset(stinger, 0, sizeof(struct stinger));
151
152 stinger->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
153 stinger->dev.keybit[LONG(BTN_A)] = BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_X) | \
154 BIT(BTN_Y) | BIT(BTN_Z) | BIT(BTN_TL) | BIT(BTN_TR) | \
155 BIT(BTN_START) | BIT(BTN_SELECT);
156 stinger->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
157
158 sprintf(stinger->phys, "%s/serio0", serio->phys);
159
160 init_input_dev(&stinger->dev);
161 stinger->dev.name = stinger_name;
162 stinger->dev.phys = stinger->phys;
163 stinger->dev.id.bustype = BUS_RS232;
164 stinger->dev.id.vendor = SERIO_STINGER;
165 stinger->dev.id.product = 0x0001;
166 stinger->dev.id.version = 0x0100;
167 stinger->dev.dev = &serio->dev;
168
169 for (i = 0; i < 2; i++) {
170 stinger->dev.absmax[ABS_X+i] = 64;
171 stinger->dev.absmin[ABS_X+i] = -64;
172 stinger->dev.absflat[ABS_X+i] = 4;
173 }
174
175 stinger->dev.private = stinger;
176
177 serio_set_drvdata(serio, stinger);
178
179 err = serio_open(serio, drv);
180 if (err) {
181 serio_set_drvdata(serio, NULL);
182 kfree(stinger);
183 return err;
184 }
185
186 input_register_device(&stinger->dev);
187
188 printk(KERN_INFO "input: %s on %s\n", stinger_name, serio->phys);
189
190 return 0;
191}
192
193/*
194 * The serio driver structure.
195 */
196
197static struct serio_device_id stinger_serio_ids[] = {
198 {
199 .type = SERIO_RS232,
200 .proto = SERIO_STINGER,
201 .id = SERIO_ANY,
202 .extra = SERIO_ANY,
203 },
204 { 0 }
205};
206
207MODULE_DEVICE_TABLE(serio, stinger_serio_ids);
208
209static struct serio_driver stinger_drv = {
210 .driver = {
211 .name = "stinger",
212 },
213 .description = DRIVER_DESC,
214 .id_table = stinger_serio_ids,
215 .interrupt = stinger_interrupt,
216 .connect = stinger_connect,
217 .disconnect = stinger_disconnect,
218};
219
220/*
221 * The functions for inserting/removing us as a module.
222 */
223
224static int __init stinger_init(void)
225{
226 serio_register_driver(&stinger_drv);
227 return 0;
228}
229
230static void __exit stinger_exit(void)
231{
232 serio_unregister_driver(&stinger_drv);
233}
234
235module_init(stinger_init);
236module_exit(stinger_exit);
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
new file mode 100644
index 000000000000..aaee52ceb920
--- /dev/null
+++ b/drivers/input/joystick/tmdc.c
@@ -0,0 +1,384 @@
1/*
2 * $Id: tmdc.c,v 1.31 2002/01/22 20:29:52 vojtech Exp $
3 *
4 * Copyright (c) 1998-2001 Vojtech Pavlik
5 *
6 * Based on the work of:
7 * Trystan Larey-Williams
8 */
9
10/*
11 * ThrustMaster DirectConnect (BSP) joystick family driver for Linux
12 */
13
14/*
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 * Should you need to contact me, the author, you can do so either by
30 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
31 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
32 */
33
34#include <linux/delay.h>
35#include <linux/kernel.h>
36#include <linux/slab.h>
37#include <linux/module.h>
38#include <linux/init.h>
39#include <linux/gameport.h>
40#include <linux/input.h>
41
42#define DRIVER_DESC "ThrustMaster DirectConnect joystick driver"
43
44MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
45MODULE_DESCRIPTION(DRIVER_DESC);
46MODULE_LICENSE("GPL");
47
48#define TMDC_MAX_START 600 /* 600 us */
49#define TMDC_MAX_STROBE 60 /* 60 us */
50#define TMDC_MAX_LENGTH 13
51
52#define TMDC_MODE_M3DI 1
53#define TMDC_MODE_3DRP 3
54#define TMDC_MODE_AT 4
55#define TMDC_MODE_FM 8
56#define TMDC_MODE_FGP 163
57
58#define TMDC_BYTE_ID 10
59#define TMDC_BYTE_REV 11
60#define TMDC_BYTE_DEF 12
61
62#define TMDC_ABS 7
63#define TMDC_ABS_HAT 4
64#define TMDC_BTN 16
65
66static unsigned char tmdc_byte_a[16] = { 0, 1, 3, 4, 6, 7 };
67static unsigned char tmdc_byte_d[16] = { 2, 5, 8, 9 };
68
69static signed char tmdc_abs[TMDC_ABS] =
70 { ABS_X, ABS_Y, ABS_RUDDER, ABS_THROTTLE, ABS_RX, ABS_RY, ABS_RZ };
71static signed char tmdc_abs_hat[TMDC_ABS_HAT] =
72 { ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y };
73static signed char tmdc_abs_at[TMDC_ABS] =
74 { ABS_X, ABS_Y, ABS_RUDDER, -1, ABS_THROTTLE };
75static signed char tmdc_abs_fm[TMDC_ABS] =
76 { ABS_RX, ABS_RY, ABS_X, ABS_Y };
77
78static short tmdc_btn_pad[TMDC_BTN] =
79 { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_START, BTN_SELECT, BTN_TL, BTN_TR };
80static short tmdc_btn_joy[TMDC_BTN] =
81 { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_THUMB2, BTN_PINKIE,
82 BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z };
83static short tmdc_btn_fm[TMDC_BTN] =
84 { BTN_TRIGGER, BTN_C, BTN_B, BTN_A, BTN_THUMB, BTN_X, BTN_Y, BTN_Z, BTN_TOP, BTN_TOP2 };
85static short tmdc_btn_at[TMDC_BTN] =
86 { BTN_TRIGGER, BTN_THUMB2, BTN_PINKIE, BTN_THUMB, BTN_BASE6, BTN_BASE5, BTN_BASE4,
87 BTN_BASE3, BTN_BASE2, BTN_BASE };
88
89static struct {
90 int x;
91 int y;
92} tmdc_hat_to_axis[] = {{ 0, 0}, { 1, 0}, { 0,-1}, {-1, 0}, { 0, 1}};
93
94struct tmdc {
95 struct gameport *gameport;
96 struct input_dev dev[2];
97 char name[2][64];
98 char phys[2][32];
99 int mode[2];
100 signed char *abs[2];
101 short *btn[2];
102 unsigned char absc[2];
103 unsigned char btnc[2][4];
104 unsigned char btno[2][4];
105 int reads;
106 int bads;
107 unsigned char exists;
108};
109
110/*
111 * tmdc_read_packet() reads a ThrustMaster packet.
112 */
113
114static int tmdc_read_packet(struct gameport *gameport, unsigned char data[2][TMDC_MAX_LENGTH])
115{
116 unsigned char u, v, w, x;
117 unsigned long flags;
118 int i[2], j[2], t[2], p, k;
119
120 p = gameport_time(gameport, TMDC_MAX_STROBE);
121
122 for (k = 0; k < 2; k++) {
123 t[k] = gameport_time(gameport, TMDC_MAX_START);
124 i[k] = j[k] = 0;
125 }
126
127 local_irq_save(flags);
128 gameport_trigger(gameport);
129
130 w = gameport_read(gameport) >> 4;
131
132 do {
133 x = w;
134 w = gameport_read(gameport) >> 4;
135
136 for (k = 0, v = w, u = x; k < 2; k++, v >>= 2, u >>= 2) {
137 if (~v & u & 2) {
138 if (t[k] <= 0 || i[k] >= TMDC_MAX_LENGTH) continue;
139 t[k] = p;
140 if (j[k] == 0) { /* Start bit */
141 if (~v & 1) t[k] = 0;
142 data[k][i[k]] = 0; j[k]++; continue;
143 }
144 if (j[k] == 9) { /* Stop bit */
145 if (v & 1) t[k] = 0;
146 j[k] = 0; i[k]++; continue;
147 }
148 data[k][i[k]] |= (~v & 1) << (j[k]++ - 1); /* Data bit */
149 }
150 t[k]--;
151 }
152 } while (t[0] > 0 || t[1] > 0);
153
154 local_irq_restore(flags);
155
156 return (i[0] == TMDC_MAX_LENGTH) | ((i[1] == TMDC_MAX_LENGTH) << 1);
157}
158
159/*
160 * tmdc_poll() reads and analyzes ThrustMaster joystick data.
161 */
162
163static void tmdc_poll(struct gameport *gameport)
164{
165 unsigned char data[2][TMDC_MAX_LENGTH];
166 struct tmdc *tmdc = gameport_get_drvdata(gameport);
167 struct input_dev *dev;
168 unsigned char r, bad = 0;
169 int i, j, k, l;
170
171 tmdc->reads++;
172
173 if ((r = tmdc_read_packet(tmdc->gameport, data)) != tmdc->exists)
174 bad = 1;
175 else
176
177 for (j = 0; j < 2; j++)
178 if (r & (1 << j) & tmdc->exists) {
179
180 if (data[j][TMDC_BYTE_ID] != tmdc->mode[j]) {
181 bad = 1;
182 continue;
183 }
184
185 dev = tmdc->dev + j;
186
187 for (i = 0; i < tmdc->absc[j]; i++) {
188 if (tmdc->abs[j][i] < 0) continue;
189 input_report_abs(dev, tmdc->abs[j][i], data[j][tmdc_byte_a[i]]);
190 }
191
192 switch (tmdc->mode[j]) {
193
194 case TMDC_MODE_M3DI:
195
196 i = tmdc_byte_d[0];
197 input_report_abs(dev, ABS_HAT0X, ((data[j][i] >> 3) & 1) - ((data[j][i] >> 1) & 1));
198 input_report_abs(dev, ABS_HAT0Y, ((data[j][i] >> 2) & 1) - ( data[j][i] & 1));
199 break;
200
201 case TMDC_MODE_AT:
202
203 i = tmdc_byte_a[3];
204 input_report_abs(dev, ABS_HAT0X, tmdc_hat_to_axis[(data[j][i] - 141) / 25].x);
205 input_report_abs(dev, ABS_HAT0Y, tmdc_hat_to_axis[(data[j][i] - 141) / 25].y);
206 break;
207
208 }
209
210 for (k = l = 0; k < 4; k++) {
211 for (i = 0; i < tmdc->btnc[j][k]; i++)
212 input_report_key(dev, tmdc->btn[j][i + l],
213 ((data[j][tmdc_byte_d[k]] >> (i + tmdc->btno[j][k])) & 1));
214 l += tmdc->btnc[j][k];
215 }
216
217 input_sync(dev);
218 }
219
220 tmdc->bads += bad;
221}
222
223static int tmdc_open(struct input_dev *dev)
224{
225 struct tmdc *tmdc = dev->private;
226
227 gameport_start_polling(tmdc->gameport);
228 return 0;
229}
230
231static void tmdc_close(struct input_dev *dev)
232{
233 struct tmdc *tmdc = dev->private;
234
235 gameport_stop_polling(tmdc->gameport);
236}
237
238/*
239 * tmdc_probe() probes for ThrustMaster type joysticks.
240 */
241
242static int tmdc_connect(struct gameport *gameport, struct gameport_driver *drv)
243{
244 static struct models {
245 unsigned char id;
246 char *name;
247 char abs;
248 char hats;
249 char btnc[4];
250 char btno[4];
251 signed char *axes;
252 short *buttons;
253 } models[] = { { 1, "ThrustMaster Millenium 3D Inceptor", 6, 2, { 4, 2 }, { 4, 6 }, tmdc_abs, tmdc_btn_joy },
254 { 3, "ThrustMaster Rage 3D Gamepad", 2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
255 { 4, "ThrustMaster Attack Throttle", 5, 2, { 4, 6 }, { 4, 2 }, tmdc_abs_at, tmdc_btn_at },
256 { 8, "ThrustMaster FragMaster", 4, 0, { 8, 2 }, { 0, 0 }, tmdc_abs_fm, tmdc_btn_fm },
257 { 163, "Thrustmaster Fusion GamePad", 2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
258 { 0, "Unknown %d-axis, %d-button TM device %d", 0, 0, { 0, 0 }, { 0, 0 }, tmdc_abs, tmdc_btn_joy }};
259
260 unsigned char data[2][TMDC_MAX_LENGTH];
261 struct tmdc *tmdc;
262 int i, j, k, l, m;
263 int err;
264
265 if (!(tmdc = kcalloc(1, sizeof(struct tmdc), GFP_KERNEL)))
266 return -ENOMEM;
267
268 tmdc->gameport = gameport;
269
270 gameport_set_drvdata(gameport, tmdc);
271
272 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
273 if (err)
274 goto fail1;
275
276 if (!(tmdc->exists = tmdc_read_packet(gameport, data))) {
277 err = -ENODEV;
278 goto fail2;
279 }
280
281 gameport_set_poll_handler(gameport, tmdc_poll);
282 gameport_set_poll_interval(gameport, 20);
283
284 for (j = 0; j < 2; j++)
285 if (tmdc->exists & (1 << j)) {
286
287 tmdc->mode[j] = data[j][TMDC_BYTE_ID];
288
289 for (m = 0; models[m].id && models[m].id != tmdc->mode[j]; m++);
290
291 tmdc->abs[j] = models[m].axes;
292 tmdc->btn[j] = models[m].buttons;
293
294 if (!models[m].id) {
295 models[m].abs = data[j][TMDC_BYTE_DEF] >> 4;
296 for (k = 0; k < 4; k++)
297 models[m].btnc[k] = k < (data[j][TMDC_BYTE_DEF] & 0xf) ? 8 : 0;
298 }
299
300 tmdc->absc[j] = models[m].abs;
301 for (k = 0; k < 4; k++) {
302 tmdc->btnc[j][k] = models[m].btnc[k];
303 tmdc->btno[j][k] = models[m].btno[k];
304 }
305
306 sprintf(tmdc->name[j], models[m].name, models[m].abs,
307 (data[j][TMDC_BYTE_DEF] & 0xf) << 3, tmdc->mode[j]);
308
309 sprintf(tmdc->phys[j], "%s/input%d", gameport->phys, j);
310
311 tmdc->dev[j].private = tmdc;
312 tmdc->dev[j].open = tmdc_open;
313 tmdc->dev[j].close = tmdc_close;
314
315 tmdc->dev[j].name = tmdc->name[j];
316 tmdc->dev[j].phys = tmdc->phys[j];
317 tmdc->dev[j].id.bustype = BUS_GAMEPORT;
318 tmdc->dev[j].id.vendor = GAMEPORT_ID_VENDOR_THRUSTMASTER;
319 tmdc->dev[j].id.product = models[m].id;
320 tmdc->dev[j].id.version = 0x0100;
321
322 tmdc->dev[j].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
323
324 for (i = 0; i < models[m].abs && i < TMDC_ABS; i++)
325 if (tmdc->abs[j][i] >= 0)
326 input_set_abs_params(&tmdc->dev[j], tmdc->abs[j][i], 8, 248, 2, 4);
327
328 for (i = 0; i < models[m].hats && i < TMDC_ABS_HAT; i++)
329 input_set_abs_params(&tmdc->dev[j], tmdc_abs_hat[i], -1, 1, 0, 0);
330
331
332 for (k = l = 0; k < 4; k++) {
333 for (i = 0; i < models[m].btnc[k] && i < TMDC_BTN; i++)
334 set_bit(tmdc->btn[j][i + l], tmdc->dev[j].keybit);
335 l += models[m].btnc[k];
336 }
337
338 input_register_device(tmdc->dev + j);
339 printk(KERN_INFO "input: %s on %s\n", tmdc->name[j], gameport->phys);
340 }
341
342 return 0;
343
344fail2: gameport_close(gameport);
345fail1: gameport_set_drvdata(gameport, NULL);
346 kfree(tmdc);
347 return err;
348}
349
350static void tmdc_disconnect(struct gameport *gameport)
351{
352 struct tmdc *tmdc = gameport_get_drvdata(gameport);
353 int i;
354
355 for (i = 0; i < 2; i++)
356 if (tmdc->exists & (1 << i))
357 input_unregister_device(tmdc->dev + i);
358 gameport_close(gameport);
359 gameport_set_drvdata(gameport, NULL);
360 kfree(tmdc);
361}
362
363static struct gameport_driver tmdc_drv = {
364 .driver = {
365 .name = "tmdc",
366 },
367 .description = DRIVER_DESC,
368 .connect = tmdc_connect,
369 .disconnect = tmdc_disconnect,
370};
371
372static int __init tmdc_init(void)
373{
374 gameport_register_driver(&tmdc_drv);
375 return 0;
376}
377
378static void __exit tmdc_exit(void)
379{
380 gameport_unregister_driver(&tmdc_drv);
381}
382
383module_init(tmdc_init);
384module_exit(tmdc_exit);
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
new file mode 100644
index 000000000000..dd88b9cb49fa
--- /dev/null
+++ b/drivers/input/joystick/turbografx.c
@@ -0,0 +1,258 @@
1/*
2 * $Id: turbografx.c,v 1.14 2002/01/22 20:30:39 vojtech Exp $
3 *
4 * Copyright (c) 1998-2001 Vojtech Pavlik
5 *
6 * Based on the work of:
7 * Steffen Schwenke
8 */
9
10/*
11 * TurboGraFX parallel port interface driver for Linux.
12 */
13
14/*
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 * Should you need to contact me, the author, you can do so either by
30 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
31 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
32 */
33
34#include <linux/kernel.h>
35#include <linux/parport.h>
36#include <linux/input.h>
37#include <linux/module.h>
38#include <linux/moduleparam.h>
39#include <linux/init.h>
40
41MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
42MODULE_DESCRIPTION("TurboGraFX parallel port interface driver");
43MODULE_LICENSE("GPL");
44
45static int tgfx[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
46static int tgfx_nargs __initdata = 0;
47module_param_array_named(map, tgfx, int, &tgfx_nargs, 0);
48MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<js1>,<js2>,..<js7>");
49
50static int tgfx_2[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
51static int tgfx_nargs_2 __initdata = 0;
52module_param_array_named(map2, tgfx_2, int, &tgfx_nargs_2, 0);
53MODULE_PARM_DESC(map2, "Describes second set of devices");
54
55static int tgfx_3[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
56static int tgfx_nargs_3 __initdata = 0;
57module_param_array_named(map3, tgfx_3, int, &tgfx_nargs_3, 0);
58MODULE_PARM_DESC(map3, "Describes third set of devices");
59
60__obsolete_setup("tgfx=");
61__obsolete_setup("tgfx_2=");
62__obsolete_setup("tgfx_3=");
63
64#define TGFX_REFRESH_TIME HZ/100 /* 10 ms */
65
66#define TGFX_TRIGGER 0x08
67#define TGFX_UP 0x10
68#define TGFX_DOWN 0x20
69#define TGFX_LEFT 0x40
70#define TGFX_RIGHT 0x80
71
72#define TGFX_THUMB 0x02
73#define TGFX_THUMB2 0x04
74#define TGFX_TOP 0x01
75#define TGFX_TOP2 0x08
76
77static int tgfx_buttons[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2 };
78static char *tgfx_name = "TurboGraFX Multisystem joystick";
79
80static struct tgfx {
81 struct pardevice *pd;
82 struct timer_list timer;
83 struct input_dev dev[7];
84 char phys[7][32];
85 int sticks;
86 int used;
87} *tgfx_base[3];
88
89/*
90 * tgfx_timer() reads and analyzes TurboGraFX joystick data.
91 */
92
93static void tgfx_timer(unsigned long private)
94{
95 struct tgfx *tgfx = (void *) private;
96 struct input_dev *dev;
97 int data1, data2, i;
98
99 for (i = 0; i < 7; i++)
100 if (tgfx->sticks & (1 << i)) {
101
102 dev = tgfx->dev + i;
103
104 parport_write_data(tgfx->pd->port, ~(1 << i));
105 data1 = parport_read_status(tgfx->pd->port) ^ 0x7f;
106 data2 = parport_read_control(tgfx->pd->port) ^ 0x04; /* CAVEAT parport */
107
108 input_report_abs(dev, ABS_X, !!(data1 & TGFX_RIGHT) - !!(data1 & TGFX_LEFT));
109 input_report_abs(dev, ABS_Y, !!(data1 & TGFX_DOWN ) - !!(data1 & TGFX_UP ));
110
111 input_report_key(dev, BTN_TRIGGER, (data1 & TGFX_TRIGGER));
112 input_report_key(dev, BTN_THUMB, (data2 & TGFX_THUMB ));
113 input_report_key(dev, BTN_THUMB2, (data2 & TGFX_THUMB2 ));
114 input_report_key(dev, BTN_TOP, (data2 & TGFX_TOP ));
115 input_report_key(dev, BTN_TOP2, (data2 & TGFX_TOP2 ));
116
117 input_sync(dev);
118 }
119
120 mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME);
121}
122
123static int tgfx_open(struct input_dev *dev)
124{
125 struct tgfx *tgfx = dev->private;
126 if (!tgfx->used++) {
127 parport_claim(tgfx->pd);
128 parport_write_control(tgfx->pd->port, 0x04);
129 mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME);
130 }
131 return 0;
132}
133
134static void tgfx_close(struct input_dev *dev)
135{
136 struct tgfx *tgfx = dev->private;
137 if (!--tgfx->used) {
138 del_timer(&tgfx->timer);
139 parport_write_control(tgfx->pd->port, 0x00);
140 parport_release(tgfx->pd);
141 }
142}
143
144/*
145 * tgfx_probe() probes for tg gamepads.
146 */
147
148static struct tgfx __init *tgfx_probe(int *config, int nargs)
149{
150 struct tgfx *tgfx;
151 struct parport *pp;
152 int i, j;
153
154 if (config[0] < 0)
155 return NULL;
156
157 if (nargs < 2) {
158 printk(KERN_ERR "turbografx.c: at least one joystick must be specified\n");
159 return NULL;
160 }
161
162 pp = parport_find_number(config[0]);
163
164 if (!pp) {
165 printk(KERN_ERR "turbografx.c: no such parport\n");
166 return NULL;
167 }
168
169 if (!(tgfx = kmalloc(sizeof(struct tgfx), GFP_KERNEL))) {
170 parport_put_port(pp);
171 return NULL;
172 }
173 memset(tgfx, 0, sizeof(struct tgfx));
174
175 tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
176
177 parport_put_port(pp);
178
179 if (!tgfx->pd) {
180 printk(KERN_ERR "turbografx.c: parport busy already - lp.o loaded?\n");
181 kfree(tgfx);
182 return NULL;
183 }
184
185 init_timer(&tgfx->timer);
186 tgfx->timer.data = (long) tgfx;
187 tgfx->timer.function = tgfx_timer;
188
189 tgfx->sticks = 0;
190
191 for (i = 0; i < nargs - 1; i++)
192 if (config[i+1] > 0 && config[i+1] < 6) {
193
194 tgfx->sticks |= (1 << i);
195
196 tgfx->dev[i].private = tgfx;
197 tgfx->dev[i].open = tgfx_open;
198 tgfx->dev[i].close = tgfx_close;
199
200 sprintf(tgfx->phys[i], "%s/input0", tgfx->pd->port->name);
201
202 tgfx->dev[i].name = tgfx_name;
203 tgfx->dev[i].phys = tgfx->phys[i];
204 tgfx->dev[i].id.bustype = BUS_PARPORT;
205 tgfx->dev[i].id.vendor = 0x0003;
206 tgfx->dev[i].id.product = config[i+1];
207 tgfx->dev[i].id.version = 0x0100;
208
209 tgfx->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
210 tgfx->dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
211
212 for (j = 0; j < config[i+1]; j++)
213 set_bit(tgfx_buttons[j], tgfx->dev[i].keybit);
214
215 tgfx->dev[i].absmin[ABS_X] = -1; tgfx->dev[i].absmax[ABS_X] = 1;
216 tgfx->dev[i].absmin[ABS_Y] = -1; tgfx->dev[i].absmax[ABS_Y] = 1;
217
218 input_register_device(tgfx->dev + i);
219 printk(KERN_INFO "input: %d-button Multisystem joystick on %s\n",
220 config[i+1], tgfx->pd->port->name);
221 }
222
223 if (!tgfx->sticks) {
224 parport_unregister_device(tgfx->pd);
225 kfree(tgfx);
226 return NULL;
227 }
228
229 return tgfx;
230}
231
232static int __init tgfx_init(void)
233{
234 tgfx_base[0] = tgfx_probe(tgfx, tgfx_nargs);
235 tgfx_base[1] = tgfx_probe(tgfx_2, tgfx_nargs_2);
236 tgfx_base[2] = tgfx_probe(tgfx_3, tgfx_nargs_3);
237
238 if (tgfx_base[0] || tgfx_base[1] || tgfx_base[2])
239 return 0;
240
241 return -ENODEV;
242}
243
244static void __exit tgfx_exit(void)
245{
246 int i, j;
247
248 for (i = 0; i < 3; i++)
249 if (tgfx_base[i]) {
250 for (j = 0; j < 7; j++)
251 if (tgfx_base[i]->sticks & (1 << j))
252 input_unregister_device(tgfx_base[i]->dev + j);
253 parport_unregister_device(tgfx_base[i]->pd);
254 }
255}
256
257module_init(tgfx_init);
258module_exit(tgfx_exit);
diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c
new file mode 100644
index 000000000000..0379bc166525
--- /dev/null
+++ b/drivers/input/joystick/twidjoy.c
@@ -0,0 +1,296 @@
1/*
2 * $Id: twidjoy.c,v 1.5 2002/01/22 20:31:53 vojtech Exp $
3 *
4 * derived from CVS-ID "stinger.c,v 1.5 2001/05/29 12:57:18 vojtech Exp"
5 *
6 * Copyright (c) 2001 Arndt Schoenewald
7 * Copyright (c) 2000-2001 Vojtech Pavlik
8 * Copyright (c) 2000 Mark Fletcher
9 *
10 * Sponsored by Quelltext AG (http://www.quelltext-ag.de), Dortmund, Germany
11 */
12
13/*
14 * Driver to use Handykey's Twiddler (the first edition, i.e. the one with
15 * the RS232 interface) as a joystick under Linux
16 *
17 * The Twiddler is a one-handed chording keyboard featuring twelve buttons on
18 * the front, six buttons on the top, and a built-in tilt sensor. The buttons
19 * on the front, which are grouped as four rows of three buttons, are pressed
20 * by the four fingers (this implies only one button per row can be held down
21 * at the same time) and the buttons on the top are for the thumb. The tilt
22 * sensor delivers X and Y axis data depending on how the Twiddler is held.
23 * Additional information can be found at http://www.handykey.com.
24 *
25 * This driver does not use the Twiddler for its intended purpose, i.e. as
26 * a chording keyboard, but as a joystick: pressing and releasing a button
27 * immediately sends a corresponding button event, and tilting it generates
28 * corresponding ABS_X and ABS_Y events. This turns the Twiddler into a game
29 * controller with amazing 18 buttons :-)
30 *
31 * Note: The Twiddler2 (the successor of the Twiddler that connects directly
32 * to the PS/2 keyboard and mouse ports) is NOT supported by this driver!
33 *
34 * For questions or feedback regarding this driver module please contact:
35 * Arndt Schoenewald <arndt@quelltext.com>
36 */
37
38/*
39 * This program is free software; you can redistribute it and/or modify
40 * it under the terms of the GNU General Public License as published by
41 * the Free Software Foundation; either version 2 of the License, or
42 * (at your option) any later version.
43 *
44 * This program is distributed in the hope that it will be useful,
45 * but WITHOUT ANY WARRANTY; without even the implied warranty of
46 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47 * GNU General Public License for more details.
48 *
49 * You should have received a copy of the GNU General Public License
50 * along with this program; if not, write to the Free Software
51 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
52 */
53
54#include <linux/kernel.h>
55#include <linux/module.h>
56#include <linux/slab.h>
57#include <linux/input.h>
58#include <linux/serio.h>
59#include <linux/init.h>
60
61#define DRIVER_DESC "Handykey Twiddler keyboard as a joystick driver"
62
63MODULE_DESCRIPTION(DRIVER_DESC);
64MODULE_LICENSE("GPL");
65
66/*
67 * Constants.
68 */
69
70#define TWIDJOY_MAX_LENGTH 5
71
72static char *twidjoy_name = "Handykey Twiddler";
73
74static struct twidjoy_button_spec {
75 int bitshift;
76 int bitmask;
77 int buttons[3];
78}
79twidjoy_buttons[] = {
80 { 0, 3, { BTN_A, BTN_B, BTN_C } },
81 { 2, 3, { BTN_X, BTN_Y, BTN_Z } },
82 { 4, 3, { BTN_TL, BTN_TR, BTN_TR2 } },
83 { 6, 3, { BTN_SELECT, BTN_START, BTN_MODE } },
84 { 8, 1, { BTN_BASE5 } },
85 { 9, 1, { BTN_BASE } },
86 { 10, 1, { BTN_BASE3 } },
87 { 11, 1, { BTN_BASE4 } },
88 { 12, 1, { BTN_BASE2 } },
89 { 13, 1, { BTN_BASE6 } },
90 { 0, 0, { 0 } }
91};
92
93/*
94 * Per-Twiddler data.
95 */
96
97struct twidjoy {
98 struct input_dev dev;
99 int idx;
100 unsigned char data[TWIDJOY_MAX_LENGTH];
101 char phys[32];
102};
103
104/*
105 * twidjoy_process_packet() decodes packets the driver receives from the
106 * Twiddler. It updates the data accordingly.
107 */
108
109static void twidjoy_process_packet(struct twidjoy *twidjoy, struct pt_regs *regs)
110{
111 if (twidjoy->idx == TWIDJOY_MAX_LENGTH) {
112 struct input_dev *dev = &twidjoy->dev;
113 unsigned char *data = twidjoy->data;
114 struct twidjoy_button_spec *bp;
115 int button_bits, abs_x, abs_y;
116
117 button_bits = ((data[1] & 0x7f) << 7) | (data[0] & 0x7f);
118
119 input_regs(dev, regs);
120
121 for (bp = twidjoy_buttons; bp->bitmask; bp++) {
122 int value = (button_bits & (bp->bitmask << bp->bitshift)) >> bp->bitshift;
123 int i;
124
125 for (i = 0; i < bp->bitmask; i++)
126 input_report_key(dev, bp->buttons[i], i+1 == value);
127 }
128
129 abs_x = ((data[4] & 0x07) << 5) | ((data[3] & 0x7C) >> 2);
130 if (data[4] & 0x08) abs_x -= 256;
131
132 abs_y = ((data[3] & 0x01) << 7) | ((data[2] & 0x7F) >> 0);
133 if (data[3] & 0x02) abs_y -= 256;
134
135 input_report_abs(dev, ABS_X, -abs_x);
136 input_report_abs(dev, ABS_Y, +abs_y);
137
138 input_sync(dev);
139 }
140
141 return;
142}
143
144/*
145 * twidjoy_interrupt() is called by the low level driver when characters
146 * are ready for us. We then buffer them for further processing, or call the
147 * packet processing routine.
148 */
149
150static irqreturn_t twidjoy_interrupt(struct serio *serio, unsigned char data, unsigned int flags, struct pt_regs *regs)
151{
152 struct twidjoy *twidjoy = serio_get_drvdata(serio);
153
154 /* All Twiddler packets are 5 bytes. The fact that the first byte
155 * has a MSB of 0 and all other bytes have a MSB of 1 can be used
156 * to check and regain sync. */
157
158 if ((data & 0x80) == 0)
159 twidjoy->idx = 0; /* this byte starts a new packet */
160 else if (twidjoy->idx == 0)
161 return IRQ_HANDLED; /* wrong MSB -- ignore this byte */
162
163 if (twidjoy->idx < TWIDJOY_MAX_LENGTH)
164 twidjoy->data[twidjoy->idx++] = data;
165
166 if (twidjoy->idx == TWIDJOY_MAX_LENGTH) {
167 twidjoy_process_packet(twidjoy, regs);
168 twidjoy->idx = 0;
169 }
170
171 return IRQ_HANDLED;
172}
173
174/*
175 * twidjoy_disconnect() is the opposite of twidjoy_connect()
176 */
177
178static void twidjoy_disconnect(struct serio *serio)
179{
180 struct twidjoy *twidjoy = serio_get_drvdata(serio);
181
182 input_unregister_device(&twidjoy->dev);
183 serio_close(serio);
184 serio_set_drvdata(serio, NULL);
185 kfree(twidjoy);
186}
187
188/*
189 * twidjoy_connect() is the routine that is called when someone adds a
190 * new serio device. It looks for the Twiddler, and if found, registers
191 * it as an input device.
192 */
193
194static int twidjoy_connect(struct serio *serio, struct serio_driver *drv)
195{
196 struct twidjoy_button_spec *bp;
197 struct twidjoy *twidjoy;
198 int i;
199 int err;
200
201 if (!(twidjoy = kmalloc(sizeof(struct twidjoy), GFP_KERNEL)))
202 return -ENOMEM;
203
204 memset(twidjoy, 0, sizeof(struct twidjoy));
205
206 sprintf(twidjoy->phys, "%s/input0", serio->phys);
207
208 init_input_dev(&twidjoy->dev);
209 twidjoy->dev.name = twidjoy_name;
210 twidjoy->dev.phys = twidjoy->phys;
211 twidjoy->dev.id.bustype = BUS_RS232;
212 twidjoy->dev.id.vendor = SERIO_TWIDJOY;
213 twidjoy->dev.id.product = 0x0001;
214 twidjoy->dev.id.version = 0x0100;
215 twidjoy->dev.dev = &serio->dev;
216
217 twidjoy->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
218
219 for (bp = twidjoy_buttons; bp->bitmask; bp++) {
220 for (i = 0; i < bp->bitmask; i++)
221 set_bit(bp->buttons[i], twidjoy->dev.keybit);
222 }
223
224 twidjoy->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
225
226 for (i = 0; i < 2; i++) {
227 twidjoy->dev.absmax[ABS_X+i] = 50;
228 twidjoy->dev.absmin[ABS_X+i] = -50;
229
230 /* TODO: arndt 20010708: Are these values appropriate? */
231 twidjoy->dev.absfuzz[ABS_X+i] = 4;
232 twidjoy->dev.absflat[ABS_X+i] = 4;
233 }
234
235 twidjoy->dev.private = twidjoy;
236
237 serio_set_drvdata(serio, twidjoy);
238
239 err = serio_open(serio, drv);
240 if (err) {
241 serio_set_drvdata(serio, NULL);
242 kfree(twidjoy);
243 return err;
244 }
245
246 input_register_device(&twidjoy->dev);
247
248 printk(KERN_INFO "input: %s on %s\n", twidjoy_name, serio->phys);
249
250 return 0;
251}
252
253/*
254 * The serio driver structure.
255 */
256
257static struct serio_device_id twidjoy_serio_ids[] = {
258 {
259 .type = SERIO_RS232,
260 .proto = SERIO_TWIDJOY,
261 .id = SERIO_ANY,
262 .extra = SERIO_ANY,
263 },
264 { 0 }
265};
266
267MODULE_DEVICE_TABLE(serio, twidjoy_serio_ids);
268
269static struct serio_driver twidjoy_drv = {
270 .driver = {
271 .name = "twidjoy",
272 },
273 .description = DRIVER_DESC,
274 .id_table = twidjoy_serio_ids,
275 .interrupt = twidjoy_interrupt,
276 .connect = twidjoy_connect,
277 .disconnect = twidjoy_disconnect,
278};
279
280/*
281 * The functions for inserting/removing us as a module.
282 */
283
284int __init twidjoy_init(void)
285{
286 serio_register_driver(&twidjoy_drv);
287 return 0;
288}
289
290void __exit twidjoy_exit(void)
291{
292 serio_unregister_driver(&twidjoy_drv);
293}
294
295module_init(twidjoy_init);
296module_exit(twidjoy_exit);
diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c
new file mode 100644
index 000000000000..6976a219504c
--- /dev/null
+++ b/drivers/input/joystick/warrior.c
@@ -0,0 +1,248 @@
1/*
2 * $Id: warrior.c,v 1.14 2002/01/22 20:32:10 vojtech Exp $
3 *
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 */
6
7/*
8 * Logitech WingMan Warrior joystick driver for Linux
9 */
10
11/*
12 * This program is free warftware; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/kernel.h>
32#include <linux/module.h>
33#include <linux/slab.h>
34#include <linux/input.h>
35#include <linux/serio.h>
36#include <linux/init.h>
37
38#define DRIVER_DESC "Logitech WingMan Warrior joystick driver"
39
40MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
41MODULE_DESCRIPTION(DRIVER_DESC);
42MODULE_LICENSE("GPL");
43
44/*
45 * Constants.
46 */
47
48#define WARRIOR_MAX_LENGTH 16
49static char warrior_lengths[] = { 0, 4, 12, 3, 4, 4, 0, 0 };
50static char *warrior_name = "Logitech WingMan Warrior";
51
52/*
53 * Per-Warrior data.
54 */
55
56struct warrior {
57 struct input_dev dev;
58 int idx, len;
59 unsigned char data[WARRIOR_MAX_LENGTH];
60 char phys[32];
61};
62
63/*
64 * warrior_process_packet() decodes packets the driver receives from the
65 * Warrior. It updates the data accordingly.
66 */
67
68static void warrior_process_packet(struct warrior *warrior, struct pt_regs *regs)
69{
70 struct input_dev *dev = &warrior->dev;
71 unsigned char *data = warrior->data;
72
73 if (!warrior->idx) return;
74
75 input_regs(dev, regs);
76
77 switch ((data[0] >> 4) & 7) {
78 case 1: /* Button data */
79 input_report_key(dev, BTN_TRIGGER, data[3] & 1);
80 input_report_key(dev, BTN_THUMB, (data[3] >> 1) & 1);
81 input_report_key(dev, BTN_TOP, (data[3] >> 2) & 1);
82 input_report_key(dev, BTN_TOP2, (data[3] >> 3) & 1);
83 break;
84 case 3: /* XY-axis info->data */
85 input_report_abs(dev, ABS_X, ((data[0] & 8) << 5) - (data[2] | ((data[0] & 4) << 5)));
86 input_report_abs(dev, ABS_Y, (data[1] | ((data[0] & 1) << 7)) - ((data[0] & 2) << 7));
87 break;
88 case 5: /* Throttle, spinner, hat info->data */
89 input_report_abs(dev, ABS_THROTTLE, (data[1] | ((data[0] & 1) << 7)) - ((data[0] & 2) << 7));
90 input_report_abs(dev, ABS_HAT0X, (data[3] & 2 ? 1 : 0) - (data[3] & 1 ? 1 : 0));
91 input_report_abs(dev, ABS_HAT0Y, (data[3] & 8 ? 1 : 0) - (data[3] & 4 ? 1 : 0));
92 input_report_rel(dev, REL_DIAL, (data[2] | ((data[0] & 4) << 5)) - ((data[0] & 8) << 5));
93 break;
94 }
95 input_sync(dev);
96}
97
98/*
99 * warrior_interrupt() is called by the low level driver when characters
100 * are ready for us. We then buffer them for further processing, or call the
101 * packet processing routine.
102 */
103
104static irqreturn_t warrior_interrupt(struct serio *serio,
105 unsigned char data, unsigned int flags, struct pt_regs *regs)
106{
107 struct warrior *warrior = serio_get_drvdata(serio);
108
109 if (data & 0x80) {
110 if (warrior->idx) warrior_process_packet(warrior, regs);
111 warrior->idx = 0;
112 warrior->len = warrior_lengths[(data >> 4) & 7];
113 }
114
115 if (warrior->idx < warrior->len)
116 warrior->data[warrior->idx++] = data;
117
118 if (warrior->idx == warrior->len) {
119 if (warrior->idx) warrior_process_packet(warrior, regs);
120 warrior->idx = 0;
121 warrior->len = 0;
122 }
123 return IRQ_HANDLED;
124}
125
126/*
127 * warrior_disconnect() is the opposite of warrior_connect()
128 */
129
130static void warrior_disconnect(struct serio *serio)
131{
132 struct warrior *warrior = serio_get_drvdata(serio);
133
134 input_unregister_device(&warrior->dev);
135 serio_close(serio);
136 serio_set_drvdata(serio, NULL);
137 kfree(warrior);
138}
139
140/*
141 * warrior_connect() is the routine that is called when someone adds a
142 * new serio device. It looks for the Warrior, and if found, registers
143 * it as an input device.
144 */
145
146static int warrior_connect(struct serio *serio, struct serio_driver *drv)
147{
148 struct warrior *warrior;
149 int i;
150 int err;
151
152 if (!(warrior = kmalloc(sizeof(struct warrior), GFP_KERNEL)))
153 return -ENOMEM;
154
155 memset(warrior, 0, sizeof(struct warrior));
156
157 warrior->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
158 warrior->dev.keybit[LONG(BTN_TRIGGER)] = BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_TOP2);
159 warrior->dev.relbit[0] = BIT(REL_DIAL);
160 warrior->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y);
161
162 sprintf(warrior->phys, "%s/input0", serio->phys);
163
164 init_input_dev(&warrior->dev);
165 warrior->dev.name = warrior_name;
166 warrior->dev.phys = warrior->phys;
167 warrior->dev.id.bustype = BUS_RS232;
168 warrior->dev.id.vendor = SERIO_WARRIOR;
169 warrior->dev.id.product = 0x0001;
170 warrior->dev.id.version = 0x0100;
171 warrior->dev.dev = &serio->dev;
172
173 for (i = 0; i < 2; i++) {
174 warrior->dev.absmax[ABS_X+i] = -64;
175 warrior->dev.absmin[ABS_X+i] = 64;
176 warrior->dev.absflat[ABS_X+i] = 8;
177 }
178
179 warrior->dev.absmax[ABS_THROTTLE] = -112;
180 warrior->dev.absmin[ABS_THROTTLE] = 112;
181
182 for (i = 0; i < 2; i++) {
183 warrior->dev.absmax[ABS_HAT0X+i] = -1;
184 warrior->dev.absmin[ABS_HAT0X+i] = 1;
185 }
186
187 warrior->dev.private = warrior;
188
189 serio_set_drvdata(serio, warrior);
190
191 err = serio_open(serio, drv);
192 if (err) {
193 serio_set_drvdata(serio, NULL);
194 kfree(warrior);
195 return err;
196 }
197
198 input_register_device(&warrior->dev);
199
200 printk(KERN_INFO "input: Logitech WingMan Warrior on %s\n", serio->phys);
201
202 return 0;
203}
204
205/*
206 * The serio driver structure.
207 */
208
209static struct serio_device_id warrior_serio_ids[] = {
210 {
211 .type = SERIO_RS232,
212 .proto = SERIO_WARRIOR,
213 .id = SERIO_ANY,
214 .extra = SERIO_ANY,
215 },
216 { 0 }
217};
218
219MODULE_DEVICE_TABLE(serio, warrior_serio_ids);
220
221static struct serio_driver warrior_drv = {
222 .driver = {
223 .name = "warrior",
224 },
225 .description = DRIVER_DESC,
226 .id_table = warrior_serio_ids,
227 .interrupt = warrior_interrupt,
228 .connect = warrior_connect,
229 .disconnect = warrior_disconnect,
230};
231
232/*
233 * The functions for inserting/removing us as a module.
234 */
235
236static int __init warrior_init(void)
237{
238 serio_register_driver(&warrior_drv);
239 return 0;
240}
241
242static void __exit warrior_exit(void)
243{
244 serio_unregister_driver(&warrior_drv);
245}
246
247module_init(warrior_init);
248module_exit(warrior_exit);
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
new file mode 100644
index 000000000000..e55dee390775
--- /dev/null
+++ b/drivers/input/keyboard/Kconfig
@@ -0,0 +1,185 @@
1#
2# Input core configuration
3#
4menuconfig INPUT_KEYBOARD
5 bool "Keyboards" if EMBEDDED || !X86
6 default y
7 help
8 Say Y here, and a list of supported keyboards will be displayed.
9 This option doesn't affect the kernel.
10
11 If unsure, say Y.
12
13if INPUT_KEYBOARD
14
15config KEYBOARD_ATKBD
16 tristate "AT keyboard" if !PC
17 default y
18 select SERIO
19 select SERIO_LIBPS2
20 select SERIO_I8042 if PC
21 select SERIO_GSCPS2 if GSC
22 help
23 Say Y here if you want to use a standard AT or PS/2 keyboard. Usually
24 you'll need this, unless you have a different type keyboard (USB, ADB
25 or other). This also works for AT and PS/2 keyboards connected over a
26 PS/2 to serial converter.
27
28 If unsure, say Y.
29
30 To compile this driver as a module, choose M here: the
31 module will be called atkbd.
32
33config KEYBOARD_ATKBD_HP_KEYCODES
34 bool "Use HP keyboard scancodes"
35 depends on PARISC && KEYBOARD_ATKBD
36 default y
37 help
38 Say Y here if you have a PA-RISC machine and want to use an AT or
39 PS/2 keyboard, and your keyboard uses keycodes that are specific to
40 PA-RISC keyboards.
41
42 Say N if you use a standard keyboard.
43
44config KEYBOARD_ATKBD_RDI_KEYCODES
45 bool "Use PrecisionBook keyboard scancodes"
46 depends on KEYBOARD_ATKBD_HP_KEYCODES
47 default n
48 help
49 If you have an RDI PrecisionBook, say Y here if you want to use its
50 built-in keyboard (as opposed to an external keyboard).
51
52 The PrecisionBook has five keys that conflict with those used by most
53 AT and PS/2 keyboards. These are as follows:
54
55 PrecisionBook Standard AT or PS/2
56
57 F1 F12
58 Left Ctrl Left Alt
59 Caps Lock Left Ctrl
60 Right Ctrl Caps Lock
61 Left 102nd key (the key to the right of Left Shift)
62
63 If you say N here, and use the PrecisionBook keyboard, then each key
64 in the left-hand column will be interpreted as the corresponding key
65 in the right-hand column.
66
67 If you say Y here, and use an external keyboard, then each key in the
68 right-hand column will be interpreted as the key shown in the
69 left-hand column.
70
71config KEYBOARD_SUNKBD
72 tristate "Sun Type 4 and Type 5 keyboard"
73 select SERIO
74 help
75 Say Y here if you want to use a Sun Type 4 or Type 5 keyboard,
76 connected either to the Sun keyboard connector or to an serial
77 (RS-232) port via a simple adapter.
78
79 To compile this driver as a module, choose M here: the
80 module will be called sunkbd.
81
82config KEYBOARD_LKKBD
83 tristate "DECstation/VAXstation LK201/LK401 keyboard"
84 select SERIO
85 help
86 Say Y here if you want to use a LK201 or LK401 style serial
87 keyboard. This keyboard is also useable on PCs if you attach
88 it with the inputattach program. The connector pinout is
89 described within lkkbd.c.
90
91 To compile this driver as a module, choose M here: the
92 module will be called lkkbd.
93
94config KEYBOARD_LOCOMO
95 tristate "LoCoMo Keyboard Support"
96 depends on SHARP_LOCOMO
97 help
98 Say Y here if you are running Linux on a Sharp Zaurus Collie or Poodle based PDA
99
100 To compile this driver as a module, choose M here: the
101 module will be called locomokbd.
102
103config KEYBOARD_XTKBD
104 tristate "XT keyboard"
105 select SERIO
106 help
107 Say Y here if you want to use the old IBM PC/XT keyboard (or
108 compatible) on your system. This is only possible with a
109 parallel port keyboard adapter, you cannot connect it to the
110 keyboard port on a PC that runs Linux.
111
112 To compile this driver as a module, choose M here: the
113 module will be called xtkbd.
114
115config KEYBOARD_NEWTON
116 tristate "Newton keyboard"
117 select SERIO
118 help
119 Say Y here if you have a Newton keyboard on a serial port.
120
121 To compile this driver as a module, choose M here: the
122 module will be called newtonkbd.
123
124config KEYBOARD_CORGI
125 tristate "Corgi keyboard"
126 depends on PXA_SHARPSL
127 default y
128 help
129 Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx
130 series of PDAs.
131
132 To compile this driver as a module, choose M here: the
133 module will be called corgikbd.
134
135config KEYBOARD_MAPLE
136 tristate "Maple bus keyboard"
137 depends on SH_DREAMCAST && MAPLE
138 help
139 Say Y here if you have a DreamCast console running Linux and have
140 a keyboard attached to its Maple bus.
141
142 To compile this driver as a module, choose M here: the
143 module will be called maple_keyb.
144
145config KEYBOARD_AMIGA
146 tristate "Amiga keyboard"
147 depends on AMIGA
148 help
149 Say Y here if you are running Linux on any AMIGA and have a keyboard
150 attached.
151
152 To compile this driver as a module, choose M here: the
153 module will be called amikbd.
154
155config KEYBOARD_HIL_OLD
156 tristate "HP HIL keyboard support (simple driver)"
157 depends on GSC
158 default y
159 help
160 The "Human Interface Loop" is a older, 8-channel USB-like
161 controller used in several Hewlett Packard models. This driver
162 was adapted from the one written for m68k/hp300, and implements
163 support for a keyboard attached to the HIL port, but not for
164 any other types of HIL input devices like mice or tablets.
165 However, it has been thoroughly tested and is stable.
166
167 If you want full HIL support including support for multiple
168 keyboards, mices and tablets, you have to enable the
169 "HP System Device Controller i8042 Support" in the input/serio
170 submenu.
171
172config KEYBOARD_HIL
173 tristate "HP HIL keyboard support"
174 depends on GSC
175 default y
176 select HP_SDC
177 select HIL_MLC
178 select SERIO
179 help
180 The "Human Interface Loop" is a older, 8-channel USB-like
181 controller used in several Hewlett Packard models.
182 This driver implements support for HIL-keyboards attached
183 to your machine, so normally you should say Y here.
184
185endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
new file mode 100644
index 000000000000..b02eeceea3c3
--- /dev/null
+++ b/drivers/input/keyboard/Makefile
@@ -0,0 +1,19 @@
1#
2# Makefile for the input core drivers.
3#
4
5# Each configuration option enables a list of files.
6
7obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o
8obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o
9obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
10obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o
11obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
12obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o
13obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o
14obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
15obj-$(CONFIG_KEYBOARD_98KBD) += 98kbd.o
16obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o
17obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
18obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
19
diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c
new file mode 100644
index 000000000000..4e8e8ea214ab
--- /dev/null
+++ b/drivers/input/keyboard/amikbd.c
@@ -0,0 +1,241 @@
1/*
2 * $Id: amikbd.c,v 1.13 2002/02/01 16:02:24 vojtech Exp $
3 *
4 * Copyright (c) 2000-2001 Vojtech Pavlik
5 *
6 * Based on the work of:
7 * Hamish Macdonald
8 */
9
10/*
11 * Amiga keyboard driver for Linux/m68k
12 */
13
14/*
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 * Should you need to contact me, the author, you can do so either by
30 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
31 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
32 */
33
34#include <linux/module.h>
35#include <linux/init.h>
36#include <linux/input.h>
37#include <linux/delay.h>
38#include <linux/interrupt.h>
39
40#include <asm/amigaints.h>
41#include <asm/amigahw.h>
42#include <asm/irq.h>
43
44MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
45MODULE_DESCRIPTION("Amiga keyboard driver");
46MODULE_LICENSE("GPL");
47
48static unsigned char amikbd_keycode[0x78] = {
49 [0] = KEY_GRAVE,
50 [1] = KEY_1,
51 [2] = KEY_2,
52 [3] = KEY_3,
53 [4] = KEY_4,
54 [5] = KEY_5,
55 [6] = KEY_6,
56 [7] = KEY_7,
57 [8] = KEY_8,
58 [9] = KEY_9,
59 [10] = KEY_0,
60 [11] = KEY_MINUS,
61 [12] = KEY_EQUAL,
62 [13] = KEY_BACKSLASH,
63 [15] = KEY_KP0,
64 [16] = KEY_Q,
65 [17] = KEY_W,
66 [18] = KEY_E,
67 [19] = KEY_R,
68 [20] = KEY_T,
69 [21] = KEY_Y,
70 [22] = KEY_U,
71 [23] = KEY_I,
72 [24] = KEY_O,
73 [25] = KEY_P,
74 [26] = KEY_LEFTBRACE,
75 [27] = KEY_RIGHTBRACE,
76 [29] = KEY_KP1,
77 [30] = KEY_KP2,
78 [31] = KEY_KP3,
79 [32] = KEY_A,
80 [33] = KEY_S,
81 [34] = KEY_D,
82 [35] = KEY_F,
83 [36] = KEY_G,
84 [37] = KEY_H,
85 [38] = KEY_J,
86 [39] = KEY_K,
87 [40] = KEY_L,
88 [41] = KEY_SEMICOLON,
89 [42] = KEY_APOSTROPHE,
90 [43] = KEY_BACKSLASH,
91 [45] = KEY_KP4,
92 [46] = KEY_KP5,
93 [47] = KEY_KP6,
94 [48] = KEY_102ND,
95 [49] = KEY_Z,
96 [50] = KEY_X,
97 [51] = KEY_C,
98 [52] = KEY_V,
99 [53] = KEY_B,
100 [54] = KEY_N,
101 [55] = KEY_M,
102 [56] = KEY_COMMA,
103 [57] = KEY_DOT,
104 [58] = KEY_SLASH,
105 [60] = KEY_KPDOT,
106 [61] = KEY_KP7,
107 [62] = KEY_KP8,
108 [63] = KEY_KP9,
109 [64] = KEY_SPACE,
110 [65] = KEY_BACKSPACE,
111 [66] = KEY_TAB,
112 [67] = KEY_KPENTER,
113 [68] = KEY_ENTER,
114 [69] = KEY_ESC,
115 [70] = KEY_DELETE,
116 [74] = KEY_KPMINUS,
117 [76] = KEY_UP,
118 [77] = KEY_DOWN,
119 [78] = KEY_RIGHT,
120 [79] = KEY_LEFT,
121 [80] = KEY_F1,
122 [81] = KEY_F2,
123 [82] = KEY_F3,
124 [83] = KEY_F4,
125 [84] = KEY_F5,
126 [85] = KEY_F6,
127 [86] = KEY_F7,
128 [87] = KEY_F8,
129 [88] = KEY_F9,
130 [89] = KEY_F10,
131 [90] = KEY_KPLEFTPAREN,
132 [91] = KEY_KPRIGHTPAREN,
133 [92] = KEY_KPSLASH,
134 [93] = KEY_KPASTERISK,
135 [94] = KEY_KPPLUS,
136 [95] = KEY_HELP,
137 [96] = KEY_LEFTSHIFT,
138 [97] = KEY_RIGHTSHIFT,
139 [98] = KEY_CAPSLOCK,
140 [99] = KEY_LEFTCTRL,
141 [100] = KEY_LEFTALT,
142 [101] = KEY_RIGHTALT,
143 [102] = KEY_LEFTMETA,
144 [103] = KEY_RIGHTMETA
145};
146
147static const char *amikbd_messages[8] = {
148 [0] = KERN_ALERT "amikbd: Ctrl-Amiga-Amiga reset warning!!\n",
149 [1] = KERN_WARNING "amikbd: keyboard lost sync\n",
150 [2] = KERN_WARNING "amikbd: keyboard buffer overflow\n",
151 [3] = KERN_WARNING "amikbd: keyboard controller failure\n",
152 [4] = KERN_ERR "amikbd: keyboard selftest failure\n",
153 [5] = KERN_INFO "amikbd: initiate power-up key stream\n",
154 [6] = KERN_INFO "amikbd: terminate power-up key stream\n",
155 [7] = KERN_WARNING "amikbd: keyboard interrupt\n"
156};
157
158static struct input_dev amikbd_dev;
159
160static char *amikbd_name = "Amiga keyboard";
161static char *amikbd_phys = "amikbd/input0";
162
163static irqreturn_t amikbd_interrupt(int irq, void *dummy, struct pt_regs *fp)
164{
165 unsigned char scancode, down;
166
167 scancode = ~ciaa.sdr; /* get and invert scancode (keyboard is active low) */
168 ciaa.cra |= 0x40; /* switch SP pin to output for handshake */
169 udelay(85); /* wait until 85 us have expired */
170 ciaa.cra &= ~0x40; /* switch CIA serial port to input mode */
171
172 down = !(scancode & 1); /* lowest bit is release bit */
173 scancode >>= 1;
174
175 if (scancode < 0x78) { /* scancodes < 0x78 are keys */
176
177 scancode = amikbd_keycode[scancode];
178
179 input_regs(&amikbd_dev, fp);
180
181 if (scancode == KEY_CAPSLOCK) { /* CapsLock is a toggle switch key on Amiga */
182 input_report_key(&amikbd_dev, scancode, 1);
183 input_report_key(&amikbd_dev, scancode, 0);
184 input_sync(&amikbd_dev);
185 } else {
186 input_report_key(&amikbd_dev, scancode, down);
187 input_sync(&amikbd_dev);
188 }
189 } else /* scancodes >= 0x78 are error codes */
190 printk(amikbd_messages[scancode - 0x78]);
191
192 return IRQ_HANDLED;
193}
194
195static int __init amikbd_init(void)
196{
197 int i;
198
199 if (!AMIGAHW_PRESENT(AMI_KEYBOARD))
200 return -EIO;
201
202 if (!request_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100, "amikeyb"))
203 return -EBUSY;
204
205 init_input_dev(&amikbd_dev);
206
207 amikbd_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
208 amikbd_dev.keycode = amikbd_keycode;
209 amikbd_dev.keycodesize = sizeof(unsigned char);
210 amikbd_dev.keycodemax = ARRAY_SIZE(amikbd_keycode);
211
212 for (i = 0; i < 0x78; i++)
213 if (amikbd_keycode[i])
214 set_bit(amikbd_keycode[i], amikbd_dev.keybit);
215
216 ciaa.cra &= ~0x41; /* serial data in, turn off TA */
217 request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", amikbd_interrupt);
218
219 amikbd_dev.name = amikbd_name;
220 amikbd_dev.phys = amikbd_phys;
221 amikbd_dev.id.bustype = BUS_AMIGA;
222 amikbd_dev.id.vendor = 0x0001;
223 amikbd_dev.id.product = 0x0001;
224 amikbd_dev.id.version = 0x0100;
225
226 input_register_device(&amikbd_dev);
227
228 printk(KERN_INFO "input: %s\n", amikbd_name);
229
230 return 0;
231}
232
233static void __exit amikbd_exit(void)
234{
235 input_unregister_device(&amikbd_dev);
236 free_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt);
237 release_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100);
238}
239
240module_init(amikbd_init);
241module_exit(amikbd_exit);
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
new file mode 100644
index 000000000000..f7304f0ce542
--- /dev/null
+++ b/drivers/input/keyboard/atkbd.c
@@ -0,0 +1,1148 @@
1/*
2 * AT and PS/2 keyboard driver
3 *
4 * Copyright (c) 1999-2002 Vojtech Pavlik
5 */
6
7/*
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 */
12
13/*
14 * This driver can handle standard AT keyboards and PS/2 keyboards in
15 * Translated and Raw Set 2 and Set 3, as well as AT keyboards on dumb
16 * input-only controllers and AT keyboards connected over a one way RS232
17 * converter.
18 */
19
20#include <linux/delay.h>
21#include <linux/module.h>
22#include <linux/moduleparam.h>
23#include <linux/slab.h>
24#include <linux/interrupt.h>
25#include <linux/init.h>
26#include <linux/input.h>
27#include <linux/serio.h>
28#include <linux/workqueue.h>
29#include <linux/libps2.h>
30
31#define DRIVER_DESC "AT and PS/2 keyboard driver"
32
33MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
34MODULE_DESCRIPTION(DRIVER_DESC);
35MODULE_LICENSE("GPL");
36
37static int atkbd_set = 2;
38module_param_named(set, atkbd_set, int, 0);
39MODULE_PARM_DESC(set, "Select keyboard code set (2 = default, 3 = PS/2 native)");
40
41#if defined(__i386__) || defined(__x86_64__) || defined(__hppa__)
42static int atkbd_reset;
43#else
44static int atkbd_reset = 1;
45#endif
46module_param_named(reset, atkbd_reset, bool, 0);
47MODULE_PARM_DESC(reset, "Reset keyboard during initialization");
48
49static int atkbd_softrepeat;
50module_param_named(softrepeat, atkbd_softrepeat, bool, 0);
51MODULE_PARM_DESC(softrepeat, "Use software keyboard repeat");
52
53static int atkbd_softraw = 1;
54module_param_named(softraw, atkbd_softraw, bool, 0);
55MODULE_PARM_DESC(softraw, "Use software generated rawmode");
56
57static int atkbd_scroll = 1;
58module_param_named(scroll, atkbd_scroll, bool, 0);
59MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards");
60
61static int atkbd_extra;
62module_param_named(extra, atkbd_extra, bool, 0);
63MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and similar keyboards");
64
65__obsolete_setup("atkbd_set=");
66__obsolete_setup("atkbd_reset");
67__obsolete_setup("atkbd_softrepeat=");
68
69/*
70 * Scancode to keycode tables. These are just the default setting, and
71 * are loadable via an userland utility.
72 */
73
74static unsigned char atkbd_set2_keycode[512] = {
75
76#ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES
77
78/* XXX: need a more general approach */
79
80#include "hpps2atkbd.h" /* include the keyboard scancodes */
81
82#else
83 0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41,117,
84 0, 56, 42, 93, 29, 16, 2, 0, 0, 0, 44, 31, 30, 17, 3, 0,
85 0, 46, 45, 32, 18, 5, 4, 95, 0, 57, 47, 33, 20, 19, 6,183,
86 0, 49, 48, 35, 34, 21, 7,184, 0, 0, 50, 36, 22, 8, 9,185,
87 0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0,
88 0, 89, 40, 0, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 85,
89 0, 86, 91, 90, 92, 0, 14, 94, 0, 79,124, 75, 71,121, 0, 0,
90 82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
91
92 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
93 217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125,
94 173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127,
95 159, 0,115, 0,164, 0, 0,116,158, 0,150,166, 0, 0, 0,142,
96 157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0,
97 226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0,
98 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112,
99 110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119, 0,
100
101 0, 0, 0, 65, 99,
102#endif
103};
104
105static unsigned char atkbd_set3_keycode[512] = {
106
107 0, 0, 0, 0, 0, 0, 0, 59, 1,138,128,129,130, 15, 41, 60,
108 131, 29, 42, 86, 58, 16, 2, 61,133, 56, 44, 31, 30, 17, 3, 62,
109 134, 46, 45, 32, 18, 5, 4, 63,135, 57, 47, 33, 20, 19, 6, 64,
110 136, 49, 48, 35, 34, 21, 7, 65,137,100, 50, 36, 22, 8, 9, 66,
111 125, 51, 37, 23, 24, 11, 10, 67,126, 52, 53, 38, 39, 25, 12, 68,
112 113,114, 40, 43, 26, 13, 87, 99, 97, 54, 28, 27, 43, 43, 88, 70,
113 108,105,119,103,111,107, 14,110, 0, 79,106, 75, 71,109,102,104,
114 82, 83, 80, 76, 77, 72, 69, 98, 0, 96, 81, 0, 78, 73, 55,183,
115
116 184,185,186,187, 74, 94, 92, 93, 0, 0, 0,125,126,127,112, 0,
117 0,139,150,163,165,115,152,150,166,140,160,154,113,114,167,168,
118 148,149,147,140
119};
120
121static unsigned char atkbd_unxlate_table[128] = {
122 0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
123 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
124 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
125 50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88, 5, 6, 4, 12, 3,
126 11, 2, 10, 1, 9,119,126,108,117,125,123,107,115,116,121,105,
127 114,122,112,113,127, 96, 97,120, 7, 15, 23, 31, 39, 47, 55, 63,
128 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
129 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
130};
131
132#define ATKBD_CMD_SETLEDS 0x10ed
133#define ATKBD_CMD_GSCANSET 0x11f0
134#define ATKBD_CMD_SSCANSET 0x10f0
135#define ATKBD_CMD_GETID 0x02f2
136#define ATKBD_CMD_SETREP 0x10f3
137#define ATKBD_CMD_ENABLE 0x00f4
138#define ATKBD_CMD_RESET_DIS 0x00f5
139#define ATKBD_CMD_SETALL_MBR 0x00fa
140#define ATKBD_CMD_RESET_BAT 0x02ff
141#define ATKBD_CMD_RESEND 0x00fe
142#define ATKBD_CMD_EX_ENABLE 0x10ea
143#define ATKBD_CMD_EX_SETLEDS 0x20eb
144#define ATKBD_CMD_OK_GETID 0x02e8
145
146#define ATKBD_RET_ACK 0xfa
147#define ATKBD_RET_NAK 0xfe
148#define ATKBD_RET_BAT 0xaa
149#define ATKBD_RET_EMUL0 0xe0
150#define ATKBD_RET_EMUL1 0xe1
151#define ATKBD_RET_RELEASE 0xf0
152#define ATKBD_RET_HANGUEL 0xf1
153#define ATKBD_RET_HANJA 0xf2
154#define ATKBD_RET_ERR 0xff
155
156#define ATKBD_KEY_UNKNOWN 0
157#define ATKBD_KEY_NULL 255
158
159#define ATKBD_SCR_1 254
160#define ATKBD_SCR_2 253
161#define ATKBD_SCR_4 252
162#define ATKBD_SCR_8 251
163#define ATKBD_SCR_CLICK 250
164#define ATKBD_SCR_LEFT 249
165#define ATKBD_SCR_RIGHT 248
166
167#define ATKBD_SPECIAL 248
168
169static struct {
170 unsigned char keycode;
171 unsigned char set2;
172} atkbd_scroll_keys[] = {
173 { ATKBD_SCR_1, 0xc5 },
174 { ATKBD_SCR_2, 0xa9 },
175 { ATKBD_SCR_4, 0xb6 },
176 { ATKBD_SCR_8, 0xa7 },
177 { ATKBD_SCR_CLICK, 0xe0 },
178 { ATKBD_SCR_LEFT, 0xcb },
179 { ATKBD_SCR_RIGHT, 0xd2 },
180};
181
182/*
183 * The atkbd control structure
184 */
185
186struct atkbd {
187
188 struct ps2dev ps2dev;
189
190 /* Written only during init */
191 char name[64];
192 char phys[32];
193 struct input_dev dev;
194
195 unsigned short id;
196 unsigned char keycode[512];
197 unsigned char set;
198 unsigned char translated;
199 unsigned char extra;
200 unsigned char write;
201 unsigned char softrepeat;
202 unsigned char softraw;
203 unsigned char scroll;
204 unsigned char enabled;
205
206 /* Accessed only from interrupt */
207 unsigned char emul;
208 unsigned char resend;
209 unsigned char release;
210 unsigned char bat_xl;
211 unsigned int last;
212 unsigned long time;
213};
214
215static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
216 ssize_t (*handler)(struct atkbd *, char *));
217static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count,
218 ssize_t (*handler)(struct atkbd *, const char *, size_t));
219#define ATKBD_DEFINE_ATTR(_name) \
220static ssize_t atkbd_show_##_name(struct atkbd *, char *); \
221static ssize_t atkbd_set_##_name(struct atkbd *, const char *, size_t); \
222static ssize_t atkbd_do_show_##_name(struct device *d, char *b) \
223{ \
224 return atkbd_attr_show_helper(d, b, atkbd_show_##_name); \
225} \
226static ssize_t atkbd_do_set_##_name(struct device *d, const char *b, size_t s) \
227{ \
228 return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name); \
229} \
230static struct device_attribute atkbd_attr_##_name = \
231 __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name);
232
233ATKBD_DEFINE_ATTR(extra);
234ATKBD_DEFINE_ATTR(scroll);
235ATKBD_DEFINE_ATTR(set);
236ATKBD_DEFINE_ATTR(softrepeat);
237ATKBD_DEFINE_ATTR(softraw);
238
239
240static void atkbd_report_key(struct input_dev *dev, struct pt_regs *regs, int code, int value)
241{
242 input_regs(dev, regs);
243 if (value == 3) {
244 input_report_key(dev, code, 1);
245 input_sync(dev);
246 input_report_key(dev, code, 0);
247 } else
248 input_event(dev, EV_KEY, code, value);
249 input_sync(dev);
250}
251
252/*
253 * atkbd_interrupt(). Here takes place processing of data received from
254 * the keyboard into events.
255 */
256
257static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
258 unsigned int flags, struct pt_regs *regs)
259{
260 struct atkbd *atkbd = serio_get_drvdata(serio);
261 unsigned int code = data;
262 int scroll = 0, hscroll = 0, click = -1;
263 int value;
264
265#ifdef ATKBD_DEBUG
266 printk(KERN_DEBUG "atkbd.c: Received %02x flags %02x\n", data, flags);
267#endif
268
269#if !defined(__i386__) && !defined (__x86_64__)
270 if ((flags & (SERIO_FRAME | SERIO_PARITY)) && (~flags & SERIO_TIMEOUT) && !atkbd->resend && atkbd->write) {
271 printk(KERN_WARNING "atkbd.c: frame/parity error: %02x\n", flags);
272 serio_write(serio, ATKBD_CMD_RESEND);
273 atkbd->resend = 1;
274 goto out;
275 }
276
277 if (!flags && data == ATKBD_RET_ACK)
278 atkbd->resend = 0;
279#endif
280
281 if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_ACK))
282 if (ps2_handle_ack(&atkbd->ps2dev, data))
283 goto out;
284
285 if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_CMD))
286 if (ps2_handle_response(&atkbd->ps2dev, data))
287 goto out;
288
289 if (!atkbd->enabled)
290 goto out;
291
292 input_event(&atkbd->dev, EV_MSC, MSC_RAW, code);
293
294 if (atkbd->translated) {
295
296 if (atkbd->emul ||
297 !(code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1 ||
298 code == ATKBD_RET_HANGUEL || code == ATKBD_RET_HANJA ||
299 code == ATKBD_RET_ERR ||
300 (code == ATKBD_RET_BAT && !atkbd->bat_xl))) {
301 atkbd->release = code >> 7;
302 code &= 0x7f;
303 }
304
305 if (!atkbd->emul &&
306 (code & 0x7f) == (ATKBD_RET_BAT & 0x7f))
307 atkbd->bat_xl = !atkbd->release;
308 }
309
310 switch (code) {
311 case ATKBD_RET_BAT:
312 atkbd->enabled = 0;
313 serio_rescan(atkbd->ps2dev.serio);
314 goto out;
315 case ATKBD_RET_EMUL0:
316 atkbd->emul = 1;
317 goto out;
318 case ATKBD_RET_EMUL1:
319 atkbd->emul = 2;
320 goto out;
321 case ATKBD_RET_RELEASE:
322 atkbd->release = 1;
323 goto out;
324 case ATKBD_RET_HANGUEL:
325 atkbd_report_key(&atkbd->dev, regs, KEY_HANGUEL, 3);
326 goto out;
327 case ATKBD_RET_HANJA:
328 atkbd_report_key(&atkbd->dev, regs, KEY_HANJA, 3);
329 goto out;
330 case ATKBD_RET_ERR:
331 printk(KERN_DEBUG "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys);
332 goto out;
333 }
334
335 if (atkbd->set != 3)
336 code = (code & 0x7f) | ((code & 0x80) << 1);
337 if (atkbd->emul) {
338 if (--atkbd->emul)
339 goto out;
340 code |= (atkbd->set != 3) ? 0x80 : 0x100;
341 }
342
343 if (atkbd->keycode[code] != ATKBD_KEY_NULL)
344 input_event(&atkbd->dev, EV_MSC, MSC_SCAN, code);
345
346 switch (atkbd->keycode[code]) {
347 case ATKBD_KEY_NULL:
348 break;
349 case ATKBD_KEY_UNKNOWN:
350 if (data == ATKBD_RET_ACK || data == ATKBD_RET_NAK) {
351 printk(KERN_WARNING "atkbd.c: Spurious %s on %s. Some program, "
352 "like XFree86, might be trying access hardware directly.\n",
353 data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
354 } else {
355 printk(KERN_WARNING "atkbd.c: Unknown key %s "
356 "(%s set %d, code %#x on %s).\n",
357 atkbd->release ? "released" : "pressed",
358 atkbd->translated ? "translated" : "raw",
359 atkbd->set, code, serio->phys);
360 printk(KERN_WARNING "atkbd.c: Use 'setkeycodes %s%02x <keycode>' "
361 "to make it known.\n",
362 code & 0x80 ? "e0" : "", code & 0x7f);
363 }
364 input_sync(&atkbd->dev);
365 break;
366 case ATKBD_SCR_1:
367 scroll = 1 - atkbd->release * 2;
368 break;
369 case ATKBD_SCR_2:
370 scroll = 2 - atkbd->release * 4;
371 break;
372 case ATKBD_SCR_4:
373 scroll = 4 - atkbd->release * 8;
374 break;
375 case ATKBD_SCR_8:
376 scroll = 8 - atkbd->release * 16;
377 break;
378 case ATKBD_SCR_CLICK:
379 click = !atkbd->release;
380 break;
381 case ATKBD_SCR_LEFT:
382 hscroll = -1;
383 break;
384 case ATKBD_SCR_RIGHT:
385 hscroll = 1;
386 break;
387 default:
388 value = atkbd->release ? 0 :
389 (1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key)));
390
391 switch (value) { /* Workaround Toshiba laptop multiple keypress */
392 case 0:
393 atkbd->last = 0;
394 break;
395 case 1:
396 atkbd->last = code;
397 atkbd->time = jiffies + msecs_to_jiffies(atkbd->dev.rep[REP_DELAY]) / 2;
398 break;
399 case 2:
400 if (!time_after(jiffies, atkbd->time) && atkbd->last == code)
401 value = 1;
402 break;
403 }
404
405 atkbd_report_key(&atkbd->dev, regs, atkbd->keycode[code], value);
406 }
407
408 if (atkbd->scroll) {
409 input_regs(&atkbd->dev, regs);
410 if (click != -1)
411 input_report_key(&atkbd->dev, BTN_MIDDLE, click);
412 input_report_rel(&atkbd->dev, REL_WHEEL, scroll);
413 input_report_rel(&atkbd->dev, REL_HWHEEL, hscroll);
414 input_sync(&atkbd->dev);
415 }
416
417 atkbd->release = 0;
418out:
419 return IRQ_HANDLED;
420}
421
422/*
423 * Event callback from the input module. Events that change the state of
424 * the hardware are processed here.
425 */
426
427static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
428{
429 struct atkbd *atkbd = dev->private;
430 const short period[32] =
431 { 33, 37, 42, 46, 50, 54, 58, 63, 67, 75, 83, 92, 100, 109, 116, 125,
432 133, 149, 167, 182, 200, 217, 232, 250, 270, 303, 333, 370, 400, 435, 470, 500 };
433 const short delay[4] =
434 { 250, 500, 750, 1000 };
435 unsigned char param[2];
436 int i, j;
437
438 if (!atkbd->write)
439 return -1;
440
441 switch (type) {
442
443 case EV_LED:
444
445 param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0)
446 | (test_bit(LED_NUML, dev->led) ? 2 : 0)
447 | (test_bit(LED_CAPSL, dev->led) ? 4 : 0);
448 ps2_schedule_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS);
449
450 if (atkbd->extra) {
451 param[0] = 0;
452 param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0)
453 | (test_bit(LED_SLEEP, dev->led) ? 0x02 : 0)
454 | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0)
455 | (test_bit(LED_MISC, dev->led) ? 0x10 : 0)
456 | (test_bit(LED_MUTE, dev->led) ? 0x20 : 0);
457 ps2_schedule_command(&atkbd->ps2dev, param, ATKBD_CMD_EX_SETLEDS);
458 }
459
460 return 0;
461
462
463 case EV_REP:
464
465 if (atkbd->softrepeat) return 0;
466
467 i = j = 0;
468 while (i < 32 && period[i] < dev->rep[REP_PERIOD]) i++;
469 while (j < 4 && delay[j] < dev->rep[REP_DELAY]) j++;
470 dev->rep[REP_PERIOD] = period[i];
471 dev->rep[REP_DELAY] = delay[j];
472 param[0] = i | (j << 5);
473 ps2_schedule_command(&atkbd->ps2dev, param, ATKBD_CMD_SETREP);
474
475 return 0;
476 }
477
478 return -1;
479}
480
481/*
482 * atkbd_enable() signals that interrupt handler is allowed to
483 * generate input events.
484 */
485
486static inline void atkbd_enable(struct atkbd *atkbd)
487{
488 serio_pause_rx(atkbd->ps2dev.serio);
489 atkbd->enabled = 1;
490 serio_continue_rx(atkbd->ps2dev.serio);
491}
492
493/*
494 * atkbd_disable() tells input handler that all incoming data except
495 * for ACKs and command response should be dropped.
496 */
497
498static inline void atkbd_disable(struct atkbd *atkbd)
499{
500 serio_pause_rx(atkbd->ps2dev.serio);
501 atkbd->enabled = 0;
502 serio_continue_rx(atkbd->ps2dev.serio);
503}
504
505/*
506 * atkbd_probe() probes for an AT keyboard on a serio port.
507 */
508
509static int atkbd_probe(struct atkbd *atkbd)
510{
511 struct ps2dev *ps2dev = &atkbd->ps2dev;
512 unsigned char param[2];
513
514/*
515 * Some systems, where the bit-twiddling when testing the io-lines of the
516 * controller may confuse the keyboard need a full reset of the keyboard. On
517 * these systems the BIOS also usually doesn't do it for us.
518 */
519
520 if (atkbd_reset)
521 if (ps2_command(ps2dev, NULL, ATKBD_CMD_RESET_BAT))
522 printk(KERN_WARNING "atkbd.c: keyboard reset failed on %s\n", ps2dev->serio->phys);
523
524/*
525 * Then we check the keyboard ID. We should get 0xab83 under normal conditions.
526 * Some keyboards report different values, but the first byte is always 0xab or
527 * 0xac. Some old AT keyboards don't report anything. If a mouse is connected, this
528 * should make sure we don't try to set the LEDs on it.
529 */
530
531 param[0] = param[1] = 0xa5; /* initialize with invalid values */
532 if (ps2_command(ps2dev, param, ATKBD_CMD_GETID)) {
533
534/*
535 * If the get ID command failed, we check if we can at least set the LEDs on
536 * the keyboard. This should work on every keyboard out there. It also turns
537 * the LEDs off, which we want anyway.
538 */
539 param[0] = 0;
540 if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS))
541 return -1;
542 atkbd->id = 0xabba;
543 return 0;
544 }
545
546 if (param[0] != 0xab && param[0] != 0xac && /* Regular and NCD Sun keyboards */
547 param[0] != 0x2b && param[0] != 0x5d && /* Trust keyboard, raw and translated */
548 param[0] != 0x60 && param[0] != 0x47) /* NMB SGI keyboard, raw and translated */
549 return -1;
550
551 atkbd->id = (param[0] << 8) | param[1];
552
553 if (atkbd->id == 0xaca1 && atkbd->translated) {
554 printk(KERN_ERR "atkbd.c: NCD terminal keyboards are only supported on non-translating\n");
555 printk(KERN_ERR "atkbd.c: controllers. Use i8042.direct=1 to disable translation.\n");
556 return -1;
557 }
558
559 return 0;
560}
561
562/*
563 * atkbd_select_set checks if a keyboard has a working Set 3 support, and
564 * sets it into that. Unfortunately there are keyboards that can be switched
565 * to Set 3, but don't work well in that (BTC Multimedia ...)
566 */
567
568static int atkbd_select_set(struct atkbd *atkbd, int target_set, int allow_extra)
569{
570 struct ps2dev *ps2dev = &atkbd->ps2dev;
571 unsigned char param[2];
572
573 atkbd->extra = 0;
574/*
575 * For known special keyboards we can go ahead and set the correct set.
576 * We check for NCD PS/2 Sun, NorthGate OmniKey 101 and
577 * IBM RapidAccess / IBM EzButton / Chicony KBP-8993 keyboards.
578 */
579
580 if (atkbd->translated)
581 return 2;
582
583 if (atkbd->id == 0xaca1) {
584 param[0] = 3;
585 ps2_command(ps2dev, param, ATKBD_CMD_SSCANSET);
586 return 3;
587 }
588
589 if (allow_extra) {
590 param[0] = 0x71;
591 if (!ps2_command(ps2dev, param, ATKBD_CMD_EX_ENABLE)) {
592 atkbd->extra = 1;
593 return 2;
594 }
595 }
596
597 if (target_set != 3)
598 return 2;
599
600 if (!ps2_command(ps2dev, param, ATKBD_CMD_OK_GETID)) {
601 atkbd->id = param[0] << 8 | param[1];
602 return 2;
603 }
604
605 param[0] = 3;
606 if (ps2_command(ps2dev, param, ATKBD_CMD_SSCANSET))
607 return 2;
608
609 param[0] = 0;
610 if (ps2_command(ps2dev, param, ATKBD_CMD_GSCANSET))
611 return 2;
612
613 if (param[0] != 3) {
614 param[0] = 2;
615 if (ps2_command(ps2dev, param, ATKBD_CMD_SSCANSET))
616 return 2;
617 }
618
619 ps2_command(ps2dev, param, ATKBD_CMD_SETALL_MBR);
620
621 return 3;
622}
623
624static int atkbd_activate(struct atkbd *atkbd)
625{
626 struct ps2dev *ps2dev = &atkbd->ps2dev;
627 unsigned char param[1];
628
629/*
630 * Set the LEDs to a defined state.
631 */
632
633 param[0] = 0;
634 if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS))
635 return -1;
636
637/*
638 * Set autorepeat to fastest possible.
639 */
640
641 param[0] = 0;
642 if (ps2_command(ps2dev, param, ATKBD_CMD_SETREP))
643 return -1;
644
645/*
646 * Enable the keyboard to receive keystrokes.
647 */
648
649 if (ps2_command(ps2dev, NULL, ATKBD_CMD_ENABLE)) {
650 printk(KERN_ERR "atkbd.c: Failed to enable keyboard on %s\n",
651 ps2dev->serio->phys);
652 return -1;
653 }
654
655 return 0;
656}
657
658/*
659 * atkbd_cleanup() restores the keyboard state so that BIOS is happy after a
660 * reboot.
661 */
662
663static void atkbd_cleanup(struct serio *serio)
664{
665 struct atkbd *atkbd = serio_get_drvdata(serio);
666 ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_BAT);
667}
668
669
670/*
671 * atkbd_disconnect() closes and frees.
672 */
673
674static void atkbd_disconnect(struct serio *serio)
675{
676 struct atkbd *atkbd = serio_get_drvdata(serio);
677
678 atkbd_disable(atkbd);
679
680 /* make sure we don't have a command in flight */
681 synchronize_kernel();
682 flush_scheduled_work();
683
684 device_remove_file(&serio->dev, &atkbd_attr_extra);
685 device_remove_file(&serio->dev, &atkbd_attr_scroll);
686 device_remove_file(&serio->dev, &atkbd_attr_set);
687 device_remove_file(&serio->dev, &atkbd_attr_softrepeat);
688 device_remove_file(&serio->dev, &atkbd_attr_softraw);
689
690 input_unregister_device(&atkbd->dev);
691 serio_close(serio);
692 serio_set_drvdata(serio, NULL);
693 kfree(atkbd);
694}
695
696
697/*
698 * atkbd_set_device_attrs() initializes keyboard's keycode table
699 * according to the selected scancode set
700 */
701
702static void atkbd_set_keycode_table(struct atkbd *atkbd)
703{
704 int i, j;
705
706 memset(atkbd->keycode, 0, sizeof(atkbd->keycode));
707
708 if (atkbd->translated) {
709 for (i = 0; i < 128; i++) {
710 atkbd->keycode[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
711 atkbd->keycode[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
712 if (atkbd->scroll)
713 for (j = 0; j < ARRAY_SIZE(atkbd_scroll_keys); j++)
714 if ((atkbd_unxlate_table[i] | 0x80) == atkbd_scroll_keys[j].set2)
715 atkbd->keycode[i | 0x80] = atkbd_scroll_keys[j].keycode;
716 }
717 } else if (atkbd->set == 3) {
718 memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode));
719 } else {
720 memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));
721
722 if (atkbd->scroll)
723 for (i = 0; i < ARRAY_SIZE(atkbd_scroll_keys); i++)
724 atkbd->keycode[atkbd_scroll_keys[i].set2] = atkbd_scroll_keys[i].keycode;
725 }
726}
727
728/*
729 * atkbd_set_device_attrs() sets up keyboard's input device structure
730 */
731
732static void atkbd_set_device_attrs(struct atkbd *atkbd)
733{
734 int i;
735
736 memset(&atkbd->dev, 0, sizeof(struct input_dev));
737
738 init_input_dev(&atkbd->dev);
739
740 atkbd->dev.name = atkbd->name;
741 atkbd->dev.phys = atkbd->phys;
742 atkbd->dev.id.bustype = BUS_I8042;
743 atkbd->dev.id.vendor = 0x0001;
744 atkbd->dev.id.product = atkbd->translated ? 1 : atkbd->set;
745 atkbd->dev.id.version = atkbd->id;
746 atkbd->dev.event = atkbd_event;
747 atkbd->dev.private = atkbd;
748 atkbd->dev.dev = &atkbd->ps2dev.serio->dev;
749
750 atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC);
751
752 if (atkbd->write) {
753 atkbd->dev.evbit[0] |= BIT(EV_LED);
754 atkbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
755 }
756
757 if (atkbd->extra)
758 atkbd->dev.ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) |
759 BIT(LED_SLEEP) | BIT(LED_MUTE) | BIT(LED_MISC);
760
761 if (!atkbd->softrepeat) {
762 atkbd->dev.rep[REP_DELAY] = 250;
763 atkbd->dev.rep[REP_PERIOD] = 33;
764 }
765
766 atkbd->dev.mscbit[0] = atkbd->softraw ? BIT(MSC_SCAN) : BIT(MSC_RAW) | BIT(MSC_SCAN);
767
768 if (atkbd->scroll) {
769 atkbd->dev.evbit[0] |= BIT(EV_REL);
770 atkbd->dev.relbit[0] = BIT(REL_WHEEL) | BIT(REL_HWHEEL);
771 set_bit(BTN_MIDDLE, atkbd->dev.keybit);
772 }
773
774 atkbd->dev.keycode = atkbd->keycode;
775 atkbd->dev.keycodesize = sizeof(unsigned char);
776 atkbd->dev.keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
777
778 for (i = 0; i < 512; i++)
779 if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL)
780 set_bit(atkbd->keycode[i], atkbd->dev.keybit);
781}
782
783/*
784 * atkbd_connect() is called when the serio module finds an interface
785 * that isn't handled yet by an appropriate device driver. We check if
786 * there is an AT keyboard out there and if yes, we register ourselves
787 * to the input module.
788 */
789
790static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
791{
792 struct atkbd *atkbd;
793 int err;
794
795 if (!(atkbd = kmalloc(sizeof(struct atkbd), GFP_KERNEL)))
796 return - ENOMEM;
797
798 memset(atkbd, 0, sizeof(struct atkbd));
799
800 ps2_init(&atkbd->ps2dev, serio);
801
802 switch (serio->id.type) {
803
804 case SERIO_8042_XL:
805 atkbd->translated = 1;
806 case SERIO_8042:
807 if (serio->write)
808 atkbd->write = 1;
809 break;
810 }
811
812 atkbd->softraw = atkbd_softraw;
813 atkbd->softrepeat = atkbd_softrepeat;
814 atkbd->scroll = atkbd_scroll;
815
816 if (!atkbd->write)
817 atkbd->softrepeat = 1;
818
819 if (atkbd->softrepeat)
820 atkbd->softraw = 1;
821
822 serio_set_drvdata(serio, atkbd);
823
824 err = serio_open(serio, drv);
825 if (err) {
826 serio_set_drvdata(serio, NULL);
827 kfree(atkbd);
828 return err;
829 }
830
831 if (atkbd->write) {
832
833 if (atkbd_probe(atkbd)) {
834 serio_close(serio);
835 serio_set_drvdata(serio, NULL);
836 kfree(atkbd);
837 return -ENODEV;
838 }
839
840 atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra);
841 atkbd_activate(atkbd);
842
843 } else {
844 atkbd->set = 2;
845 atkbd->id = 0xab00;
846 }
847
848 if (atkbd->extra)
849 sprintf(atkbd->name, "AT Set 2 Extra keyboard");
850 else
851 sprintf(atkbd->name, "AT %s Set %d keyboard",
852 atkbd->translated ? "Translated" : "Raw", atkbd->set);
853
854 sprintf(atkbd->phys, "%s/input0", serio->phys);
855
856 atkbd_set_keycode_table(atkbd);
857 atkbd_set_device_attrs(atkbd);
858
859 input_register_device(&atkbd->dev);
860
861 device_create_file(&serio->dev, &atkbd_attr_extra);
862 device_create_file(&serio->dev, &atkbd_attr_scroll);
863 device_create_file(&serio->dev, &atkbd_attr_set);
864 device_create_file(&serio->dev, &atkbd_attr_softrepeat);
865 device_create_file(&serio->dev, &atkbd_attr_softraw);
866
867 atkbd_enable(atkbd);
868
869 printk(KERN_INFO "input: %s on %s\n", atkbd->name, serio->phys);
870
871 return 0;
872}
873
874/*
875 * atkbd_reconnect() tries to restore keyboard into a sane state and is
876 * most likely called on resume.
877 */
878
879static int atkbd_reconnect(struct serio *serio)
880{
881 struct atkbd *atkbd = serio_get_drvdata(serio);
882 struct serio_driver *drv = serio->drv;
883 unsigned char param[1];
884
885 if (!atkbd || !drv) {
886 printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
887 return -1;
888 }
889
890 atkbd_disable(atkbd);
891
892 if (atkbd->write) {
893 param[0] = (test_bit(LED_SCROLLL, atkbd->dev.led) ? 1 : 0)
894 | (test_bit(LED_NUML, atkbd->dev.led) ? 2 : 0)
895 | (test_bit(LED_CAPSL, atkbd->dev.led) ? 4 : 0);
896
897 if (atkbd_probe(atkbd))
898 return -1;
899 if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra))
900 return -1;
901
902 atkbd_activate(atkbd);
903
904 if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS))
905 return -1;
906 }
907
908 atkbd_enable(atkbd);
909
910 return 0;
911}
912
913static struct serio_device_id atkbd_serio_ids[] = {
914 {
915 .type = SERIO_8042,
916 .proto = SERIO_ANY,
917 .id = SERIO_ANY,
918 .extra = SERIO_ANY,
919 },
920 {
921 .type = SERIO_8042_XL,
922 .proto = SERIO_ANY,
923 .id = SERIO_ANY,
924 .extra = SERIO_ANY,
925 },
926 {
927 .type = SERIO_RS232,
928 .proto = SERIO_PS2SER,
929 .id = SERIO_ANY,
930 .extra = SERIO_ANY,
931 },
932 { 0 }
933};
934
935MODULE_DEVICE_TABLE(serio, atkbd_serio_ids);
936
937static struct serio_driver atkbd_drv = {
938 .driver = {
939 .name = "atkbd",
940 },
941 .description = DRIVER_DESC,
942 .id_table = atkbd_serio_ids,
943 .interrupt = atkbd_interrupt,
944 .connect = atkbd_connect,
945 .reconnect = atkbd_reconnect,
946 .disconnect = atkbd_disconnect,
947 .cleanup = atkbd_cleanup,
948};
949
950static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
951 ssize_t (*handler)(struct atkbd *, char *))
952{
953 struct serio *serio = to_serio_port(dev);
954 int retval;
955
956 retval = serio_pin_driver(serio);
957 if (retval)
958 return retval;
959
960 if (serio->drv != &atkbd_drv) {
961 retval = -ENODEV;
962 goto out;
963 }
964
965 retval = handler((struct atkbd *)serio_get_drvdata(serio), buf);
966
967out:
968 serio_unpin_driver(serio);
969 return retval;
970}
971
972static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count,
973 ssize_t (*handler)(struct atkbd *, const char *, size_t))
974{
975 struct serio *serio = to_serio_port(dev);
976 struct atkbd *atkbd;
977 int retval;
978
979 retval = serio_pin_driver(serio);
980 if (retval)
981 return retval;
982
983 if (serio->drv != &atkbd_drv) {
984 retval = -ENODEV;
985 goto out;
986 }
987
988 atkbd = serio_get_drvdata(serio);
989 atkbd_disable(atkbd);
990 retval = handler(atkbd, buf, count);
991 atkbd_enable(atkbd);
992
993out:
994 serio_unpin_driver(serio);
995 return retval;
996}
997
998static ssize_t atkbd_show_extra(struct atkbd *atkbd, char *buf)
999{
1000 return sprintf(buf, "%d\n", atkbd->extra ? 1 : 0);
1001}
1002
1003static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t count)
1004{
1005 unsigned long value;
1006 char *rest;
1007
1008 if (!atkbd->write)
1009 return -EIO;
1010
1011 value = simple_strtoul(buf, &rest, 10);
1012 if (*rest || value > 1)
1013 return -EINVAL;
1014
1015 if (atkbd->extra != value) {
1016 /* unregister device as it's properties will change */
1017 input_unregister_device(&atkbd->dev);
1018 atkbd->set = atkbd_select_set(atkbd, atkbd->set, value);
1019 atkbd_activate(atkbd);
1020 atkbd_set_device_attrs(atkbd);
1021 input_register_device(&atkbd->dev);
1022 }
1023 return count;
1024}
1025
1026static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf)
1027{
1028 return sprintf(buf, "%d\n", atkbd->scroll ? 1 : 0);
1029}
1030
1031static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t count)
1032{
1033 unsigned long value;
1034 char *rest;
1035
1036 value = simple_strtoul(buf, &rest, 10);
1037 if (*rest || value > 1)
1038 return -EINVAL;
1039
1040 if (atkbd->scroll != value) {
1041 /* unregister device as it's properties will change */
1042 input_unregister_device(&atkbd->dev);
1043 atkbd->scroll = value;
1044 atkbd_set_keycode_table(atkbd);
1045 atkbd_set_device_attrs(atkbd);
1046 input_register_device(&atkbd->dev);
1047 }
1048 return count;
1049}
1050
1051static ssize_t atkbd_show_set(struct atkbd *atkbd, char *buf)
1052{
1053 return sprintf(buf, "%d\n", atkbd->set);
1054}
1055
1056static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
1057{
1058 unsigned long value;
1059 char *rest;
1060
1061 if (!atkbd->write)
1062 return -EIO;
1063
1064 value = simple_strtoul(buf, &rest, 10);
1065 if (*rest || (value != 2 && value != 3))
1066 return -EINVAL;
1067
1068 if (atkbd->set != value) {
1069 /* unregister device as it's properties will change */
1070 input_unregister_device(&atkbd->dev);
1071 atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra);
1072 atkbd_activate(atkbd);
1073 atkbd_set_keycode_table(atkbd);
1074 atkbd_set_device_attrs(atkbd);
1075 input_register_device(&atkbd->dev);
1076 }
1077 return count;
1078}
1079
1080static ssize_t atkbd_show_softrepeat(struct atkbd *atkbd, char *buf)
1081{
1082 return sprintf(buf, "%d\n", atkbd->softrepeat ? 1 : 0);
1083}
1084
1085static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t count)
1086{
1087 unsigned long value;
1088 char *rest;
1089
1090 if (!atkbd->write)
1091 return -EIO;
1092
1093 value = simple_strtoul(buf, &rest, 10);
1094 if (*rest || value > 1)
1095 return -EINVAL;
1096
1097 if (atkbd->softrepeat != value) {
1098 /* unregister device as it's properties will change */
1099 input_unregister_device(&atkbd->dev);
1100 atkbd->softrepeat = value;
1101 if (atkbd->softrepeat)
1102 atkbd->softraw = 1;
1103 atkbd_set_device_attrs(atkbd);
1104 input_register_device(&atkbd->dev);
1105 }
1106
1107 return count;
1108}
1109
1110
1111static ssize_t atkbd_show_softraw(struct atkbd *atkbd, char *buf)
1112{
1113 return sprintf(buf, "%d\n", atkbd->softraw ? 1 : 0);
1114}
1115
1116static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t count)
1117{
1118 unsigned long value;
1119 char *rest;
1120
1121 value = simple_strtoul(buf, &rest, 10);
1122 if (*rest || value > 1)
1123 return -EINVAL;
1124
1125 if (atkbd->softraw != value) {
1126 /* unregister device as it's properties will change */
1127 input_unregister_device(&atkbd->dev);
1128 atkbd->softraw = value;
1129 atkbd_set_device_attrs(atkbd);
1130 input_register_device(&atkbd->dev);
1131 }
1132 return count;
1133}
1134
1135
1136static int __init atkbd_init(void)
1137{
1138 serio_register_driver(&atkbd_drv);
1139 return 0;
1140}
1141
1142static void __exit atkbd_exit(void)
1143{
1144 serio_unregister_driver(&atkbd_drv);
1145}
1146
1147module_init(atkbd_init);
1148module_exit(atkbd_exit);
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
new file mode 100644
index 000000000000..0f1220a0ceb5
--- /dev/null
+++ b/drivers/input/keyboard/corgikbd.c
@@ -0,0 +1,361 @@
1/*
2 * Keyboard driver for Sharp Corgi models (SL-C7xx)
3 *
4 * Copyright (c) 2004-2005 Richard Purdie
5 *
6 * Based on xtkbd.c/locomkbd.c
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 */
13
14#include <linux/delay.h>
15#include <linux/device.h>
16#include <linux/init.h>
17#include <linux/input.h>
18#include <linux/interrupt.h>
19#include <linux/module.h>
20#include <linux/slab.h>
21#include <asm/irq.h>
22
23#include <asm/arch/corgi.h>
24#include <asm/arch/hardware.h>
25#include <asm/arch/pxa-regs.h>
26#include <asm/hardware/scoop.h>
27
28#define KB_ROWS 8
29#define KB_COLS 12
30#define KB_ROWMASK(r) (1 << (r))
31#define SCANCODE(r,c) ( ((r)<<4) + (c) + 1 )
32/* zero code, 124 scancodes + 3 hinge combinations */
33#define NR_SCANCODES ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 +3 )
34#define SCAN_INTERVAL (HZ/10)
35#define CORGIKBD_PRESSED 1
36
37#define HINGE_SCAN_INTERVAL (HZ/4)
38
39#define CORGI_KEY_CALENDER KEY_F1
40#define CORGI_KEY_ADDRESS KEY_F2
41#define CORGI_KEY_FN KEY_F3
42#define CORGI_KEY_OFF KEY_SUSPEND
43#define CORGI_KEY_EXOK KEY_F5
44#define CORGI_KEY_EXCANCEL KEY_F6
45#define CORGI_KEY_EXJOGDOWN KEY_F7
46#define CORGI_KEY_EXJOGUP KEY_F8
47#define CORGI_KEY_JAP1 KEY_LEFTCTRL
48#define CORGI_KEY_JAP2 KEY_LEFTALT
49#define CORGI_KEY_OK KEY_F11
50#define CORGI_KEY_MENU KEY_F12
51#define CORGI_HINGE_0 KEY_KP0
52#define CORGI_HINGE_1 KEY_KP1
53#define CORGI_HINGE_2 KEY_KP2
54
55static unsigned char corgikbd_keycode[NR_SCANCODES] = {
56 0, /* 0 */
57 0, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, 0, 0, 0, 0, 0, 0, 0, /* 1-16 */
58 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, 0, 0, 0, 0, 0, 0, 0, /* 17-32 */
59 KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */
60 CORGI_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */
61 CORGI_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, /* 65-80 */
62 KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */
63 KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */
64 CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */
65 CORGI_HINGE_0, CORGI_HINGE_1, CORGI_HINGE_2 /* 125-127 */
66};
67
68
69struct corgikbd {
70 unsigned char keycode[ARRAY_SIZE(corgikbd_keycode)];
71 struct input_dev input;
72 char phys[32];
73
74 unsigned char state[ARRAY_SIZE(corgikbd_keycode)];
75 spinlock_t lock;
76
77 struct timer_list timer;
78 struct timer_list htimer;
79};
80
81static void handle_scancode(unsigned int pressed,unsigned int scancode, struct corgikbd *corgikbd_data)
82{
83 if (pressed && !(corgikbd_data->state[scancode] & CORGIKBD_PRESSED)) {
84 corgikbd_data->state[scancode] |= CORGIKBD_PRESSED;
85 input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 1);
86 if (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF)
87 input_event(&corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1);
88 } else if (!pressed && corgikbd_data->state[scancode] & CORGIKBD_PRESSED) {
89 corgikbd_data->state[scancode] &= ~CORGIKBD_PRESSED;
90 input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 0);
91 }
92}
93
94#define KB_DISCHARGE_DELAY 10
95#define KB_ACTIVATE_DELAY 10
96
97/* Helper functions for reading the keyboard matrix
98 * Note: We should really be using pxa_gpio_mode to alter GPDR but it
99 * requires a function call per GPIO bit which is excessive
100 * when we need to access 12 bits at once multiple times.
101 * These functions must be called within local_irq_save()/local_irq_restore()
102 * or similar.
103 */
104static inline void corgikbd_discharge_all(void)
105{
106 // STROBE All HiZ
107 GPCR2 = CORGI_GPIO_ALL_STROBE_BIT;
108 GPDR2 &= ~CORGI_GPIO_ALL_STROBE_BIT;
109}
110
111static inline void corgikbd_activate_all(void)
112{
113 // STROBE ALL -> High
114 GPSR2 = CORGI_GPIO_ALL_STROBE_BIT;
115 GPDR2 |= CORGI_GPIO_ALL_STROBE_BIT;
116
117 udelay(KB_DISCHARGE_DELAY);
118
119 // Clear any interrupts we may have triggered when altering the GPIO lines
120 GEDR1 = CORGI_GPIO_HIGH_SENSE_BIT;
121 GEDR2 = CORGI_GPIO_LOW_SENSE_BIT;
122}
123
124static inline void corgikbd_activate_col(int col)
125{
126 // STROBE col -> High, not col -> HiZ
127 GPSR2 = CORGI_GPIO_STROBE_BIT(col);
128 GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col);
129}
130
131static inline void corgikbd_reset_col(int col)
132{
133 // STROBE col -> Low
134 GPCR2 = CORGI_GPIO_STROBE_BIT(col);
135 // STROBE col -> out, not col -> HiZ
136 GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col);
137}
138
139#define GET_ROWS_STATUS(c) (((GPLR1 & CORGI_GPIO_HIGH_SENSE_BIT) >> CORGI_GPIO_HIGH_SENSE_RSHIFT) | ((GPLR2 & CORGI_GPIO_LOW_SENSE_BIT) << CORGI_GPIO_LOW_SENSE_LSHIFT))
140
141/*
142 * The corgi keyboard only generates interrupts when a key is pressed.
143 * When a key is pressed, we enable a timer which then scans the
144 * keyboard to detect when the key is released.
145 */
146
147/* Scan the hardware keyboard and push any changes up through the input layer */
148static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs *regs)
149{
150 unsigned int row, col, rowd, scancode;
151 unsigned long flags;
152 unsigned int num_pressed;
153
154 spin_lock_irqsave(&corgikbd_data->lock, flags);
155
156 if (regs)
157 input_regs(&corgikbd_data->input, regs);
158
159 num_pressed = 0;
160 for (col = 0; col < KB_COLS; col++) {
161 /*
162 * Discharge the output driver capacitatance
163 * in the keyboard matrix. (Yes it is significant..)
164 */
165
166 corgikbd_discharge_all();
167 udelay(KB_DISCHARGE_DELAY);
168
169 corgikbd_activate_col(col);
170 udelay(KB_ACTIVATE_DELAY);
171
172 rowd = GET_ROWS_STATUS(col);
173 for (row = 0; row < KB_ROWS; row++) {
174 scancode = SCANCODE(row, col);
175 handle_scancode((rowd & KB_ROWMASK(row)), scancode, corgikbd_data);
176 if (rowd & KB_ROWMASK(row))
177 num_pressed++;
178 }
179 corgikbd_reset_col(col);
180 }
181
182 corgikbd_activate_all();
183
184 input_sync(&corgikbd_data->input);
185
186 /* if any keys are pressed, enable the timer */
187 if (num_pressed)
188 mod_timer(&corgikbd_data->timer, jiffies + SCAN_INTERVAL);
189
190 spin_unlock_irqrestore(&corgikbd_data->lock, flags);
191}
192
193/*
194 * corgi keyboard interrupt handler.
195 */
196static irqreturn_t corgikbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
197{
198 struct corgikbd *corgikbd_data = dev_id;
199
200 if (!timer_pending(&corgikbd_data->timer)) {
201 /** wait chattering delay **/
202 udelay(20);
203 corgikbd_scankeyboard(corgikbd_data, regs);
204 }
205
206 return IRQ_HANDLED;
207}
208
209/*
210 * corgi timer checking for released keys
211 */
212static void corgikbd_timer_callback(unsigned long data)
213{
214 struct corgikbd *corgikbd_data = (struct corgikbd *) data;
215 corgikbd_scankeyboard(corgikbd_data, NULL);
216}
217
218/*
219 * The hinge switches generate no interrupt so they need to be
220 * monitored by a timer.
221 *
222 * When we detect changes, we debounce it and then pass the three
223 * positions the system can take as keypresses to the input system.
224 */
225
226#define HINGE_STABLE_COUNT 2
227static int sharpsl_hinge_state;
228static int hinge_count;
229
230static void corgikbd_hinge_timer(unsigned long data)
231{
232 struct corgikbd *corgikbd_data = (struct corgikbd *) data;
233 unsigned long gprr;
234 unsigned long flags;
235
236 gprr = read_scoop_reg(SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB);
237 if (gprr != sharpsl_hinge_state) {
238 hinge_count = 0;
239 sharpsl_hinge_state = gprr;
240 } else if (hinge_count < HINGE_STABLE_COUNT) {
241 hinge_count++;
242 if (hinge_count >= HINGE_STABLE_COUNT) {
243 spin_lock_irqsave(&corgikbd_data->lock, flags);
244
245 handle_scancode((sharpsl_hinge_state == 0x00), 125, corgikbd_data); /* Keyboard with Landscape Screen */
246 handle_scancode((sharpsl_hinge_state == 0x08), 126, corgikbd_data); /* No Keyboard with Portrait Screen */
247 handle_scancode((sharpsl_hinge_state == 0x0c), 127, corgikbd_data); /* Keyboard and Screen Closed */
248 input_sync(&corgikbd_data->input);
249
250 spin_unlock_irqrestore(&corgikbd_data->lock, flags);
251 }
252 }
253 mod_timer(&corgikbd_data->htimer, jiffies + HINGE_SCAN_INTERVAL);
254}
255
256static int __init corgikbd_probe(struct device *dev)
257{
258 int i;
259 struct corgikbd *corgikbd;
260
261 corgikbd = kcalloc(1, sizeof(struct corgikbd), GFP_KERNEL);
262 if (!corgikbd)
263 return -ENOMEM;
264
265 dev_set_drvdata(dev,corgikbd);
266 strcpy(corgikbd->phys, "corgikbd/input0");
267
268 spin_lock_init(corgikbd->lock);
269
270 /* Init Keyboard rescan timer */
271 init_timer(&corgikbd->timer);
272 corgikbd->timer.function = corgikbd_timer_callback;
273 corgikbd->timer.data = (unsigned long) corgikbd;
274
275 /* Init Hinge Timer */
276 init_timer(&corgikbd->htimer);
277 corgikbd->htimer.function = corgikbd_hinge_timer;
278 corgikbd->htimer.data = (unsigned long) corgikbd;
279
280 init_input_dev(&corgikbd->input);
281 corgikbd->input.private = corgikbd;
282 corgikbd->input.name = "Corgi Keyboard";
283 corgikbd->input.dev = dev;
284 corgikbd->input.phys = corgikbd->phys;
285 corgikbd->input.id.bustype = BUS_HOST;
286 corgikbd->input.id.vendor = 0x0001;
287 corgikbd->input.id.product = 0x0001;
288 corgikbd->input.id.version = 0x0100;
289 corgikbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR);
290 corgikbd->input.keycode = corgikbd->keycode;
291 corgikbd->input.keycodesize = sizeof(unsigned char);
292 corgikbd->input.keycodemax = ARRAY_SIZE(corgikbd_keycode);
293
294 memcpy(corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode));
295 for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)
296 set_bit(corgikbd->keycode[i], corgikbd->input.keybit);
297 clear_bit(0, corgikbd->input.keybit);
298
299 input_register_device(&corgikbd->input);
300 mod_timer(&corgikbd->htimer, jiffies + HINGE_SCAN_INTERVAL);
301
302 /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
303 for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) {
304 pxa_gpio_mode(CORGI_GPIO_KEY_SENSE(i) | GPIO_IN);
305 if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd_interrupt,
306 SA_INTERRUPT, "corgikbd", corgikbd))
307 printk(KERN_WARNING "corgikbd: Can't get IRQ: %d!\n", i);
308 else
309 set_irq_type(CORGI_IRQ_GPIO_KEY_SENSE(i),IRQT_RISING);
310 }
311
312 /* Set Strobe lines as outputs - set high */
313 for (i = 0; i < CORGI_KEY_STROBE_NUM; i++)
314 pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH);
315
316 printk(KERN_INFO "input: Corgi Keyboard Registered\n");
317
318 return 0;
319}
320
321static int corgikbd_remove(struct device *dev)
322{
323 int i;
324 struct corgikbd *corgikbd = dev_get_drvdata(dev);
325
326 for (i = 0; i < CORGI_KEY_SENSE_NUM; i++)
327 free_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd);
328
329 del_timer_sync(&corgikbd->htimer);
330 del_timer_sync(&corgikbd->timer);
331
332 input_unregister_device(&corgikbd->input);
333
334 kfree(corgikbd);
335
336 return 0;
337}
338
339static struct device_driver corgikbd_driver = {
340 .name = "corgi-keyboard",
341 .bus = &platform_bus_type,
342 .probe = corgikbd_probe,
343 .remove = corgikbd_remove,
344};
345
346static int __devinit corgikbd_init(void)
347{
348 return driver_register(&corgikbd_driver);
349}
350
351static void __exit corgikbd_exit(void)
352{
353 driver_unregister(&corgikbd_driver);
354}
355
356module_init(corgikbd_init);
357module_exit(corgikbd_exit);
358
359MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
360MODULE_DESCRIPTION("Corgi Keyboard Driver");
361MODULE_LICENSE("GPLv2");
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
new file mode 100644
index 000000000000..ef78bffed5e7
--- /dev/null
+++ b/drivers/input/keyboard/hil_kbd.c
@@ -0,0 +1,375 @@
1/*
2 * Generic linux-input device driver for keyboard devices
3 *
4 * Copyright (c) 2001 Brian S. Julin
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * Alternatively, this software may be distributed under the terms of the
17 * GNU General Public License ("GPL").
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 *
29 * References:
30 * HP-HIL Technical Reference Manual. Hewlett Packard Product No. 45918A
31 *
32 */
33
34#include <linux/hil.h>
35#include <linux/input.h>
36#include <linux/serio.h>
37#include <linux/kernel.h>
38#include <linux/module.h>
39#include <linux/init.h>
40#include <linux/slab.h>
41#include <linux/pci_ids.h>
42
43#define PREFIX "HIL KEYB: "
44#define HIL_GENERIC_NAME "HIL keyboard"
45
46MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
47MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver");
48MODULE_LICENSE("Dual BSD/GPL");
49
50#define HIL_KBD_MAX_LENGTH 16
51
52#define HIL_KBD_SET1_UPBIT 0x01
53#define HIL_KBD_SET1_SHIFT 1
54static unsigned int hil_kbd_set1[HIL_KEYCODES_SET1_TBLSIZE] =
55 { HIL_KEYCODES_SET1 };
56
57#define HIL_KBD_SET2_UPBIT 0x01
58#define HIL_KBD_SET2_SHIFT 1
59/* Set2 is user defined */
60
61#define HIL_KBD_SET3_UPBIT 0x80
62#define HIL_KBD_SET3_SHIFT 0
63static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] =
64 { HIL_KEYCODES_SET3 };
65
66static char hil_language[][16] = { HIL_LOCALE_MAP };
67
68struct hil_kbd {
69 struct input_dev dev;
70 struct serio *serio;
71
72 /* Input buffer and index for packets from HIL bus. */
73 hil_packet data[HIL_KBD_MAX_LENGTH];
74 int idx4; /* four counts per packet */
75
76 /* Raw device info records from HIL bus, see hil.h for fields. */
77 char idd[HIL_KBD_MAX_LENGTH]; /* DID byte and IDD record */
78 char rsc[HIL_KBD_MAX_LENGTH]; /* RSC record */
79 char exd[HIL_KBD_MAX_LENGTH]; /* EXD record */
80 char rnm[HIL_KBD_MAX_LENGTH + 1]; /* RNM record + NULL term. */
81
82 /* Something to sleep around with. */
83 struct semaphore sem;
84};
85
86/* Process a complete packet after transfer from the HIL */
87static void hil_kbd_process_record(struct hil_kbd *kbd)
88{
89 struct input_dev *dev = &kbd->dev;
90 hil_packet *data = kbd->data;
91 hil_packet p;
92 int idx, i, cnt;
93
94 idx = kbd->idx4/4;
95 p = data[idx - 1];
96
97 if ((p & ~HIL_CMDCT_POL) ==
98 (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report;
99 if ((p & ~HIL_CMDCT_RPL) ==
100 (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report;
101
102 /* Not a poll response. See if we are loading config records. */
103 switch (p & HIL_PKT_DATA_MASK) {
104 case HIL_CMD_IDD:
105 for (i = 0; i < idx; i++)
106 kbd->idd[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
107 for (; i < HIL_KBD_MAX_LENGTH; i++)
108 kbd->idd[i] = 0;
109 break;
110 case HIL_CMD_RSC:
111 for (i = 0; i < idx; i++)
112 kbd->rsc[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
113 for (; i < HIL_KBD_MAX_LENGTH; i++)
114 kbd->rsc[i] = 0;
115 break;
116 case HIL_CMD_EXD:
117 for (i = 0; i < idx; i++)
118 kbd->exd[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
119 for (; i < HIL_KBD_MAX_LENGTH; i++)
120 kbd->exd[i] = 0;
121 break;
122 case HIL_CMD_RNM:
123 for (i = 0; i < idx; i++)
124 kbd->rnm[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
125 for (; i < HIL_KBD_MAX_LENGTH + 1; i++)
126 kbd->rnm[i] = '\0';
127 break;
128 default:
129 /* These occur when device isn't present */
130 if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break;
131 /* Anything else we'd like to know about. */
132 printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p);
133 break;
134 }
135 goto out;
136
137 report:
138 cnt = 1;
139 switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) {
140 case HIL_POL_CHARTYPE_NONE:
141 break;
142 case HIL_POL_CHARTYPE_ASCII:
143 while (cnt < idx - 1)
144 input_report_key(dev, kbd->data[cnt++] & 0x7f, 1);
145 break;
146 case HIL_POL_CHARTYPE_RSVD1:
147 case HIL_POL_CHARTYPE_RSVD2:
148 case HIL_POL_CHARTYPE_BINARY:
149 while (cnt < idx - 1)
150 input_report_key(dev, kbd->data[cnt++], 1);
151 break;
152 case HIL_POL_CHARTYPE_SET1:
153 while (cnt < idx - 1) {
154 unsigned int key;
155 int up;
156 key = kbd->data[cnt++];
157 up = key & HIL_KBD_SET1_UPBIT;
158 key &= (~HIL_KBD_SET1_UPBIT & 0xff);
159 key = hil_kbd_set1[key >> HIL_KBD_SET1_SHIFT];
160 if (key != KEY_RESERVED)
161 input_report_key(dev, key, !up);
162 }
163 break;
164 case HIL_POL_CHARTYPE_SET2:
165 while (cnt < idx - 1) {
166 unsigned int key;
167 int up;
168 key = kbd->data[cnt++];
169 up = key & HIL_KBD_SET2_UPBIT;
170 key &= (~HIL_KBD_SET1_UPBIT & 0xff);
171 key = key >> HIL_KBD_SET2_SHIFT;
172 if (key != KEY_RESERVED)
173 input_report_key(dev, key, !up);
174 }
175 break;
176 case HIL_POL_CHARTYPE_SET3:
177 while (cnt < idx - 1) {
178 unsigned int key;
179 int up;
180 key = kbd->data[cnt++];
181 up = key & HIL_KBD_SET3_UPBIT;
182 key &= (~HIL_KBD_SET1_UPBIT & 0xff);
183 key = hil_kbd_set3[key >> HIL_KBD_SET3_SHIFT];
184 if (key != KEY_RESERVED)
185 input_report_key(dev, key, !up);
186 }
187 break;
188 }
189 out:
190 kbd->idx4 = 0;
191 up(&kbd->sem);
192}
193
194static void hil_kbd_process_err(struct hil_kbd *kbd) {
195 printk(KERN_WARNING PREFIX "errored HIL packet\n");
196 kbd->idx4 = 0;
197 up(&kbd->sem);
198}
199
200static irqreturn_t hil_kbd_interrupt(struct serio *serio,
201 unsigned char data, unsigned int flags, struct pt_regs *regs)
202{
203 struct hil_kbd *kbd;
204 hil_packet packet;
205 int idx;
206
207 kbd = (struct hil_kbd *)serio->private;
208 if (kbd == NULL) {
209 BUG();
210 return IRQ_HANDLED;
211 }
212
213 if (kbd->idx4 >= (HIL_KBD_MAX_LENGTH * sizeof(hil_packet))) {
214 hil_kbd_process_err(kbd);
215 return IRQ_HANDLED;
216 }
217 idx = kbd->idx4/4;
218 if (!(kbd->idx4 % 4)) kbd->data[idx] = 0;
219 packet = kbd->data[idx];
220 packet |= ((hil_packet)data) << ((3 - (kbd->idx4 % 4)) * 8);
221 kbd->data[idx] = packet;
222
223 /* Records of N 4-byte hil_packets must terminate with a command. */
224 if ((++(kbd->idx4)) % 4) return IRQ_HANDLED;
225 if ((packet & 0xffff0000) != HIL_ERR_INT) {
226 hil_kbd_process_err(kbd);
227 return IRQ_HANDLED;
228 }
229 if (packet & HIL_PKT_CMD) hil_kbd_process_record(kbd);
230 return IRQ_HANDLED;
231}
232
233static void hil_kbd_disconnect(struct serio *serio)
234{
235 struct hil_kbd *kbd;
236
237 kbd = (struct hil_kbd *)serio->private;
238 if (kbd == NULL) {
239 BUG();
240 return;
241 }
242
243 input_unregister_device(&kbd->dev);
244 serio_close(serio);
245 kfree(kbd);
246}
247
248static void hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
249{
250 struct hil_kbd *kbd;
251 uint8_t did, *idd;
252 int i;
253
254 if (serio->type != (SERIO_HIL_MLC | SERIO_HIL)) return;
255
256 if (!(kbd = kmalloc(sizeof(struct hil_kbd), GFP_KERNEL))) return;
257 memset(kbd, 0, sizeof(struct hil_kbd));
258
259 if (serio_open(serio, drv)) goto bail0;
260
261 serio->private = kbd;
262 kbd->serio = serio;
263 kbd->dev.private = kbd;
264
265 init_MUTEX_LOCKED(&(kbd->sem));
266
267 /* Get device info. MLC driver supplies devid/status/etc. */
268 serio->write(serio, 0);
269 serio->write(serio, 0);
270 serio->write(serio, HIL_PKT_CMD >> 8);
271 serio->write(serio, HIL_CMD_IDD);
272 down(&(kbd->sem));
273
274 serio->write(serio, 0);
275 serio->write(serio, 0);
276 serio->write(serio, HIL_PKT_CMD >> 8);
277 serio->write(serio, HIL_CMD_RSC);
278 down(&(kbd->sem));
279
280 serio->write(serio, 0);
281 serio->write(serio, 0);
282 serio->write(serio, HIL_PKT_CMD >> 8);
283 serio->write(serio, HIL_CMD_RNM);
284 down(&(kbd->sem));
285
286 serio->write(serio, 0);
287 serio->write(serio, 0);
288 serio->write(serio, HIL_PKT_CMD >> 8);
289 serio->write(serio, HIL_CMD_EXD);
290 down(&(kbd->sem));
291
292 up(&(kbd->sem));
293
294 did = kbd->idd[0];
295 idd = kbd->idd + 1;
296 switch (did & HIL_IDD_DID_TYPE_MASK) {
297 case HIL_IDD_DID_TYPE_KB_INTEGRAL:
298 case HIL_IDD_DID_TYPE_KB_ITF:
299 case HIL_IDD_DID_TYPE_KB_RSVD:
300 case HIL_IDD_DID_TYPE_CHAR:
301 printk(KERN_INFO PREFIX "HIL keyboard found (did = 0x%02x, lang = %s)\n",
302 did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]);
303 break;
304 default:
305 goto bail1;
306 }
307
308 if(HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) {
309 printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n");
310 goto bail1;
311 }
312
313
314 kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
315 kbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
316 kbd->dev.keycodemax = HIL_KEYCODES_SET1_TBLSIZE;
317 kbd->dev.keycodesize = sizeof(hil_kbd_set1[0]);
318 kbd->dev.keycode = hil_kbd_set1;
319 kbd->dev.name = strlen(kbd->rnm) ? kbd->rnm : HIL_GENERIC_NAME;
320 kbd->dev.phys = "hpkbd/input0"; /* XXX */
321
322 kbd->dev.id.bustype = BUS_HIL;
323 kbd->dev.id.vendor = PCI_VENDOR_ID_HP;
324 kbd->dev.id.product = 0x0001; /* TODO: get from kbd->rsc */
325 kbd->dev.id.version = 0x0100; /* TODO: get from kbd->rsc */
326 kbd->dev.dev = &serio->dev;
327
328 for (i = 0; i < 128; i++) {
329 set_bit(hil_kbd_set1[i], kbd->dev.keybit);
330 set_bit(hil_kbd_set3[i], kbd->dev.keybit);
331 }
332 clear_bit(0, kbd->dev.keybit);
333
334 input_register_device(&kbd->dev);
335 printk(KERN_INFO "input: %s, ID: %d\n",
336 kbd->dev.name, did);
337
338 serio->write(serio, 0);
339 serio->write(serio, 0);
340 serio->write(serio, HIL_PKT_CMD >> 8);
341 serio->write(serio, HIL_CMD_EK1); /* Enable Keyswitch Autorepeat 1 */
342 down(&(kbd->sem));
343 up(&(kbd->sem));
344
345 return;
346 bail1:
347 serio_close(serio);
348 bail0:
349 kfree(kbd);
350}
351
352
353struct serio_driver hil_kbd_serio_drv = {
354 .driver = {
355 .name = "hil_kbd",
356 },
357 .description = "HP HIL keyboard driver",
358 .connect = hil_kbd_connect,
359 .disconnect = hil_kbd_disconnect,
360 .interrupt = hil_kbd_interrupt
361};
362
363static int __init hil_kbd_init(void)
364{
365 serio_register_driver(&hil_kbd_serio_drv);
366 return 0;
367}
368
369static void __exit hil_kbd_exit(void)
370{
371 serio_unregister_driver(&hil_kbd_serio_drv);
372}
373
374module_init(hil_kbd_init);
375module_exit(hil_kbd_exit);
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c
new file mode 100644
index 000000000000..eecb77db0847
--- /dev/null
+++ b/drivers/input/keyboard/hilkbd.c
@@ -0,0 +1,343 @@
1/*
2 * linux/drivers/hil/hilkbd.c
3 *
4 * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
5 * Copyright (C) 1999 Matthew Wilcox <willy@bofh.ai>
6 * Copyright (C) 1999-2003 Helge Deller <deller@gmx.de>
7 *
8 * Very basic HP Human Interface Loop (HIL) driver.
9 * This driver handles the keyboard on HP300 (m68k) and on some
10 * HP700 (parisc) series machines.
11 *
12 *
13 * This file is subject to the terms and conditions of the GNU General Public
14 * License version 2. See the file COPYING in the main directory of this
15 * archive for more details.
16 */
17
18#include <linux/pci_ids.h>
19#include <linux/ioport.h>
20#include <linux/module.h>
21#include <linux/config.h>
22#include <linux/errno.h>
23#include <linux/input.h>
24#include <linux/init.h>
25#include <linux/irq.h>
26#include <linux/hil.h>
27#include <linux/spinlock.h>
28
29
30MODULE_AUTHOR("Philip Blundell, Matthew Wilcox, Helge Deller");
31MODULE_DESCRIPTION("HIL keyboard driver (basic functionality)");
32MODULE_LICENSE("GPL v2");
33
34
35#if defined(CONFIG_PARISC)
36
37 #include <asm/io.h>
38 #include <asm/hardware.h>
39 #include <asm/parisc-device.h>
40 static unsigned long hil_base; /* HPA for the HIL device */
41 static unsigned int hil_irq;
42 #define HILBASE hil_base /* HPPA (parisc) port address */
43 #define HIL_DATA 0x800
44 #define HIL_CMD 0x801
45 #define HIL_IRQ hil_irq
46 #define hil_readb(p) gsc_readb(p)
47 #define hil_writeb(v,p) gsc_writeb((v),(p))
48
49#elif defined(CONFIG_HP300)
50
51 #define HILBASE 0xf0428000 /* HP300 (m86k) port address */
52 #define HIL_DATA 0x1
53 #define HIL_CMD 0x3
54 #define HIL_IRQ 2
55 #define hil_readb(p) readb(p)
56 #define hil_writeb(v,p) writeb((v),(p))
57
58#else
59#error "HIL is not supported on this platform"
60#endif
61
62
63
64/* HIL helper functions */
65
66#define hil_busy() (hil_readb(HILBASE + HIL_CMD) & HIL_BUSY)
67#define hil_data_available() (hil_readb(HILBASE + HIL_CMD) & HIL_DATA_RDY)
68#define hil_status() (hil_readb(HILBASE + HIL_CMD))
69#define hil_command(x) do { hil_writeb((x), HILBASE + HIL_CMD); } while (0)
70#define hil_read_data() (hil_readb(HILBASE + HIL_DATA))
71#define hil_write_data(x) do { hil_writeb((x), HILBASE + HIL_DATA); } while (0)
72
73/* HIL constants */
74
75#define HIL_BUSY 0x02
76#define HIL_DATA_RDY 0x01
77
78#define HIL_SETARD 0xA0 /* set auto-repeat delay */
79#define HIL_SETARR 0xA2 /* set auto-repeat rate */
80#define HIL_SETTONE 0xA3 /* set tone generator */
81#define HIL_CNMT 0xB2 /* clear nmi */
82#define HIL_INTON 0x5C /* Turn on interrupts. */
83#define HIL_INTOFF 0x5D /* Turn off interrupts. */
84
85#define HIL_READKBDSADR 0xF9
86#define HIL_WRITEKBDSADR 0xE9
87
88static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] =
89 { HIL_KEYCODES_SET1 };
90
91/* HIL structure */
92static struct {
93 struct input_dev dev;
94
95 unsigned int curdev;
96
97 unsigned char s;
98 unsigned char c;
99 int valid;
100
101 unsigned char data[16];
102 unsigned int ptr;
103 spinlock_t lock;
104
105 void *dev_id; /* native bus device */
106} hil_dev;
107
108
109static void poll_finished(void)
110{
111 int down;
112 int key;
113 unsigned char scode;
114
115 switch (hil_dev.data[0]) {
116 case 0x40:
117 down = (hil_dev.data[1] & 1) == 0;
118 scode = hil_dev.data[1] >> 1;
119 key = hphilkeyb_keycode[scode];
120 input_report_key(&hil_dev.dev, key, down);
121 break;
122 }
123 hil_dev.curdev = 0;
124}
125
126static inline void handle_status(unsigned char s, unsigned char c)
127{
128 if (c & 0x8) {
129 /* End of block */
130 if (c & 0x10)
131 poll_finished();
132 } else {
133 if (c & 0x10) {
134 if (hil_dev.curdev)
135 poll_finished(); /* just in case */
136 hil_dev.curdev = c & 7;
137 hil_dev.ptr = 0;
138 }
139 }
140}
141
142static inline void handle_data(unsigned char s, unsigned char c)
143{
144 if (hil_dev.curdev) {
145 hil_dev.data[hil_dev.ptr++] = c;
146 hil_dev.ptr &= 15;
147 }
148}
149
150
151/*
152 * Handle HIL interrupts.
153 */
154static irqreturn_t hil_interrupt(int irq, void *handle, struct pt_regs *regs)
155{
156 unsigned char s, c;
157
158 s = hil_status();
159 c = hil_read_data();
160
161 switch (s >> 4) {
162 case 0x5:
163 handle_status(s, c);
164 break;
165 case 0x6:
166 handle_data(s, c);
167 break;
168 case 0x4:
169 hil_dev.s = s;
170 hil_dev.c = c;
171 mb();
172 hil_dev.valid = 1;
173 break;
174 }
175 return IRQ_HANDLED;
176}
177
178/*
179 * Send a command to the HIL
180 */
181
182static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len)
183{
184 unsigned long flags;
185
186 spin_lock_irqsave(&hil_dev.lock, flags);
187 while (hil_busy())
188 /* wait */;
189 hil_command(cmd);
190 while (len--) {
191 while (hil_busy())
192 /* wait */;
193 hil_write_data(*(data++));
194 }
195 spin_unlock_irqrestore(&hil_dev.lock, flags);
196}
197
198
199/*
200 * Initialise HIL.
201 */
202
203static int __init
204hil_keyb_init(void)
205{
206 unsigned char c;
207 unsigned int i, kbid;
208 wait_queue_head_t hil_wait;
209
210 if (hil_dev.dev.id.bustype) {
211 return -ENODEV; /* already initialized */
212 }
213
214#if defined(CONFIG_HP300)
215 if (!hwreg_present((void *)(HILBASE + HIL_DATA)))
216 return -ENODEV;
217
218 request_region(HILBASE+HIL_DATA, 2, "hil");
219#endif
220
221 request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id);
222
223 /* Turn on interrupts */
224 hil_do(HIL_INTON, NULL, 0);
225
226 /* Look for keyboards */
227 hil_dev.valid = 0; /* clear any pending data */
228 hil_do(HIL_READKBDSADR, NULL, 0);
229
230 init_waitqueue_head(&hil_wait);
231 wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3*HZ);
232 if (!hil_dev.valid) {
233 printk(KERN_WARNING "HIL: timed out, assuming no keyboard present.\n");
234 }
235
236 c = hil_dev.c;
237 hil_dev.valid = 0;
238 if (c == 0) {
239 kbid = -1;
240 printk(KERN_WARNING "HIL: no keyboard present.\n");
241 } else {
242 kbid = ffz(~c);
243 /* printk(KERN_INFO "HIL: keyboard found at id %d\n", kbid); */
244 }
245
246 /* set it to raw mode */
247 c = 0;
248 hil_do(HIL_WRITEKBDSADR, &c, 1);
249
250 init_input_dev(&hil_dev.dev);
251
252 for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++)
253 if (hphilkeyb_keycode[i] != KEY_RESERVED)
254 set_bit(hphilkeyb_keycode[i], hil_dev.dev.keybit);
255
256 hil_dev.dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
257 hil_dev.dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
258 hil_dev.dev.keycodemax = HIL_KEYCODES_SET1_TBLSIZE;
259 hil_dev.dev.keycodesize = sizeof(hphilkeyb_keycode[0]);
260 hil_dev.dev.keycode = hphilkeyb_keycode;
261 hil_dev.dev.name = "HIL keyboard";
262 hil_dev.dev.phys = "hpkbd/input0";
263
264 hil_dev.dev.id.bustype = BUS_HIL;
265 hil_dev.dev.id.vendor = PCI_VENDOR_ID_HP;
266 hil_dev.dev.id.product = 0x0001;
267 hil_dev.dev.id.version = 0x0010;
268
269 input_register_device(&hil_dev.dev);
270 printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n",
271 hil_dev.dev.name, kbid, HILBASE, HIL_IRQ);
272
273 return 0;
274}
275
276#if defined(CONFIG_PARISC)
277static int __init
278hil_init_chip(struct parisc_device *dev)
279{
280 if (!dev->irq) {
281 printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%08lx\n", dev->hpa);
282 return -ENODEV;
283 }
284
285 hil_base = dev->hpa;
286 hil_irq = dev->irq;
287 hil_dev.dev_id = dev;
288
289 printk(KERN_INFO "Found HIL bus at 0x%08lx, IRQ %d\n", hil_base, hil_irq);
290
291 return hil_keyb_init();
292}
293
294static struct parisc_device_id hil_tbl[] = {
295 { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00073 },
296 { 0, }
297};
298
299MODULE_DEVICE_TABLE(parisc, hil_tbl);
300
301static struct parisc_driver hil_driver = {
302 .name = "HIL",
303 .id_table = hil_tbl,
304 .probe = hil_init_chip,
305};
306#endif /* CONFIG_PARISC */
307
308
309
310
311
312static int __init hil_init(void)
313{
314#if defined(CONFIG_PARISC)
315 return register_parisc_driver(&hil_driver);
316#else
317 return hil_keyb_init();
318#endif
319}
320
321
322static void __exit hil_exit(void)
323{
324 if (HIL_IRQ) {
325 disable_irq(HIL_IRQ);
326 free_irq(HIL_IRQ, hil_dev.dev_id);
327 }
328
329 /* Turn off interrupts */
330 hil_do(HIL_INTOFF, NULL, 0);
331
332 input_unregister_device(&hil_dev.dev);
333
334#if defined(CONFIG_PARISC)
335 unregister_parisc_driver(&hil_driver);
336#else
337 release_region(HILBASE+HIL_DATA, 2);
338#endif
339}
340
341module_init(hil_init);
342module_exit(hil_exit);
343
diff --git a/drivers/input/keyboard/hpps2atkbd.h b/drivers/input/keyboard/hpps2atkbd.h
new file mode 100644
index 000000000000..dc33f6945222
--- /dev/null
+++ b/drivers/input/keyboard/hpps2atkbd.h
@@ -0,0 +1,110 @@
1/*
2 * drivers/input/keyboard/hpps2atkbd.h
3 *
4 * Copyright (c) 2004 Helge Deller <deller@gmx.de>
5 * Copyright (c) 2002 Laurent Canet <canetl@esiee.fr>
6 * Copyright (c) 2002 Thibaut Varene <varenet@parisc-linux.org>
7 * Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr>
8 *
9 * HP PS/2 AT-compatible Keyboard, found in PA/RISC Workstations & Laptops
10 *
11 * This file is subject to the terms and conditions of the GNU General Public
12 * License. See the file "COPYING" in the main directory of this archive
13 * for more details.
14 */
15
16
17/* Is the keyboard an RDI PrecisionBook? */
18#ifndef CONFIG_KEYBOARD_ATKBD_RDI_KEYCODES
19# define CONFLICT(x,y) x
20#else
21# define CONFLICT(x,y) y
22#endif
23
24/* sadly RDI (Tadpole) decided to ship a different keyboard layout
25 than HP for their PS/2 laptop keyboard which leads to conflicting
26 keycodes between a normal HP PS/2 keyboard and a RDI Precisionbook.
27 HP: RDI: */
28#define C_07 CONFLICT( KEY_F12, KEY_F1 )
29#define C_11 CONFLICT( KEY_LEFTALT, KEY_LEFTCTRL )
30#define C_14 CONFLICT( KEY_LEFTCTRL, KEY_CAPSLOCK )
31#define C_58 CONFLICT( KEY_CAPSLOCK, KEY_RIGHTCTRL )
32#define C_61 CONFLICT( KEY_102ND, KEY_LEFT )
33
34/* Raw SET 2 scancode table */
35
36/* 00 */ KEY_RESERVED, KEY_F9, KEY_RESERVED, KEY_F5, KEY_F3, KEY_F1, KEY_F2, C_07,
37/* 08 */ KEY_ESC, KEY_F10, KEY_F8, KEY_F6, KEY_F4, KEY_TAB, KEY_GRAVE, KEY_F2,
38/* 10 */ KEY_RESERVED, C_11, KEY_LEFTSHIFT, KEY_RESERVED, C_14, KEY_Q, KEY_1, KEY_F3,
39/* 18 */ KEY_RESERVED, KEY_LEFTALT, KEY_Z, KEY_S, KEY_A, KEY_W, KEY_2, KEY_F4,
40/* 20 */ KEY_RESERVED, KEY_C, KEY_X, KEY_D, KEY_E, KEY_4, KEY_3, KEY_F5,
41/* 28 */ KEY_RESERVED, KEY_SPACE, KEY_V, KEY_F, KEY_T, KEY_R, KEY_5, KEY_F6,
42/* 30 */ KEY_RESERVED, KEY_N, KEY_B, KEY_H, KEY_G, KEY_Y, KEY_6, KEY_F7,
43/* 38 */ KEY_RESERVED, KEY_RIGHTALT, KEY_M, KEY_J, KEY_U, KEY_7, KEY_8, KEY_F8,
44/* 40 */ KEY_RESERVED, KEY_COMMA, KEY_K, KEY_I, KEY_O, KEY_0, KEY_9, KEY_F9,
45/* 48 */ KEY_RESERVED, KEY_DOT, KEY_SLASH, KEY_L, KEY_SEMICOLON, KEY_P, KEY_MINUS, KEY_F10,
46/* 50 */ KEY_RESERVED, KEY_RESERVED, KEY_APOSTROPHE,KEY_RESERVED, KEY_LEFTBRACE, KEY_EQUAL, KEY_F11, KEY_SYSRQ,
47/* 58 */ C_58, KEY_RIGHTSHIFT,KEY_ENTER, KEY_RIGHTBRACE,KEY_BACKSLASH, KEY_BACKSLASH,KEY_F12, KEY_SCROLLLOCK,
48/* 60 */ KEY_DOWN, C_61, KEY_PAUSE, KEY_UP, KEY_DELETE, KEY_END, KEY_BACKSPACE, KEY_INSERT,
49/* 68 */ KEY_RESERVED, KEY_KP1, KEY_RIGHT, KEY_KP4, KEY_KP7, KEY_PAGEDOWN, KEY_HOME, KEY_PAGEUP,
50/* 70 */ KEY_KP0, KEY_KPDOT, KEY_KP2, KEY_KP5, KEY_KP6, KEY_KP8, KEY_ESC, KEY_NUMLOCK,
51/* 78 */ KEY_F11, KEY_KPPLUS, KEY_KP3, KEY_KPMINUS, KEY_KPASTERISK,KEY_KP9, KEY_SCROLLLOCK,KEY_102ND,
52/* 80 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
53/* 88 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
54/* 90 */ KEY_RESERVED, KEY_RIGHTALT, 255, KEY_RESERVED, KEY_RIGHTCTRL, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
55/* 98 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_CAPSLOCK, KEY_RESERVED, KEY_LEFTMETA,
56/* a0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RIGHTMETA,
57/* a8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_COMPOSE,
58/* b0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
59/* b8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
60/* c0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
61/* c8 */ KEY_RESERVED, KEY_RESERVED, KEY_KPSLASH, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
62/* d0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
63/* d8 */ KEY_RESERVED, KEY_RESERVED, KEY_KPENTER, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
64/* e0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
65/* e8 */ KEY_RESERVED, KEY_END, KEY_RESERVED, KEY_LEFT, KEY_HOME, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
66/* f0 */ KEY_INSERT, KEY_DELETE, KEY_DOWN, KEY_RESERVED, KEY_RIGHT, KEY_UP, KEY_RESERVED, KEY_PAUSE,
67/* f8 */ KEY_RESERVED, KEY_RESERVED, KEY_PAGEDOWN, KEY_RESERVED, KEY_SYSRQ, KEY_PAGEUP, KEY_RESERVED, KEY_RESERVED,
68
69/* These are offset for escaped keycodes: */
70
71/* 00 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_F7, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
72/* 08 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_LEFTMETA, KEY_RIGHTMETA, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
73/* 10 */ KEY_RESERVED, KEY_RIGHTALT, KEY_RESERVED, KEY_RESERVED, KEY_RIGHTCTRL, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
74/* 18 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
75/* 20 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
76/* 28 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
77/* 30 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
78/* 38 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
79/* 40 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
80/* 48 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
81/* 50 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
82/* 58 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
83/* 60 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
84/* 68 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
85/* 70 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
86/* 78 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
87/* 80 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
88/* 88 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
89/* 90 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
90/* 98 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
91/* a0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
92/* a8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
93/* b0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
94/* b8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
95/* c0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
96/* c8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
97/* d0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
98/* d8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
99/* e0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
100/* e8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
101/* f0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
102/* f8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED
103
104#undef CONFLICT
105#undef C_07
106#undef C_11
107#undef C_14
108#undef C_58
109#undef C_61
110
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c
new file mode 100644
index 000000000000..2694ff2b5beb
--- /dev/null
+++ b/drivers/input/keyboard/lkkbd.c
@@ -0,0 +1,752 @@
1/*
2 * Copyright (C) 2004 by Jan-Benedict Glaw <jbglaw@lug-owl.de>
3 */
4
5/*
6 * LK keyboard driver for Linux, based on sunkbd.c (C) by Vojtech Pavlik
7 */
8
9/*
10 * DEC LK201 and LK401 keyboard driver for Linux (primary for DECstations
11 * and VAXstations, but can also be used on any standard RS232 with an
12 * adaptor).
13 *
14 * DISCLAIMER: This works for _me_. If you break anything by using the
15 * information given below, I will _not_ be liable!
16 *
17 * RJ10 pinout: To DE9: Or DB25:
18 * 1 - RxD <----> Pin 3 (TxD) <-> Pin 2 (TxD)
19 * 2 - GND <----> Pin 5 (GND) <-> Pin 7 (GND)
20 * 4 - TxD <----> Pin 2 (RxD) <-> Pin 3 (RxD)
21 * 3 - +12V (from HDD drive connector), DON'T connect to DE9 or DB25!!!
22 *
23 * Pin numbers for DE9 and DB25 are noted on the plug (quite small:). For
24 * RJ10, it's like this:
25 *
26 * __=__ Hold the plug in front of you, cable downwards,
27 * /___/| nose is hidden behind the plug. Now, pin 1 is at
28 * |1234|| the left side, pin 4 at the right and 2 and 3 are
29 * |IIII|| in between, of course:)
30 * | ||
31 * |____|/
32 * || So the adaptor consists of three connected cables
33 * || for data transmission (RxD and TxD) and signal ground.
34 * Additionally, you have to get +12V from somewhere.
35 * Most easily, you'll get that from a floppy or HDD power connector.
36 * It's the yellow cable there (black is ground and red is +5V).
37 *
38 * The keyboard and all the commands it understands are documented in
39 * "VCB02 Video Subsystem - Technical Manual", EK-104AA-TM-001. This
40 * document is LK201 specific, but LK401 is mostly compatible. It comes
41 * up in LK201 mode and doesn't report any of the additional keys it
42 * has. These need to be switched on with the LK_CMD_ENABLE_LK401
43 * command. You'll find this document (scanned .pdf file) on MANX,
44 * a search engine specific to DEC documentation. Try
45 * http://www.vt100.net/manx/details?pn=EK-104AA-TM-001;id=21;cp=1
46 */
47
48/*
49 * This program is free software; you can redistribute it and/or modify
50 * it under the terms of the GNU General Public License as published by
51 * the Free Software Foundation; either version 2 of the License, or
52 * (at your option) any later version.
53 *
54 * This program is distributed in the hope that it will be useful,
55 * but WITHOUT ANY WARRANTY; without even the implied warranty of
56 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57 * GNU General Public License for more details.
58 *
59 * You should have received a copy of the GNU General Public License
60 * along with this program; if not, write to the Free Software
61 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
62 *
63 * Should you need to contact me, the author, you can do so either by
64 * email or by paper mail:
65 * Jan-Benedict Glaw, Lilienstraße 16, 33790 Hörste (near Halle/Westf.),
66 * Germany.
67 */
68
69#include <linux/delay.h>
70#include <linux/slab.h>
71#include <linux/module.h>
72#include <linux/moduleparam.h>
73#include <linux/interrupt.h>
74#include <linux/init.h>
75#include <linux/input.h>
76#include <linux/serio.h>
77#include <linux/workqueue.h>
78
79#define DRIVER_DESC "LK keyboard driver"
80
81MODULE_AUTHOR ("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
82MODULE_DESCRIPTION (DRIVER_DESC);
83MODULE_LICENSE ("GPL");
84
85/*
86 * Known parameters:
87 * bell_volume
88 * keyclick_volume
89 * ctrlclick_volume
90 *
91 * Please notice that there's not yet an API to set these at runtime.
92 */
93static int bell_volume = 100; /* % */
94module_param (bell_volume, int, 0);
95MODULE_PARM_DESC (bell_volume, "Bell volume (in %). default is 100%");
96
97static int keyclick_volume = 100; /* % */
98module_param (keyclick_volume, int, 0);
99MODULE_PARM_DESC (keyclick_volume, "Keyclick volume (in %), default is 100%");
100
101static int ctrlclick_volume = 100; /* % */
102module_param (ctrlclick_volume, int, 0);
103MODULE_PARM_DESC (ctrlclick_volume, "Ctrlclick volume (in %), default is 100%");
104
105static int lk201_compose_is_alt = 0;
106module_param (lk201_compose_is_alt, int, 0);
107MODULE_PARM_DESC (lk201_compose_is_alt, "If set non-zero, LK201' Compose key "
108 "will act as an Alt key");
109
110
111
112#undef LKKBD_DEBUG
113#ifdef LKKBD_DEBUG
114#define DBG(x...) printk (x)
115#else
116#define DBG(x...) do {} while (0)
117#endif
118
119/* LED control */
120#define LK_LED_WAIT 0x81
121#define LK_LED_COMPOSE 0x82
122#define LK_LED_SHIFTLOCK 0x84
123#define LK_LED_SCROLLLOCK 0x88
124#define LK_CMD_LED_ON 0x13
125#define LK_CMD_LED_OFF 0x11
126
127/* Mode control */
128#define LK_MODE_DOWN 0x80
129#define LK_MODE_AUTODOWN 0x82
130#define LK_MODE_UPDOWN 0x86
131#define LK_CMD_SET_MODE(mode,div) ((mode) | ((div) << 3))
132
133/* Misc commands */
134#define LK_CMD_ENABLE_KEYCLICK 0x1b
135#define LK_CMD_DISABLE_KEYCLICK 0x99
136#define LK_CMD_DISABLE_BELL 0xa1
137#define LK_CMD_SOUND_BELL 0xa7
138#define LK_CMD_ENABLE_BELL 0x23
139#define LK_CMD_DISABLE_CTRCLICK 0xb9
140#define LK_CMD_ENABLE_CTRCLICK 0xbb
141#define LK_CMD_SET_DEFAULTS 0xd3
142#define LK_CMD_POWERCYCLE_RESET 0xfd
143#define LK_CMD_ENABLE_LK401 0xe9
144#define LK_CMD_REQUEST_ID 0xab
145
146/* Misc responses from keyboard */
147#define LK_STUCK_KEY 0x3d
148#define LK_SELFTEST_FAILED 0x3e
149#define LK_ALL_KEYS_UP 0xb3
150#define LK_METRONOME 0xb4
151#define LK_OUTPUT_ERROR 0xb5
152#define LK_INPUT_ERROR 0xb6
153#define LK_KBD_LOCKED 0xb7
154#define LK_KBD_TEST_MODE_ACK 0xb8
155#define LK_PREFIX_KEY_DOWN 0xb9
156#define LK_MODE_CHANGE_ACK 0xba
157#define LK_RESPONSE_RESERVED 0xbb
158
159#define LK_NUM_KEYCODES 256
160#define LK_NUM_IGNORE_BYTES 6
161typedef u_int16_t lk_keycode_t;
162
163
164
165static lk_keycode_t lkkbd_keycode[LK_NUM_KEYCODES] = {
166 [0x56] = KEY_F1,
167 [0x57] = KEY_F2,
168 [0x58] = KEY_F3,
169 [0x59] = KEY_F4,
170 [0x5a] = KEY_F5,
171 [0x64] = KEY_F6,
172 [0x65] = KEY_F7,
173 [0x66] = KEY_F8,
174 [0x67] = KEY_F9,
175 [0x68] = KEY_F10,
176 [0x71] = KEY_F11,
177 [0x72] = KEY_F12,
178 [0x73] = KEY_F13,
179 [0x74] = KEY_F14,
180 [0x7c] = KEY_F15,
181 [0x7d] = KEY_F16,
182 [0x80] = KEY_F17,
183 [0x81] = KEY_F18,
184 [0x82] = KEY_F19,
185 [0x83] = KEY_F20,
186 [0x8a] = KEY_FIND,
187 [0x8b] = KEY_INSERT,
188 [0x8c] = KEY_DELETE,
189 [0x8d] = KEY_SELECT,
190 [0x8e] = KEY_PAGEUP,
191 [0x8f] = KEY_PAGEDOWN,
192 [0x92] = KEY_KP0,
193 [0x94] = KEY_KPDOT,
194 [0x95] = KEY_KPENTER,
195 [0x96] = KEY_KP1,
196 [0x97] = KEY_KP2,
197 [0x98] = KEY_KP3,
198 [0x99] = KEY_KP4,
199 [0x9a] = KEY_KP5,
200 [0x9b] = KEY_KP6,
201 [0x9c] = KEY_KPCOMMA,
202 [0x9d] = KEY_KP7,
203 [0x9e] = KEY_KP8,
204 [0x9f] = KEY_KP9,
205 [0xa0] = KEY_KPMINUS,
206 [0xa1] = KEY_PROG1,
207 [0xa2] = KEY_PROG2,
208 [0xa3] = KEY_PROG3,
209 [0xa4] = KEY_PROG4,
210 [0xa7] = KEY_LEFT,
211 [0xa8] = KEY_RIGHT,
212 [0xa9] = KEY_DOWN,
213 [0xaa] = KEY_UP,
214 [0xab] = KEY_RIGHTSHIFT,
215 [0xac] = KEY_LEFTALT,
216 [0xad] = KEY_COMPOSE, /* Right Compose, that is. */
217 [0xae] = KEY_LEFTSHIFT, /* Same as KEY_RIGHTSHIFT on LK201 */
218 [0xaf] = KEY_LEFTCTRL,
219 [0xb0] = KEY_CAPSLOCK,
220 [0xb1] = KEY_COMPOSE, /* Left Compose, that is. */
221 [0xb2] = KEY_RIGHTALT,
222 [0xbc] = KEY_BACKSPACE,
223 [0xbd] = KEY_ENTER,
224 [0xbe] = KEY_TAB,
225 [0xbf] = KEY_ESC,
226 [0xc0] = KEY_1,
227 [0xc1] = KEY_Q,
228 [0xc2] = KEY_A,
229 [0xc3] = KEY_Z,
230 [0xc5] = KEY_2,
231 [0xc6] = KEY_W,
232 [0xc7] = KEY_S,
233 [0xc8] = KEY_X,
234 [0xc9] = KEY_102ND,
235 [0xcb] = KEY_3,
236 [0xcc] = KEY_E,
237 [0xcd] = KEY_D,
238 [0xce] = KEY_C,
239 [0xd0] = KEY_4,
240 [0xd1] = KEY_R,
241 [0xd2] = KEY_F,
242 [0xd3] = KEY_V,
243 [0xd4] = KEY_SPACE,
244 [0xd6] = KEY_5,
245 [0xd7] = KEY_T,
246 [0xd8] = KEY_G,
247 [0xd9] = KEY_B,
248 [0xdb] = KEY_6,
249 [0xdc] = KEY_Y,
250 [0xdd] = KEY_H,
251 [0xde] = KEY_N,
252 [0xe0] = KEY_7,
253 [0xe1] = KEY_U,
254 [0xe2] = KEY_J,
255 [0xe3] = KEY_M,
256 [0xe5] = KEY_8,
257 [0xe6] = KEY_I,
258 [0xe7] = KEY_K,
259 [0xe8] = KEY_COMMA,
260 [0xea] = KEY_9,
261 [0xeb] = KEY_O,
262 [0xec] = KEY_L,
263 [0xed] = KEY_DOT,
264 [0xef] = KEY_0,
265 [0xf0] = KEY_P,
266 [0xf2] = KEY_SEMICOLON,
267 [0xf3] = KEY_SLASH,
268 [0xf5] = KEY_EQUAL,
269 [0xf6] = KEY_RIGHTBRACE,
270 [0xf7] = KEY_BACKSLASH,
271 [0xf9] = KEY_MINUS,
272 [0xfa] = KEY_LEFTBRACE,
273 [0xfb] = KEY_APOSTROPHE,
274};
275
276#define CHECK_LED(LED, BITS) do { \
277 if (test_bit (LED, lk->dev.led)) \
278 leds_on |= BITS; \
279 else \
280 leds_off |= BITS; \
281 } while (0)
282
283/*
284 * Per-keyboard data
285 */
286struct lkkbd {
287 lk_keycode_t keycode[LK_NUM_KEYCODES];
288 int ignore_bytes;
289 unsigned char id[LK_NUM_IGNORE_BYTES];
290 struct input_dev dev;
291 struct serio *serio;
292 struct work_struct tq;
293 char name[64];
294 char phys[32];
295 char type;
296 int bell_volume;
297 int keyclick_volume;
298 int ctrlclick_volume;
299};
300
301/*
302 * Calculate volume parameter byte for a given volume.
303 */
304static unsigned char
305volume_to_hw (int volume_percent)
306{
307 unsigned char ret = 0;
308
309 if (volume_percent < 0)
310 volume_percent = 0;
311 if (volume_percent > 100)
312 volume_percent = 100;
313
314 if (volume_percent >= 0)
315 ret = 7;
316 if (volume_percent >= 13) /* 12.5 */
317 ret = 6;
318 if (volume_percent >= 25)
319 ret = 5;
320 if (volume_percent >= 38) /* 37.5 */
321 ret = 4;
322 if (volume_percent >= 50)
323 ret = 3;
324 if (volume_percent >= 63) /* 62.5 */
325 ret = 2; /* This is the default volume */
326 if (volume_percent >= 75)
327 ret = 1;
328 if (volume_percent >= 88) /* 87.5 */
329 ret = 0;
330
331 ret |= 0x80;
332
333 return ret;
334}
335
336static void
337lkkbd_detection_done (struct lkkbd *lk)
338{
339 int i;
340
341 /*
342 * Reset setting for Compose key. Let Compose be KEY_COMPOSE.
343 */
344 lk->keycode[0xb1] = KEY_COMPOSE;
345
346 /*
347 * Print keyboard name and modify Compose=Alt on user's request.
348 */
349 switch (lk->id[4]) {
350 case 1:
351 sprintf (lk->name, "DEC LK201 keyboard");
352
353 if (lk201_compose_is_alt)
354 lk->keycode[0xb1] = KEY_LEFTALT;
355 break;
356
357 case 2:
358 sprintf (lk->name, "DEC LK401 keyboard");
359 break;
360
361 default:
362 sprintf (lk->name, "Unknown DEC keyboard");
363 printk (KERN_ERR "lkkbd: keyboard on %s is unknown, "
364 "please report to Jan-Benedict Glaw "
365 "<jbglaw@lug-owl.de>\n", lk->phys);
366 printk (KERN_ERR "lkkbd: keyboard ID'ed as:");
367 for (i = 0; i < LK_NUM_IGNORE_BYTES; i++)
368 printk (" 0x%02x", lk->id[i]);
369 printk ("\n");
370 break;
371 }
372 printk (KERN_INFO "lkkbd: keyboard on %s identified as: %s\n",
373 lk->phys, lk->name);
374
375 /*
376 * Report errors during keyboard boot-up.
377 */
378 switch (lk->id[2]) {
379 case 0x00:
380 /* All okay */
381 break;
382
383 case LK_STUCK_KEY:
384 printk (KERN_ERR "lkkbd: Stuck key on keyboard at "
385 "%s\n", lk->phys);
386 break;
387
388 case LK_SELFTEST_FAILED:
389 printk (KERN_ERR "lkkbd: Selftest failed on keyboard "
390 "at %s, keyboard may not work "
391 "properly\n", lk->phys);
392 break;
393
394 default:
395 printk (KERN_ERR "lkkbd: Unknown error %02x on "
396 "keyboard at %s\n", lk->id[2],
397 lk->phys);
398 break;
399 }
400
401 /*
402 * Try to hint user if there's a stuck key.
403 */
404 if (lk->id[2] == LK_STUCK_KEY && lk->id[3] != 0)
405 printk (KERN_ERR "Scancode of stuck key is 0x%02x, keycode "
406 "is 0x%04x\n", lk->id[3],
407 lk->keycode[lk->id[3]]);
408
409 return;
410}
411
412/*
413 * lkkbd_interrupt() is called by the low level driver when a character
414 * is received.
415 */
416static irqreturn_t
417lkkbd_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
418 struct pt_regs *regs)
419{
420 struct lkkbd *lk = serio_get_drvdata (serio);
421 int i;
422
423 DBG (KERN_INFO "Got byte 0x%02x\n", data);
424
425 if (lk->ignore_bytes > 0) {
426 DBG (KERN_INFO "Ignoring a byte on %s\n",
427 lk->name);
428 lk->id[LK_NUM_IGNORE_BYTES - lk->ignore_bytes--] = data;
429
430 if (lk->ignore_bytes == 0)
431 lkkbd_detection_done (lk);
432
433 return IRQ_HANDLED;
434 }
435
436 switch (data) {
437 case LK_ALL_KEYS_UP:
438 input_regs (&lk->dev, regs);
439 for (i = 0; i < ARRAY_SIZE (lkkbd_keycode); i++)
440 if (lk->keycode[i] != KEY_RESERVED)
441 input_report_key (&lk->dev, lk->keycode[i], 0);
442 input_sync (&lk->dev);
443 break;
444 case LK_METRONOME:
445 DBG (KERN_INFO "Got LK_METRONOME and don't "
446 "know how to handle...\n");
447 break;
448 case LK_OUTPUT_ERROR:
449 DBG (KERN_INFO "Got LK_OUTPUT_ERROR and don't "
450 "know how to handle...\n");
451 break;
452 case LK_INPUT_ERROR:
453 DBG (KERN_INFO "Got LK_INPUT_ERROR and don't "
454 "know how to handle...\n");
455 break;
456 case LK_KBD_LOCKED:
457 DBG (KERN_INFO "Got LK_KBD_LOCKED and don't "
458 "know how to handle...\n");
459 break;
460 case LK_KBD_TEST_MODE_ACK:
461 DBG (KERN_INFO "Got LK_KBD_TEST_MODE_ACK and don't "
462 "know how to handle...\n");
463 break;
464 case LK_PREFIX_KEY_DOWN:
465 DBG (KERN_INFO "Got LK_PREFIX_KEY_DOWN and don't "
466 "know how to handle...\n");
467 break;
468 case LK_MODE_CHANGE_ACK:
469 DBG (KERN_INFO "Got LK_MODE_CHANGE_ACK and ignored "
470 "it properly...\n");
471 break;
472 case LK_RESPONSE_RESERVED:
473 DBG (KERN_INFO "Got LK_RESPONSE_RESERVED and don't "
474 "know how to handle...\n");
475 break;
476 case 0x01:
477 DBG (KERN_INFO "Got 0x01, scheduling re-initialization\n");
478 lk->ignore_bytes = LK_NUM_IGNORE_BYTES;
479 lk->id[LK_NUM_IGNORE_BYTES - lk->ignore_bytes--] = data;
480 schedule_work (&lk->tq);
481 break;
482
483 default:
484 if (lk->keycode[data] != KEY_RESERVED) {
485 input_regs (&lk->dev, regs);
486 if (!test_bit (lk->keycode[data], lk->dev.key))
487 input_report_key (&lk->dev, lk->keycode[data], 1);
488 else
489 input_report_key (&lk->dev, lk->keycode[data], 0);
490 input_sync (&lk->dev);
491 } else
492 printk (KERN_WARNING "%s: Unknown key with "
493 "scancode 0x%02x on %s.\n",
494 __FILE__, data, lk->name);
495 }
496
497 return IRQ_HANDLED;
498}
499
500/*
501 * lkkbd_event() handles events from the input module.
502 */
503static int
504lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code,
505 int value)
506{
507 struct lkkbd *lk = dev->private;
508 unsigned char leds_on = 0;
509 unsigned char leds_off = 0;
510
511 switch (type) {
512 case EV_LED:
513 CHECK_LED (LED_CAPSL, LK_LED_SHIFTLOCK);
514 CHECK_LED (LED_COMPOSE, LK_LED_COMPOSE);
515 CHECK_LED (LED_SCROLLL, LK_LED_SCROLLLOCK);
516 CHECK_LED (LED_SLEEP, LK_LED_WAIT);
517 if (leds_on != 0) {
518 lk->serio->write (lk->serio, LK_CMD_LED_ON);
519 lk->serio->write (lk->serio, leds_on);
520 }
521 if (leds_off != 0) {
522 lk->serio->write (lk->serio, LK_CMD_LED_OFF);
523 lk->serio->write (lk->serio, leds_off);
524 }
525 return 0;
526
527 case EV_SND:
528 switch (code) {
529 case SND_CLICK:
530 if (value == 0) {
531 DBG ("%s: Deactivating key clicks\n", __FUNCTION__);
532 lk->serio->write (lk->serio, LK_CMD_DISABLE_KEYCLICK);
533 lk->serio->write (lk->serio, LK_CMD_DISABLE_CTRCLICK);
534 } else {
535 DBG ("%s: Activating key clicks\n", __FUNCTION__);
536 lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK);
537 lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume));
538 lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK);
539 lk->serio->write (lk->serio, volume_to_hw (lk->ctrlclick_volume));
540 }
541 return 0;
542
543 case SND_BELL:
544 if (value != 0)
545 lk->serio->write (lk->serio, LK_CMD_SOUND_BELL);
546
547 return 0;
548 }
549 break;
550
551 default:
552 printk (KERN_ERR "%s (): Got unknown type %d, code %d, value %d\n",
553 __FUNCTION__, type, code, value);
554 }
555
556 return -1;
557}
558
559/*
560 * lkkbd_reinit() sets leds and beeps to a state the computer remembers they
561 * were in.
562 */
563static void
564lkkbd_reinit (void *data)
565{
566 struct lkkbd *lk = data;
567 int division;
568 unsigned char leds_on = 0;
569 unsigned char leds_off = 0;
570
571 /* Ask for ID */
572 lk->serio->write (lk->serio, LK_CMD_REQUEST_ID);
573
574 /* Reset parameters */
575 lk->serio->write (lk->serio, LK_CMD_SET_DEFAULTS);
576
577 /* Set LEDs */
578 CHECK_LED (LED_CAPSL, LK_LED_SHIFTLOCK);
579 CHECK_LED (LED_COMPOSE, LK_LED_COMPOSE);
580 CHECK_LED (LED_SCROLLL, LK_LED_SCROLLLOCK);
581 CHECK_LED (LED_SLEEP, LK_LED_WAIT);
582 if (leds_on != 0) {
583 lk->serio->write (lk->serio, LK_CMD_LED_ON);
584 lk->serio->write (lk->serio, leds_on);
585 }
586 if (leds_off != 0) {
587 lk->serio->write (lk->serio, LK_CMD_LED_OFF);
588 lk->serio->write (lk->serio, leds_off);
589 }
590
591 /*
592 * Try to activate extended LK401 mode. This command will
593 * only work with a LK401 keyboard and grants access to
594 * LAlt, RAlt, RCompose and RShift.
595 */
596 lk->serio->write (lk->serio, LK_CMD_ENABLE_LK401);
597
598 /* Set all keys to UPDOWN mode */
599 for (division = 1; division <= 14; division++)
600 lk->serio->write (lk->serio, LK_CMD_SET_MODE (LK_MODE_UPDOWN,
601 division));
602
603 /* Enable bell and set volume */
604 lk->serio->write (lk->serio, LK_CMD_ENABLE_BELL);
605 lk->serio->write (lk->serio, volume_to_hw (lk->bell_volume));
606
607 /* Enable/disable keyclick (and possibly set volume) */
608 if (test_bit (SND_CLICK, lk->dev.snd)) {
609 lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK);
610 lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume));
611 lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK);
612 lk->serio->write (lk->serio, volume_to_hw (lk->ctrlclick_volume));
613 } else {
614 lk->serio->write (lk->serio, LK_CMD_DISABLE_KEYCLICK);
615 lk->serio->write (lk->serio, LK_CMD_DISABLE_CTRCLICK);
616 }
617
618 /* Sound the bell if needed */
619 if (test_bit (SND_BELL, lk->dev.snd))
620 lk->serio->write (lk->serio, LK_CMD_SOUND_BELL);
621}
622
623/*
624 * lkkbd_connect() probes for a LK keyboard and fills the necessary structures.
625 */
626static int
627lkkbd_connect (struct serio *serio, struct serio_driver *drv)
628{
629 struct lkkbd *lk;
630 int i;
631 int err;
632
633 if (!(lk = kmalloc (sizeof (struct lkkbd), GFP_KERNEL)))
634 return -ENOMEM;
635
636 memset (lk, 0, sizeof (struct lkkbd));
637
638 init_input_dev (&lk->dev);
639 set_bit (EV_KEY, lk->dev.evbit);
640 set_bit (EV_LED, lk->dev.evbit);
641 set_bit (EV_SND, lk->dev.evbit);
642 set_bit (EV_REP, lk->dev.evbit);
643 set_bit (LED_CAPSL, lk->dev.ledbit);
644 set_bit (LED_SLEEP, lk->dev.ledbit);
645 set_bit (LED_COMPOSE, lk->dev.ledbit);
646 set_bit (LED_SCROLLL, lk->dev.ledbit);
647 set_bit (SND_BELL, lk->dev.sndbit);
648 set_bit (SND_CLICK, lk->dev.sndbit);
649
650 lk->serio = serio;
651
652 INIT_WORK (&lk->tq, lkkbd_reinit, lk);
653
654 lk->bell_volume = bell_volume;
655 lk->keyclick_volume = keyclick_volume;
656 lk->ctrlclick_volume = ctrlclick_volume;
657
658 lk->dev.keycode = lk->keycode;
659 lk->dev.keycodesize = sizeof (lk_keycode_t);
660 lk->dev.keycodemax = LK_NUM_KEYCODES;
661
662 lk->dev.event = lkkbd_event;
663 lk->dev.private = lk;
664
665 serio_set_drvdata (serio, lk);
666
667 err = serio_open (serio, drv);
668 if (err) {
669 serio_set_drvdata (serio, NULL);
670 kfree (lk);
671 return err;
672 }
673
674 sprintf (lk->name, "DEC LK keyboard");
675 sprintf (lk->phys, "%s/input0", serio->phys);
676
677 memcpy (lk->keycode, lkkbd_keycode, sizeof (lk_keycode_t) * LK_NUM_KEYCODES);
678 for (i = 0; i < LK_NUM_KEYCODES; i++)
679 set_bit (lk->keycode[i], lk->dev.keybit);
680
681 lk->dev.name = lk->name;
682 lk->dev.phys = lk->phys;
683 lk->dev.id.bustype = BUS_RS232;
684 lk->dev.id.vendor = SERIO_LKKBD;
685 lk->dev.id.product = 0;
686 lk->dev.id.version = 0x0100;
687 lk->dev.dev = &serio->dev;
688
689 input_register_device (&lk->dev);
690
691 printk (KERN_INFO "input: %s on %s, initiating reset\n", lk->name, serio->phys);
692 lk->serio->write (lk->serio, LK_CMD_POWERCYCLE_RESET);
693
694 return 0;
695}
696
697/*
698 * lkkbd_disconnect() unregisters and closes behind us.
699 */
700static void
701lkkbd_disconnect (struct serio *serio)
702{
703 struct lkkbd *lk = serio_get_drvdata (serio);
704
705 input_unregister_device (&lk->dev);
706 serio_close (serio);
707 serio_set_drvdata (serio, NULL);
708 kfree (lk);
709}
710
711static struct serio_device_id lkkbd_serio_ids[] = {
712 {
713 .type = SERIO_RS232,
714 .proto = SERIO_LKKBD,
715 .id = SERIO_ANY,
716 .extra = SERIO_ANY,
717 },
718 { 0 }
719};
720
721MODULE_DEVICE_TABLE(serio, lkkbd_serio_ids);
722
723static struct serio_driver lkkbd_drv = {
724 .driver = {
725 .name = "lkkbd",
726 },
727 .description = DRIVER_DESC,
728 .id_table = lkkbd_serio_ids,
729 .connect = lkkbd_connect,
730 .disconnect = lkkbd_disconnect,
731 .interrupt = lkkbd_interrupt,
732};
733
734/*
735 * The functions for insering/removing us as a module.
736 */
737static int __init
738lkkbd_init (void)
739{
740 serio_register_driver(&lkkbd_drv);
741 return 0;
742}
743
744static void __exit
745lkkbd_exit (void)
746{
747 serio_unregister_driver(&lkkbd_drv);
748}
749
750module_init (lkkbd_init);
751module_exit (lkkbd_exit);
752
diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
new file mode 100644
index 000000000000..d3e9dd6a13cd
--- /dev/null
+++ b/drivers/input/keyboard/locomokbd.c
@@ -0,0 +1,309 @@
1/*
2 * Copyright (c) 2005 John Lenz
3 *
4 * Based on from xtkbd.c
5 */
6
7/*
8 * LoCoMo keyboard driver for Linux/ARM
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 */
27
28#include <linux/config.h>
29#include <linux/slab.h>
30#include <linux/module.h>
31#include <linux/init.h>
32#include <linux/input.h>
33#include <linux/delay.h>
34#include <linux/device.h>
35#include <linux/interrupt.h>
36#include <linux/ioport.h>
37
38#include <asm/hardware/locomo.h>
39#include <asm/irq.h>
40
41MODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>");
42MODULE_DESCRIPTION("LoCoMo keyboard driver");
43MODULE_LICENSE("GPL");
44
45#define LOCOMOKBD_NUMKEYS 128
46
47#define KEY_ACTIVITY KEY_F16
48#define KEY_CONTACT KEY_F18
49#define KEY_CENTER KEY_F15
50
51static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = {
52 0, KEY_ESC, KEY_ACTIVITY, 0, 0, 0, 0, 0, 0, 0, /* 0 - 9 */
53 0, 0, 0, 0, 0, 0, 0, KEY_MENU, KEY_HOME, KEY_CONTACT, /* 10 - 19 */
54 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 29 */
55 0, 0, 0, KEY_CENTER, 0, KEY_MAIL, 0, 0, 0, 0, /* 30 - 39 */
56 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_RIGHT, /* 40 - 49 */
57 KEY_UP, KEY_LEFT, 0, 0, KEY_P, 0, KEY_O, KEY_I, KEY_Y, KEY_T, /* 50 - 59 */
58 KEY_E, KEY_W, 0, 0, 0, 0, KEY_DOWN, KEY_ENTER, 0, 0, /* 60 - 69 */
59 KEY_BACKSPACE, 0, KEY_L, KEY_U, KEY_H, KEY_R, KEY_D, KEY_Q, 0, 0, /* 70 - 79 */
60 0, 0, 0, 0, 0, 0, KEY_ENTER, KEY_RIGHTSHIFT, KEY_K, KEY_J, /* 80 - 89 */
61 KEY_G, KEY_F, KEY_X, KEY_S, 0, 0, 0, 0, 0, 0, /* 90 - 99 */
62 0, 0, KEY_DOT, 0, KEY_COMMA, KEY_N, KEY_B, KEY_C, KEY_Z, KEY_A, /* 100 - 109 */
63 KEY_LEFTSHIFT, KEY_TAB, KEY_LEFTCTRL, 0, 0, 0, 0, 0, 0, 0, /* 110 - 119 */
64 KEY_M, KEY_SPACE, KEY_V, KEY_APOSTROPHE, KEY_SLASH, 0, 0, 0 /* 120 - 128 */
65};
66
67#define KB_ROWS 16
68#define KB_COLS 8
69#define KB_ROWMASK(r) (1 << (r))
70#define SCANCODE(c,r) ( ((c)<<4) + (r) + 1 )
71#define NR_SCANCODES 128
72
73#define KB_DELAY 8
74#define SCAN_INTERVAL (HZ/10)
75#define LOCOMOKBD_PRESSED 1
76
77struct locomokbd {
78 unsigned char keycode[LOCOMOKBD_NUMKEYS];
79 struct input_dev input;
80 char phys[32];
81
82 struct locomo_dev *ldev;
83 unsigned long base;
84 spinlock_t lock;
85
86 struct timer_list timer;
87};
88
89/* helper functions for reading the keyboard matrix */
90static inline void locomokbd_charge_all(unsigned long membase)
91{
92 locomo_writel(0x00FF, membase + LOCOMO_KSC);
93}
94
95static inline void locomokbd_activate_all(unsigned long membase)
96{
97 unsigned long r;
98
99 locomo_writel(0, membase + LOCOMO_KSC);
100 r = locomo_readl(membase + LOCOMO_KIC);
101 r &= 0xFEFF;
102 locomo_writel(r, membase + LOCOMO_KIC);
103}
104
105static inline void locomokbd_activate_col(unsigned long membase, int col)
106{
107 unsigned short nset;
108 unsigned short nbset;
109
110 nset = 0xFF & ~(1 << col);
111 nbset = (nset << 8) + nset;
112 locomo_writel(nbset, membase + LOCOMO_KSC);
113}
114
115static inline void locomokbd_reset_col(unsigned long membase, int col)
116{
117 unsigned short nbset;
118
119 nbset = ((0xFF & ~(1 << col)) << 8) + 0xFF;
120 locomo_writel(nbset, membase + LOCOMO_KSC);
121}
122
123/*
124 * The LoCoMo keyboard only generates interrupts when a key is pressed.
125 * So when a key is pressed, we enable a timer. This timer scans the
126 * keyboard, and this is how we detect when the key is released.
127 */
128
129/* Scan the hardware keyboard and push any changes up through the input layer */
130static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *regs)
131{
132 unsigned int row, col, rowd, scancode;
133 unsigned long flags;
134 unsigned int num_pressed;
135 unsigned long membase = locomokbd->base;
136
137 spin_lock_irqsave(&locomokbd->lock, flags);
138
139 if (regs)
140 input_regs(&locomokbd->input, regs);
141
142 locomokbd_charge_all(membase);
143
144 num_pressed = 0;
145 for (col = 0; col < KB_COLS; col++) {
146
147 locomokbd_activate_col(membase, col);
148 udelay(KB_DELAY);
149
150 rowd = ~locomo_readl(membase + LOCOMO_KIB);
151 for (row = 0; row < KB_ROWS; row++ ) {
152 scancode = SCANCODE(col, row);
153 if (rowd & KB_ROWMASK(row)) {
154 num_pressed += 1;
155 input_report_key(&locomokbd->input, locomokbd->keycode[scancode], 1);
156 } else {
157 input_report_key(&locomokbd->input, locomokbd->keycode[scancode], 0);
158 }
159 }
160 locomokbd_reset_col(membase, col);
161 }
162 locomokbd_activate_all(membase);
163
164 input_sync(&locomokbd->input);
165
166 /* if any keys are pressed, enable the timer */
167 if (num_pressed)
168 mod_timer(&locomokbd->timer, jiffies + SCAN_INTERVAL);
169
170 spin_unlock_irqrestore(&locomokbd->lock, flags);
171}
172
173/*
174 * LoCoMo keyboard interrupt handler.
175 */
176static irqreturn_t locomokbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
177{
178 struct locomokbd *locomokbd = dev_id;
179 /** wait chattering delay **/
180 udelay(100);
181
182 locomokbd_scankeyboard(locomokbd, regs);
183
184 return IRQ_HANDLED;
185}
186
187/*
188 * LoCoMo timer checking for released keys
189 */
190static void locomokbd_timer_callback(unsigned long data)
191{
192 struct locomokbd *locomokbd = (struct locomokbd *) data;
193 locomokbd_scankeyboard(locomokbd, NULL);
194}
195
196static int locomokbd_probe(struct locomo_dev *dev)
197{
198 struct locomokbd *locomokbd;
199 int i, ret;
200
201 locomokbd = kmalloc(sizeof(struct locomokbd), GFP_KERNEL);
202 if (!locomokbd)
203 return -ENOMEM;
204
205 memset(locomokbd, 0, sizeof(struct locomokbd));
206
207 /* try and claim memory region */
208 if (!request_mem_region((unsigned long) dev->mapbase,
209 dev->length,
210 LOCOMO_DRIVER_NAME(dev))) {
211 ret = -EBUSY;
212 printk(KERN_ERR "locomokbd: Can't acquire access to io memory for keyboard\n");
213 goto free;
214 }
215
216 locomokbd->ldev = dev;
217 locomo_set_drvdata(dev, locomokbd);
218
219 locomokbd->base = (unsigned long) dev->mapbase;
220
221 spin_lock_init(&locomokbd->lock);
222
223 init_timer(&locomokbd->timer);
224 locomokbd->timer.function = locomokbd_timer_callback;
225 locomokbd->timer.data = (unsigned long) locomokbd;
226
227 locomokbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
228
229 init_input_dev(&locomokbd->input);
230 locomokbd->input.keycode = locomokbd->keycode;
231 locomokbd->input.keycodesize = sizeof(unsigned char);
232 locomokbd->input.keycodemax = ARRAY_SIZE(locomokbd_keycode);
233 locomokbd->input.private = locomokbd;
234
235 memcpy(locomokbd->keycode, locomokbd_keycode, sizeof(locomokbd->keycode));
236 for (i = 0; i < LOCOMOKBD_NUMKEYS; i++)
237 set_bit(locomokbd->keycode[i], locomokbd->input.keybit);
238 clear_bit(0, locomokbd->input.keybit);
239
240 strcpy(locomokbd->phys, "locomokbd/input0");
241
242 locomokbd->input.name = "LoCoMo keyboard";
243 locomokbd->input.phys = locomokbd->phys;
244 locomokbd->input.id.bustype = BUS_XTKBD;
245 locomokbd->input.id.vendor = 0x0001;
246 locomokbd->input.id.product = 0x0001;
247 locomokbd->input.id.version = 0x0100;
248
249 /* attempt to get the interrupt */
250 ret = request_irq(dev->irq[0], locomokbd_interrupt, 0, "locomokbd", locomokbd);
251 if (ret) {
252 printk(KERN_ERR "locomokbd: Can't get irq for keyboard\n");
253 goto out;
254 }
255
256 input_register_device(&locomokbd->input);
257
258 printk(KERN_INFO "input: LoCoMo keyboard on locomokbd\n");
259
260 return 0;
261
262out:
263 release_mem_region((unsigned long) dev->mapbase, dev->length);
264 locomo_set_drvdata(dev, NULL);
265free:
266 kfree(locomokbd);
267
268 return ret;
269}
270
271static int locomokbd_remove(struct locomo_dev *dev)
272{
273 struct locomokbd *locomokbd = locomo_get_drvdata(dev);
274
275 free_irq(dev->irq[0], locomokbd);
276
277 del_timer_sync(&locomokbd->timer);
278
279 input_unregister_device(&locomokbd->input);
280 locomo_set_drvdata(dev, NULL);
281
282 release_mem_region((unsigned long) dev->mapbase, dev->length);
283
284 kfree(locomokbd);
285
286 return 0;
287}
288
289static struct locomo_driver keyboard_driver = {
290 .drv = {
291 .name = "locomokbd"
292 },
293 .devid = LOCOMO_DEVID_KEYBOARD,
294 .probe = locomokbd_probe,
295 .remove = locomokbd_remove,
296};
297
298static int __init locomokbd_init(void)
299{
300 return locomo_driver_register(&keyboard_driver);
301}
302
303static void __exit locomokbd_exit(void)
304{
305 locomo_driver_unregister(&keyboard_driver);
306}
307
308module_init(locomokbd_init);
309module_exit(locomokbd_exit);
diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c
new file mode 100644
index 000000000000..859ed771ee0a
--- /dev/null
+++ b/drivers/input/keyboard/maple_keyb.c
@@ -0,0 +1,190 @@
1/*
2 * $Id: maple_keyb.c,v 1.4 2004/03/22 01:18:15 lethal Exp $
3 * SEGA Dreamcast keyboard driver
4 * Based on drivers/usb/usbkbd.c
5 */
6
7#include <linux/kernel.h>
8#include <linux/slab.h>
9#include <linux/input.h>
10#include <linux/module.h>
11#include <linux/init.h>
12#include <linux/timer.h>
13#include <linux/maple.h>
14
15MODULE_AUTHOR("YAEGASHI Takeshi <t@keshi.org>");
16MODULE_DESCRIPTION("SEGA Dreamcast keyboard driver");
17MODULE_LICENSE("GPL");
18
19static unsigned char dc_kbd_keycode[256] = {
20 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
21 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
22 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
23 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
24 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
25 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
26 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
27 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
28 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0,
29 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
30 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
31 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
32 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
33 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
34 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
35 150,158,159,128,136,177,178,176,142,152,173,140
36};
37
38
39struct dc_kbd {
40 struct input_dev dev;
41 unsigned char new[8];
42 unsigned char old[8];
43 int open;
44};
45
46
47static void dc_scan_kbd(struct dc_kbd *kbd)
48{
49 int i;
50 struct input_dev *dev = &kbd->dev;
51
52 for(i=0; i<8; i++)
53 input_report_key(dev,
54 dc_kbd_keycode[i+224],
55 (kbd->new[0]>>i)&1);
56
57 for(i=2; i<8; i++) {
58
59 if(kbd->old[i]>3&&memscan(kbd->new+2, kbd->old[i], 6)==NULL) {
60 if(dc_kbd_keycode[kbd->old[i]])
61 input_report_key(dev,
62 dc_kbd_keycode[kbd->old[i]],
63 0);
64 else
65 printk("Unknown key (scancode %#x) released.",
66 kbd->old[i]);
67 }
68
69 if(kbd->new[i]>3&&memscan(kbd->old+2, kbd->new[i], 6)!=NULL) {
70 if(dc_kbd_keycode[kbd->new[i]])
71 input_report_key(dev,
72 dc_kbd_keycode[kbd->new[i]],
73 1);
74 else
75 printk("Unknown key (scancode %#x) pressed.",
76 kbd->new[i]);
77 }
78 }
79
80 input_sync(dev);
81
82 memcpy(kbd->old, kbd->new, 8);
83}
84
85
86static void dc_kbd_callback(struct mapleq *mq)
87{
88 struct maple_device *mapledev = mq->dev;
89 struct dc_kbd *kbd = mapledev->private_data;
90 unsigned long *buf = mq->recvbuf;
91
92 if (buf[1] == mapledev->function) {
93 memcpy(kbd->new, buf+2, 8);
94 dc_scan_kbd(kbd);
95 }
96}
97
98
99static int dc_kbd_open(struct input_dev *dev)
100{
101 struct dc_kbd *kbd = dev->private;
102 kbd->open++;
103 return 0;
104}
105
106
107static void dc_kbd_close(struct input_dev *dev)
108{
109 struct dc_kbd *kbd = dev->private;
110 kbd->open--;
111}
112
113
114static int dc_kbd_connect(struct maple_device *dev)
115{
116 int i;
117 unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
118 struct dc_kbd *kbd;
119
120 if (!(kbd = kmalloc(sizeof(struct dc_kbd), GFP_KERNEL)))
121 return -1;
122 memset(kbd, 0, sizeof(struct dc_kbd));
123
124 dev->private_data = kbd;
125
126 kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
127
128 init_input_dev(&kbd->dev);
129
130 for (i=0; i<255; i++)
131 set_bit(dc_kbd_keycode[i], kbd->dev.keybit);
132
133 clear_bit(0, kbd->dev.keybit);
134
135 kbd->dev.private = kbd;
136 kbd->dev.open = dc_kbd_open;
137 kbd->dev.close = dc_kbd_close;
138 kbd->dev.event = NULL;
139
140 kbd->dev.name = dev->product_name;
141 kbd->dev.id.bustype = BUS_MAPLE;
142
143 input_register_device(&kbd->dev);
144
145 maple_getcond_callback(dev, dc_kbd_callback, 1, MAPLE_FUNC_KEYBOARD);
146
147 printk(KERN_INFO "input: keyboard(0x%lx): %s\n", data, kbd->dev.name);
148
149 return 0;
150}
151
152
153static void dc_kbd_disconnect(struct maple_device *dev)
154{
155 struct dc_kbd *kbd = dev->private_data;
156
157 input_unregister_device(&kbd->dev);
158 kfree(kbd);
159}
160
161
162static struct maple_driver dc_kbd_driver = {
163 .function = MAPLE_FUNC_KEYBOARD,
164 .name = "Dreamcast keyboard",
165 .connect = dc_kbd_connect,
166 .disconnect = dc_kbd_disconnect,
167};
168
169
170static int __init dc_kbd_init(void)
171{
172 maple_register_driver(&dc_kbd_driver);
173 return 0;
174}
175
176
177static void __exit dc_kbd_exit(void)
178{
179 maple_unregister_driver(&dc_kbd_driver);
180}
181
182
183module_init(dc_kbd_init);
184module_exit(dc_kbd_exit);
185
186/*
187 * Local variables:
188 * c-basic-offset: 8
189 * End:
190 */
diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c
new file mode 100644
index 000000000000..2e8ce1613eec
--- /dev/null
+++ b/drivers/input/keyboard/newtonkbd.c
@@ -0,0 +1,184 @@
1/*
2 * Copyright (c) 2000 Justin Cormack
3 */
4
5/*
6 * Newton keyboard driver for Linux
7 */
8
9/*
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * Should you need to contact me, the author, you can do so either by
25 * e-mail - mail your message to <j.cormack@doc.ic.ac.uk>, or by paper mail:
26 * Justin Cormack, 68 Dartmouth Park Road, London NW5 1SN, UK.
27 */
28
29#include <linux/slab.h>
30#include <linux/module.h>
31#include <linux/input.h>
32#include <linux/init.h>
33#include <linux/serio.h>
34
35#define DRIVER_DESC "Newton keyboard driver"
36
37MODULE_AUTHOR("Justin Cormack <j.cormack@doc.ic.ac.uk>");
38MODULE_DESCRIPTION(DRIVER_DESC);
39MODULE_LICENSE("GPL");
40
41#define NKBD_KEY 0x7f
42#define NKBD_PRESS 0x80
43
44static unsigned char nkbd_keycode[128] = {
45 KEY_A, KEY_S, KEY_D, KEY_F, KEY_H, KEY_G, KEY_Z, KEY_X,
46 KEY_C, KEY_V, 0, KEY_B, KEY_Q, KEY_W, KEY_E, KEY_R,
47 KEY_Y, KEY_T, KEY_1, KEY_2, KEY_3, KEY_4, KEY_6, KEY_5,
48 KEY_EQUAL, KEY_9, KEY_7, KEY_MINUS, KEY_8, KEY_0, KEY_RIGHTBRACE, KEY_O,
49 KEY_U, KEY_LEFTBRACE, KEY_I, KEY_P, KEY_ENTER, KEY_L, KEY_J, KEY_APOSTROPHE,
50 KEY_K, KEY_SEMICOLON, KEY_BACKSLASH, KEY_COMMA, KEY_SLASH, KEY_N, KEY_M, KEY_DOT,
51 KEY_TAB, KEY_SPACE, KEY_GRAVE, KEY_DELETE, 0, 0, 0, KEY_LEFTMETA,
52 KEY_LEFTSHIFT, KEY_CAPSLOCK, KEY_LEFTALT, KEY_LEFTCTRL, KEY_RIGHTSHIFT, 0, 0, 0,
53 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
54 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
55 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57 KEY_LEFT, KEY_RIGHT, KEY_DOWN, KEY_UP, 0
58};
59
60static char *nkbd_name = "Newton Keyboard";
61
62struct nkbd {
63 unsigned char keycode[128];
64 struct input_dev dev;
65 struct serio *serio;
66 char phys[32];
67};
68
69static irqreturn_t nkbd_interrupt(struct serio *serio,
70 unsigned char data, unsigned int flags, struct pt_regs *regs)
71{
72 struct nkbd *nkbd = serio_get_drvdata(serio);
73
74 /* invalid scan codes are probably the init sequence, so we ignore them */
75 if (nkbd->keycode[data & NKBD_KEY]) {
76 input_regs(&nkbd->dev, regs);
77 input_report_key(&nkbd->dev, nkbd->keycode[data & NKBD_KEY], data & NKBD_PRESS);
78 input_sync(&nkbd->dev);
79 }
80
81 else if (data == 0xe7) /* end of init sequence */
82 printk(KERN_INFO "input: %s on %s\n", nkbd_name, serio->phys);
83 return IRQ_HANDLED;
84
85}
86
87static int nkbd_connect(struct serio *serio, struct serio_driver *drv)
88{
89 struct nkbd *nkbd;
90 int i;
91 int err;
92
93 if (!(nkbd = kmalloc(sizeof(struct nkbd), GFP_KERNEL)))
94 return -ENOMEM;
95
96 memset(nkbd, 0, sizeof(struct nkbd));
97
98 nkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
99
100 nkbd->serio = serio;
101
102 init_input_dev(&nkbd->dev);
103 nkbd->dev.keycode = nkbd->keycode;
104 nkbd->dev.keycodesize = sizeof(unsigned char);
105 nkbd->dev.keycodemax = ARRAY_SIZE(nkbd_keycode);
106 nkbd->dev.private = nkbd;
107
108 serio_set_drvdata(serio, nkbd);
109
110 err = serio_open(serio, drv);
111 if (err) {
112 serio_set_drvdata(serio, NULL);
113 kfree(nkbd);
114 return err;
115 }
116
117 memcpy(nkbd->keycode, nkbd_keycode, sizeof(nkbd->keycode));
118 for (i = 0; i < 128; i++)
119 set_bit(nkbd->keycode[i], nkbd->dev.keybit);
120 clear_bit(0, nkbd->dev.keybit);
121
122 sprintf(nkbd->phys, "%s/input0", serio->phys);
123
124 nkbd->dev.name = nkbd_name;
125 nkbd->dev.phys = nkbd->phys;
126 nkbd->dev.id.bustype = BUS_RS232;
127 nkbd->dev.id.vendor = SERIO_NEWTON;
128 nkbd->dev.id.product = 0x0001;
129 nkbd->dev.id.version = 0x0100;
130 nkbd->dev.dev = &serio->dev;
131
132 input_register_device(&nkbd->dev);
133
134 printk(KERN_INFO "input: %s on %s\n", nkbd_name, serio->phys);
135
136 return 0;
137}
138
139static void nkbd_disconnect(struct serio *serio)
140{
141 struct nkbd *nkbd = serio_get_drvdata(serio);
142
143 input_unregister_device(&nkbd->dev);
144 serio_close(serio);
145 serio_set_drvdata(serio, NULL);
146 kfree(nkbd);
147}
148
149static struct serio_device_id nkbd_serio_ids[] = {
150 {
151 .type = SERIO_RS232,
152 .proto = SERIO_NEWTON,
153 .id = SERIO_ANY,
154 .extra = SERIO_ANY,
155 },
156 { 0 }
157};
158
159MODULE_DEVICE_TABLE(serio, nkbd_serio_ids);
160
161static struct serio_driver nkbd_drv = {
162 .driver = {
163 .name = "newtonkbd",
164 },
165 .description = DRIVER_DESC,
166 .id_table = nkbd_serio_ids,
167 .interrupt = nkbd_interrupt,
168 .connect = nkbd_connect,
169 .disconnect = nkbd_disconnect,
170};
171
172static int __init nkbd_init(void)
173{
174 serio_register_driver(&nkbd_drv);
175 return 0;
176}
177
178static void __exit nkbd_exit(void)
179{
180 serio_unregister_driver(&nkbd_drv);
181}
182
183module_init(nkbd_init);
184module_exit(nkbd_exit);
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
new file mode 100644
index 000000000000..596964ceb96d
--- /dev/null
+++ b/drivers/input/keyboard/sunkbd.c
@@ -0,0 +1,353 @@
1/*
2 * $Id: sunkbd.c,v 1.14 2001/09/25 10:12:07 vojtech Exp $
3 *
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 */
6
7/*
8 * Sun keyboard driver for Linux
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/delay.h>
32#include <linux/slab.h>
33#include <linux/module.h>
34#include <linux/interrupt.h>
35#include <linux/init.h>
36#include <linux/input.h>
37#include <linux/serio.h>
38#include <linux/workqueue.h>
39
40#define DRIVER_DESC "Sun keyboard driver"
41
42MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
43MODULE_DESCRIPTION(DRIVER_DESC);
44MODULE_LICENSE("GPL");
45
46static unsigned char sunkbd_keycode[128] = {
47 0,128,114,129,115, 59, 60, 68, 61, 87, 62, 88, 63,100, 64, 0,
48 65, 66, 67, 56,103,119, 99, 70,105,130,131,108,106, 1, 2, 3,
49 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 41, 14,110,113, 98, 55,
50 116,132, 83,133,102, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
51 26, 27,111,127, 71, 72, 73, 74,134,135,107, 0, 29, 30, 31, 32,
52 33, 34, 35, 36, 37, 38, 39, 40, 43, 28, 96, 75, 76, 77, 82,136,
53 104,137, 69, 42, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,101,
54 79, 80, 81, 0, 0, 0,138, 58,125, 57,126,109, 86, 78
55};
56
57#define SUNKBD_CMD_RESET 0x1
58#define SUNKBD_CMD_BELLON 0x2
59#define SUNKBD_CMD_BELLOFF 0x3
60#define SUNKBD_CMD_CLICK 0xa
61#define SUNKBD_CMD_NOCLICK 0xb
62#define SUNKBD_CMD_SETLED 0xe
63#define SUNKBD_CMD_LAYOUT 0xf
64
65#define SUNKBD_RET_RESET 0xff
66#define SUNKBD_RET_ALLUP 0x7f
67#define SUNKBD_RET_LAYOUT 0xfe
68
69#define SUNKBD_LAYOUT_5_MASK 0x20
70#define SUNKBD_RELEASE 0x80
71#define SUNKBD_KEY 0x7f
72
73/*
74 * Per-keyboard data.
75 */
76
77struct sunkbd {
78 unsigned char keycode[128];
79 struct input_dev dev;
80 struct serio *serio;
81 struct work_struct tq;
82 wait_queue_head_t wait;
83 char name[64];
84 char phys[32];
85 char type;
86 volatile s8 reset;
87 volatile s8 layout;
88};
89
90/*
91 * sunkbd_interrupt() is called by the low level driver when a character
92 * is received.
93 */
94
95static irqreturn_t sunkbd_interrupt(struct serio *serio,
96 unsigned char data, unsigned int flags, struct pt_regs *regs)
97{
98 struct sunkbd* sunkbd = serio_get_drvdata(serio);
99
100 if (sunkbd->reset <= -1) { /* If cp[i] is 0xff, sunkbd->reset will stay -1. */
101 sunkbd->reset = data; /* The keyboard sends 0xff 0xff 0xID on powerup */
102 wake_up_interruptible(&sunkbd->wait);
103 goto out;
104 }
105
106 if (sunkbd->layout == -1) {
107 sunkbd->layout = data;
108 wake_up_interruptible(&sunkbd->wait);
109 goto out;
110 }
111
112 switch (data) {
113
114 case SUNKBD_RET_RESET:
115 schedule_work(&sunkbd->tq);
116 sunkbd->reset = -1;
117 break;
118
119 case SUNKBD_RET_LAYOUT:
120 sunkbd->layout = -1;
121 break;
122
123 case SUNKBD_RET_ALLUP: /* All keys released */
124 break;
125
126 default:
127 if (sunkbd->keycode[data & SUNKBD_KEY]) {
128 input_regs(&sunkbd->dev, regs);
129 input_report_key(&sunkbd->dev, sunkbd->keycode[data & SUNKBD_KEY], !(data & SUNKBD_RELEASE));
130 input_sync(&sunkbd->dev);
131 } else {
132 printk(KERN_WARNING "sunkbd.c: Unknown key (scancode %#x) %s.\n",
133 data & SUNKBD_KEY, data & SUNKBD_RELEASE ? "released" : "pressed");
134 }
135 }
136out:
137 return IRQ_HANDLED;
138}
139
140/*
141 * sunkbd_event() handles events from the input module.
142 */
143
144static int sunkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
145{
146 struct sunkbd *sunkbd = dev->private;
147
148 switch (type) {
149
150 case EV_LED:
151
152 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED);
153 sunkbd->serio->write(sunkbd->serio,
154 (!!test_bit(LED_CAPSL, dev->led) << 3) | (!!test_bit(LED_SCROLLL, dev->led) << 2) |
155 (!!test_bit(LED_COMPOSE, dev->led) << 1) | !!test_bit(LED_NUML, dev->led));
156 return 0;
157
158 case EV_SND:
159
160 switch (code) {
161
162 case SND_CLICK:
163 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - value);
164 return 0;
165
166 case SND_BELL:
167 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - value);
168 return 0;
169 }
170
171 break;
172 }
173
174 return -1;
175}
176
177/*
178 * sunkbd_initialize() checks for a Sun keyboard attached, and determines
179 * its type.
180 */
181
182static int sunkbd_initialize(struct sunkbd *sunkbd)
183{
184 sunkbd->reset = -2;
185 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_RESET);
186 wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
187 if (sunkbd->reset <0)
188 return -1;
189
190 sunkbd->type = sunkbd->reset;
191
192 if (sunkbd->type == 4) { /* Type 4 keyboard */
193 sunkbd->layout = -2;
194 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_LAYOUT);
195 wait_event_interruptible_timeout(sunkbd->wait, sunkbd->layout >= 0, HZ/4);
196 if (sunkbd->layout < 0) return -1;
197 if (sunkbd->layout & SUNKBD_LAYOUT_5_MASK) sunkbd->type = 5;
198 }
199
200 return 0;
201}
202
203/*
204 * sunkbd_reinit() sets leds and beeps to a state the computer remembers they
205 * were in.
206 */
207
208static void sunkbd_reinit(void *data)
209{
210 struct sunkbd *sunkbd = data;
211
212 wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
213
214 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED);
215 sunkbd->serio->write(sunkbd->serio,
216 (!!test_bit(LED_CAPSL, sunkbd->dev.led) << 3) | (!!test_bit(LED_SCROLLL, sunkbd->dev.led) << 2) |
217 (!!test_bit(LED_COMPOSE, sunkbd->dev.led) << 1) | !!test_bit(LED_NUML, sunkbd->dev.led));
218 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev.snd));
219 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev.snd));
220}
221
222/*
223 * sunkbd_connect() probes for a Sun keyboard and fills the necessary structures.
224 */
225
226static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
227{
228 struct sunkbd *sunkbd;
229 int i;
230 int err;
231
232 if (!(sunkbd = kmalloc(sizeof(struct sunkbd), GFP_KERNEL)))
233 return -ENOMEM;
234
235 memset(sunkbd, 0, sizeof(struct sunkbd));
236
237 init_input_dev(&sunkbd->dev);
238 init_waitqueue_head(&sunkbd->wait);
239
240 sunkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_SND) | BIT(EV_REP);
241 sunkbd->dev.ledbit[0] = BIT(LED_CAPSL) | BIT(LED_COMPOSE) | BIT(LED_SCROLLL) | BIT(LED_NUML);
242 sunkbd->dev.sndbit[0] = BIT(SND_CLICK) | BIT(SND_BELL);
243
244 sunkbd->serio = serio;
245
246 INIT_WORK(&sunkbd->tq, sunkbd_reinit, sunkbd);
247
248 sunkbd->dev.keycode = sunkbd->keycode;
249 sunkbd->dev.keycodesize = sizeof(unsigned char);
250 sunkbd->dev.keycodemax = ARRAY_SIZE(sunkbd_keycode);
251
252 sunkbd->dev.event = sunkbd_event;
253 sunkbd->dev.private = sunkbd;
254
255 serio_set_drvdata(serio, sunkbd);
256
257 err = serio_open(serio, drv);
258 if (err) {
259 serio_set_drvdata(serio, NULL);
260 kfree(sunkbd);
261 return err;
262 }
263
264 if (sunkbd_initialize(sunkbd) < 0) {
265 serio_close(serio);
266 serio_set_drvdata(serio, NULL);
267 kfree(sunkbd);
268 return -ENODEV;
269 }
270
271 sprintf(sunkbd->name, "Sun Type %d keyboard", sunkbd->type);
272
273 memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode));
274 for (i = 0; i < 128; i++)
275 set_bit(sunkbd->keycode[i], sunkbd->dev.keybit);
276 clear_bit(0, sunkbd->dev.keybit);
277
278 sprintf(sunkbd->phys, "%s/input0", serio->phys);
279
280 sunkbd->dev.name = sunkbd->name;
281 sunkbd->dev.phys = sunkbd->phys;
282 sunkbd->dev.id.bustype = BUS_RS232;
283 sunkbd->dev.id.vendor = SERIO_SUNKBD;
284 sunkbd->dev.id.product = sunkbd->type;
285 sunkbd->dev.id.version = 0x0100;
286 sunkbd->dev.dev = &serio->dev;
287
288 input_register_device(&sunkbd->dev);
289
290 printk(KERN_INFO "input: %s on %s\n", sunkbd->name, serio->phys);
291
292 return 0;
293}
294
295/*
296 * sunkbd_disconnect() unregisters and closes behind us.
297 */
298
299static void sunkbd_disconnect(struct serio *serio)
300{
301 struct sunkbd *sunkbd = serio_get_drvdata(serio);
302 input_unregister_device(&sunkbd->dev);
303 serio_close(serio);
304 serio_set_drvdata(serio, NULL);
305 kfree(sunkbd);
306}
307
308static struct serio_device_id sunkbd_serio_ids[] = {
309 {
310 .type = SERIO_RS232,
311 .proto = SERIO_SUNKBD,
312 .id = SERIO_ANY,
313 .extra = SERIO_ANY,
314 },
315 {
316 .type = SERIO_RS232,
317 .proto = SERIO_UNKNOWN, /* sunkbd does probe */
318 .id = SERIO_ANY,
319 .extra = SERIO_ANY,
320 },
321 { 0 }
322};
323
324MODULE_DEVICE_TABLE(serio, sunkbd_serio_ids);
325
326static struct serio_driver sunkbd_drv = {
327 .driver = {
328 .name = "sunkbd",
329 },
330 .description = DRIVER_DESC,
331 .id_table = sunkbd_serio_ids,
332 .interrupt = sunkbd_interrupt,
333 .connect = sunkbd_connect,
334 .disconnect = sunkbd_disconnect,
335};
336
337/*
338 * The functions for insering/removing us as a module.
339 */
340
341static int __init sunkbd_init(void)
342{
343 serio_register_driver(&sunkbd_drv);
344 return 0;
345}
346
347static void __exit sunkbd_exit(void)
348{
349 serio_unregister_driver(&sunkbd_drv);
350}
351
352module_init(sunkbd_init);
353module_exit(sunkbd_exit);
diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c
new file mode 100644
index 000000000000..19eaec7789d1
--- /dev/null
+++ b/drivers/input/keyboard/xtkbd.c
@@ -0,0 +1,188 @@
1/*
2 * $Id: xtkbd.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
3 *
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 */
6
7/*
8 * XT keyboard driver for Linux
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/slab.h>
32#include <linux/module.h>
33#include <linux/input.h>
34#include <linux/init.h>
35#include <linux/serio.h>
36
37#define DRIVER_DESC "XT keyboard driver"
38
39MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
40MODULE_DESCRIPTION(DRIVER_DESC);
41MODULE_LICENSE("GPL");
42
43#define XTKBD_EMUL0 0xe0
44#define XTKBD_EMUL1 0xe1
45#define XTKBD_KEY 0x7f
46#define XTKBD_RELEASE 0x80
47
48static unsigned char xtkbd_keycode[256] = {
49 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
50 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
51 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
52 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
53 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
54 80, 81, 82, 83, 0, 0, 0, 87, 88, 0, 0, 0, 0, 0, 0, 0,
55 0, 0, 0, 0, 0, 87, 88, 0, 0, 0, 0,110,111,103,108,105,
56 106
57};
58
59static char *xtkbd_name = "XT Keyboard";
60
61struct xtkbd {
62 unsigned char keycode[256];
63 struct input_dev dev;
64 struct serio *serio;
65 char phys[32];
66};
67
68static irqreturn_t xtkbd_interrupt(struct serio *serio,
69 unsigned char data, unsigned int flags, struct pt_regs *regs)
70{
71 struct xtkbd *xtkbd = serio_get_drvdata(serio);
72
73 switch (data) {
74 case XTKBD_EMUL0:
75 case XTKBD_EMUL1:
76 break;
77 default:
78
79 if (xtkbd->keycode[data & XTKBD_KEY]) {
80 input_regs(&xtkbd->dev, regs);
81 input_report_key(&xtkbd->dev, xtkbd->keycode[data & XTKBD_KEY], !(data & XTKBD_RELEASE));
82 input_sync(&xtkbd->dev);
83 } else {
84 printk(KERN_WARNING "xtkbd.c: Unknown key (scancode %#x) %s.\n",
85 data & XTKBD_KEY, data & XTKBD_RELEASE ? "released" : "pressed");
86 }
87 }
88 return IRQ_HANDLED;
89}
90
91static int xtkbd_connect(struct serio *serio, struct serio_driver *drv)
92{
93 struct xtkbd *xtkbd;
94 int i;
95 int err;
96
97 if (!(xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL)))
98 return -ENOMEM;
99
100 memset(xtkbd, 0, sizeof(struct xtkbd));
101
102 xtkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
103
104 xtkbd->serio = serio;
105
106 init_input_dev(&xtkbd->dev);
107 xtkbd->dev.keycode = xtkbd->keycode;
108 xtkbd->dev.keycodesize = sizeof(unsigned char);
109 xtkbd->dev.keycodemax = ARRAY_SIZE(xtkbd_keycode);
110 xtkbd->dev.private = xtkbd;
111
112 serio_set_drvdata(serio, xtkbd);
113
114 err = serio_open(serio, drv);
115 if (err) {
116 serio_set_drvdata(serio, NULL);
117 kfree(xtkbd);
118 return err;
119 }
120
121 memcpy(xtkbd->keycode, xtkbd_keycode, sizeof(xtkbd->keycode));
122 for (i = 0; i < 255; i++)
123 set_bit(xtkbd->keycode[i], xtkbd->dev.keybit);
124 clear_bit(0, xtkbd->dev.keybit);
125
126 sprintf(xtkbd->phys, "%s/input0", serio->phys);
127
128 xtkbd->dev.name = xtkbd_name;
129 xtkbd->dev.phys = xtkbd->phys;
130 xtkbd->dev.id.bustype = BUS_XTKBD;
131 xtkbd->dev.id.vendor = 0x0001;
132 xtkbd->dev.id.product = 0x0001;
133 xtkbd->dev.id.version = 0x0100;
134 xtkbd->dev.dev = &serio->dev;
135
136 input_register_device(&xtkbd->dev);
137
138 printk(KERN_INFO "input: %s on %s\n", xtkbd_name, serio->phys);
139
140 return 0;
141}
142
143static void xtkbd_disconnect(struct serio *serio)
144{
145 struct xtkbd *xtkbd = serio_get_drvdata(serio);
146
147 input_unregister_device(&xtkbd->dev);
148 serio_close(serio);
149 serio_set_drvdata(serio, NULL);
150 kfree(xtkbd);
151}
152
153static struct serio_device_id xtkbd_serio_ids[] = {
154 {
155 .type = SERIO_XT,
156 .proto = SERIO_ANY,
157 .id = SERIO_ANY,
158 .extra = SERIO_ANY,
159 },
160 { 0 }
161};
162
163MODULE_DEVICE_TABLE(serio, xtkbd_serio_ids);
164
165static struct serio_driver xtkbd_drv = {
166 .driver = {
167 .name = "xtkbd",
168 },
169 .description = DRIVER_DESC,
170 .id_table = xtkbd_serio_ids,
171 .interrupt = xtkbd_interrupt,
172 .connect = xtkbd_connect,
173 .disconnect = xtkbd_disconnect,
174};
175
176static int __init xtkbd_init(void)
177{
178 serio_register_driver(&xtkbd_drv);
179 return 0;
180}
181
182static void __exit xtkbd_exit(void)
183{
184 serio_unregister_driver(&xtkbd_drv);
185}
186
187module_init(xtkbd_init);
188module_exit(xtkbd_exit);
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
new file mode 100644
index 000000000000..bb934e6d9636
--- /dev/null
+++ b/drivers/input/misc/Kconfig
@@ -0,0 +1,60 @@
1#
2# Input misc drivers configuration
3#
4menuconfig INPUT_MISC
5 bool "Miscellaneous devices"
6 help
7 Say Y here, and a list of miscellaneous input drivers will be displayed.
8 Everything that didn't fit into the other categories is here. This option
9 doesn't affect the kernel.
10
11 If unsure, say Y.
12
13if INPUT_MISC
14
15config INPUT_PCSPKR
16 tristate "PC Speaker support"
17 depends on ALPHA || X86 || X86_64 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES
18 help
19 Say Y here if you want the standard PC Speaker to be used for
20 bells and whistles.
21
22 If unsure, say Y.
23
24 To compile this driver as a module, choose M here: the
25 module will be called pcspkr.
26
27config INPUT_SPARCSPKR
28 tristate "SPARC Speaker support"
29 depends on PCI && (SPARC32 || SPARC64)
30 help
31 Say Y here if you want the standard Speaker on Sparc PCI systems
32 to be used for bells and whistles.
33
34 If unsure, say Y.
35
36 To compile this driver as a module, choose M here: the
37 module will be called sparcspkr.
38
39config INPUT_M68K_BEEP
40 tristate "M68k Beeper support"
41 depends on M68K
42
43config INPUT_UINPUT
44 tristate "User level driver support"
45 help
46 Say Y here if you want to support user level drivers for input
47 subsystem accessible under char device 10:223 - /dev/input/uinput.
48
49 To compile this driver as a module, choose M here: the
50 module will be called uinput.
51
52config HP_SDC_RTC
53 tristate "HP SDC Real Time Clock"
54 depends on GSC
55 select HP_SDC
56 help
57 Say Y here if you want to support the built-in real time clock
58 of the HP SDC controller.
59
60endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
new file mode 100644
index 000000000000..f8d01c69f349
--- /dev/null
+++ b/drivers/input/misc/Makefile
@@ -0,0 +1,12 @@
1#
2# Makefile for the input misc drivers.
3#
4
5# Each configuration option enables a list of files.
6
7obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o
8obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
9obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
10obj-$(CONFIG_INPUT_98SPKR) += 98spkr.o
11obj-$(CONFIG_INPUT_UINPUT) += uinput.o
12obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c
new file mode 100644
index 000000000000..1cd7657f7e42
--- /dev/null
+++ b/drivers/input/misc/hp_sdc_rtc.c
@@ -0,0 +1,724 @@
1/*
2 * HP i8042 SDC + MSM-58321 BBRTC driver.
3 *
4 * Copyright (c) 2001 Brian S. Julin
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * Alternatively, this software may be distributed under the terms of the
17 * GNU General Public License ("GPL").
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 *
29 * References:
30 * System Device Controller Microprocessor Firmware Theory of Operation
31 * for Part Number 1820-4784 Revision B. Dwg No. A-1820-4784-2
32 * efirtc.c by Stephane Eranian/Hewlett Packard
33 *
34 */
35
36#include <linux/hp_sdc.h>
37#include <linux/errno.h>
38#include <linux/types.h>
39#include <linux/init.h>
40#include <linux/module.h>
41#include <linux/time.h>
42#include <linux/miscdevice.h>
43#include <linux/proc_fs.h>
44#include <linux/poll.h>
45#include <linux/rtc.h>
46
47MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
48MODULE_DESCRIPTION("HP i8042 SDC + MSM-58321 RTC Driver");
49MODULE_LICENSE("Dual BSD/GPL");
50
51#define RTC_VERSION "1.10d"
52
53static unsigned long epoch = 2000;
54
55static struct semaphore i8042tregs;
56
57static hp_sdc_irqhook hp_sdc_rtc_isr;
58
59static struct fasync_struct *hp_sdc_rtc_async_queue;
60
61static DECLARE_WAIT_QUEUE_HEAD(hp_sdc_rtc_wait);
62
63static loff_t hp_sdc_rtc_llseek(struct file *file, loff_t offset, int origin);
64
65static ssize_t hp_sdc_rtc_read(struct file *file, char *buf,
66 size_t count, loff_t *ppos);
67
68static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file,
69 unsigned int cmd, unsigned long arg);
70
71static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait);
72
73static int hp_sdc_rtc_open(struct inode *inode, struct file *file);
74static int hp_sdc_rtc_release(struct inode *inode, struct file *file);
75static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on);
76
77static int hp_sdc_rtc_read_proc(char *page, char **start, off_t off,
78 int count, int *eof, void *data);
79
80static void hp_sdc_rtc_isr (int irq, void *dev_id,
81 uint8_t status, uint8_t data)
82{
83 return;
84}
85
86static int hp_sdc_rtc_do_read_bbrtc (struct rtc_time *rtctm)
87{
88 struct semaphore tsem;
89 hp_sdc_transaction t;
90 uint8_t tseq[91];
91 int i;
92
93 i = 0;
94 while (i < 91) {
95 tseq[i++] = HP_SDC_ACT_DATAREG |
96 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN;
97 tseq[i++] = 0x01; /* write i8042[0x70] */
98 tseq[i] = i / 7; /* BBRTC reg address */
99 i++;
100 tseq[i++] = HP_SDC_CMD_DO_RTCR; /* Trigger command */
101 tseq[i++] = 2; /* expect 1 stat/dat pair back. */
102 i++; i++; /* buffer for stat/dat pair */
103 }
104 tseq[84] |= HP_SDC_ACT_SEMAPHORE;
105 t.endidx = 91;
106 t.seq = tseq;
107 t.act.semaphore = &tsem;
108 init_MUTEX_LOCKED(&tsem);
109
110 if (hp_sdc_enqueue_transaction(&t)) return -1;
111
112 down_interruptible(&tsem); /* Put ourselves to sleep for results. */
113
114 /* Check for nonpresence of BBRTC */
115 if (!((tseq[83] | tseq[90] | tseq[69] | tseq[76] |
116 tseq[55] | tseq[62] | tseq[34] | tseq[41] |
117 tseq[20] | tseq[27] | tseq[6] | tseq[13]) & 0x0f))
118 return -1;
119
120 memset(rtctm, 0, sizeof(struct rtc_time));
121 rtctm->tm_year = (tseq[83] & 0x0f) + (tseq[90] & 0x0f) * 10;
122 rtctm->tm_mon = (tseq[69] & 0x0f) + (tseq[76] & 0x0f) * 10;
123 rtctm->tm_mday = (tseq[55] & 0x0f) + (tseq[62] & 0x0f) * 10;
124 rtctm->tm_wday = (tseq[48] & 0x0f);
125 rtctm->tm_hour = (tseq[34] & 0x0f) + (tseq[41] & 0x0f) * 10;
126 rtctm->tm_min = (tseq[20] & 0x0f) + (tseq[27] & 0x0f) * 10;
127 rtctm->tm_sec = (tseq[6] & 0x0f) + (tseq[13] & 0x0f) * 10;
128
129 return 0;
130}
131
132static int hp_sdc_rtc_read_bbrtc (struct rtc_time *rtctm)
133{
134 struct rtc_time tm, tm_last;
135 int i = 0;
136
137 /* MSM-58321 has no read latch, so must read twice and compare. */
138
139 if (hp_sdc_rtc_do_read_bbrtc(&tm_last)) return -1;
140 if (hp_sdc_rtc_do_read_bbrtc(&tm)) return -1;
141
142 while (memcmp(&tm, &tm_last, sizeof(struct rtc_time))) {
143 if (i++ > 4) return -1;
144 memcpy(&tm_last, &tm, sizeof(struct rtc_time));
145 if (hp_sdc_rtc_do_read_bbrtc(&tm)) return -1;
146 }
147
148 memcpy(rtctm, &tm, sizeof(struct rtc_time));
149
150 return 0;
151}
152
153
154static int64_t hp_sdc_rtc_read_i8042timer (uint8_t loadcmd, int numreg)
155{
156 hp_sdc_transaction t;
157 uint8_t tseq[26] = {
158 HP_SDC_ACT_PRECMD | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN,
159 0,
160 HP_SDC_CMD_READ_T1, 2, 0, 0,
161 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN,
162 HP_SDC_CMD_READ_T2, 2, 0, 0,
163 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN,
164 HP_SDC_CMD_READ_T3, 2, 0, 0,
165 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN,
166 HP_SDC_CMD_READ_T4, 2, 0, 0,
167 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN,
168 HP_SDC_CMD_READ_T5, 2, 0, 0
169 };
170
171 t.endidx = numreg * 5;
172
173 tseq[1] = loadcmd;
174 tseq[t.endidx - 4] |= HP_SDC_ACT_SEMAPHORE; /* numreg assumed > 1 */
175
176 t.seq = tseq;
177 t.act.semaphore = &i8042tregs;
178
179 down_interruptible(&i8042tregs); /* Sleep if output regs in use. */
180
181 if (hp_sdc_enqueue_transaction(&t)) return -1;
182
183 down_interruptible(&i8042tregs); /* Sleep until results come back. */
184 up(&i8042tregs);
185
186 return (tseq[5] |
187 ((uint64_t)(tseq[10]) << 8) | ((uint64_t)(tseq[15]) << 16) |
188 ((uint64_t)(tseq[20]) << 24) | ((uint64_t)(tseq[25]) << 32));
189}
190
191
192/* Read the i8042 real-time clock */
193static inline int hp_sdc_rtc_read_rt(struct timeval *res) {
194 int64_t raw;
195 uint32_t tenms;
196 unsigned int days;
197
198 raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_RT, 5);
199 if (raw < 0) return -1;
200
201 tenms = (uint32_t)raw & 0xffffff;
202 days = (unsigned int)(raw >> 24) & 0xffff;
203
204 res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
205 res->tv_sec = (time_t)(tenms / 100) + days * 86400;
206
207 return 0;
208}
209
210
211/* Read the i8042 fast handshake timer */
212static inline int hp_sdc_rtc_read_fhs(struct timeval *res) {
213 uint64_t raw;
214 unsigned int tenms;
215
216 raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_FHS, 2);
217 if (raw < 0) return -1;
218
219 tenms = (unsigned int)raw & 0xffff;
220
221 res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
222 res->tv_sec = (time_t)(tenms / 100);
223
224 return 0;
225}
226
227
228/* Read the i8042 match timer (a.k.a. alarm) */
229static inline int hp_sdc_rtc_read_mt(struct timeval *res) {
230 int64_t raw;
231 uint32_t tenms;
232
233 raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_MT, 3);
234 if (raw < 0) return -1;
235
236 tenms = (uint32_t)raw & 0xffffff;
237
238 res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
239 res->tv_sec = (time_t)(tenms / 100);
240
241 return 0;
242}
243
244
245/* Read the i8042 delay timer */
246static inline int hp_sdc_rtc_read_dt(struct timeval *res) {
247 int64_t raw;
248 uint32_t tenms;
249
250 raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_DT, 3);
251 if (raw < 0) return -1;
252
253 tenms = (uint32_t)raw & 0xffffff;
254
255 res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
256 res->tv_sec = (time_t)(tenms / 100);
257
258 return 0;
259}
260
261
262/* Read the i8042 cycle timer (a.k.a. periodic) */
263static inline int hp_sdc_rtc_read_ct(struct timeval *res) {
264 int64_t raw;
265 uint32_t tenms;
266
267 raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_CT, 3);
268 if (raw < 0) return -1;
269
270 tenms = (uint32_t)raw & 0xffffff;
271
272 res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
273 res->tv_sec = (time_t)(tenms / 100);
274
275 return 0;
276}
277
278
279/* Set the i8042 real-time clock */
280static int hp_sdc_rtc_set_rt (struct timeval *setto)
281{
282 uint32_t tenms;
283 unsigned int days;
284 hp_sdc_transaction t;
285 uint8_t tseq[11] = {
286 HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
287 HP_SDC_CMD_SET_RTMS, 3, 0, 0, 0,
288 HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
289 HP_SDC_CMD_SET_RTD, 2, 0, 0
290 };
291
292 t.endidx = 10;
293
294 if (0xffff < setto->tv_sec / 86400) return -1;
295 days = setto->tv_sec / 86400;
296 if (0xffff < setto->tv_usec / 1000000 / 86400) return -1;
297 days += ((setto->tv_sec % 86400) + setto->tv_usec / 1000000) / 86400;
298 if (days > 0xffff) return -1;
299
300 if (0xffffff < setto->tv_sec) return -1;
301 tenms = setto->tv_sec * 100;
302 if (0xffffff < setto->tv_usec / 10000) return -1;
303 tenms += setto->tv_usec / 10000;
304 if (tenms > 0xffffff) return -1;
305
306 tseq[3] = (uint8_t)(tenms & 0xff);
307 tseq[4] = (uint8_t)((tenms >> 8) & 0xff);
308 tseq[5] = (uint8_t)((tenms >> 16) & 0xff);
309
310 tseq[9] = (uint8_t)(days & 0xff);
311 tseq[10] = (uint8_t)((days >> 8) & 0xff);
312
313 t.seq = tseq;
314
315 if (hp_sdc_enqueue_transaction(&t)) return -1;
316 return 0;
317}
318
319/* Set the i8042 fast handshake timer */
320static int hp_sdc_rtc_set_fhs (struct timeval *setto)
321{
322 uint32_t tenms;
323 hp_sdc_transaction t;
324 uint8_t tseq[5] = {
325 HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
326 HP_SDC_CMD_SET_FHS, 2, 0, 0
327 };
328
329 t.endidx = 4;
330
331 if (0xffff < setto->tv_sec) return -1;
332 tenms = setto->tv_sec * 100;
333 if (0xffff < setto->tv_usec / 10000) return -1;
334 tenms += setto->tv_usec / 10000;
335 if (tenms > 0xffff) return -1;
336
337 tseq[3] = (uint8_t)(tenms & 0xff);
338 tseq[4] = (uint8_t)((tenms >> 8) & 0xff);
339
340 t.seq = tseq;
341
342 if (hp_sdc_enqueue_transaction(&t)) return -1;
343 return 0;
344}
345
346
347/* Set the i8042 match timer (a.k.a. alarm) */
348#define hp_sdc_rtc_set_mt (setto) \
349 hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_MT)
350
351/* Set the i8042 delay timer */
352#define hp_sdc_rtc_set_dt (setto) \
353 hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_DT)
354
355/* Set the i8042 cycle timer (a.k.a. periodic) */
356#define hp_sdc_rtc_set_ct (setto) \
357 hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_CT)
358
359/* Set one of the i8042 3-byte wide timers */
360static int hp_sdc_rtc_set_i8042timer (struct timeval *setto, uint8_t setcmd)
361{
362 uint32_t tenms;
363 hp_sdc_transaction t;
364 uint8_t tseq[6] = {
365 HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
366 0, 3, 0, 0, 0
367 };
368
369 t.endidx = 6;
370
371 if (0xffffff < setto->tv_sec) return -1;
372 tenms = setto->tv_sec * 100;
373 if (0xffffff < setto->tv_usec / 10000) return -1;
374 tenms += setto->tv_usec / 10000;
375 if (tenms > 0xffffff) return -1;
376
377 tseq[1] = setcmd;
378 tseq[3] = (uint8_t)(tenms & 0xff);
379 tseq[4] = (uint8_t)((tenms >> 8) & 0xff);
380 tseq[5] = (uint8_t)((tenms >> 16) & 0xff);
381
382 t.seq = tseq;
383
384 if (hp_sdc_enqueue_transaction(&t)) {
385 return -1;
386 }
387 return 0;
388}
389
390static loff_t hp_sdc_rtc_llseek(struct file *file, loff_t offset, int origin)
391{
392 return -ESPIPE;
393}
394
395static ssize_t hp_sdc_rtc_read(struct file *file, char *buf,
396 size_t count, loff_t *ppos) {
397 ssize_t retval;
398
399 if (count < sizeof(unsigned long))
400 return -EINVAL;
401
402 retval = put_user(68, (unsigned long *)buf);
403 return retval;
404}
405
406static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait)
407{
408 unsigned long l;
409
410 l = 0;
411 if (l != 0)
412 return POLLIN | POLLRDNORM;
413 return 0;
414}
415
416static int hp_sdc_rtc_open(struct inode *inode, struct file *file)
417{
418 return 0;
419}
420
421static int hp_sdc_rtc_release(struct inode *inode, struct file *file)
422{
423 /* Turn off interrupts? */
424
425 if (file->f_flags & FASYNC) {
426 hp_sdc_rtc_fasync (-1, file, 0);
427 }
428
429 return 0;
430}
431
432static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on)
433{
434 return fasync_helper (fd, filp, on, &hp_sdc_rtc_async_queue);
435}
436
437static int hp_sdc_rtc_proc_output (char *buf)
438{
439#define YN(bit) ("no")
440#define NY(bit) ("yes")
441 char *p;
442 struct rtc_time tm;
443 struct timeval tv;
444
445 memset(&tm, 0, sizeof(struct rtc_time));
446
447 p = buf;
448
449 if (hp_sdc_rtc_read_bbrtc(&tm)) {
450 p += sprintf(p, "BBRTC\t\t: READ FAILED!\n");
451 } else {
452 p += sprintf(p,
453 "rtc_time\t: %02d:%02d:%02d\n"
454 "rtc_date\t: %04d-%02d-%02d\n"
455 "rtc_epoch\t: %04lu\n",
456 tm.tm_hour, tm.tm_min, tm.tm_sec,
457 tm.tm_year + 1900, tm.tm_mon + 1,
458 tm.tm_mday, epoch);
459 }
460
461 if (hp_sdc_rtc_read_rt(&tv)) {
462 p += sprintf(p, "i8042 rtc\t: READ FAILED!\n");
463 } else {
464 p += sprintf(p, "i8042 rtc\t: %ld.%02d seconds\n",
465 tv.tv_sec, tv.tv_usec/1000);
466 }
467
468 if (hp_sdc_rtc_read_fhs(&tv)) {
469 p += sprintf(p, "handshake\t: READ FAILED!\n");
470 } else {
471 p += sprintf(p, "handshake\t: %ld.%02d seconds\n",
472 tv.tv_sec, tv.tv_usec/1000);
473 }
474
475 if (hp_sdc_rtc_read_mt(&tv)) {
476 p += sprintf(p, "alarm\t\t: READ FAILED!\n");
477 } else {
478 p += sprintf(p, "alarm\t\t: %ld.%02d seconds\n",
479 tv.tv_sec, tv.tv_usec/1000);
480 }
481
482 if (hp_sdc_rtc_read_dt(&tv)) {
483 p += sprintf(p, "delay\t\t: READ FAILED!\n");
484 } else {
485 p += sprintf(p, "delay\t\t: %ld.%02d seconds\n",
486 tv.tv_sec, tv.tv_usec/1000);
487 }
488
489 if (hp_sdc_rtc_read_ct(&tv)) {
490 p += sprintf(p, "periodic\t: READ FAILED!\n");
491 } else {
492 p += sprintf(p, "periodic\t: %ld.%02d seconds\n",
493 tv.tv_sec, tv.tv_usec/1000);
494 }
495
496 p += sprintf(p,
497 "DST_enable\t: %s\n"
498 "BCD\t\t: %s\n"
499 "24hr\t\t: %s\n"
500 "square_wave\t: %s\n"
501 "alarm_IRQ\t: %s\n"
502 "update_IRQ\t: %s\n"
503 "periodic_IRQ\t: %s\n"
504 "periodic_freq\t: %ld\n"
505 "batt_status\t: %s\n",
506 YN(RTC_DST_EN),
507 NY(RTC_DM_BINARY),
508 YN(RTC_24H),
509 YN(RTC_SQWE),
510 YN(RTC_AIE),
511 YN(RTC_UIE),
512 YN(RTC_PIE),
513 1UL,
514 1 ? "okay" : "dead");
515
516 return p - buf;
517#undef YN
518#undef NY
519}
520
521static int hp_sdc_rtc_read_proc(char *page, char **start, off_t off,
522 int count, int *eof, void *data)
523{
524 int len = hp_sdc_rtc_proc_output (page);
525 if (len <= off+count) *eof = 1;
526 *start = page + off;
527 len -= off;
528 if (len>count) len = count;
529 if (len<0) len = 0;
530 return len;
531}
532
533static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file,
534 unsigned int cmd, unsigned long arg)
535{
536#if 1
537 return -EINVAL;
538#else
539
540 struct rtc_time wtime;
541 struct timeval ttime;
542 int use_wtime = 0;
543
544 /* This needs major work. */
545
546 switch (cmd) {
547
548 case RTC_AIE_OFF: /* Mask alarm int. enab. bit */
549 case RTC_AIE_ON: /* Allow alarm interrupts. */
550 case RTC_PIE_OFF: /* Mask periodic int. enab. bit */
551 case RTC_PIE_ON: /* Allow periodic ints */
552 case RTC_UIE_ON: /* Allow ints for RTC updates. */
553 case RTC_UIE_OFF: /* Allow ints for RTC updates. */
554 {
555 /* We cannot mask individual user timers and we
556 cannot tell them apart when they occur, so it
557 would be disingenuous to succeed these IOCTLs */
558 return -EINVAL;
559 }
560 case RTC_ALM_READ: /* Read the present alarm time */
561 {
562 if (hp_sdc_rtc_read_mt(&ttime)) return -EFAULT;
563 if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT;
564
565 wtime.tm_hour = ttime.tv_sec / 3600; ttime.tv_sec %= 3600;
566 wtime.tm_min = ttime.tv_sec / 60; ttime.tv_sec %= 60;
567 wtime.tm_sec = ttime.tv_sec;
568
569 break;
570 }
571 case RTC_IRQP_READ: /* Read the periodic IRQ rate. */
572 {
573 return put_user(hp_sdc_rtc_freq, (unsigned long *)arg);
574 }
575 case RTC_IRQP_SET: /* Set periodic IRQ rate. */
576 {
577 /*
578 * The max we can do is 100Hz.
579 */
580
581 if ((arg < 1) || (arg > 100)) return -EINVAL;
582 ttime.tv_sec = 0;
583 ttime.tv_usec = 1000000 / arg;
584 if (hp_sdc_rtc_set_ct(&ttime)) return -EFAULT;
585 hp_sdc_rtc_freq = arg;
586 return 0;
587 }
588 case RTC_ALM_SET: /* Store a time into the alarm */
589 {
590 /*
591 * This expects a struct hp_sdc_rtc_time. Writing 0xff means
592 * "don't care" or "match all" for PC timers. The HP SDC
593 * does not support that perk, but it could be emulated fairly
594 * easily. Only the tm_hour, tm_min and tm_sec are used.
595 * We could do it with 10ms accuracy with the HP SDC, if the
596 * rtc interface left us a way to do that.
597 */
598 struct hp_sdc_rtc_time alm_tm;
599
600 if (copy_from_user(&alm_tm, (struct hp_sdc_rtc_time*)arg,
601 sizeof(struct hp_sdc_rtc_time)))
602 return -EFAULT;
603
604 if (alm_tm.tm_hour > 23) return -EINVAL;
605 if (alm_tm.tm_min > 59) return -EINVAL;
606 if (alm_tm.tm_sec > 59) return -EINVAL;
607
608 ttime.sec = alm_tm.tm_hour * 3600 +
609 alm_tm.tm_min * 60 + alm_tm.tm_sec;
610 ttime.usec = 0;
611 if (hp_sdc_rtc_set_mt(&ttime)) return -EFAULT;
612 return 0;
613 }
614 case RTC_RD_TIME: /* Read the time/date from RTC */
615 {
616 if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT;
617 break;
618 }
619 case RTC_SET_TIME: /* Set the RTC */
620 {
621 struct rtc_time hp_sdc_rtc_tm;
622 unsigned char mon, day, hrs, min, sec, leap_yr;
623 unsigned int yrs;
624
625 if (!capable(CAP_SYS_TIME))
626 return -EACCES;
627 if (copy_from_user(&hp_sdc_rtc_tm, (struct rtc_time *)arg,
628 sizeof(struct rtc_time)))
629 return -EFAULT;
630
631 yrs = hp_sdc_rtc_tm.tm_year + 1900;
632 mon = hp_sdc_rtc_tm.tm_mon + 1; /* tm_mon starts at zero */
633 day = hp_sdc_rtc_tm.tm_mday;
634 hrs = hp_sdc_rtc_tm.tm_hour;
635 min = hp_sdc_rtc_tm.tm_min;
636 sec = hp_sdc_rtc_tm.tm_sec;
637
638 if (yrs < 1970)
639 return -EINVAL;
640
641 leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
642
643 if ((mon > 12) || (day == 0))
644 return -EINVAL;
645 if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
646 return -EINVAL;
647 if ((hrs >= 24) || (min >= 60) || (sec >= 60))
648 return -EINVAL;
649
650 if ((yrs -= eH) > 255) /* They are unsigned */
651 return -EINVAL;
652
653
654 return 0;
655 }
656 case RTC_EPOCH_READ: /* Read the epoch. */
657 {
658 return put_user (epoch, (unsigned long *)arg);
659 }
660 case RTC_EPOCH_SET: /* Set the epoch. */
661 {
662 /*
663 * There were no RTC clocks before 1900.
664 */
665 if (arg < 1900)
666 return -EINVAL;
667 if (!capable(CAP_SYS_TIME))
668 return -EACCES;
669
670 epoch = arg;
671 return 0;
672 }
673 default:
674 return -EINVAL;
675 }
676 return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
677#endif
678}
679
680static struct file_operations hp_sdc_rtc_fops = {
681 .owner = THIS_MODULE,
682 .llseek = hp_sdc_rtc_llseek,
683 .read = hp_sdc_rtc_read,
684 .poll = hp_sdc_rtc_poll,
685 .ioctl = hp_sdc_rtc_ioctl,
686 .open = hp_sdc_rtc_open,
687 .release = hp_sdc_rtc_release,
688 .fasync = hp_sdc_rtc_fasync,
689};
690
691static struct miscdevice hp_sdc_rtc_dev = {
692 .minor = RTC_MINOR,
693 .name = "rtc_HIL",
694 .fops = &hp_sdc_rtc_fops
695};
696
697static int __init hp_sdc_rtc_init(void)
698{
699 int ret;
700
701 init_MUTEX(&i8042tregs);
702
703 if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr)))
704 return ret;
705 misc_register(&hp_sdc_rtc_dev);
706 create_proc_read_entry ("driver/rtc", 0, 0,
707 hp_sdc_rtc_read_proc, NULL);
708
709 printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support loaded "
710 "(RTC v " RTC_VERSION ")\n");
711
712 return 0;
713}
714
715static void __exit hp_sdc_rtc_exit(void)
716{
717 remove_proc_entry ("driver/rtc", NULL);
718 misc_deregister(&hp_sdc_rtc_dev);
719 hp_sdc_release_timer_irq(hp_sdc_rtc_isr);
720 printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support unloaded\n");
721}
722
723module_init(hp_sdc_rtc_init);
724module_exit(hp_sdc_rtc_exit);
diff --git a/drivers/input/misc/m68kspkr.c b/drivers/input/misc/m68kspkr.c
new file mode 100644
index 000000000000..64abdd98d482
--- /dev/null
+++ b/drivers/input/misc/m68kspkr.c
@@ -0,0 +1,83 @@
1/*
2 * m68k beeper driver for Linux
3 *
4 * Copyright (c) 2002 Richard Zidlicky
5 * Copyright (c) 2002 Vojtech Pavlik
6 * Copyright (c) 1992 Orest Zborowski
7 *
8 */
9
10/*
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License version 2 as published by
13 * the Free Software Foundation
14 */
15
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/init.h>
19#include <linux/input.h>
20#include <asm/machdep.h>
21#include <asm/io.h>
22
23MODULE_AUTHOR("Richard Zidlicky <rz@linux-m68k.org>");
24MODULE_DESCRIPTION("m68k beeper driver");
25MODULE_LICENSE("GPL");
26
27static char m68kspkr_name[] = "m68k beeper";
28static char m68kspkr_phys[] = "m68k/generic";
29static struct input_dev m68kspkr_dev;
30
31static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
32{
33 unsigned int count = 0;
34
35 if (type != EV_SND)
36 return -1;
37
38 switch (code) {
39 case SND_BELL: if (value) value = 1000;
40 case SND_TONE: break;
41 default: return -1;
42 }
43
44 if (value > 20 && value < 32767)
45 count = 1193182 / value;
46
47 mach_beep(count, -1);
48
49 return 0;
50}
51
52static int __init m68kspkr_init(void)
53{
54 if (!mach_beep){
55 printk("%s: no lowlevel beep support\n", m68kspkr_name);
56 return -1;
57 }
58
59 m68kspkr_dev.evbit[0] = BIT(EV_SND);
60 m68kspkr_dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
61 m68kspkr_dev.event = m68kspkr_event;
62
63 m68kspkr_dev.name = m68kspkr_name;
64 m68kspkr_dev.phys = m68kspkr_phys;
65 m68kspkr_dev.id.bustype = BUS_HOST;
66 m68kspkr_dev.id.vendor = 0x001f;
67 m68kspkr_dev.id.product = 0x0001;
68 m68kspkr_dev.id.version = 0x0100;
69
70 input_register_device(&m68kspkr_dev);
71
72 printk(KERN_INFO "input: %s\n", m68kspkr_name);
73
74 return 0;
75}
76
77static void __exit m68kspkr_exit(void)
78{
79 input_unregister_device(&m68kspkr_dev);
80}
81
82module_init(m68kspkr_init);
83module_exit(m68kspkr_exit);
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
new file mode 100644
index 000000000000..3013194f462b
--- /dev/null
+++ b/drivers/input/misc/pcspkr.c
@@ -0,0 +1,97 @@
1/*
2 * PC Speaker beeper driver for Linux
3 *
4 * Copyright (c) 2002 Vojtech Pavlik
5 * Copyright (c) 1992 Orest Zborowski
6 *
7 */
8
9/*
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation
13 */
14
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/init.h>
18#include <linux/input.h>
19#include <asm/8253pit.h>
20#include <asm/io.h>
21
22MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
23MODULE_DESCRIPTION("PC Speaker beeper driver");
24MODULE_LICENSE("GPL");
25
26static char pcspkr_name[] = "PC Speaker";
27static char pcspkr_phys[] = "isa0061/input0";
28static struct input_dev pcspkr_dev;
29
30static DEFINE_SPINLOCK(i8253_beep_lock);
31
32static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
33{
34 unsigned int count = 0;
35 unsigned long flags;
36
37 if (type != EV_SND)
38 return -1;
39
40 switch (code) {
41 case SND_BELL: if (value) value = 1000;
42 case SND_TONE: break;
43 default: return -1;
44 }
45
46 if (value > 20 && value < 32767)
47 count = PIT_TICK_RATE / value;
48
49 spin_lock_irqsave(&i8253_beep_lock, flags);
50
51 if (count) {
52 /* enable counter 2 */
53 outb_p(inb_p(0x61) | 3, 0x61);
54 /* set command for counter 2, 2 byte write */
55 outb_p(0xB6, 0x43);
56 /* select desired HZ */
57 outb_p(count & 0xff, 0x42);
58 outb((count >> 8) & 0xff, 0x42);
59 } else {
60 /* disable counter 2 */
61 outb(inb_p(0x61) & 0xFC, 0x61);
62 }
63
64 spin_unlock_irqrestore(&i8253_beep_lock, flags);
65
66 return 0;
67}
68
69static int __init pcspkr_init(void)
70{
71 pcspkr_dev.evbit[0] = BIT(EV_SND);
72 pcspkr_dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
73 pcspkr_dev.event = pcspkr_event;
74
75 pcspkr_dev.name = pcspkr_name;
76 pcspkr_dev.phys = pcspkr_phys;
77 pcspkr_dev.id.bustype = BUS_ISA;
78 pcspkr_dev.id.vendor = 0x001f;
79 pcspkr_dev.id.product = 0x0001;
80 pcspkr_dev.id.version = 0x0100;
81
82 input_register_device(&pcspkr_dev);
83
84 printk(KERN_INFO "input: %s\n", pcspkr_name);
85
86 return 0;
87}
88
89static void __exit pcspkr_exit(void)
90{
91 input_unregister_device(&pcspkr_dev);
92 /* turn off the speaker */
93 pcspkr_event(NULL, EV_SND, SND_BELL, 0);
94}
95
96module_init(pcspkr_init);
97module_exit(pcspkr_exit);
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
new file mode 100644
index 000000000000..cdc3fb3d5f46
--- /dev/null
+++ b/drivers/input/misc/sparcspkr.c
@@ -0,0 +1,189 @@
1/*
2 * Driver for PC-speaker like devices found on various Sparc systems.
3 *
4 * Copyright (c) 2002 Vojtech Pavlik
5 * Copyright (c) 2002 David S. Miller (davem@redhat.com)
6 */
7#include <linux/config.h>
8#include <linux/kernel.h>
9#include <linux/module.h>
10#include <linux/init.h>
11#include <linux/input.h>
12
13#include <asm/io.h>
14#include <asm/ebus.h>
15#ifdef CONFIG_SPARC64
16#include <asm/isa.h>
17#endif
18
19MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
20MODULE_DESCRIPTION("PC Speaker beeper driver");
21MODULE_LICENSE("GPL");
22
23static unsigned long beep_iobase;
24
25static char *sparcspkr_isa_name = "Sparc ISA Speaker";
26static char *sparcspkr_ebus_name = "Sparc EBUS Speaker";
27static char *sparcspkr_phys = "sparc/input0";
28static struct input_dev sparcspkr_dev;
29
30DEFINE_SPINLOCK(beep_lock);
31
32static void __init init_sparcspkr_struct(void)
33{
34 sparcspkr_dev.evbit[0] = BIT(EV_SND);
35 sparcspkr_dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
36
37 sparcspkr_dev.phys = sparcspkr_phys;
38 sparcspkr_dev.id.bustype = BUS_ISA;
39 sparcspkr_dev.id.vendor = 0x001f;
40 sparcspkr_dev.id.product = 0x0001;
41 sparcspkr_dev.id.version = 0x0100;
42}
43
44static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
45{
46 unsigned int count = 0;
47 unsigned long flags;
48
49 if (type != EV_SND)
50 return -1;
51
52 switch (code) {
53 case SND_BELL: if (value) value = 1000;
54 case SND_TONE: break;
55 default: return -1;
56 }
57
58 if (value > 20 && value < 32767)
59 count = 1193182 / value;
60
61 spin_lock_irqsave(&beep_lock, flags);
62
63 /* EBUS speaker only has on/off state, the frequency does not
64 * appear to be programmable.
65 */
66 if (count) {
67 if (beep_iobase & 0x2UL)
68 outb(1, beep_iobase);
69 else
70 outl(1, beep_iobase);
71 } else {
72 if (beep_iobase & 0x2UL)
73 outb(0, beep_iobase);
74 else
75 outl(0, beep_iobase);
76 }
77
78 spin_unlock_irqrestore(&beep_lock, flags);
79
80 return 0;
81}
82
83static int __init init_ebus_beep(struct linux_ebus_device *edev)
84{
85 beep_iobase = edev->resource[0].start;
86
87 init_sparcspkr_struct();
88
89 sparcspkr_dev.name = sparcspkr_ebus_name;
90 sparcspkr_dev.event = ebus_spkr_event;
91
92 input_register_device(&sparcspkr_dev);
93
94 printk(KERN_INFO "input: %s\n", sparcspkr_ebus_name);
95 return 0;
96}
97
98#ifdef CONFIG_SPARC64
99static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
100{
101 unsigned int count = 0;
102 unsigned long flags;
103
104 if (type != EV_SND)
105 return -1;
106
107 switch (code) {
108 case SND_BELL: if (value) value = 1000;
109 case SND_TONE: break;
110 default: return -1;
111 }
112
113 if (value > 20 && value < 32767)
114 count = 1193182 / value;
115
116 spin_lock_irqsave(&beep_lock, flags);
117
118 if (count) {
119 /* enable counter 2 */
120 outb(inb(beep_iobase + 0x61) | 3, beep_iobase + 0x61);
121 /* set command for counter 2, 2 byte write */
122 outb(0xB6, beep_iobase + 0x43);
123 /* select desired HZ */
124 outb(count & 0xff, beep_iobase + 0x42);
125 outb((count >> 8) & 0xff, beep_iobase + 0x42);
126 } else {
127 /* disable counter 2 */
128 outb(inb_p(beep_iobase + 0x61) & 0xFC, beep_iobase + 0x61);
129 }
130
131 spin_unlock_irqrestore(&beep_lock, flags);
132
133 return 0;
134}
135
136static int __init init_isa_beep(struct sparc_isa_device *isa_dev)
137{
138 beep_iobase = isa_dev->resource.start;
139
140 init_sparcspkr_struct();
141
142 sparcspkr_dev.name = sparcspkr_isa_name;
143 sparcspkr_dev.event = isa_spkr_event;
144 sparcspkr_dev.id.bustype = BUS_ISA;
145
146 input_register_device(&sparcspkr_dev);
147
148 printk(KERN_INFO "input: %s\n", sparcspkr_isa_name);
149 return 0;
150}
151#endif
152
153static int __init sparcspkr_init(void)
154{
155 struct linux_ebus *ebus;
156 struct linux_ebus_device *edev = NULL;
157#ifdef CONFIG_SPARC64
158 struct sparc_isa_bridge *isa_br;
159 struct sparc_isa_device *isa_dev;
160#endif
161
162 for_each_ebus(ebus) {
163 for_each_ebusdev(edev, ebus) {
164 if (!strcmp(edev->prom_name, "beep"))
165 return init_ebus_beep(edev);
166 }
167 }
168#ifdef CONFIG_SPARC64
169 for_each_isa(isa_br) {
170 for_each_isadev(isa_dev, isa_br) {
171 /* A hack, the beep device's base lives in
172 * the DMA isa node.
173 */
174 if (!strcmp(isa_dev->prom_name, "dma"))
175 return init_isa_beep(isa_dev);
176 }
177 }
178#endif
179
180 return -ENODEV;
181}
182
183static void __exit sparcspkr_exit(void)
184{
185 input_unregister_device(&sparcspkr_dev);
186}
187
188module_init(sparcspkr_init);
189module_exit(sparcspkr_exit);
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
new file mode 100644
index 000000000000..158c8e845ff9
--- /dev/null
+++ b/drivers/input/misc/uinput.c
@@ -0,0 +1,620 @@
1/*
2 * User level driver support for input subsystem
3 *
4 * Heavily based on evdev.c by Vojtech Pavlik
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
21 *
22 * Changes/Revisions:
23 * 0.2 16/10/2004 (Micah Dowty <micah@navi.cx>)
24 * - added force feedback support
25 * - added UI_SET_PHYS
26 * 0.1 20/06/2002
27 * - first public version
28 */
29#include <linux/poll.h>
30#include <linux/slab.h>
31#include <linux/module.h>
32#include <linux/init.h>
33#include <linux/input.h>
34#include <linux/smp_lock.h>
35#include <linux/fs.h>
36#include <linux/miscdevice.h>
37#include <linux/uinput.h>
38
39static int uinput_dev_open(struct input_dev *dev)
40{
41 return 0;
42}
43
44static void uinput_dev_close(struct input_dev *dev)
45{
46
47}
48
49static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
50{
51 struct uinput_device *udev;
52
53 udev = dev->private;
54
55 udev->buff[udev->head].type = type;
56 udev->buff[udev->head].code = code;
57 udev->buff[udev->head].value = value;
58 do_gettimeofday(&udev->buff[udev->head].time);
59 udev->head = (udev->head + 1) % UINPUT_BUFFER_SIZE;
60
61 wake_up_interruptible(&udev->waitq);
62
63 return 0;
64}
65
66static int uinput_request_alloc_id(struct input_dev *dev, struct uinput_request *request)
67{
68 /* Atomically allocate an ID for the given request. Returns 0 on success. */
69 struct uinput_device *udev = dev->private;
70 int id;
71
72 down(&udev->requests_sem);
73 for (id=0; id<UINPUT_NUM_REQUESTS; id++)
74 if (!udev->requests[id]) {
75 udev->requests[id] = request;
76 request->id = id;
77 up(&udev->requests_sem);
78 return 0;
79 }
80 up(&udev->requests_sem);
81 return -1;
82}
83
84static struct uinput_request* uinput_request_find(struct uinput_device *udev, int id)
85{
86 /* Find an input request, by ID. Returns NULL if the ID isn't valid. */
87 if (id >= UINPUT_NUM_REQUESTS || id < 0)
88 return NULL;
89 if (udev->requests[id]->completed)
90 return NULL;
91 return udev->requests[id];
92}
93
94static void uinput_request_init(struct input_dev *dev, struct uinput_request *request, int code)
95{
96 struct uinput_device *udev = dev->private;
97
98 memset(request, 0, sizeof(struct uinput_request));
99 request->code = code;
100 init_waitqueue_head(&request->waitq);
101
102 /* Allocate an ID. If none are available right away, wait. */
103 request->retval = wait_event_interruptible(udev->requests_waitq,
104 !uinput_request_alloc_id(dev, request));
105}
106
107static void uinput_request_submit(struct input_dev *dev, struct uinput_request *request)
108{
109 struct uinput_device *udev = dev->private;
110 int retval;
111
112 /* Tell our userspace app about this new request by queueing an input event */
113 uinput_dev_event(dev, EV_UINPUT, request->code, request->id);
114
115 /* Wait for the request to complete */
116 retval = wait_event_interruptible(request->waitq, request->completed);
117 if (retval)
118 request->retval = retval;
119
120 /* Release this request's ID, let others know it's available */
121 udev->requests[request->id] = NULL;
122 wake_up_interruptible(&udev->requests_waitq);
123}
124
125static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *effect)
126{
127 struct uinput_request request;
128
129 if (!test_bit(EV_FF, dev->evbit))
130 return -ENOSYS;
131
132 uinput_request_init(dev, &request, UI_FF_UPLOAD);
133 if (request.retval)
134 return request.retval;
135 request.u.effect = effect;
136 uinput_request_submit(dev, &request);
137 return request.retval;
138}
139
140static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id)
141{
142 struct uinput_request request;
143
144 if (!test_bit(EV_FF, dev->evbit))
145 return -ENOSYS;
146
147 uinput_request_init(dev, &request, UI_FF_ERASE);
148 if (request.retval)
149 return request.retval;
150 request.u.effect_id = effect_id;
151 uinput_request_submit(dev, &request);
152 return request.retval;
153}
154
155static int uinput_create_device(struct uinput_device *udev)
156{
157 if (!udev->dev->name) {
158 printk(KERN_DEBUG "%s: write device info first\n", UINPUT_NAME);
159 return -EINVAL;
160 }
161
162 udev->dev->open = uinput_dev_open;
163 udev->dev->close = uinput_dev_close;
164 udev->dev->event = uinput_dev_event;
165 udev->dev->upload_effect = uinput_dev_upload_effect;
166 udev->dev->erase_effect = uinput_dev_erase_effect;
167 udev->dev->private = udev;
168
169 init_waitqueue_head(&(udev->waitq));
170
171 input_register_device(udev->dev);
172
173 set_bit(UIST_CREATED, &(udev->state));
174
175 return 0;
176}
177
178static int uinput_destroy_device(struct uinput_device *udev)
179{
180 if (!test_bit(UIST_CREATED, &(udev->state))) {
181 printk(KERN_WARNING "%s: create the device first\n", UINPUT_NAME);
182 return -EINVAL;
183 }
184
185 input_unregister_device(udev->dev);
186
187 clear_bit(UIST_CREATED, &(udev->state));
188
189 return 0;
190}
191
192static int uinput_open(struct inode *inode, struct file *file)
193{
194 struct uinput_device *newdev;
195 struct input_dev *newinput;
196
197 newdev = kmalloc(sizeof(struct uinput_device), GFP_KERNEL);
198 if (!newdev)
199 goto error;
200 memset(newdev, 0, sizeof(struct uinput_device));
201 init_MUTEX(&newdev->requests_sem);
202 init_waitqueue_head(&newdev->requests_waitq);
203
204 newinput = kmalloc(sizeof(struct input_dev), GFP_KERNEL);
205 if (!newinput)
206 goto cleanup;
207 memset(newinput, 0, sizeof(struct input_dev));
208
209 newdev->dev = newinput;
210
211 file->private_data = newdev;
212
213 return 0;
214cleanup:
215 kfree(newdev);
216error:
217 return -ENOMEM;
218}
219
220static int uinput_validate_absbits(struct input_dev *dev)
221{
222 unsigned int cnt;
223 int retval = 0;
224
225 for (cnt = 0; cnt < ABS_MAX + 1; cnt++) {
226 if (!test_bit(cnt, dev->absbit))
227 continue;
228
229 if ((dev->absmax[cnt] <= dev->absmin[cnt])) {
230 printk(KERN_DEBUG
231 "%s: invalid abs[%02x] min:%d max:%d\n",
232 UINPUT_NAME, cnt,
233 dev->absmin[cnt], dev->absmax[cnt]);
234 retval = -EINVAL;
235 break;
236 }
237
238 if (dev->absflat[cnt] > (dev->absmax[cnt] - dev->absmin[cnt])) {
239 printk(KERN_DEBUG
240 "%s: absflat[%02x] out of range: %d "
241 "(min:%d/max:%d)\n",
242 UINPUT_NAME, cnt, dev->absflat[cnt],
243 dev->absmin[cnt], dev->absmax[cnt]);
244 retval = -EINVAL;
245 break;
246 }
247 }
248 return retval;
249}
250
251static int uinput_alloc_device(struct file *file, const char __user *buffer, size_t count)
252{
253 struct uinput_user_dev *user_dev;
254 struct input_dev *dev;
255 struct uinput_device *udev;
256 int size,
257 retval;
258
259 retval = count;
260
261 udev = file->private_data;
262 dev = udev->dev;
263
264 user_dev = kmalloc(sizeof(*user_dev), GFP_KERNEL);
265 if (!user_dev) {
266 retval = -ENOMEM;
267 goto exit;
268 }
269
270 if (copy_from_user(user_dev, buffer, sizeof(struct uinput_user_dev))) {
271 retval = -EFAULT;
272 goto exit;
273 }
274
275 if (NULL != dev->name)
276 kfree(dev->name);
277
278 size = strnlen(user_dev->name, UINPUT_MAX_NAME_SIZE) + 1;
279 dev->name = kmalloc(size, GFP_KERNEL);
280 if (!dev->name) {
281 retval = -ENOMEM;
282 goto exit;
283 }
284
285 strlcpy(dev->name, user_dev->name, size);
286 dev->id.bustype = user_dev->id.bustype;
287 dev->id.vendor = user_dev->id.vendor;
288 dev->id.product = user_dev->id.product;
289 dev->id.version = user_dev->id.version;
290 dev->ff_effects_max = user_dev->ff_effects_max;
291
292 size = sizeof(int) * (ABS_MAX + 1);
293 memcpy(dev->absmax, user_dev->absmax, size);
294 memcpy(dev->absmin, user_dev->absmin, size);
295 memcpy(dev->absfuzz, user_dev->absfuzz, size);
296 memcpy(dev->absflat, user_dev->absflat, size);
297
298 /* check if absmin/absmax/absfuzz/absflat are filled as
299 * told in Documentation/input/input-programming.txt */
300 if (test_bit(EV_ABS, dev->evbit)) {
301 retval = uinput_validate_absbits(dev);
302 if (retval < 0)
303 kfree(dev->name);
304 }
305
306exit:
307 kfree(user_dev);
308 return retval;
309}
310
311static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
312{
313 struct uinput_device *udev = file->private_data;
314
315 if (test_bit(UIST_CREATED, &(udev->state))) {
316 struct input_event ev;
317
318 if (copy_from_user(&ev, buffer, sizeof(struct input_event)))
319 return -EFAULT;
320 input_event(udev->dev, ev.type, ev.code, ev.value);
321 }
322 else
323 count = uinput_alloc_device(file, buffer, count);
324
325 return count;
326}
327
328static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
329{
330 struct uinput_device *udev = file->private_data;
331 int retval = 0;
332
333 if (!test_bit(UIST_CREATED, &(udev->state)))
334 return -ENODEV;
335
336 if ((udev->head == udev->tail) && (file->f_flags & O_NONBLOCK))
337 return -EAGAIN;
338
339 retval = wait_event_interruptible(udev->waitq,
340 (udev->head != udev->tail) ||
341 !test_bit(UIST_CREATED, &(udev->state)));
342
343 if (retval)
344 return retval;
345
346 if (!test_bit(UIST_CREATED, &(udev->state)))
347 return -ENODEV;
348
349 while ((udev->head != udev->tail) &&
350 (retval + sizeof(struct input_event) <= count)) {
351 if (copy_to_user(buffer + retval, &(udev->buff[udev->tail]),
352 sizeof(struct input_event))) return -EFAULT;
353 udev->tail = (udev->tail + 1) % UINPUT_BUFFER_SIZE;
354 retval += sizeof(struct input_event);
355 }
356
357 return retval;
358}
359
360static unsigned int uinput_poll(struct file *file, poll_table *wait)
361{
362 struct uinput_device *udev = file->private_data;
363
364 poll_wait(file, &udev->waitq, wait);
365
366 if (udev->head != udev->tail)
367 return POLLIN | POLLRDNORM;
368
369 return 0;
370}
371
372static int uinput_burn_device(struct uinput_device *udev)
373{
374 if (test_bit(UIST_CREATED, &(udev->state)))
375 uinput_destroy_device(udev);
376
377 if (NULL != udev->dev->name)
378 kfree(udev->dev->name);
379 if (NULL != udev->dev->phys)
380 kfree(udev->dev->phys);
381
382 kfree(udev->dev);
383 kfree(udev);
384
385 return 0;
386}
387
388static int uinput_close(struct inode *inode, struct file *file)
389{
390 return uinput_burn_device(file->private_data);
391}
392
393static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
394{
395 int retval = 0;
396 struct uinput_device *udev;
397 void __user *p = (void __user *)arg;
398 struct uinput_ff_upload ff_up;
399 struct uinput_ff_erase ff_erase;
400 struct uinput_request *req;
401 int length;
402
403 udev = file->private_data;
404
405 /* device attributes can not be changed after the device is created */
406 switch (cmd) {
407 case UI_SET_EVBIT:
408 case UI_SET_KEYBIT:
409 case UI_SET_RELBIT:
410 case UI_SET_ABSBIT:
411 case UI_SET_MSCBIT:
412 case UI_SET_LEDBIT:
413 case UI_SET_SNDBIT:
414 case UI_SET_FFBIT:
415 case UI_SET_PHYS:
416 if (test_bit(UIST_CREATED, &(udev->state)))
417 return -EINVAL;
418 }
419
420 switch (cmd) {
421 case UI_DEV_CREATE:
422 retval = uinput_create_device(udev);
423 break;
424
425 case UI_DEV_DESTROY:
426 retval = uinput_destroy_device(udev);
427 break;
428
429 case UI_SET_EVBIT:
430 if (arg > EV_MAX) {
431 retval = -EINVAL;
432 break;
433 }
434 set_bit(arg, udev->dev->evbit);
435 break;
436
437 case UI_SET_KEYBIT:
438 if (arg > KEY_MAX) {
439 retval = -EINVAL;
440 break;
441 }
442 set_bit(arg, udev->dev->keybit);
443 break;
444
445 case UI_SET_RELBIT:
446 if (arg > REL_MAX) {
447 retval = -EINVAL;
448 break;
449 }
450 set_bit(arg, udev->dev->relbit);
451 break;
452
453 case UI_SET_ABSBIT:
454 if (arg > ABS_MAX) {
455 retval = -EINVAL;
456 break;
457 }
458 set_bit(arg, udev->dev->absbit);
459 break;
460
461 case UI_SET_MSCBIT:
462 if (arg > MSC_MAX) {
463 retval = -EINVAL;
464 break;
465 }
466 set_bit(arg, udev->dev->mscbit);
467 break;
468
469 case UI_SET_LEDBIT:
470 if (arg > LED_MAX) {
471 retval = -EINVAL;
472 break;
473 }
474 set_bit(arg, udev->dev->ledbit);
475 break;
476
477 case UI_SET_SNDBIT:
478 if (arg > SND_MAX) {
479 retval = -EINVAL;
480 break;
481 }
482 set_bit(arg, udev->dev->sndbit);
483 break;
484
485 case UI_SET_FFBIT:
486 if (arg > FF_MAX) {
487 retval = -EINVAL;
488 break;
489 }
490 set_bit(arg, udev->dev->ffbit);
491 break;
492
493 case UI_SET_PHYS:
494 length = strnlen_user(p, 1024);
495 if (length <= 0) {
496 retval = -EFAULT;
497 break;
498 }
499 if (NULL != udev->dev->phys)
500 kfree(udev->dev->phys);
501 udev->dev->phys = kmalloc(length, GFP_KERNEL);
502 if (!udev->dev->phys) {
503 retval = -ENOMEM;
504 break;
505 }
506 if (copy_from_user(udev->dev->phys, p, length)) {
507 retval = -EFAULT;
508 kfree(udev->dev->phys);
509 udev->dev->phys = NULL;
510 break;
511 }
512 udev->dev->phys[length-1] = '\0';
513 break;
514
515 case UI_BEGIN_FF_UPLOAD:
516 if (copy_from_user(&ff_up, p, sizeof(ff_up))) {
517 retval = -EFAULT;
518 break;
519 }
520 req = uinput_request_find(udev, ff_up.request_id);
521 if (!(req && req->code==UI_FF_UPLOAD && req->u.effect)) {
522 retval = -EINVAL;
523 break;
524 }
525 ff_up.retval = 0;
526 memcpy(&ff_up.effect, req->u.effect, sizeof(struct ff_effect));
527 if (copy_to_user(p, &ff_up, sizeof(ff_up))) {
528 retval = -EFAULT;
529 break;
530 }
531 break;
532
533 case UI_BEGIN_FF_ERASE:
534 if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
535 retval = -EFAULT;
536 break;
537 }
538 req = uinput_request_find(udev, ff_erase.request_id);
539 if (!(req && req->code==UI_FF_ERASE)) {
540 retval = -EINVAL;
541 break;
542 }
543 ff_erase.retval = 0;
544 ff_erase.effect_id = req->u.effect_id;
545 if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) {
546 retval = -EFAULT;
547 break;
548 }
549 break;
550
551 case UI_END_FF_UPLOAD:
552 if (copy_from_user(&ff_up, p, sizeof(ff_up))) {
553 retval = -EFAULT;
554 break;
555 }
556 req = uinput_request_find(udev, ff_up.request_id);
557 if (!(req && req->code==UI_FF_UPLOAD && req->u.effect)) {
558 retval = -EINVAL;
559 break;
560 }
561 req->retval = ff_up.retval;
562 memcpy(req->u.effect, &ff_up.effect, sizeof(struct ff_effect));
563 req->completed = 1;
564 wake_up_interruptible(&req->waitq);
565 break;
566
567 case UI_END_FF_ERASE:
568 if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
569 retval = -EFAULT;
570 break;
571 }
572 req = uinput_request_find(udev, ff_erase.request_id);
573 if (!(req && req->code==UI_FF_ERASE)) {
574 retval = -EINVAL;
575 break;
576 }
577 req->retval = ff_erase.retval;
578 req->completed = 1;
579 wake_up_interruptible(&req->waitq);
580 break;
581
582 default:
583 retval = -EINVAL;
584 }
585 return retval;
586}
587
588static struct file_operations uinput_fops = {
589 .owner = THIS_MODULE,
590 .open = uinput_open,
591 .release = uinput_close,
592 .read = uinput_read,
593 .write = uinput_write,
594 .poll = uinput_poll,
595 .ioctl = uinput_ioctl,
596};
597
598static struct miscdevice uinput_misc = {
599 .fops = &uinput_fops,
600 .minor = UINPUT_MINOR,
601 .name = UINPUT_NAME,
602};
603
604static int __init uinput_init(void)
605{
606 return misc_register(&uinput_misc);
607}
608
609static void __exit uinput_exit(void)
610{
611 misc_deregister(&uinput_misc);
612}
613
614MODULE_AUTHOR("Aristeu Sergio Rozanski Filho");
615MODULE_DESCRIPTION("User level driver support for input subsystem");
616MODULE_LICENSE("GPL");
617
618module_init(uinput_init);
619module_exit(uinput_exit);
620
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
new file mode 100644
index 000000000000..537154dd7a87
--- /dev/null
+++ b/drivers/input/mouse/Kconfig
@@ -0,0 +1,138 @@
1#
2# Mouse driver configuration
3#
4menuconfig INPUT_MOUSE
5 bool "Mouse"
6 default y
7 help
8 Say Y here, and a list of supported mice will be displayed.
9 This option doesn't affect the kernel.
10
11 If unsure, say Y.
12
13if INPUT_MOUSE
14
15config MOUSE_PS2
16 tristate "PS/2 mouse"
17 default y
18 select SERIO
19 select SERIO_LIBPS2
20 select SERIO_I8042 if PC
21 select SERIO_GSCPS2 if GSC
22 ---help---
23 Say Y here if you have a PS/2 mouse connected to your system. This
24 includes the standard 2 or 3-button PS/2 mouse, as well as PS/2
25 mice with wheels and extra buttons, Microsoft, Logitech or Genius
26 compatible.
27
28 Synaptics TouchPad users might be interested in a specialized
29 XFree86 driver at:
30 <http://w1.894.telia.com/~u89404340/touchpad/index.html>
31 and a new version of GPM at:
32 <http://www.geocities.com/dt_or/gpm/gpm.html>
33 to take advantage of the advanced features of the touchpad.
34
35 If unsure, say Y.
36
37 To compile this driver as a module, choose M here: the
38 module will be called psmouse.
39
40config MOUSE_SERIAL
41 tristate "Serial mouse"
42 select SERIO
43 ---help---
44 Say Y here if you have a serial (RS-232, COM port) mouse connected
45 to your system. This includes Sun, MouseSystems, Microsoft,
46 Logitech and all other compatible serial mice.
47
48 If unsure, say N.
49
50 To compile this driver as a module, choose M here: the
51 module will be called sermouse.
52
53config MOUSE_INPORT
54 tristate "InPort/MS/ATIXL busmouse"
55 depends on ISA
56 help
57 Say Y here if you have an InPort, Microsoft or ATI XL busmouse.
58 They are rather rare these days.
59
60 To compile this driver as a module, choose M here: the
61 module will be called inport.
62
63config MOUSE_ATIXL
64 bool "ATI XL variant"
65 depends on MOUSE_INPORT
66 help
67 Say Y here if your mouse is of the ATI XL variety.
68
69config MOUSE_LOGIBM
70 tristate "Logitech busmouse"
71 depends on ISA
72 help
73 Say Y here if you have a Logitech busmouse.
74 They are rather rare these days.
75
76 To compile this driver as a module, choose M here: the
77 module will be called logibm.
78
79config MOUSE_PC110PAD
80 tristate "IBM PC110 touchpad"
81 depends on ISA
82 help
83 Say Y if you have the IBM PC-110 micro-notebook and want its
84 touchpad supported.
85
86 To compile this driver as a module, choose M here: the
87 module will be called pc110pad.
88
89config MOUSE_MAPLE
90 tristate "Maple bus mouse"
91 depends on SH_DREAMCAST && MAPLE
92 help
93 Say Y if you have a DreamCast console and a mouse attached to
94 its Maple bus.
95
96 To compile this driver as a module, choose M here: the
97 module will be called maplemouse.
98
99config MOUSE_AMIGA
100 tristate "Amiga mouse"
101 depends on AMIGA
102 help
103 Say Y here if you have an Amiga and want its native mouse
104 supported by the kernel.
105
106 To compile this driver as a module, choose M here: the
107 module will be called amimouse.
108
109config MOUSE_RISCPC
110 tristate "Acorn RiscPC mouse"
111 depends on ARCH_ACORN
112 help
113 Say Y here if you have the Acorn RiscPC computer and want its
114 native mouse supported.
115
116 To compile this driver as a module, choose M here: the
117 module will be called rpcmouse.
118
119config MOUSE_VSXXXAA
120 tristate "DEC VSXXX-AA/GA mouse and VSXXX-AB tablet"
121 select SERIO
122 help
123 Say Y (or M) if you want to use a DEC VSXXX-AA (hockey
124 puck) or a VSXXX-GA (rectangular) mouse. Theses mice are
125 typically used on DECstations or VAXstations, but can also
126 be used on any box capable of RS232 (with some adaptor
127 described in the source file). This driver also works with the
128 digitizer (VSXXX-AB) DEC produced.
129
130config MOUSE_HIL
131 tristate "HIL pointers (mice etc)."
132 depends on GSC
133 select HP_SDC
134 select HIL_MLC
135 help
136 Say Y here to support HIL pointers.
137
138endif
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
new file mode 100644
index 000000000000..a7864195806a
--- /dev/null
+++ b/drivers/input/mouse/Makefile
@@ -0,0 +1,18 @@
1#
2# Makefile for the mouse drivers.
3#
4
5# Each configuration option enables a list of files.
6
7obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o
8obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o
9obj-$(CONFIG_MOUSE_INPORT) += inport.o
10obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o
11obj-$(CONFIG_MOUSE_MAPLE) += maplemouse.o
12obj-$(CONFIG_MOUSE_PC110PAD) += pc110pad.o
13obj-$(CONFIG_MOUSE_PS2) += psmouse.o
14obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
15obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o
16obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o
17
18psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
new file mode 100644
index 000000000000..1f85a9718c89
--- /dev/null
+++ b/drivers/input/mouse/alps.c
@@ -0,0 +1,477 @@
1/*
2 * ALPS touchpad PS/2 mouse driver
3 *
4 * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au>
5 * Copyright (c) 2003 Peter Osterlund <petero2@telia.com>
6 * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru>
7 * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
8 *
9 * ALPS detection, tap switching and status querying info is taken from
10 * tpconfig utility (by C. Scott Ananian and Bruce Kall).
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License version 2 as published by
14 * the Free Software Foundation.
15 */
16
17#include <linux/input.h>
18#include <linux/serio.h>
19#include <linux/libps2.h>
20
21#include "psmouse.h"
22#include "alps.h"
23
24#undef DEBUG
25#ifdef DEBUG
26#define dbg(format, arg...) printk(KERN_INFO "alps.c: " format "\n", ## arg)
27#else
28#define dbg(format, arg...) do {} while (0)
29#endif
30
31#define ALPS_DUALPOINT 0x01
32#define ALPS_WHEEL 0x02
33#define ALPS_FW_BK 0x04
34#define ALPS_4BTN 0x08
35#define ALPS_OLDPROTO 0x10
36#define ALPS_PASS 0x20
37
38static struct alps_model_info alps_model_data[] = {
39 { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */
40 { { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
41 { { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
42 { { 0x63, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
43 { { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
44 { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, 0 },
45 { { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */
46 { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK }, /* NEC Versa L320 */
47 { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 },
48 { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */
49 { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
50 { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
51 { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */
52 { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },
53 { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */
54};
55
56/*
57 * XXX - this entry is suspicious. First byte has zero lower nibble,
58 * which is what a normal mouse would report. Also, the value 0x0e
59 * isn't valid per PS/2 spec.
60 */
61
62/*
63 * ALPS abolute Mode - new format
64 *
65 * byte 0: 1 ? ? ? 1 ? ? ?
66 * byte 1: 0 x6 x5 x4 x3 x2 x1 x0
67 * byte 2: 0 x10 x9 x8 x7 ? fin ges
68 * byte 3: 0 y9 y8 y7 1 M R L
69 * byte 4: 0 y6 y5 y4 y3 y2 y1 y0
70 * byte 5: 0 z6 z5 z4 z3 z2 z1 z0
71 *
72 * ?'s can have different meanings on different models,
73 * such as wheel rotation, extra buttons, stick buttons
74 * on a dualpoint, etc.
75 */
76
77static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
78{
79 struct alps_data *priv = psmouse->private;
80 unsigned char *packet = psmouse->packet;
81 struct input_dev *dev = &psmouse->dev;
82 struct input_dev *dev2 = &priv->dev2;
83 int x, y, z, ges, fin, left, right, middle;
84
85 input_regs(dev, regs);
86
87 if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */
88 input_report_key(dev2, BTN_LEFT, packet[0] & 1);
89 input_report_key(dev2, BTN_RIGHT, packet[0] & 2);
90 input_report_key(dev2, BTN_MIDDLE, packet[0] & 4);
91 input_report_rel(dev2, REL_X,
92 packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0);
93 input_report_rel(dev2, REL_Y,
94 packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0);
95 input_sync(dev2);
96 return;
97 }
98
99 if (priv->i->flags & ALPS_OLDPROTO) {
100 left = packet[2] & 0x08;
101 right = packet[2] & 0x10;
102 middle = 0;
103 x = packet[1] | ((packet[0] & 0x07) << 7);
104 y = packet[4] | ((packet[3] & 0x07) << 7);
105 z = packet[5];
106 } else {
107 left = packet[3] & 1;
108 right = packet[3] & 2;
109 middle = packet[3] & 4;
110 x = packet[1] | ((packet[2] & 0x78) << (7 - 3));
111 y = packet[4] | ((packet[3] & 0x70) << (7 - 4));
112 z = packet[5];
113 }
114
115 ges = packet[2] & 1;
116 fin = packet[2] & 2;
117
118 input_report_key(dev, BTN_LEFT, left);
119 input_report_key(dev, BTN_RIGHT, right);
120 input_report_key(dev, BTN_MIDDLE, middle);
121
122 if ((priv->i->flags & ALPS_DUALPOINT) && z == 127) {
123 input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x));
124 input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y));
125 input_sync(dev);
126 input_sync(dev2);
127 return;
128 }
129
130 /* Convert hardware tap to a reasonable Z value */
131 if (ges && !fin) z = 40;
132
133 /*
134 * A "tap and drag" operation is reported by the hardware as a transition
135 * from (!fin && ges) to (fin && ges). This should be translated to the
136 * sequence Z>0, Z==0, Z>0, so the Z==0 event has to be generated manually.
137 */
138 if (ges && fin && !priv->prev_fin) {
139 input_report_abs(dev, ABS_X, x);
140 input_report_abs(dev, ABS_Y, y);
141 input_report_abs(dev, ABS_PRESSURE, 0);
142 input_report_key(dev, BTN_TOOL_FINGER, 0);
143 input_sync(dev);
144 }
145 priv->prev_fin = fin;
146
147 if (z > 30) input_report_key(dev, BTN_TOUCH, 1);
148 if (z < 25) input_report_key(dev, BTN_TOUCH, 0);
149
150 if (z > 0) {
151 input_report_abs(dev, ABS_X, x);
152 input_report_abs(dev, ABS_Y, y);
153 }
154
155 input_report_abs(dev, ABS_PRESSURE, z);
156 input_report_key(dev, BTN_TOOL_FINGER, z > 0);
157
158
159 if (priv->i->flags & ALPS_WHEEL)
160 input_report_rel(dev, REL_WHEEL, ((packet[0] >> 4) & 0x07) | ((packet[2] >> 2) & 0x08));
161
162 if (priv->i->flags & ALPS_FW_BK) {
163 input_report_key(dev, BTN_FORWARD, packet[0] & 0x10);
164 input_report_key(dev, BTN_BACK, packet[2] & 0x04);
165 }
166
167 input_sync(dev);
168}
169
170static psmouse_ret_t alps_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
171{
172 struct alps_data *priv = psmouse->private;
173
174 if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */
175 if (psmouse->pktcnt == 3) {
176 alps_process_packet(psmouse, regs);
177 return PSMOUSE_FULL_PACKET;
178 }
179 return PSMOUSE_GOOD_DATA;
180 }
181
182 if ((psmouse->packet[0] & priv->i->mask0) != priv->i->byte0)
183 return PSMOUSE_BAD_DATA;
184
185 /* Bytes 2 - 6 should have 0 in the highest bit */
186 if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 &&
187 (psmouse->packet[psmouse->pktcnt - 1] & 0x80))
188 return PSMOUSE_BAD_DATA;
189
190 if (psmouse->pktcnt == 6) {
191 alps_process_packet(psmouse, regs);
192 return PSMOUSE_FULL_PACKET;
193 }
194
195 return PSMOUSE_GOOD_DATA;
196}
197
198static struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version)
199{
200 struct ps2dev *ps2dev = &psmouse->ps2dev;
201 unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 };
202 unsigned char param[4];
203 int i;
204
205 /*
206 * First try "E6 report".
207 * ALPS should return 0,0,10 or 0,0,100
208 */
209 param[0] = 0;
210 if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) ||
211 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
212 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
213 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11))
214 return NULL;
215
216 param[0] = param[1] = param[2] = 0xff;
217 if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
218 return NULL;
219
220 dbg("E6 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
221
222 if (param[0] != 0 || param[1] != 0 || (param[2] != 10 && param[2] != 100))
223 return NULL;
224
225 /*
226 * Now try "E7 report". Allowed responses are in
227 * alps_model_data[].signature
228 */
229 param[0] = 0;
230 if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) ||
231 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
232 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
233 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21))
234 return NULL;
235
236 param[0] = param[1] = param[2] = 0xff;
237 if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
238 return NULL;
239
240 dbg("E7 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
241
242 for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++);
243 *version = (param[0] << 8) | (param[1] << 4) | i;
244
245 for (i = 0; i < ARRAY_SIZE(alps_model_data); i++)
246 if (!memcmp(param, alps_model_data[i].signature, sizeof(alps_model_data[i].signature)))
247 return alps_model_data + i;
248
249 return NULL;
250}
251
252/*
253 * For DualPoint devices select the device that should respond to
254 * subsequent commands. It looks like glidepad is behind stickpointer,
255 * I'd thought it would be other way around...
256 */
257static int alps_passthrough_mode(struct psmouse *psmouse, int enable)
258{
259 struct ps2dev *ps2dev = &psmouse->ps2dev;
260 unsigned char param[3];
261 int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11;
262
263 if (ps2_command(ps2dev, NULL, cmd) ||
264 ps2_command(ps2dev, NULL, cmd) ||
265 ps2_command(ps2dev, NULL, cmd) ||
266 ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE))
267 return -1;
268
269 /* we may get 3 more bytes, just ignore them */
270 ps2_command(ps2dev, param, 0x0300);
271
272 return 0;
273}
274
275static int alps_absolute_mode(struct psmouse *psmouse)
276{
277 struct ps2dev *ps2dev = &psmouse->ps2dev;
278
279 /* Try ALPS magic knock - 4 disable before enable */
280 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
281 ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
282 ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
283 ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
284 ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE))
285 return -1;
286
287 /*
288 * Switch mouse to poll (remote) mode so motion data will not
289 * get in our way
290 */
291 return ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETPOLL);
292}
293
294static int alps_get_status(struct psmouse *psmouse, char *param)
295{
296 struct ps2dev *ps2dev = &psmouse->ps2dev;
297
298 /* Get status: 0xF5 0xF5 0xF5 0xE9 */
299 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
300 ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
301 ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
302 ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
303 return -1;
304
305 dbg("Status: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
306
307 return 0;
308}
309
310/*
311 * Turn touchpad tapping on or off. The sequences are:
312 * 0xE9 0xF5 0xF5 0xF3 0x0A to enable,
313 * 0xE9 0xF5 0xF5 0xE8 0x00 to disable.
314 * My guess that 0xE9 (GetInfo) is here as a sync point.
315 * For models that also have stickpointer (DualPoints) its tapping
316 * is controlled separately (0xE6 0xE6 0xE6 0xF3 0x14|0x0A) but
317 * we don't fiddle with it.
318 */
319static int alps_tap_mode(struct psmouse *psmouse, int enable)
320{
321 struct ps2dev *ps2dev = &psmouse->ps2dev;
322 int cmd = enable ? PSMOUSE_CMD_SETRATE : PSMOUSE_CMD_SETRES;
323 unsigned char tap_arg = enable ? 0x0A : 0x00;
324 unsigned char param[4];
325
326 if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO) ||
327 ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
328 ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
329 ps2_command(ps2dev, &tap_arg, cmd))
330 return -1;
331
332 if (alps_get_status(psmouse, param))
333 return -1;
334
335 return 0;
336}
337
338static int alps_reconnect(struct psmouse *psmouse)
339{
340 struct alps_data *priv = psmouse->private;
341 unsigned char param[4];
342 int version;
343
344 if (!(priv->i = alps_get_model(psmouse, &version)))
345 return -1;
346
347 if (priv->i->flags & ALPS_PASS && alps_passthrough_mode(psmouse, 1))
348 return -1;
349
350 if (alps_get_status(psmouse, param))
351 return -1;
352
353 if (param[0] & 0x04)
354 alps_tap_mode(psmouse, 1);
355
356 if (alps_absolute_mode(psmouse)) {
357 printk(KERN_ERR "alps.c: Failed to enable absolute mode\n");
358 return -1;
359 }
360
361 if (priv->i->flags == ALPS_PASS && alps_passthrough_mode(psmouse, 0))
362 return -1;
363
364 return 0;
365}
366
367static void alps_disconnect(struct psmouse *psmouse)
368{
369 struct alps_data *priv = psmouse->private;
370 psmouse_reset(psmouse);
371 input_unregister_device(&priv->dev2);
372 kfree(priv);
373}
374
375int alps_init(struct psmouse *psmouse)
376{
377 struct alps_data *priv;
378 unsigned char param[4];
379 int version;
380
381 psmouse->private = priv = kmalloc(sizeof(struct alps_data), GFP_KERNEL);
382 if (!priv)
383 goto init_fail;
384 memset(priv, 0, sizeof(struct alps_data));
385
386 if (!(priv->i = alps_get_model(psmouse, &version)))
387 goto init_fail;
388
389 if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 1))
390 goto init_fail;
391
392 if (alps_get_status(psmouse, param)) {
393 printk(KERN_ERR "alps.c: touchpad status report request failed\n");
394 goto init_fail;
395 }
396
397 if (param[0] & 0x04) {
398 printk(KERN_INFO " Enabling hardware tapping\n");
399 if (alps_tap_mode(psmouse, 1))
400 printk(KERN_WARNING "alps.c: Failed to enable hardware tapping\n");
401 }
402
403 if (alps_absolute_mode(psmouse)) {
404 printk(KERN_ERR "alps.c: Failed to enable absolute mode\n");
405 goto init_fail;
406 }
407
408 if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 0))
409 goto init_fail;
410
411 psmouse->dev.evbit[LONG(EV_KEY)] |= BIT(EV_KEY);
412 psmouse->dev.keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH);
413 psmouse->dev.keybit[LONG(BTN_TOOL_FINGER)] |= BIT(BTN_TOOL_FINGER);
414 psmouse->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
415
416 psmouse->dev.evbit[LONG(EV_ABS)] |= BIT(EV_ABS);
417 input_set_abs_params(&psmouse->dev, ABS_X, 0, 1023, 0, 0);
418 input_set_abs_params(&psmouse->dev, ABS_Y, 0, 767, 0, 0);
419 input_set_abs_params(&psmouse->dev, ABS_PRESSURE, 0, 127, 0, 0);
420
421 if (priv->i->flags & ALPS_WHEEL) {
422 psmouse->dev.evbit[LONG(EV_REL)] |= BIT(EV_REL);
423 psmouse->dev.relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL);
424 }
425
426 if (priv->i->flags & ALPS_FW_BK) {
427 psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD);
428 psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK);
429 }
430
431 sprintf(priv->phys, "%s/input1", psmouse->ps2dev.serio->phys);
432 priv->dev2.phys = priv->phys;
433 priv->dev2.name = (priv->i->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse";
434 priv->dev2.id.bustype = BUS_I8042;
435 priv->dev2.id.vendor = 0x0002;
436 priv->dev2.id.product = PSMOUSE_ALPS;
437 priv->dev2.id.version = 0x0000;
438
439 priv->dev2.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
440 priv->dev2.relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y);
441 priv->dev2.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
442
443 input_register_device(&priv->dev2);
444
445 printk(KERN_INFO "input: %s on %s\n", priv->dev2.name, psmouse->ps2dev.serio->phys);
446
447 psmouse->protocol_handler = alps_process_byte;
448 psmouse->disconnect = alps_disconnect;
449 psmouse->reconnect = alps_reconnect;
450 psmouse->pktsize = 6;
451
452 return 0;
453
454init_fail:
455 kfree(priv);
456 return -1;
457}
458
459int alps_detect(struct psmouse *psmouse, int set_properties)
460{
461 int version;
462 struct alps_model_info *model;
463
464 if (!(model = alps_get_model(psmouse, &version)))
465 return -1;
466
467 if (set_properties) {
468 psmouse->vendor = "ALPS";
469 if (model->flags & ALPS_DUALPOINT)
470 psmouse->name = "DualPoint TouchPad";
471 else
472 psmouse->name = "GlidePoint";
473 psmouse->model = version;
474 }
475 return 0;
476}
477
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
new file mode 100644
index 000000000000..aba103dd65b7
--- /dev/null
+++ b/drivers/input/mouse/alps.h
@@ -0,0 +1,32 @@
1/*
2 * ALPS touchpad PS/2 mouse driver
3 *
4 * Copyright (c) 2003 Peter Osterlund <petero2@telia.com>
5 * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 */
11
12#ifndef _ALPS_H
13#define _ALPS_H
14
15int alps_detect(struct psmouse *psmouse, int set_properties);
16int alps_init(struct psmouse *psmouse);
17
18struct alps_model_info {
19 unsigned char signature[3];
20 unsigned char byte0, mask0;
21 unsigned char flags;
22};
23
24struct alps_data {
25 struct input_dev dev2; /* Relative device */
26 char name[32]; /* Name */
27 char phys[32]; /* Phys */
28 struct alps_model_info *i; /* Info */
29 int prev_fin; /* Finger bit from previous packet */
30};
31
32#endif
diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c
new file mode 100644
index 000000000000..7baa09cca7c5
--- /dev/null
+++ b/drivers/input/mouse/amimouse.c
@@ -0,0 +1,137 @@
1/*
2 * Amiga mouse driver for Linux/m68k
3 *
4 * Copyright (c) 2000-2002 Vojtech Pavlik
5 *
6 * Based on the work of:
7 * Michael Rausch James Banks
8 * Matther Dillon David Giller
9 * Nathan Laredo Linus Torvalds
10 * Johan Myreen Jes Sorensen
11 * Russell King
12 */
13
14/*
15 * This program is free software; you can redistribute it and/or modify it
16 * under the terms of the GNU General Public License version 2 as published by
17 * the Free Software Foundation
18 */
19
20#include <linux/module.h>
21#include <linux/init.h>
22#include <linux/input.h>
23#include <linux/interrupt.h>
24
25#include <asm/irq.h>
26#include <asm/setup.h>
27#include <asm/system.h>
28#include <asm/uaccess.h>
29#include <asm/amigahw.h>
30#include <asm/amigaints.h>
31
32MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
33MODULE_DESCRIPTION("Amiga mouse driver");
34MODULE_LICENSE("GPL");
35
36static int amimouse_used = 0;
37static int amimouse_lastx, amimouse_lasty;
38static struct input_dev amimouse_dev;
39
40static char *amimouse_name = "Amiga mouse";
41static char *amimouse_phys = "amimouse/input0";
42
43static irqreturn_t amimouse_interrupt(int irq, void *dummy, struct pt_regs *fp)
44{
45 unsigned short joy0dat, potgor;
46 int nx, ny, dx, dy;
47
48 joy0dat = custom.joy0dat;
49
50 nx = joy0dat & 0xff;
51 ny = joy0dat >> 8;
52
53 dx = nx - amimouse_lastx;
54 dy = ny - amimouse_lasty;
55
56 if (dx < -127) dx = (256 + nx) - amimouse_lastx;
57 if (dx > 127) dx = (nx - 256) - amimouse_lastx;
58 if (dy < -127) dy = (256 + ny) - amimouse_lasty;
59 if (dy > 127) dy = (ny - 256) - amimouse_lasty;
60
61 amimouse_lastx = nx;
62 amimouse_lasty = ny;
63
64 potgor = custom.potgor;
65
66 input_regs(&amimouse_dev, fp);
67
68 input_report_rel(&amimouse_dev, REL_X, dx);
69 input_report_rel(&amimouse_dev, REL_Y, dy);
70
71 input_report_key(&amimouse_dev, BTN_LEFT, ciaa.pra & 0x40);
72 input_report_key(&amimouse_dev, BTN_MIDDLE, potgor & 0x0100);
73 input_report_key(&amimouse_dev, BTN_RIGHT, potgor & 0x0400);
74
75 input_sync(&amimouse_dev);
76
77 return IRQ_HANDLED;
78}
79
80static int amimouse_open(struct input_dev *dev)
81{
82 unsigned short joy0dat;
83
84 if (amimouse_used++)
85 return 0;
86
87 joy0dat = custom.joy0dat;
88
89 amimouse_lastx = joy0dat & 0xff;
90 amimouse_lasty = joy0dat >> 8;
91
92 if (request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse", amimouse_interrupt)) {
93 amimouse_used--;
94 printk(KERN_ERR "amimouse.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB);
95 return -EBUSY;
96 }
97
98 return 0;
99}
100
101static void amimouse_close(struct input_dev *dev)
102{
103 if (!--amimouse_used)
104 free_irq(IRQ_AMIGA_VERTB, amimouse_interrupt);
105}
106
107static int __init amimouse_init(void)
108{
109 if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE))
110 return -ENODEV;
111
112 amimouse_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
113 amimouse_dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
114 amimouse_dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
115 amimouse_dev.open = amimouse_open;
116 amimouse_dev.close = amimouse_close;
117
118 amimouse_dev.name = amimouse_name;
119 amimouse_dev.phys = amimouse_phys;
120 amimouse_dev.id.bustype = BUS_AMIGA;
121 amimouse_dev.id.vendor = 0x0001;
122 amimouse_dev.id.product = 0x0002;
123 amimouse_dev.id.version = 0x0100;
124
125 input_register_device(&amimouse_dev);
126
127 printk(KERN_INFO "input: %s at joy0dat\n", amimouse_name);
128 return 0;
129}
130
131static void __exit amimouse_exit(void)
132{
133 input_unregister_device(&amimouse_dev);
134}
135
136module_init(amimouse_init);
137module_exit(amimouse_exit);
diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c
new file mode 100644
index 000000000000..bc22849c6c79
--- /dev/null
+++ b/drivers/input/mouse/hil_ptr.c
@@ -0,0 +1,414 @@
1/*
2 * Generic linux-input device driver for axis-bearing devices
3 *
4 * Copyright (c) 2001 Brian S. Julin
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * Alternatively, this software may be distributed under the terms of the
17 * GNU General Public License ("GPL").
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 *
29 * References:
30 * HP-HIL Technical Reference Manual. Hewlett Packard Product No. 45918A
31 *
32 */
33
34#include <linux/hil.h>
35#include <linux/input.h>
36#include <linux/serio.h>
37#include <linux/kernel.h>
38#include <linux/module.h>
39#include <linux/init.h>
40#include <linux/slab.h>
41#include <linux/pci_ids.h>
42
43#define PREFIX "HIL PTR: "
44#define HIL_GENERIC_NAME "HIL pointer device"
45
46MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
47MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver");
48MODULE_LICENSE("Dual BSD/GPL");
49
50
51#define TABLET_SIMULATES_MOUSE /* allow tablet to be used as mouse */
52#undef TABLET_AUTOADJUST /* auto-adjust valid tablet ranges */
53
54
55#define HIL_PTR_MAX_LENGTH 16
56
57struct hil_ptr {
58 struct input_dev dev;
59 struct serio *serio;
60
61 /* Input buffer and index for packets from HIL bus. */
62 hil_packet data[HIL_PTR_MAX_LENGTH];
63 int idx4; /* four counts per packet */
64
65 /* Raw device info records from HIL bus, see hil.h for fields. */
66 char idd[HIL_PTR_MAX_LENGTH]; /* DID byte and IDD record */
67 char rsc[HIL_PTR_MAX_LENGTH]; /* RSC record */
68 char exd[HIL_PTR_MAX_LENGTH]; /* EXD record */
69 char rnm[HIL_PTR_MAX_LENGTH + 1]; /* RNM record + NULL term. */
70
71 /* Extra device details not contained in struct input_dev. */
72 unsigned int nbtn, naxes;
73 unsigned int btnmap[7];
74
75 /* Something to sleep around with. */
76 struct semaphore sem;
77};
78
79/* Process a complete packet after transfer from the HIL */
80static void hil_ptr_process_record(struct hil_ptr *ptr)
81{
82 struct input_dev *dev = &ptr->dev;
83 hil_packet *data = ptr->data;
84 hil_packet p;
85 int idx, i, cnt, laxis;
86 int ax16, absdev;
87
88 idx = ptr->idx4/4;
89 p = data[idx - 1];
90
91 if ((p & ~HIL_CMDCT_POL) ==
92 (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report;
93 if ((p & ~HIL_CMDCT_RPL) ==
94 (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report;
95
96 /* Not a poll response. See if we are loading config records. */
97 switch (p & HIL_PKT_DATA_MASK) {
98 case HIL_CMD_IDD:
99 for (i = 0; i < idx; i++)
100 ptr->idd[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
101 for (; i < HIL_PTR_MAX_LENGTH; i++)
102 ptr->idd[i] = 0;
103 break;
104 case HIL_CMD_RSC:
105 for (i = 0; i < idx; i++)
106 ptr->rsc[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
107 for (; i < HIL_PTR_MAX_LENGTH; i++)
108 ptr->rsc[i] = 0;
109 break;
110 case HIL_CMD_EXD:
111 for (i = 0; i < idx; i++)
112 ptr->exd[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
113 for (; i < HIL_PTR_MAX_LENGTH; i++)
114 ptr->exd[i] = 0;
115 break;
116 case HIL_CMD_RNM:
117 for (i = 0; i < idx; i++)
118 ptr->rnm[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
119 for (; i < HIL_PTR_MAX_LENGTH + 1; i++)
120 ptr->rnm[i] = '\0';
121 break;
122 default:
123 /* These occur when device isn't present */
124 if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break;
125 /* Anything else we'd like to know about. */
126 printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p);
127 break;
128 }
129 goto out;
130
131 report:
132 if ((p & HIL_CMDCT_POL) != idx - 1) {
133 printk(KERN_WARNING PREFIX "Malformed poll packet %x (idx = %i)\n", p, idx);
134 goto out;
135 }
136
137 i = (ptr->data[0] & HIL_POL_AXIS_ALT) ? 3 : 0;
138 laxis = ptr->data[0] & HIL_POL_NUM_AXES_MASK;
139 laxis += i;
140
141 ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */
142 absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS;
143
144 for (cnt = 1; i < laxis; i++) {
145 unsigned int lo,hi,val;
146 lo = ptr->data[cnt++] & HIL_PKT_DATA_MASK;
147 hi = ax16 ? (ptr->data[cnt++] & HIL_PKT_DATA_MASK) : 0;
148 if (absdev) {
149 val = lo + (hi<<8);
150#ifdef TABLET_AUTOADJUST
151 if (val < ptr->dev.absmin[ABS_X + i])
152 ptr->dev.absmin[ABS_X + i] = val;
153 if (val > ptr->dev.absmax[ABS_X + i])
154 ptr->dev.absmax[ABS_X + i] = val;
155#endif
156 if (i%3) val = ptr->dev.absmax[ABS_X + i] - val;
157 input_report_abs(dev, ABS_X + i, val);
158 } else {
159 val = (int) (((int8_t)lo) | ((int8_t)hi<<8));
160 if (i%3) val *= -1;
161 input_report_rel(dev, REL_X + i, val);
162 }
163 }
164
165 while (cnt < idx - 1) {
166 unsigned int btn;
167 int up;
168 btn = ptr->data[cnt++];
169 up = btn & 1;
170 btn &= 0xfe;
171 if (btn == 0x8e) {
172 continue; /* TODO: proximity == touch? */
173 }
174 else if ((btn > 0x8c) || (btn < 0x80)) continue;
175 btn = (btn - 0x80) >> 1;
176 btn = ptr->btnmap[btn];
177 input_report_key(dev, btn, !up);
178 }
179 input_sync(dev);
180 out:
181 ptr->idx4 = 0;
182 up(&ptr->sem);
183}
184
185static void hil_ptr_process_err(struct hil_ptr *ptr) {
186 printk(KERN_WARNING PREFIX "errored HIL packet\n");
187 ptr->idx4 = 0;
188 up(&ptr->sem);
189 return;
190}
191
192static irqreturn_t hil_ptr_interrupt(struct serio *serio,
193 unsigned char data, unsigned int flags, struct pt_regs *regs)
194{
195 struct hil_ptr *ptr;
196 hil_packet packet;
197 int idx;
198
199 ptr = (struct hil_ptr *)serio->private;
200 if (ptr == NULL) {
201 BUG();
202 return IRQ_HANDLED;
203 }
204
205 if (ptr->idx4 >= (HIL_PTR_MAX_LENGTH * sizeof(hil_packet))) {
206 hil_ptr_process_err(ptr);
207 return IRQ_HANDLED;
208 }
209 idx = ptr->idx4/4;
210 if (!(ptr->idx4 % 4)) ptr->data[idx] = 0;
211 packet = ptr->data[idx];
212 packet |= ((hil_packet)data) << ((3 - (ptr->idx4 % 4)) * 8);
213 ptr->data[idx] = packet;
214
215 /* Records of N 4-byte hil_packets must terminate with a command. */
216 if ((++(ptr->idx4)) % 4) return IRQ_HANDLED;
217 if ((packet & 0xffff0000) != HIL_ERR_INT) {
218 hil_ptr_process_err(ptr);
219 return IRQ_HANDLED;
220 }
221 if (packet & HIL_PKT_CMD)
222 hil_ptr_process_record(ptr);
223 return IRQ_HANDLED;
224}
225
226static void hil_ptr_disconnect(struct serio *serio)
227{
228 struct hil_ptr *ptr;
229
230 ptr = (struct hil_ptr *)serio->private;
231 if (ptr == NULL) {
232 BUG();
233 return;
234 }
235
236 input_unregister_device(&ptr->dev);
237 serio_close(serio);
238 kfree(ptr);
239}
240
241static void hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
242{
243 struct hil_ptr *ptr;
244 char *txt;
245 unsigned int i, naxsets, btntype;
246 uint8_t did, *idd;
247
248 if (serio->type != (SERIO_HIL_MLC | SERIO_HIL)) return;
249
250 if (!(ptr = kmalloc(sizeof(struct hil_ptr), GFP_KERNEL))) return;
251 memset(ptr, 0, sizeof(struct hil_ptr));
252
253 if (serio_open(serio, driver)) goto bail0;
254
255 serio->private = ptr;
256 ptr->serio = serio;
257 ptr->dev.private = ptr;
258
259 init_MUTEX_LOCKED(&(ptr->sem));
260
261 /* Get device info. MLC driver supplies devid/status/etc. */
262 serio->write(serio, 0);
263 serio->write(serio, 0);
264 serio->write(serio, HIL_PKT_CMD >> 8);
265 serio->write(serio, HIL_CMD_IDD);
266 down(&(ptr->sem));
267
268 serio->write(serio, 0);
269 serio->write(serio, 0);
270 serio->write(serio, HIL_PKT_CMD >> 8);
271 serio->write(serio, HIL_CMD_RSC);
272 down(&(ptr->sem));
273
274 serio->write(serio, 0);
275 serio->write(serio, 0);
276 serio->write(serio, HIL_PKT_CMD >> 8);
277 serio->write(serio, HIL_CMD_RNM);
278 down(&(ptr->sem));
279
280 serio->write(serio, 0);
281 serio->write(serio, 0);
282 serio->write(serio, HIL_PKT_CMD >> 8);
283 serio->write(serio, HIL_CMD_EXD);
284 down(&(ptr->sem));
285
286 up(&(ptr->sem));
287
288 init_input_dev(&ptr->dev);
289 did = ptr->idd[0];
290 idd = ptr->idd + 1;
291 txt = "unknown";
292 if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) {
293 ptr->dev.evbit[0] = BIT(EV_REL);
294 txt = "relative";
295 }
296
297 if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_ABS) {
298 ptr->dev.evbit[0] = BIT(EV_ABS);
299 txt = "absolute";
300 }
301 if (!ptr->dev.evbit[0]) {
302 goto bail1;
303 }
304
305 ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd);
306 if (ptr->nbtn) ptr->dev.evbit[0] |= BIT(EV_KEY);
307
308 naxsets = HIL_IDD_NUM_AXSETS(*idd);
309 ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd);
310
311 printk(KERN_INFO PREFIX "HIL pointer device found (did: 0x%02x, axis: %s)\n",
312 did, txt);
313 printk(KERN_INFO PREFIX "HIL pointer has %i buttons and %i sets of %i axes\n",
314 ptr->nbtn, naxsets, ptr->naxes);
315
316 btntype = BTN_MISC;
317 if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET)
318#ifdef TABLET_SIMULATES_MOUSE
319 btntype = BTN_TOUCH;
320#else
321 btntype = BTN_DIGI;
322#endif
323 if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN)
324 btntype = BTN_TOUCH;
325
326 if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE)
327 btntype = BTN_MOUSE;
328
329 for (i = 0; i < ptr->nbtn; i++) {
330 set_bit(btntype | i, ptr->dev.keybit);
331 ptr->btnmap[i] = btntype | i;
332 }
333
334 if (btntype == BTN_MOUSE) {
335 /* Swap buttons 2 and 3 */
336 ptr->btnmap[1] = BTN_MIDDLE;
337 ptr->btnmap[2] = BTN_RIGHT;
338 }
339
340 if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) {
341 for (i = 0; i < ptr->naxes; i++) {
342 set_bit(REL_X + i, ptr->dev.relbit);
343 }
344 for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) {
345 set_bit(REL_X + i, ptr->dev.relbit);
346 }
347 } else {
348 for (i = 0; i < ptr->naxes; i++) {
349 set_bit(ABS_X + i, ptr->dev.absbit);
350 ptr->dev.absmin[ABS_X + i] = 0;
351 ptr->dev.absmax[ABS_X + i] =
352 HIL_IDD_AXIS_MAX((ptr->idd + 1), i);
353 }
354 for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) {
355 set_bit(ABS_X + i, ptr->dev.absbit);
356 ptr->dev.absmin[ABS_X + i] = 0;
357 ptr->dev.absmax[ABS_X + i] =
358 HIL_IDD_AXIS_MAX((ptr->idd + 1), (i - 3));
359 }
360#ifdef TABLET_AUTOADJUST
361 for (i = 0; i < ABS_MAX; i++) {
362 int diff = ptr->dev.absmax[ABS_X + i] / 10;
363 ptr->dev.absmin[ABS_X + i] += diff;
364 ptr->dev.absmax[ABS_X + i] -= diff;
365 }
366#endif
367 }
368
369 ptr->dev.name = strlen(ptr->rnm) ? ptr->rnm : HIL_GENERIC_NAME;
370
371 ptr->dev.id.bustype = BUS_HIL;
372 ptr->dev.id.vendor = PCI_VENDOR_ID_HP;
373 ptr->dev.id.product = 0x0001; /* TODO: get from ptr->rsc */
374 ptr->dev.id.version = 0x0100; /* TODO: get from ptr->rsc */
375 ptr->dev.dev = &serio->dev;
376
377 input_register_device(&ptr->dev);
378 printk(KERN_INFO "input: %s (%s), ID: %d\n",
379 ptr->dev.name,
380 (btntype == BTN_MOUSE) ? "HIL mouse":"HIL tablet or touchpad",
381 did);
382
383 return;
384 bail1:
385 serio_close(serio);
386 bail0:
387 kfree(ptr);
388 return;
389}
390
391
392static struct serio_driver hil_ptr_serio_driver = {
393 .driver = {
394 .name = "hil_ptr",
395 },
396 .description = "HP HIL mouse/tablet driver",
397 .connect = hil_ptr_connect,
398 .disconnect = hil_ptr_disconnect,
399 .interrupt = hil_ptr_interrupt
400};
401
402static int __init hil_ptr_init(void)
403{
404 serio_register_driver(&hil_ptr_serio_driver);
405 return 0;
406}
407
408static void __exit hil_ptr_exit(void)
409{
410 serio_unregister_driver(&hil_ptr_serio_driver);
411}
412
413module_init(hil_ptr_init);
414module_exit(hil_ptr_exit);
diff --git a/drivers/input/mouse/inport.c b/drivers/input/mouse/inport.c
new file mode 100644
index 000000000000..ca4e96886627
--- /dev/null
+++ b/drivers/input/mouse/inport.c
@@ -0,0 +1,196 @@
1/*
2 * $Id: inport.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
3 *
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 *
6 * Based on the work of:
7 * Teemu Rantanen Derrick Cole
8 * Peter Cervasio Christoph Niemann
9 * Philip Blundell Russell King
10 * Bob Harris
11 */
12
13/*
14 * Inport (ATI XL and Microsoft) busmouse driver for Linux
15 */
16
17/*
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 *
32 * Should you need to contact me, the author, you can do so either by
33 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
34 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
35 */
36
37#include <linux/module.h>
38#include <linux/moduleparam.h>
39#include <linux/config.h>
40#include <linux/ioport.h>
41#include <linux/init.h>
42#include <linux/interrupt.h>
43#include <linux/input.h>
44
45#include <asm/io.h>
46#include <asm/irq.h>
47
48MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
49MODULE_DESCRIPTION("Inport (ATI XL and Microsoft) busmouse driver");
50MODULE_LICENSE("GPL");
51
52#define INPORT_BASE 0x23c
53#define INPORT_EXTENT 4
54
55#define INPORT_CONTROL_PORT INPORT_BASE + 0
56#define INPORT_DATA_PORT INPORT_BASE + 1
57#define INPORT_SIGNATURE_PORT INPORT_BASE + 2
58
59#define INPORT_REG_BTNS 0x00
60#define INPORT_REG_X 0x01
61#define INPORT_REG_Y 0x02
62#define INPORT_REG_MODE 0x07
63#define INPORT_RESET 0x80
64
65#ifdef CONFIG_INPUT_ATIXL
66#define INPORT_NAME "ATI XL Mouse"
67#define INPORT_VENDOR 0x0002
68#define INPORT_SPEED_30HZ 0x01
69#define INPORT_SPEED_50HZ 0x02
70#define INPORT_SPEED_100HZ 0x03
71#define INPORT_SPEED_200HZ 0x04
72#define INPORT_MODE_BASE INPORT_SPEED_100HZ
73#define INPORT_MODE_IRQ 0x08
74#else
75#define INPORT_NAME "Microsoft InPort Mouse"
76#define INPORT_VENDOR 0x0001
77#define INPORT_MODE_BASE 0x10
78#define INPORT_MODE_IRQ 0x01
79#endif
80#define INPORT_MODE_HOLD 0x20
81
82#define INPORT_IRQ 5
83
84static int inport_irq = INPORT_IRQ;
85module_param_named(irq, inport_irq, uint, 0);
86MODULE_PARM_DESC(irq, "IRQ number (5=default)");
87
88__obsolete_setup("inport_irq=");
89
90static int inport_used;
91
92static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs);
93
94static int inport_open(struct input_dev *dev)
95{
96 if (!inport_used++) {
97 if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL))
98 return -EBUSY;
99 outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
100 outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
101 }
102
103 return 0;
104}
105
106static void inport_close(struct input_dev *dev)
107{
108 if (!--inport_used) {
109 outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
110 outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
111 free_irq(inport_irq, NULL);
112 }
113}
114
115static struct input_dev inport_dev = {
116 .evbit = { BIT(EV_KEY) | BIT(EV_REL) },
117 .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
118 .relbit = { BIT(REL_X) | BIT(REL_Y) },
119 .open = inport_open,
120 .close = inport_close,
121 .name = INPORT_NAME,
122 .phys = "isa023c/input0",
123 .id = {
124 .bustype = BUS_ISA,
125 .vendor = INPORT_VENDOR,
126 .product = 0x0001,
127 .version = 0x0100,
128 },
129};
130
131static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
132{
133 unsigned char buttons;
134
135 outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
136 outb(INPORT_MODE_HOLD | INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
137
138 input_regs(&inport_dev, regs);
139
140 outb(INPORT_REG_X, INPORT_CONTROL_PORT);
141 input_report_rel(&inport_dev, REL_X, inb(INPORT_DATA_PORT));
142
143 outb(INPORT_REG_Y, INPORT_CONTROL_PORT);
144 input_report_rel(&inport_dev, REL_Y, inb(INPORT_DATA_PORT));
145
146 outb(INPORT_REG_BTNS, INPORT_CONTROL_PORT);
147 buttons = inb(INPORT_DATA_PORT);
148
149 input_report_key(&inport_dev, BTN_MIDDLE, buttons & 1);
150 input_report_key(&inport_dev, BTN_LEFT, buttons & 2);
151 input_report_key(&inport_dev, BTN_RIGHT, buttons & 4);
152
153 outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
154 outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
155
156 input_sync(&inport_dev);
157 return IRQ_HANDLED;
158}
159
160static int __init inport_init(void)
161{
162 unsigned char a,b,c;
163
164 if (!request_region(INPORT_BASE, INPORT_EXTENT, "inport")) {
165 printk(KERN_ERR "inport.c: Can't allocate ports at %#x\n", INPORT_BASE);
166 return -EBUSY;
167 }
168
169 a = inb(INPORT_SIGNATURE_PORT);
170 b = inb(INPORT_SIGNATURE_PORT);
171 c = inb(INPORT_SIGNATURE_PORT);
172 if (( a == b ) || ( a != c )) {
173 release_region(INPORT_BASE, INPORT_EXTENT);
174 printk(KERN_ERR "inport.c: Didn't find InPort mouse at %#x\n", INPORT_BASE);
175 return -ENODEV;
176 }
177
178 outb(INPORT_RESET, INPORT_CONTROL_PORT);
179 outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
180 outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
181
182 input_register_device(&inport_dev);
183
184 printk(KERN_INFO "input: " INPORT_NAME " at %#x irq %d\n", INPORT_BASE, inport_irq);
185
186 return 0;
187}
188
189static void __exit inport_exit(void)
190{
191 input_unregister_device(&inport_dev);
192 release_region(INPORT_BASE, INPORT_EXTENT);
193}
194
195module_init(inport_init);
196module_exit(inport_exit);
diff --git a/drivers/input/mouse/logibm.c b/drivers/input/mouse/logibm.c
new file mode 100644
index 000000000000..77eb83e87f61
--- /dev/null
+++ b/drivers/input/mouse/logibm.c
@@ -0,0 +1,183 @@
1/*
2 * $Id: logibm.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
3 *
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 *
6 * Based on the work of:
7 * James Banks Matthew Dillon
8 * David Giller Nathan Laredo
9 * Linus Torvalds Johan Myreen
10 * Cliff Matthews Philip Blundell
11 * Russell King
12 */
13
14/*
15 * Logitech Bus Mouse Driver for Linux
16 */
17
18/*
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 *
33 * Should you need to contact me, the author, you can do so either by
34 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
35 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
36 */
37
38#include <linux/module.h>
39#include <linux/moduleparam.h>
40#include <linux/delay.h>
41#include <linux/ioport.h>
42#include <linux/init.h>
43#include <linux/input.h>
44#include <linux/interrupt.h>
45
46#include <asm/io.h>
47#include <asm/irq.h>
48
49MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
50MODULE_DESCRIPTION("Logitech busmouse driver");
51MODULE_LICENSE("GPL");
52
53#define LOGIBM_BASE 0x23c
54#define LOGIBM_EXTENT 4
55
56#define LOGIBM_DATA_PORT LOGIBM_BASE + 0
57#define LOGIBM_SIGNATURE_PORT LOGIBM_BASE + 1
58#define LOGIBM_CONTROL_PORT LOGIBM_BASE + 2
59#define LOGIBM_CONFIG_PORT LOGIBM_BASE + 3
60
61#define LOGIBM_ENABLE_IRQ 0x00
62#define LOGIBM_DISABLE_IRQ 0x10
63#define LOGIBM_READ_X_LOW 0x80
64#define LOGIBM_READ_X_HIGH 0xa0
65#define LOGIBM_READ_Y_LOW 0xc0
66#define LOGIBM_READ_Y_HIGH 0xe0
67
68#define LOGIBM_DEFAULT_MODE 0x90
69#define LOGIBM_CONFIG_BYTE 0x91
70#define LOGIBM_SIGNATURE_BYTE 0xa5
71
72#define LOGIBM_IRQ 5
73
74static int logibm_irq = LOGIBM_IRQ;
75module_param_named(irq, logibm_irq, uint, 0);
76MODULE_PARM_DESC(irq, "IRQ number (5=default)");
77
78__obsolete_setup("logibm_irq=");
79
80static int logibm_used = 0;
81
82static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs);
83
84static int logibm_open(struct input_dev *dev)
85{
86 if (logibm_used++)
87 return 0;
88 if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) {
89 logibm_used--;
90 printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq);
91 return -EBUSY;
92 }
93 outb(LOGIBM_ENABLE_IRQ, LOGIBM_CONTROL_PORT);
94 return 0;
95}
96
97static void logibm_close(struct input_dev *dev)
98{
99 if (--logibm_used)
100 return;
101 outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
102 free_irq(logibm_irq, NULL);
103}
104
105static struct input_dev logibm_dev = {
106 .evbit = { BIT(EV_KEY) | BIT(EV_REL) },
107 .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
108 .relbit = { BIT(REL_X) | BIT(REL_Y) },
109 .open = logibm_open,
110 .close = logibm_close,
111 .name = "Logitech bus mouse",
112 .phys = "isa023c/input0",
113 .id = {
114 .bustype = BUS_ISA,
115 .vendor = 0x0003,
116 .product = 0x0001,
117 .version = 0x0100,
118 },
119};
120
121static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs)
122{
123 char dx, dy;
124 unsigned char buttons;
125
126 outb(LOGIBM_READ_X_LOW, LOGIBM_CONTROL_PORT);
127 dx = (inb(LOGIBM_DATA_PORT) & 0xf);
128 outb(LOGIBM_READ_X_HIGH, LOGIBM_CONTROL_PORT);
129 dx |= (inb(LOGIBM_DATA_PORT) & 0xf) << 4;
130 outb(LOGIBM_READ_Y_LOW, LOGIBM_CONTROL_PORT);
131 dy = (inb(LOGIBM_DATA_PORT) & 0xf);
132 outb(LOGIBM_READ_Y_HIGH, LOGIBM_CONTROL_PORT);
133 buttons = inb(LOGIBM_DATA_PORT);
134 dy |= (buttons & 0xf) << 4;
135 buttons = ~buttons >> 5;
136
137 input_regs(&logibm_dev, regs);
138 input_report_rel(&logibm_dev, REL_X, dx);
139 input_report_rel(&logibm_dev, REL_Y, dy);
140 input_report_key(&logibm_dev, BTN_RIGHT, buttons & 1);
141 input_report_key(&logibm_dev, BTN_MIDDLE, buttons & 2);
142 input_report_key(&logibm_dev, BTN_LEFT, buttons & 4);
143 input_sync(&logibm_dev);
144
145 outb(LOGIBM_ENABLE_IRQ, LOGIBM_CONTROL_PORT);
146 return IRQ_HANDLED;
147}
148
149static int __init logibm_init(void)
150{
151 if (!request_region(LOGIBM_BASE, LOGIBM_EXTENT, "logibm")) {
152 printk(KERN_ERR "logibm.c: Can't allocate ports at %#x\n", LOGIBM_BASE);
153 return -EBUSY;
154 }
155
156 outb(LOGIBM_CONFIG_BYTE, LOGIBM_CONFIG_PORT);
157 outb(LOGIBM_SIGNATURE_BYTE, LOGIBM_SIGNATURE_PORT);
158 udelay(100);
159
160 if (inb(LOGIBM_SIGNATURE_PORT) != LOGIBM_SIGNATURE_BYTE) {
161 release_region(LOGIBM_BASE, LOGIBM_EXTENT);
162 printk(KERN_ERR "logibm.c: Didn't find Logitech busmouse at %#x\n", LOGIBM_BASE);
163 return -ENODEV;
164 }
165
166 outb(LOGIBM_DEFAULT_MODE, LOGIBM_CONFIG_PORT);
167 outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
168
169 input_register_device(&logibm_dev);
170
171 printk(KERN_INFO "input: Logitech bus mouse at %#x irq %d\n", LOGIBM_BASE, logibm_irq);
172
173 return 0;
174}
175
176static void __exit logibm_exit(void)
177{
178 input_unregister_device(&logibm_dev);
179 release_region(LOGIBM_BASE, LOGIBM_EXTENT);
180}
181
182module_init(logibm_init);
183module_exit(logibm_exit);
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
new file mode 100644
index 000000000000..5ab1bd7d529d
--- /dev/null
+++ b/drivers/input/mouse/logips2pp.c
@@ -0,0 +1,397 @@
1/*
2 * Logitech PS/2++ mouse driver
3 *
4 * Copyright (c) 1999-2003 Vojtech Pavlik <vojtech@suse.cz>
5 * Copyright (c) 2003 Eric Wong <eric@yhbt.net>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 */
11
12#include <linux/input.h>
13#include <linux/serio.h>
14#include <linux/libps2.h>
15#include "psmouse.h"
16#include "logips2pp.h"
17
18/* Logitech mouse types */
19#define PS2PP_KIND_WHEEL 1
20#define PS2PP_KIND_MX 2
21#define PS2PP_KIND_TP3 3
22
23/* Logitech mouse features */
24#define PS2PP_WHEEL 0x01
25#define PS2PP_HWHEEL 0x02
26#define PS2PP_SIDE_BTN 0x04
27#define PS2PP_EXTRA_BTN 0x08
28#define PS2PP_TASK_BTN 0x10
29#define PS2PP_NAV_BTN 0x20
30
31struct ps2pp_info {
32 const int model;
33 unsigned const int kind;
34 unsigned const int features;
35};
36
37/*
38 * Process a PS2++ or PS2T++ packet.
39 */
40
41static psmouse_ret_t ps2pp_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
42{
43 struct input_dev *dev = &psmouse->dev;
44 unsigned char *packet = psmouse->packet;
45
46 if (psmouse->pktcnt < 3)
47 return PSMOUSE_GOOD_DATA;
48
49/*
50 * Full packet accumulated, process it
51 */
52
53 input_regs(dev, regs);
54
55 if ((packet[0] & 0x48) == 0x48 && (packet[1] & 0x02) == 0x02) {
56
57 /* Logitech extended packet */
58 switch ((packet[1] >> 4) | (packet[0] & 0x30)) {
59
60 case 0x0d: /* Mouse extra info */
61
62 input_report_rel(dev, packet[2] & 0x80 ? REL_HWHEEL : REL_WHEEL,
63 (int) (packet[2] & 8) - (int) (packet[2] & 7));
64 input_report_key(dev, BTN_SIDE, (packet[2] >> 4) & 1);
65 input_report_key(dev, BTN_EXTRA, (packet[2] >> 5) & 1);
66
67 break;
68
69 case 0x0e: /* buttons 4, 5, 6, 7, 8, 9, 10 info */
70
71 input_report_key(dev, BTN_SIDE, (packet[2]) & 1);
72 input_report_key(dev, BTN_EXTRA, (packet[2] >> 1) & 1);
73 input_report_key(dev, BTN_BACK, (packet[2] >> 3) & 1);
74 input_report_key(dev, BTN_FORWARD, (packet[2] >> 4) & 1);
75 input_report_key(dev, BTN_TASK, (packet[2] >> 2) & 1);
76
77 break;
78
79 case 0x0f: /* TouchPad extra info */
80
81 input_report_rel(dev, packet[2] & 0x08 ? REL_HWHEEL : REL_WHEEL,
82 (int) ((packet[2] >> 4) & 8) - (int) ((packet[2] >> 4) & 7));
83 packet[0] = packet[2] | 0x08;
84 break;
85
86#ifdef DEBUG
87 default:
88 printk(KERN_WARNING "psmouse.c: Received PS2++ packet #%x, but don't know how to handle.\n",
89 (packet[1] >> 4) | (packet[0] & 0x30));
90#endif
91 }
92 } else {
93 /* Standard PS/2 motion data */
94 input_report_rel(dev, REL_X, packet[1] ? (int) packet[1] - (int) ((packet[0] << 4) & 0x100) : 0);
95 input_report_rel(dev, REL_Y, packet[2] ? (int) ((packet[0] << 3) & 0x100) - (int) packet[2] : 0);
96 }
97
98 input_report_key(dev, BTN_LEFT, packet[0] & 1);
99 input_report_key(dev, BTN_MIDDLE, (packet[0] >> 2) & 1);
100 input_report_key(dev, BTN_RIGHT, (packet[0] >> 1) & 1);
101
102 input_sync(dev);
103
104 return PSMOUSE_FULL_PACKET;
105
106}
107
108/*
109 * ps2pp_cmd() sends a PS2++ command, sliced into two bit
110 * pieces through the SETRES command. This is needed to send extended
111 * commands to mice on notebooks that try to understand the PS/2 protocol
112 * Ugly.
113 */
114
115static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned char command)
116{
117 if (psmouse_sliced_command(psmouse, command))
118 return -1;
119
120 if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL))
121 return -1;
122
123 return 0;
124}
125
126/*
127 * SmartScroll / CruiseControl for some newer Logitech mice Defaults to
128 * enabled if we do nothing to it. Of course I put this in because I want it
129 * disabled :P
130 * 1 - enabled (if previously disabled, also default)
131 * 0 - disabled
132 */
133
134static void ps2pp_set_smartscroll(struct psmouse *psmouse, unsigned int smartscroll)
135{
136 struct ps2dev *ps2dev = &psmouse->ps2dev;
137 unsigned char param[4];
138
139 if (smartscroll > 1)
140 smartscroll = 1;
141
142 ps2pp_cmd(psmouse, param, 0x32);
143
144 param[0] = 0;
145 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
146 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
147 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
148
149 param[0] = smartscroll;
150 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
151}
152
153static ssize_t psmouse_attr_show_smartscroll(struct psmouse *psmouse, char *buf)
154{
155 return sprintf(buf, "%d\n", psmouse->smartscroll ? 1 : 0);
156}
157
158static ssize_t psmouse_attr_set_smartscroll(struct psmouse *psmouse, const char *buf, size_t count)
159{
160 unsigned long value;
161 char *rest;
162
163 value = simple_strtoul(buf, &rest, 10);
164 if (*rest || value > 1)
165 return -EINVAL;
166
167 ps2pp_set_smartscroll(psmouse, value);
168 psmouse->smartscroll = value;
169 return count;
170}
171
172PSMOUSE_DEFINE_ATTR(smartscroll);
173
174/*
175 * Support 800 dpi resolution _only_ if the user wants it (there are good
176 * reasons to not use it even if the mouse supports it, and of course there are
177 * also good reasons to use it, let the user decide).
178 */
179
180static void ps2pp_set_resolution(struct psmouse *psmouse, unsigned int resolution)
181{
182 if (resolution > 400) {
183 struct ps2dev *ps2dev = &psmouse->ps2dev;
184 unsigned char param = 3;
185
186 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11);
187 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11);
188 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11);
189 ps2_command(ps2dev, &param, PSMOUSE_CMD_SETRES);
190 psmouse->resolution = 800;
191 } else
192 psmouse_set_resolution(psmouse, resolution);
193}
194
195static void ps2pp_disconnect(struct psmouse *psmouse)
196{
197 device_remove_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll);
198}
199
200static struct ps2pp_info *get_model_info(unsigned char model)
201{
202 static struct ps2pp_info ps2pp_list[] = {
203 { 12, 0, PS2PP_SIDE_BTN},
204 { 13, 0, 0 },
205 { 15, PS2PP_KIND_MX, /* MX1000 */
206 PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
207 PS2PP_EXTRA_BTN | PS2PP_NAV_BTN | PS2PP_HWHEEL },
208 { 40, 0, PS2PP_SIDE_BTN },
209 { 41, 0, PS2PP_SIDE_BTN },
210 { 42, 0, PS2PP_SIDE_BTN },
211 { 43, 0, PS2PP_SIDE_BTN },
212 { 50, 0, 0 },
213 { 51, 0, 0 },
214 { 52, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL },
215 { 53, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
216 { 61, PS2PP_KIND_MX, /* MX700 */
217 PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
218 PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },
219 { 73, 0, PS2PP_SIDE_BTN },
220 { 75, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
221 { 76, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
222 { 80, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL },
223 { 81, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
224 { 83, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
225 { 88, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
226 { 96, 0, 0 },
227 { 97, PS2PP_KIND_TP3, PS2PP_WHEEL | PS2PP_HWHEEL },
228 { 100, PS2PP_KIND_MX, /* MX510 */
229 PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
230 PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },
231 { 111, PS2PP_KIND_MX, /* MX300 */
232 PS2PP_WHEEL | PS2PP_EXTRA_BTN | PS2PP_TASK_BTN },
233 { 112, PS2PP_KIND_MX, /* MX500 */
234 PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
235 PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },
236 { 114, PS2PP_KIND_MX, /* MX310 */
237 PS2PP_WHEEL | PS2PP_SIDE_BTN |
238 PS2PP_TASK_BTN | PS2PP_EXTRA_BTN },
239 { }
240 };
241 int i;
242
243 for (i = 0; ps2pp_list[i].model; i++)
244 if (model == ps2pp_list[i].model)
245 return &ps2pp_list[i];
246
247 printk(KERN_WARNING "logips2pp: Detected unknown logitech mouse model %d\n", model);
248 return NULL;
249}
250
251/*
252 * Set up input device's properties based on the detected mouse model.
253 */
254
255static void ps2pp_set_model_properties(struct psmouse *psmouse, struct ps2pp_info *model_info,
256 int using_ps2pp)
257{
258 if (model_info->features & PS2PP_SIDE_BTN)
259 set_bit(BTN_SIDE, psmouse->dev.keybit);
260
261 if (model_info->features & PS2PP_EXTRA_BTN)
262 set_bit(BTN_EXTRA, psmouse->dev.keybit);
263
264 if (model_info->features & PS2PP_TASK_BTN)
265 set_bit(BTN_TASK, psmouse->dev.keybit);
266
267 if (model_info->features & PS2PP_NAV_BTN) {
268 set_bit(BTN_FORWARD, psmouse->dev.keybit);
269 set_bit(BTN_BACK, psmouse->dev.keybit);
270 }
271
272 if (model_info->features & PS2PP_WHEEL)
273 set_bit(REL_WHEEL, psmouse->dev.relbit);
274
275 if (model_info->features & PS2PP_HWHEEL)
276 set_bit(REL_HWHEEL, psmouse->dev.relbit);
277
278 switch (model_info->kind) {
279 case PS2PP_KIND_WHEEL:
280 psmouse->name = "Wheel Mouse";
281 break;
282
283 case PS2PP_KIND_MX:
284 psmouse->name = "MX Mouse";
285 break;
286
287 case PS2PP_KIND_TP3:
288 psmouse->name = "TouchPad 3";
289 break;
290
291 default:
292 /*
293 * Set name to "Mouse" only when using PS2++,
294 * otherwise let other protocols define suitable
295 * name
296 */
297 if (using_ps2pp)
298 psmouse->name = "Mouse";
299 break;
300 }
301}
302
303
304/*
305 * Logitech magic init. Detect whether the mouse is a Logitech one
306 * and its exact model and try turning on extended protocol for ones
307 * that support it.
308 */
309
310int ps2pp_init(struct psmouse *psmouse, int set_properties)
311{
312 struct ps2dev *ps2dev = &psmouse->ps2dev;
313 unsigned char param[4];
314 unsigned char model, buttons;
315 struct ps2pp_info *model_info;
316 int use_ps2pp = 0;
317
318 param[0] = 0;
319 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
320 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11);
321 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11);
322 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11);
323 param[1] = 0;
324 ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
325
326 if (!param[1])
327 return -1;
328
329 model = ((param[0] >> 4) & 0x07) | ((param[0] << 3) & 0x78);
330 buttons = param[1];
331
332 if ((model_info = get_model_info(model)) != NULL) {
333
334/*
335 * Do Logitech PS2++ / PS2T++ magic init.
336 */
337 if (model == 97) { /* Touch Pad 3 */
338
339 /* Unprotect RAM */
340 param[0] = 0x11; param[1] = 0x04; param[2] = 0x68;
341 ps2_command(ps2dev, param, 0x30d1);
342 /* Enable features */
343 param[0] = 0x11; param[1] = 0x05; param[2] = 0x0b;
344 ps2_command(ps2dev, param, 0x30d1);
345 /* Enable PS2++ */
346 param[0] = 0x11; param[1] = 0x09; param[2] = 0xc3;
347 ps2_command(ps2dev, param, 0x30d1);
348
349 param[0] = 0;
350 if (!ps2_command(ps2dev, param, 0x13d1) &&
351 param[0] == 0x06 && param[1] == 0x00 && param[2] == 0x14) {
352 use_ps2pp = 1;
353 }
354
355 } else {
356
357 param[0] = param[1] = param[2] = 0;
358 ps2pp_cmd(psmouse, param, 0x39); /* Magic knock */
359 ps2pp_cmd(psmouse, param, 0xDB);
360
361 if ((param[0] & 0x78) == 0x48 &&
362 (param[1] & 0xf3) == 0xc2 &&
363 (param[2] & 0x03) == ((param[1] >> 2) & 3)) {
364 ps2pp_set_smartscroll(psmouse, psmouse->smartscroll);
365 use_ps2pp = 1;
366 }
367 }
368 }
369
370 if (set_properties) {
371 psmouse->vendor = "Logitech";
372 psmouse->model = model;
373
374 if (use_ps2pp) {
375 psmouse->protocol_handler = ps2pp_process_byte;
376 psmouse->pktsize = 3;
377
378 if (model_info->kind != PS2PP_KIND_TP3) {
379 psmouse->set_resolution = ps2pp_set_resolution;
380 psmouse->disconnect = ps2pp_disconnect;
381
382 device_create_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll);
383 }
384 }
385
386 if (buttons < 3)
387 clear_bit(BTN_MIDDLE, psmouse->dev.keybit);
388 if (buttons < 2)
389 clear_bit(BTN_RIGHT, psmouse->dev.keybit);
390
391 if (model_info)
392 ps2pp_set_model_properties(psmouse, model_info, use_ps2pp);
393 }
394
395 return use_ps2pp ? 0 : -1;
396}
397
diff --git a/drivers/input/mouse/logips2pp.h b/drivers/input/mouse/logips2pp.h
new file mode 100644
index 000000000000..64a8ec52ea6d
--- /dev/null
+++ b/drivers/input/mouse/logips2pp.h
@@ -0,0 +1,16 @@
1/*
2 * Logitech PS/2++ mouse driver header
3 *
4 * Copyright (c) 2003 Vojtech Pavlik <vojtech@suse.cz>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 */
10
11#ifndef _LOGIPS2PP_H
12#define _LOGIPS2PP_H
13
14int ps2pp_init(struct psmouse *psmouse, int set_properties);
15
16#endif
diff --git a/drivers/input/mouse/maplemouse.c b/drivers/input/mouse/maplemouse.c
new file mode 100644
index 000000000000..12dc0ef5020f
--- /dev/null
+++ b/drivers/input/mouse/maplemouse.c
@@ -0,0 +1,134 @@
1/*
2 * $Id: maplemouse.c,v 1.2 2004/03/22 01:18:15 lethal Exp $
3 * SEGA Dreamcast mouse driver
4 * Based on drivers/usb/usbmouse.c
5 */
6
7#include <linux/kernel.h>
8#include <linux/slab.h>
9#include <linux/input.h>
10#include <linux/module.h>
11#include <linux/init.h>
12#include <linux/timer.h>
13#include <linux/maple.h>
14
15MODULE_AUTHOR("YAEGASHI Takeshi <t@keshi.org>");
16MODULE_DESCRIPTION("SEGA Dreamcast mouse driver");
17
18struct dc_mouse {
19 struct input_dev dev;
20 int open;
21};
22
23
24static void dc_mouse_callback(struct mapleq *mq)
25{
26 int buttons, relx, rely, relz;
27 struct maple_device *mapledev = mq->dev;
28 struct dc_mouse *mouse = mapledev->private_data;
29 struct input_dev *dev = &mouse->dev;
30 unsigned char *res = mq->recvbuf;
31
32 buttons = ~res[8];
33 relx=*(unsigned short *)(res+12)-512;
34 rely=*(unsigned short *)(res+14)-512;
35 relz=*(unsigned short *)(res+16)-512;
36
37 input_report_key(dev, BTN_LEFT, buttons&4);
38 input_report_key(dev, BTN_MIDDLE, buttons&9);
39 input_report_key(dev, BTN_RIGHT, buttons&2);
40 input_report_rel(dev, REL_X, relx);
41 input_report_rel(dev, REL_Y, rely);
42 input_report_rel(dev, REL_WHEEL, relz);
43 input_sync(dev);
44}
45
46
47static int dc_mouse_open(struct input_dev *dev)
48{
49 struct dc_mouse *mouse = dev->private;
50 mouse->open++;
51 return 0;
52}
53
54
55static void dc_mouse_close(struct input_dev *dev)
56{
57 struct dc_mouse *mouse = dev->private;
58 mouse->open--;
59}
60
61
62static int dc_mouse_connect(struct maple_device *dev)
63{
64 unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
65 struct dc_mouse *mouse;
66
67 if (!(mouse = kmalloc(sizeof(struct dc_mouse), GFP_KERNEL)))
68 return -1;
69 memset(mouse, 0, sizeof(struct dc_mouse));
70
71 dev->private_data = mouse;
72
73 mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
74 mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
75 mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
76
77 init_input_dev(&mouse->dev);
78
79 mouse->dev.private = mouse;
80 mouse->dev.open = dc_mouse_open;
81 mouse->dev.close = dc_mouse_close;
82 mouse->dev.event = NULL;
83
84 mouse->dev.name = dev->product_name;
85 mouse->dev.id.bustype = BUS_MAPLE;
86
87 input_register_device(&mouse->dev);
88
89 maple_getcond_callback(dev, dc_mouse_callback, 1, MAPLE_FUNC_MOUSE);
90
91 printk(KERN_INFO "input: mouse(0x%lx): %s\n", data, mouse->dev.name);
92
93 return 0;
94}
95
96
97static void dc_mouse_disconnect(struct maple_device *dev)
98{
99 struct dc_mouse *mouse = dev->private_data;
100
101 input_unregister_device(&mouse->dev);
102 kfree(mouse);
103}
104
105
106static struct maple_driver dc_mouse_driver = {
107 .function = MAPLE_FUNC_MOUSE,
108 .name = "Dreamcast mouse",
109 .connect = dc_mouse_connect,
110 .disconnect = dc_mouse_disconnect,
111};
112
113
114static int __init dc_mouse_init(void)
115{
116 maple_register_driver(&dc_mouse_driver);
117 return 0;
118}
119
120
121static void __exit dc_mouse_exit(void)
122{
123 maple_unregister_driver(&dc_mouse_driver);
124}
125
126
127module_init(dc_mouse_init);
128module_exit(dc_mouse_exit);
129
130/*
131 * Local variables:
132 * c-basic-offset: 8
133 * End:
134 */
diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c
new file mode 100644
index 000000000000..0c74918fe254
--- /dev/null
+++ b/drivers/input/mouse/pc110pad.c
@@ -0,0 +1,178 @@
1/*
2 * $Id: pc110pad.c,v 1.12 2001/09/25 10:12:07 vojtech Exp $
3 *
4 * Copyright (c) 2000-2001 Vojtech Pavlik
5 *
6 * Based on the work of:
7 * Alan Cox Robin O'Leary
8 */
9
10/*
11 * IBM PC110 touchpad driver for Linux
12 */
13
14/*
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 * Should you need to contact me, the author, you can do so either by
30 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
31 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
32 */
33
34#include <linux/module.h>
35#include <linux/kernel.h>
36#include <linux/errno.h>
37#include <linux/ioport.h>
38#include <linux/input.h>
39#include <linux/init.h>
40#include <linux/interrupt.h>
41#include <linux/pci.h>
42
43#include <asm/io.h>
44#include <asm/irq.h>
45
46MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
47MODULE_DESCRIPTION("IBM PC110 touchpad driver");
48MODULE_LICENSE("GPL");
49
50#define PC110PAD_OFF 0x30
51#define PC110PAD_ON 0x38
52
53static int pc110pad_irq = 10;
54static int pc110pad_io = 0x15e0;
55
56static struct input_dev pc110pad_dev;
57static int pc110pad_data[3];
58static int pc110pad_count;
59static int pc110pad_used;
60
61static char *pc110pad_name = "IBM PC110 TouchPad";
62static char *pc110pad_phys = "isa15e0/input0";
63
64static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs)
65{
66 int value = inb_p(pc110pad_io);
67 int handshake = inb_p(pc110pad_io + 2);
68
69 outb_p(handshake | 1, pc110pad_io + 2);
70 outb_p(handshake & ~1, pc110pad_io + 2);
71 inb_p(0x64);
72
73 pc110pad_data[pc110pad_count++] = value;
74
75 if (pc110pad_count < 3)
76 return IRQ_HANDLED;
77
78 input_regs(&pc110pad_dev, regs);
79 input_report_key(&pc110pad_dev, BTN_TOUCH,
80 pc110pad_data[0] & 0x01);
81 input_report_abs(&pc110pad_dev, ABS_X,
82 pc110pad_data[1] | ((pc110pad_data[0] << 3) & 0x80) | ((pc110pad_data[0] << 1) & 0x100));
83 input_report_abs(&pc110pad_dev, ABS_Y,
84 pc110pad_data[2] | ((pc110pad_data[0] << 4) & 0x80));
85 input_sync(&pc110pad_dev);
86
87 pc110pad_count = 0;
88 return IRQ_HANDLED;
89}
90
91static void pc110pad_close(struct input_dev *dev)
92{
93 if (!--pc110pad_used)
94 outb(PC110PAD_OFF, pc110pad_io + 2);
95}
96
97static int pc110pad_open(struct input_dev *dev)
98{
99 if (pc110pad_used++)
100 return 0;
101
102 pc110pad_interrupt(0,NULL,NULL);
103 pc110pad_interrupt(0,NULL,NULL);
104 pc110pad_interrupt(0,NULL,NULL);
105 outb(PC110PAD_ON, pc110pad_io + 2);
106 pc110pad_count = 0;
107
108 return 0;
109}
110
111/*
112 * We try to avoid enabling the hardware if it's not
113 * there, but we don't know how to test. But we do know
114 * that the PC110 is not a PCI system. So if we find any
115 * PCI devices in the machine, we don't have a PC110.
116 */
117static int __init pc110pad_init(void)
118{
119 struct pci_dev *dev;
120
121 dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
122 if (dev) {
123 pci_dev_put(dev);
124 return -ENOENT;
125 }
126
127 if (!request_region(pc110pad_io, 4, "pc110pad")) {
128 printk(KERN_ERR "pc110pad: I/O area %#x-%#x in use.\n",
129 pc110pad_io, pc110pad_io + 4);
130 return -EBUSY;
131 }
132
133 outb(PC110PAD_OFF, pc110pad_io + 2);
134
135 if (request_irq(pc110pad_irq, pc110pad_interrupt, 0, "pc110pad", NULL))
136 {
137 release_region(pc110pad_io, 4);
138 printk(KERN_ERR "pc110pad: Unable to get irq %d.\n", pc110pad_irq);
139 return -EBUSY;
140 }
141
142 pc110pad_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
143 pc110pad_dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
144 pc110pad_dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
145
146 pc110pad_dev.absmax[ABS_X] = 0x1ff;
147 pc110pad_dev.absmax[ABS_Y] = 0x0ff;
148
149 pc110pad_dev.open = pc110pad_open;
150 pc110pad_dev.close = pc110pad_close;
151
152 pc110pad_dev.name = pc110pad_name;
153 pc110pad_dev.phys = pc110pad_phys;
154 pc110pad_dev.id.bustype = BUS_ISA;
155 pc110pad_dev.id.vendor = 0x0003;
156 pc110pad_dev.id.product = 0x0001;
157 pc110pad_dev.id.version = 0x0100;
158
159 input_register_device(&pc110pad_dev);
160
161 printk(KERN_INFO "input: %s at %#x irq %d\n",
162 pc110pad_name, pc110pad_io, pc110pad_irq);
163
164 return 0;
165}
166
167static void __exit pc110pad_exit(void)
168{
169 input_unregister_device(&pc110pad_dev);
170
171 outb(PC110PAD_OFF, pc110pad_io + 2);
172
173 free_irq(pc110pad_irq, NULL);
174 release_region(pc110pad_io, 4);
175}
176
177module_init(pc110pad_init);
178module_exit(pc110pad_exit);
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
new file mode 100644
index 000000000000..cd8509549eac
--- /dev/null
+++ b/drivers/input/mouse/psmouse-base.c
@@ -0,0 +1,1011 @@
1/*
2 * PS/2 mouse driver
3 *
4 * Copyright (c) 1999-2002 Vojtech Pavlik
5 * Copyright (c) 2003-2004 Dmitry Torokhov
6 */
7
8/*
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published by
11 * the Free Software Foundation.
12 */
13
14#include <linux/delay.h>
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/slab.h>
18#include <linux/interrupt.h>
19#include <linux/input.h>
20#include <linux/serio.h>
21#include <linux/init.h>
22#include <linux/libps2.h>
23#include "psmouse.h"
24#include "synaptics.h"
25#include "logips2pp.h"
26#include "alps.h"
27
28#define DRIVER_DESC "PS/2 mouse driver"
29
30MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
31MODULE_DESCRIPTION(DRIVER_DESC);
32MODULE_LICENSE("GPL");
33
34static unsigned int psmouse_max_proto = -1U;
35static int psmouse_set_maxproto(const char *val, struct kernel_param *kp);
36static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp);
37static char *psmouse_proto_abbrev[] = { NULL, "bare", NULL, NULL, NULL, "imps", "exps", NULL, NULL, NULL };
38#define param_check_proto_abbrev(name, p) __param_check(name, p, unsigned int)
39#define param_set_proto_abbrev psmouse_set_maxproto
40#define param_get_proto_abbrev psmouse_get_maxproto
41module_param_named(proto, psmouse_max_proto, proto_abbrev, 0644);
42MODULE_PARM_DESC(proto, "Highest protocol extension to probe (bare, imps, exps, any). Useful for KVM switches.");
43
44static unsigned int psmouse_resolution = 200;
45module_param_named(resolution, psmouse_resolution, uint, 0644);
46MODULE_PARM_DESC(resolution, "Resolution, in dpi.");
47
48static unsigned int psmouse_rate = 100;
49module_param_named(rate, psmouse_rate, uint, 0644);
50MODULE_PARM_DESC(rate, "Report rate, in reports per second.");
51
52static unsigned int psmouse_smartscroll = 1;
53module_param_named(smartscroll, psmouse_smartscroll, bool, 0644);
54MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");
55
56static unsigned int psmouse_resetafter;
57module_param_named(resetafter, psmouse_resetafter, uint, 0644);
58MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");
59
60PSMOUSE_DEFINE_ATTR(rate);
61PSMOUSE_DEFINE_ATTR(resolution);
62PSMOUSE_DEFINE_ATTR(resetafter);
63
64__obsolete_setup("psmouse_noext");
65__obsolete_setup("psmouse_resolution=");
66__obsolete_setup("psmouse_smartscroll=");
67__obsolete_setup("psmouse_resetafter=");
68__obsolete_setup("psmouse_rate=");
69
70static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "ThinkPS/2", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2", "AlpsPS/2" };
71
72/*
73 * psmouse_process_byte() analyzes the PS/2 data stream and reports
74 * relevant events to the input module once full packet has arrived.
75 */
76
77static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
78{
79 struct input_dev *dev = &psmouse->dev;
80 unsigned char *packet = psmouse->packet;
81
82 if (psmouse->pktcnt < psmouse->pktsize)
83 return PSMOUSE_GOOD_DATA;
84
85/*
86 * Full packet accumulated, process it
87 */
88
89 input_regs(dev, regs);
90
91/*
92 * Scroll wheel on IntelliMice, scroll buttons on NetMice
93 */
94
95 if (psmouse->type == PSMOUSE_IMPS || psmouse->type == PSMOUSE_GENPS)
96 input_report_rel(dev, REL_WHEEL, -(signed char) packet[3]);
97
98/*
99 * Scroll wheel and buttons on IntelliMouse Explorer
100 */
101
102 if (psmouse->type == PSMOUSE_IMEX) {
103 input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 8) - (int) (packet[3] & 7));
104 input_report_key(dev, BTN_SIDE, (packet[3] >> 4) & 1);
105 input_report_key(dev, BTN_EXTRA, (packet[3] >> 5) & 1);
106 }
107
108/*
109 * Extra buttons on Genius NewNet 3D
110 */
111
112 if (psmouse->type == PSMOUSE_GENPS) {
113 input_report_key(dev, BTN_SIDE, (packet[0] >> 6) & 1);
114 input_report_key(dev, BTN_EXTRA, (packet[0] >> 7) & 1);
115 }
116
117/*
118 * Extra button on ThinkingMouse
119 */
120 if (psmouse->type == PSMOUSE_THINKPS) {
121 input_report_key(dev, BTN_EXTRA, (packet[0] >> 3) & 1);
122 /* Without this bit of weirdness moving up gives wildly high Y changes. */
123 packet[1] |= (packet[0] & 0x40) << 1;
124 }
125
126/*
127 * Generic PS/2 Mouse
128 */
129
130 input_report_key(dev, BTN_LEFT, packet[0] & 1);
131 input_report_key(dev, BTN_MIDDLE, (packet[0] >> 2) & 1);
132 input_report_key(dev, BTN_RIGHT, (packet[0] >> 1) & 1);
133
134 input_report_rel(dev, REL_X, packet[1] ? (int) packet[1] - (int) ((packet[0] << 4) & 0x100) : 0);
135 input_report_rel(dev, REL_Y, packet[2] ? (int) ((packet[0] << 3) & 0x100) - (int) packet[2] : 0);
136
137 input_sync(dev);
138
139 return PSMOUSE_FULL_PACKET;
140}
141
142/*
143 * psmouse_interrupt() handles incoming characters, either gathering them into
144 * packets or passing them to the command routine as command output.
145 */
146
147static irqreturn_t psmouse_interrupt(struct serio *serio,
148 unsigned char data, unsigned int flags, struct pt_regs *regs)
149{
150 struct psmouse *psmouse = serio_get_drvdata(serio);
151 psmouse_ret_t rc;
152
153 if (psmouse->state == PSMOUSE_IGNORE)
154 goto out;
155
156 if (flags & (SERIO_PARITY|SERIO_TIMEOUT)) {
157 if (psmouse->state == PSMOUSE_ACTIVATED)
158 printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n",
159 flags & SERIO_TIMEOUT ? " timeout" : "",
160 flags & SERIO_PARITY ? " bad parity" : "");
161 ps2_cmd_aborted(&psmouse->ps2dev);
162 goto out;
163 }
164
165 if (unlikely(psmouse->ps2dev.flags & PS2_FLAG_ACK))
166 if (ps2_handle_ack(&psmouse->ps2dev, data))
167 goto out;
168
169 if (unlikely(psmouse->ps2dev.flags & PS2_FLAG_CMD))
170 if (ps2_handle_response(&psmouse->ps2dev, data))
171 goto out;
172
173 if (psmouse->state == PSMOUSE_INITIALIZING)
174 goto out;
175
176 if (psmouse->state == PSMOUSE_ACTIVATED &&
177 psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {
178 printk(KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n",
179 psmouse->name, psmouse->phys, psmouse->pktcnt);
180 psmouse->pktcnt = 0;
181 }
182
183 psmouse->last = jiffies;
184 psmouse->packet[psmouse->pktcnt++] = data;
185
186 if (psmouse->packet[0] == PSMOUSE_RET_BAT) {
187 if (psmouse->pktcnt == 1)
188 goto out;
189
190 if (psmouse->pktcnt == 2) {
191 if (psmouse->packet[1] == PSMOUSE_RET_ID) {
192 psmouse->state = PSMOUSE_IGNORE;
193 serio_reconnect(serio);
194 goto out;
195 }
196 if (psmouse->type == PSMOUSE_SYNAPTICS) {
197 /* neither 0xAA nor 0x00 are valid first bytes
198 * for a packet in absolute mode
199 */
200 psmouse->pktcnt = 0;
201 goto out;
202 }
203 }
204 }
205
206 rc = psmouse->protocol_handler(psmouse, regs);
207
208 switch (rc) {
209 case PSMOUSE_BAD_DATA:
210 printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n",
211 psmouse->name, psmouse->phys, psmouse->pktcnt);
212 psmouse->pktcnt = 0;
213
214 if (++psmouse->out_of_sync == psmouse->resetafter) {
215 psmouse->state = PSMOUSE_IGNORE;
216 printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n");
217 serio_reconnect(psmouse->ps2dev.serio);
218 }
219 break;
220
221 case PSMOUSE_FULL_PACKET:
222 psmouse->pktcnt = 0;
223 if (psmouse->out_of_sync) {
224 psmouse->out_of_sync = 0;
225 printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n",
226 psmouse->name, psmouse->phys);
227 }
228 break;
229
230 case PSMOUSE_GOOD_DATA:
231 break;
232 }
233out:
234 return IRQ_HANDLED;
235}
236
237
238/*
239 * psmouse_sliced_command() sends an extended PS/2 command to the mouse
240 * using sliced syntax, understood by advanced devices, such as Logitech
241 * or Synaptics touchpads. The command is encoded as:
242 * 0xE6 0xE8 rr 0xE8 ss 0xE8 tt 0xE8 uu where (rr*64)+(ss*16)+(tt*4)+uu
243 * is the command.
244 */
245int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command)
246{
247 int i;
248
249 if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11))
250 return -1;
251
252 for (i = 6; i >= 0; i -= 2) {
253 unsigned char d = (command >> i) & 3;
254 if (ps2_command(&psmouse->ps2dev, &d, PSMOUSE_CMD_SETRES))
255 return -1;
256 }
257
258 return 0;
259}
260
261
262/*
263 * psmouse_reset() resets the mouse into power-on state.
264 */
265int psmouse_reset(struct psmouse *psmouse)
266{
267 unsigned char param[2];
268
269 if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_RESET_BAT))
270 return -1;
271
272 if (param[0] != PSMOUSE_RET_BAT && param[1] != PSMOUSE_RET_ID)
273 return -1;
274
275 return 0;
276}
277
278
279/*
280 * Genius NetMouse magic init.
281 */
282static int genius_detect(struct psmouse *psmouse, int set_properties)
283{
284 struct ps2dev *ps2dev = &psmouse->ps2dev;
285 unsigned char param[4];
286
287 param[0] = 3;
288 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
289 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11);
290 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11);
291 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11);
292 ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
293
294 if (param[0] != 0x00 || param[1] != 0x33 || param[2] != 0x55)
295 return -1;
296
297 if (set_properties) {
298 set_bit(BTN_EXTRA, psmouse->dev.keybit);
299 set_bit(BTN_SIDE, psmouse->dev.keybit);
300 set_bit(REL_WHEEL, psmouse->dev.relbit);
301
302 psmouse->vendor = "Genius";
303 psmouse->name = "Wheel Mouse";
304 psmouse->pktsize = 4;
305 }
306
307 return 0;
308}
309
310/*
311 * IntelliMouse magic init.
312 */
313static int intellimouse_detect(struct psmouse *psmouse, int set_properties)
314{
315 struct ps2dev *ps2dev = &psmouse->ps2dev;
316 unsigned char param[2];
317
318 param[0] = 200;
319 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
320 param[0] = 100;
321 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
322 param[0] = 80;
323 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
324 ps2_command(ps2dev, param, PSMOUSE_CMD_GETID);
325
326 if (param[0] != 3)
327 return -1;
328
329 if (set_properties) {
330 set_bit(REL_WHEEL, psmouse->dev.relbit);
331
332 if (!psmouse->vendor) psmouse->vendor = "Generic";
333 if (!psmouse->name) psmouse->name = "Wheel Mouse";
334 psmouse->pktsize = 4;
335 }
336
337 return 0;
338}
339
340/*
341 * Try IntelliMouse/Explorer magic init.
342 */
343static int im_explorer_detect(struct psmouse *psmouse, int set_properties)
344{
345 struct ps2dev *ps2dev = &psmouse->ps2dev;
346 unsigned char param[2];
347
348 intellimouse_detect(psmouse, 0);
349
350 param[0] = 200;
351 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
352 param[0] = 200;
353 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
354 param[0] = 80;
355 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
356 ps2_command(ps2dev, param, PSMOUSE_CMD_GETID);
357
358 if (param[0] != 4)
359 return -1;
360
361 if (set_properties) {
362 set_bit(REL_WHEEL, psmouse->dev.relbit);
363 set_bit(BTN_SIDE, psmouse->dev.keybit);
364 set_bit(BTN_EXTRA, psmouse->dev.keybit);
365
366 if (!psmouse->vendor) psmouse->vendor = "Generic";
367 if (!psmouse->name) psmouse->name = "Explorer Mouse";
368 psmouse->pktsize = 4;
369 }
370
371 return 0;
372}
373
374/*
375 * Kensington ThinkingMouse / ExpertMouse magic init.
376 */
377static int thinking_detect(struct psmouse *psmouse, int set_properties)
378{
379 struct ps2dev *ps2dev = &psmouse->ps2dev;
380 unsigned char param[2];
381 unsigned char seq[] = { 20, 60, 40, 20, 20, 60, 40, 20, 20, 0 };
382 int i;
383
384 param[0] = 10;
385 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
386 param[0] = 0;
387 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
388 for (i = 0; seq[i]; i++)
389 ps2_command(ps2dev, seq + i, PSMOUSE_CMD_SETRATE);
390 ps2_command(ps2dev, param, PSMOUSE_CMD_GETID);
391
392 if (param[0] != 2)
393 return -1;
394
395 if (set_properties) {
396 set_bit(BTN_EXTRA, psmouse->dev.keybit);
397
398 psmouse->vendor = "Kensington";
399 psmouse->name = "ThinkingMouse";
400 }
401
402 return 0;
403}
404
405/*
406 * Bare PS/2 protocol "detection". Always succeeds.
407 */
408static int ps2bare_detect(struct psmouse *psmouse, int set_properties)
409{
410 if (!psmouse->vendor) psmouse->vendor = "Generic";
411 if (!psmouse->name) psmouse->name = "Mouse";
412
413 return 0;
414}
415
416/*
417 * psmouse_extensions() probes for any extensions to the basic PS/2 protocol
418 * the mouse may have.
419 */
420
421static int psmouse_extensions(struct psmouse *psmouse,
422 unsigned int max_proto, int set_properties)
423{
424 int synaptics_hardware = 0;
425
426/*
427 * Try Kensington ThinkingMouse (we try first, because synaptics probe
428 * upsets the thinkingmouse).
429 */
430
431 if (max_proto > PSMOUSE_IMEX && thinking_detect(psmouse, set_properties) == 0)
432 return PSMOUSE_THINKPS;
433
434/*
435 * Try Synaptics TouchPad
436 */
437 if (max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse, set_properties) == 0) {
438 synaptics_hardware = 1;
439
440 if (max_proto > PSMOUSE_IMEX) {
441 if (!set_properties || synaptics_init(psmouse) == 0)
442 return PSMOUSE_SYNAPTICS;
443/*
444 * Some Synaptics touchpads can emulate extended protocols (like IMPS/2).
445 * Unfortunately Logitech/Genius probes confuse some firmware versions so
446 * we'll have to skip them.
447 */
448 max_proto = PSMOUSE_IMEX;
449 }
450/*
451 * Make sure that touchpad is in relative mode, gestures (taps) are enabled
452 */
453 synaptics_reset(psmouse);
454 }
455
456/*
457 * Try ALPS TouchPad
458 */
459 if (max_proto > PSMOUSE_IMEX) {
460 ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
461 if (alps_detect(psmouse, set_properties) == 0) {
462 if (!set_properties || alps_init(psmouse) == 0)
463 return PSMOUSE_ALPS;
464/*
465 * Init failed, try basic relative protocols
466 */
467 max_proto = PSMOUSE_IMEX;
468 }
469 }
470
471 if (max_proto > PSMOUSE_IMEX && genius_detect(psmouse, set_properties) == 0)
472 return PSMOUSE_GENPS;
473
474 if (max_proto > PSMOUSE_IMEX && ps2pp_init(psmouse, set_properties) == 0)
475 return PSMOUSE_PS2PP;
476
477/*
478 * Reset to defaults in case the device got confused by extended
479 * protocol probes.
480 */
481 ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
482
483 if (max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse, set_properties) == 0)
484 return PSMOUSE_IMEX;
485
486 if (max_proto >= PSMOUSE_IMPS && intellimouse_detect(psmouse, set_properties) == 0)
487 return PSMOUSE_IMPS;
488
489/*
490 * Okay, all failed, we have a standard mouse here. The number of the buttons
491 * is still a question, though. We assume 3.
492 */
493 ps2bare_detect(psmouse, set_properties);
494
495 if (synaptics_hardware) {
496/*
497 * We detected Synaptics hardware but it did not respond to IMPS/2 probes.
498 * We need to reset the touchpad because if there is a track point on the
499 * pass through port it could get disabled while probing for protocol
500 * extensions.
501 */
502 psmouse_reset(psmouse);
503 ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
504 }
505
506 return PSMOUSE_PS2;
507}
508
509/*
510 * psmouse_probe() probes for a PS/2 mouse.
511 */
512
513static int psmouse_probe(struct psmouse *psmouse)
514{
515 struct ps2dev *ps2dev = &psmouse->ps2dev;
516 unsigned char param[2];
517
518/*
519 * First, we check if it's a mouse. It should send 0x00 or 0x03
520 * in case of an IntelliMouse in 4-byte mode or 0x04 for IM Explorer.
521 */
522
523 param[0] = 0xa5;
524 if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETID))
525 return -1;
526
527 if (param[0] != 0x00 && param[0] != 0x03 && param[0] != 0x04)
528 return -1;
529
530/*
531 * Then we reset and disable the mouse so that it doesn't generate events.
532 */
533
534 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_DIS))
535 printk(KERN_WARNING "psmouse.c: Failed to reset mouse on %s\n", ps2dev->serio->phys);
536
537 return 0;
538}
539
540/*
541 * Here we set the mouse resolution.
542 */
543
544void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution)
545{
546 unsigned char params[] = { 0, 1, 2, 2, 3 };
547
548 if (resolution == 0 || resolution > 200)
549 resolution = 200;
550
551 ps2_command(&psmouse->ps2dev, &params[resolution / 50], PSMOUSE_CMD_SETRES);
552 psmouse->resolution = 25 << params[resolution / 50];
553}
554
555/*
556 * Here we set the mouse report rate.
557 */
558
559static void psmouse_set_rate(struct psmouse *psmouse, unsigned int rate)
560{
561 unsigned char rates[] = { 200, 100, 80, 60, 40, 20, 10, 0 };
562 int i = 0;
563
564 while (rates[i] > rate) i++;
565 ps2_command(&psmouse->ps2dev, &rates[i], PSMOUSE_CMD_SETRATE);
566 psmouse->rate = rates[i];
567}
568
569/*
570 * psmouse_initialize() initializes the mouse to a sane state.
571 */
572
573static void psmouse_initialize(struct psmouse *psmouse)
574{
575/*
576 * We set the mouse into streaming mode.
577 */
578
579 ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM);
580
581/*
582 * We set the mouse report rate, resolution and scaling.
583 */
584
585 if (psmouse_max_proto != PSMOUSE_PS2) {
586 psmouse->set_rate(psmouse, psmouse->rate);
587 psmouse->set_resolution(psmouse, psmouse->resolution);
588 ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11);
589 }
590}
591
592/*
593 * psmouse_set_state() sets new psmouse state and resets all flags and
594 * counters while holding serio lock so fighting with interrupt handler
595 * is not a concern.
596 */
597
598static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
599{
600 serio_pause_rx(psmouse->ps2dev.serio);
601 psmouse->state = new_state;
602 psmouse->pktcnt = psmouse->out_of_sync = 0;
603 psmouse->ps2dev.flags = 0;
604 serio_continue_rx(psmouse->ps2dev.serio);
605}
606
607/*
608 * psmouse_activate() enables the mouse so that we get motion reports from it.
609 */
610
611static void psmouse_activate(struct psmouse *psmouse)
612{
613 if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE))
614 printk(KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n",
615 psmouse->ps2dev.serio->phys);
616
617 psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
618}
619
620
621/*
622 * psmouse_deactivate() puts the mouse into poll mode so that we don't get motion
623 * reports from it unless we explicitely request it.
624 */
625
626static void psmouse_deactivate(struct psmouse *psmouse)
627{
628 if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE))
629 printk(KERN_WARNING "psmouse.c: Failed to deactivate mouse on %s\n",
630 psmouse->ps2dev.serio->phys);
631
632 psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
633}
634
635
636/*
637 * psmouse_cleanup() resets the mouse into power-on state.
638 */
639
640static void psmouse_cleanup(struct serio *serio)
641{
642 struct psmouse *psmouse = serio_get_drvdata(serio);
643
644 psmouse_reset(psmouse);
645}
646
647/*
648 * psmouse_disconnect() closes and frees.
649 */
650
651static void psmouse_disconnect(struct serio *serio)
652{
653 struct psmouse *psmouse, *parent;
654
655 device_remove_file(&serio->dev, &psmouse_attr_rate);
656 device_remove_file(&serio->dev, &psmouse_attr_resolution);
657 device_remove_file(&serio->dev, &psmouse_attr_resetafter);
658
659 psmouse = serio_get_drvdata(serio);
660 psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
661
662 if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
663 parent = serio_get_drvdata(serio->parent);
664 if (parent->pt_deactivate)
665 parent->pt_deactivate(parent);
666 }
667
668 if (psmouse->disconnect)
669 psmouse->disconnect(psmouse);
670
671 psmouse_set_state(psmouse, PSMOUSE_IGNORE);
672
673 input_unregister_device(&psmouse->dev);
674 serio_close(serio);
675 serio_set_drvdata(serio, NULL);
676 kfree(psmouse);
677}
678
679/*
680 * psmouse_connect() is a callback from the serio module when
681 * an unhandled serio port is found.
682 */
683static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
684{
685 struct psmouse *psmouse, *parent = NULL;
686 int retval;
687
688 /*
689 * If this is a pass-through port deactivate parent so the device
690 * connected to this port can be successfully identified
691 */
692 if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
693 parent = serio_get_drvdata(serio->parent);
694 psmouse_deactivate(parent);
695 }
696
697 if (!(psmouse = kmalloc(sizeof(struct psmouse), GFP_KERNEL))) {
698 retval = -ENOMEM;
699 goto out;
700 }
701
702 memset(psmouse, 0, sizeof(struct psmouse));
703
704 ps2_init(&psmouse->ps2dev, serio);
705 sprintf(psmouse->phys, "%s/input0", serio->phys);
706 psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
707 psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
708 psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
709 psmouse->dev.private = psmouse;
710 psmouse->dev.dev = &serio->dev;
711 psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
712
713 serio_set_drvdata(serio, psmouse);
714
715 retval = serio_open(serio, drv);
716 if (retval) {
717 serio_set_drvdata(serio, NULL);
718 kfree(psmouse);
719 goto out;
720 }
721
722 if (psmouse_probe(psmouse) < 0) {
723 serio_close(serio);
724 serio_set_drvdata(serio, NULL);
725 kfree(psmouse);
726 retval = -ENODEV;
727 goto out;
728 }
729
730 psmouse->rate = psmouse_rate;
731 psmouse->resolution = psmouse_resolution;
732 psmouse->resetafter = psmouse_resetafter;
733 psmouse->smartscroll = psmouse_smartscroll;
734 psmouse->set_rate = psmouse_set_rate;
735 psmouse->set_resolution = psmouse_set_resolution;
736 psmouse->protocol_handler = psmouse_process_byte;
737 psmouse->pktsize = 3;
738
739 psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1);
740
741 sprintf(psmouse->devname, "%s %s %s",
742 psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name);
743
744 psmouse->dev.name = psmouse->devname;
745 psmouse->dev.phys = psmouse->phys;
746 psmouse->dev.id.bustype = BUS_I8042;
747 psmouse->dev.id.vendor = 0x0002;
748 psmouse->dev.id.product = psmouse->type;
749 psmouse->dev.id.version = psmouse->model;
750
751 input_register_device(&psmouse->dev);
752
753 printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys);
754
755 psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
756
757 psmouse_initialize(psmouse);
758
759 if (parent && parent->pt_activate)
760 parent->pt_activate(parent);
761
762 device_create_file(&serio->dev, &psmouse_attr_rate);
763 device_create_file(&serio->dev, &psmouse_attr_resolution);
764 device_create_file(&serio->dev, &psmouse_attr_resetafter);
765
766 psmouse_activate(psmouse);
767
768 retval = 0;
769
770out:
771 /* If this is a pass-through port the parent awaits to be activated */
772 if (parent)
773 psmouse_activate(parent);
774
775 return retval;
776}
777
778
779static int psmouse_reconnect(struct serio *serio)
780{
781 struct psmouse *psmouse = serio_get_drvdata(serio);
782 struct psmouse *parent = NULL;
783 struct serio_driver *drv = serio->drv;
784 int rc = -1;
785
786 if (!drv || !psmouse) {
787 printk(KERN_DEBUG "psmouse: reconnect request, but serio is disconnected, ignoring...\n");
788 return -1;
789 }
790
791 if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
792 parent = serio_get_drvdata(serio->parent);
793 psmouse_deactivate(parent);
794 }
795
796 psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
797
798 if (psmouse->reconnect) {
799 if (psmouse->reconnect(psmouse))
800 goto out;
801 } else if (psmouse_probe(psmouse) < 0 ||
802 psmouse->type != psmouse_extensions(psmouse, psmouse_max_proto, 0))
803 goto out;
804
805 /* ok, the device type (and capabilities) match the old one,
806 * we can continue using it, complete intialization
807 */
808 psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
809
810 psmouse_initialize(psmouse);
811
812 if (parent && parent->pt_activate)
813 parent->pt_activate(parent);
814
815 psmouse_activate(psmouse);
816 rc = 0;
817
818out:
819 /* If this is a pass-through port the parent waits to be activated */
820 if (parent)
821 psmouse_activate(parent);
822
823 return rc;
824}
825
826static struct serio_device_id psmouse_serio_ids[] = {
827 {
828 .type = SERIO_8042,
829 .proto = SERIO_ANY,
830 .id = SERIO_ANY,
831 .extra = SERIO_ANY,
832 },
833 {
834 .type = SERIO_PS_PSTHRU,
835 .proto = SERIO_ANY,
836 .id = SERIO_ANY,
837 .extra = SERIO_ANY,
838 },
839 { 0 }
840};
841
842MODULE_DEVICE_TABLE(serio, psmouse_serio_ids);
843
844static struct serio_driver psmouse_drv = {
845 .driver = {
846 .name = "psmouse",
847 },
848 .description = DRIVER_DESC,
849 .id_table = psmouse_serio_ids,
850 .interrupt = psmouse_interrupt,
851 .connect = psmouse_connect,
852 .reconnect = psmouse_reconnect,
853 .disconnect = psmouse_disconnect,
854 .cleanup = psmouse_cleanup,
855};
856
857ssize_t psmouse_attr_show_helper(struct device *dev, char *buf,
858 ssize_t (*handler)(struct psmouse *, char *))
859{
860 struct serio *serio = to_serio_port(dev);
861 int retval;
862
863 retval = serio_pin_driver(serio);
864 if (retval)
865 return retval;
866
867 if (serio->drv != &psmouse_drv) {
868 retval = -ENODEV;
869 goto out;
870 }
871
872 retval = handler(serio_get_drvdata(serio), buf);
873
874out:
875 serio_unpin_driver(serio);
876 return retval;
877}
878
879ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t count,
880 ssize_t (*handler)(struct psmouse *, const char *, size_t))
881{
882 struct serio *serio = to_serio_port(dev);
883 struct psmouse *psmouse = serio_get_drvdata(serio);
884 struct psmouse *parent = NULL;
885 int retval;
886
887 retval = serio_pin_driver(serio);
888 if (retval)
889 return retval;
890
891 if (serio->drv != &psmouse_drv) {
892 retval = -ENODEV;
893 goto out;
894 }
895
896 if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
897 parent = serio_get_drvdata(serio->parent);
898 psmouse_deactivate(parent);
899 }
900 psmouse_deactivate(psmouse);
901
902 retval = handler(psmouse, buf, count);
903
904 psmouse_activate(psmouse);
905 if (parent)
906 psmouse_activate(parent);
907
908out:
909 serio_unpin_driver(serio);
910 return retval;
911}
912
913static ssize_t psmouse_attr_show_rate(struct psmouse *psmouse, char *buf)
914{
915 return sprintf(buf, "%d\n", psmouse->rate);
916}
917
918static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, const char *buf, size_t count)
919{
920 unsigned long value;
921 char *rest;
922
923 value = simple_strtoul(buf, &rest, 10);
924 if (*rest)
925 return -EINVAL;
926
927 psmouse->set_rate(psmouse, value);
928 return count;
929}
930
931static ssize_t psmouse_attr_show_resolution(struct psmouse *psmouse, char *buf)
932{
933 return sprintf(buf, "%d\n", psmouse->resolution);
934}
935
936static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, const char *buf, size_t count)
937{
938 unsigned long value;
939 char *rest;
940
941 value = simple_strtoul(buf, &rest, 10);
942 if (*rest)
943 return -EINVAL;
944
945 psmouse->set_resolution(psmouse, value);
946 return count;
947}
948
949static ssize_t psmouse_attr_show_resetafter(struct psmouse *psmouse, char *buf)
950{
951 return sprintf(buf, "%d\n", psmouse->resetafter);
952}
953
954static ssize_t psmouse_attr_set_resetafter(struct psmouse *psmouse, const char *buf, size_t count)
955{
956 unsigned long value;
957 char *rest;
958
959 value = simple_strtoul(buf, &rest, 10);
960 if (*rest)
961 return -EINVAL;
962
963 psmouse->resetafter = value;
964 return count;
965}
966
967static int psmouse_set_maxproto(const char *val, struct kernel_param *kp)
968{
969 int i;
970
971 if (!val)
972 return -EINVAL;
973
974 if (!strncmp(val, "any", 3)) {
975 *((unsigned int *)kp->arg) = -1UL;
976 return 0;
977 }
978
979 for (i = 0; i < ARRAY_SIZE(psmouse_proto_abbrev); i++) {
980 if (!psmouse_proto_abbrev[i])
981 continue;
982
983 if (!strncmp(val, psmouse_proto_abbrev[i], strlen(psmouse_proto_abbrev[i]))) {
984 *((unsigned int *)kp->arg) = i;
985 return 0;
986 }
987 }
988
989 return -EINVAL; \
990}
991
992static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp)
993{
994 return sprintf(buffer, "%s\n",
995 psmouse_max_proto < ARRAY_SIZE(psmouse_proto_abbrev) ?
996 psmouse_proto_abbrev[psmouse_max_proto] : "any");
997}
998
999static int __init psmouse_init(void)
1000{
1001 serio_register_driver(&psmouse_drv);
1002 return 0;
1003}
1004
1005static void __exit psmouse_exit(void)
1006{
1007 serio_unregister_driver(&psmouse_drv);
1008}
1009
1010module_init(psmouse_init);
1011module_exit(psmouse_exit);
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
new file mode 100644
index 000000000000..bda5b065d03c
--- /dev/null
+++ b/drivers/input/mouse/psmouse.h
@@ -0,0 +1,106 @@
1#ifndef _PSMOUSE_H
2#define _PSMOUSE_H
3
4#define PSMOUSE_CMD_SETSCALE11 0x00e6
5#define PSMOUSE_CMD_SETSCALE21 0x00e7
6#define PSMOUSE_CMD_SETRES 0x10e8
7#define PSMOUSE_CMD_GETINFO 0x03e9
8#define PSMOUSE_CMD_SETSTREAM 0x00ea
9#define PSMOUSE_CMD_SETPOLL 0x00f0
10#define PSMOUSE_CMD_POLL 0x03eb
11#define PSMOUSE_CMD_GETID 0x02f2
12#define PSMOUSE_CMD_SETRATE 0x10f3
13#define PSMOUSE_CMD_ENABLE 0x00f4
14#define PSMOUSE_CMD_DISABLE 0x00f5
15#define PSMOUSE_CMD_RESET_DIS 0x00f6
16#define PSMOUSE_CMD_RESET_BAT 0x02ff
17
18#define PSMOUSE_RET_BAT 0xaa
19#define PSMOUSE_RET_ID 0x00
20#define PSMOUSE_RET_ACK 0xfa
21#define PSMOUSE_RET_NAK 0xfe
22
23enum psmouse_state {
24 PSMOUSE_IGNORE,
25 PSMOUSE_INITIALIZING,
26 PSMOUSE_CMD_MODE,
27 PSMOUSE_ACTIVATED,
28};
29
30/* psmouse protocol handler return codes */
31typedef enum {
32 PSMOUSE_BAD_DATA,
33 PSMOUSE_GOOD_DATA,
34 PSMOUSE_FULL_PACKET
35} psmouse_ret_t;
36
37struct psmouse {
38 void *private;
39 struct input_dev dev;
40 struct ps2dev ps2dev;
41 char *vendor;
42 char *name;
43 unsigned char packet[8];
44 unsigned char pktcnt;
45 unsigned char pktsize;
46 unsigned char type;
47 unsigned int model;
48 unsigned long last;
49 unsigned long out_of_sync;
50 enum psmouse_state state;
51 char devname[64];
52 char phys[32];
53
54 unsigned int rate;
55 unsigned int resolution;
56 unsigned int resetafter;
57 unsigned int smartscroll; /* Logitech only */
58
59 psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs);
60 void (*set_rate)(struct psmouse *psmouse, unsigned int rate);
61 void (*set_resolution)(struct psmouse *psmouse, unsigned int resolution);
62
63 int (*reconnect)(struct psmouse *psmouse);
64 void (*disconnect)(struct psmouse *psmouse);
65
66 void (*pt_activate)(struct psmouse *psmouse);
67 void (*pt_deactivate)(struct psmouse *psmouse);
68};
69
70enum psmouse_type {
71 PSMOUSE_NONE,
72 PSMOUSE_PS2,
73 PSMOUSE_PS2PP,
74 PSMOUSE_THINKPS,
75 PSMOUSE_GENPS,
76 PSMOUSE_IMPS,
77 PSMOUSE_IMEX,
78 PSMOUSE_SYNAPTICS,
79 PSMOUSE_ALPS,
80};
81
82int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command);
83int psmouse_reset(struct psmouse *psmouse);
84void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution);
85
86ssize_t psmouse_attr_show_helper(struct device *dev, char *buf,
87 ssize_t (*handler)(struct psmouse *, char *));
88ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t count,
89 ssize_t (*handler)(struct psmouse *, const char *, size_t));
90
91#define PSMOUSE_DEFINE_ATTR(_name) \
92static ssize_t psmouse_attr_show_##_name(struct psmouse *, char *); \
93static ssize_t psmouse_attr_set_##_name(struct psmouse *, const char *, size_t);\
94static ssize_t psmouse_do_show_##_name(struct device *d, char *b) \
95{ \
96 return psmouse_attr_show_helper(d, b, psmouse_attr_show_##_name); \
97} \
98static ssize_t psmouse_do_set_##_name(struct device *d, const char *b, size_t s)\
99{ \
100 return psmouse_attr_set_helper(d, b, s, psmouse_attr_set_##_name); \
101} \
102static struct device_attribute psmouse_attr_##_name = \
103 __ATTR(_name, S_IWUSR | S_IRUGO, \
104 psmouse_do_show_##_name, psmouse_do_set_##_name);
105
106#endif /* _PSMOUSE_H */
diff --git a/drivers/input/mouse/rpcmouse.c b/drivers/input/mouse/rpcmouse.c
new file mode 100644
index 000000000000..7280f68afcee
--- /dev/null
+++ b/drivers/input/mouse/rpcmouse.c
@@ -0,0 +1,107 @@
1/*
2 * Acorn RiscPC mouse driver for Linux/ARM
3 *
4 * Copyright (c) 2000-2002 Vojtech Pavlik
5 * Copyright (C) 1996-2002 Russell King
6 *
7 */
8
9/*
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This handles the Acorn RiscPCs mouse. We basically have a couple of
15 * hardware registers that track the sensor count for the X-Y movement and
16 * another register holding the button state. On every VSYNC interrupt we read
17 * the complete state and then work out if something has changed.
18 */
19
20#include <linux/module.h>
21#include <linux/sched.h>
22#include <linux/ptrace.h>
23#include <linux/interrupt.h>
24#include <linux/init.h>
25#include <linux/input.h>
26
27#include <asm/hardware.h>
28#include <asm/irq.h>
29#include <asm/io.h>
30#include <asm/hardware/iomd.h>
31
32MODULE_AUTHOR("Vojtech Pavlik, Russell King");
33MODULE_DESCRIPTION("Acorn RiscPC mouse driver");
34MODULE_LICENSE("GPL");
35
36static short rpcmouse_lastx, rpcmouse_lasty;
37
38static struct input_dev rpcmouse_dev = {
39 .evbit = { BIT(EV_KEY) | BIT(EV_REL) },
40 .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
41 .relbit = { BIT(REL_X) | BIT(REL_Y) },
42 .name = "Acorn RiscPC Mouse",
43 .phys = "rpcmouse/input0",
44 .id = {
45 .bustype = BUS_HOST,
46 .vendor = 0x0005,
47 .product = 0x0001,
48 .version = 0x0100,
49 },
50};
51
52static irqreturn_t rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs)
53{
54 struct input_dev *dev = dev_id;
55 short x, y, dx, dy, b;
56
57 x = (short) iomd_readl(IOMD_MOUSEX);
58 y = (short) iomd_readl(IOMD_MOUSEY);
59 b = (short) (__raw_readl(0xe0310000) ^ 0x70);
60
61 dx = x - rpcmouse_lastx;
62 dy = y - rpcmouse_lasty;
63
64 rpcmouse_lastx = x;
65 rpcmouse_lasty = y;
66
67 input_regs(dev, regs);
68
69 input_report_rel(dev, REL_X, dx);
70 input_report_rel(dev, REL_Y, -dy);
71
72 input_report_key(dev, BTN_LEFT, b & 0x40);
73 input_report_key(dev, BTN_MIDDLE, b & 0x20);
74 input_report_key(dev, BTN_RIGHT, b & 0x10);
75
76 input_sync(dev);
77
78 return IRQ_HANDLED;
79}
80
81static int __init rpcmouse_init(void)
82{
83 init_input_dev(&rpcmouse_dev);
84
85 rpcmouse_lastx = (short) iomd_readl(IOMD_MOUSEX);
86 rpcmouse_lasty = (short) iomd_readl(IOMD_MOUSEY);
87
88 if (request_irq(IRQ_VSYNCPULSE, rpcmouse_irq, SA_SHIRQ, "rpcmouse", &rpcmouse_dev)) {
89 printk(KERN_ERR "rpcmouse: unable to allocate VSYNC interrupt\n");
90 return -1;
91 }
92
93 input_register_device(&rpcmouse_dev);
94
95 printk(KERN_INFO "input: Acorn RiscPC mouse\n");
96
97 return 0;
98}
99
100static void __exit rpcmouse_exit(void)
101{
102 input_unregister_device(&rpcmouse_dev);
103 free_irq(IRQ_VSYNCPULSE, &rpcmouse_dev);
104}
105
106module_init(rpcmouse_init);
107module_exit(rpcmouse_exit);
diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c
new file mode 100644
index 000000000000..d12b93ae3900
--- /dev/null
+++ b/drivers/input/mouse/sermouse.c
@@ -0,0 +1,370 @@
1/*
2 * $Id: sermouse.c,v 1.17 2002/03/13 10:03:43 vojtech Exp $
3 *
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 */
6
7/*
8 * Serial mouse driver for Linux
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/delay.h>
32#include <linux/module.h>
33#include <linux/slab.h>
34#include <linux/interrupt.h>
35#include <linux/input.h>
36#include <linux/config.h>
37#include <linux/serio.h>
38#include <linux/init.h>
39
40#define DRIVER_DESC "Serial mouse driver"
41
42MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
43MODULE_DESCRIPTION(DRIVER_DESC);
44MODULE_LICENSE("GPL");
45
46static char *sermouse_protocols[] = { "None", "Mouse Systems Mouse", "Sun Mouse", "Microsoft Mouse",
47 "Logitech M+ Mouse", "Microsoft MZ Mouse", "Logitech MZ+ Mouse",
48 "Logitech MZ++ Mouse"};
49
50struct sermouse {
51 struct input_dev dev;
52 signed char buf[8];
53 unsigned char count;
54 unsigned char type;
55 unsigned long last;
56 char phys[32];
57};
58
59/*
60 * sermouse_process_msc() analyzes the incoming MSC/Sun bytestream and
61 * applies some prediction to the data, resulting in 96 updates per
62 * second, which is as good as a PS/2 or USB mouse.
63 */
64
65static void sermouse_process_msc(struct sermouse *sermouse, signed char data, struct pt_regs *regs)
66{
67 struct input_dev *dev = &sermouse->dev;
68 signed char *buf = sermouse->buf;
69
70 input_regs(dev, regs);
71
72 switch (sermouse->count) {
73
74 case 0:
75 if ((data & 0xf8) != 0x80) return;
76 input_report_key(dev, BTN_LEFT, !(data & 4));
77 input_report_key(dev, BTN_RIGHT, !(data & 1));
78 input_report_key(dev, BTN_MIDDLE, !(data & 2));
79 break;
80
81 case 1:
82 case 3:
83 input_report_rel(dev, REL_X, data / 2);
84 input_report_rel(dev, REL_Y, -buf[1]);
85 buf[0] = data - data / 2;
86 break;
87
88 case 2:
89 case 4:
90 input_report_rel(dev, REL_X, buf[0]);
91 input_report_rel(dev, REL_Y, buf[1] - data);
92 buf[1] = data / 2;
93 break;
94 }
95
96 input_sync(dev);
97
98 if (++sermouse->count == (5 - ((sermouse->type == SERIO_SUN) << 1)))
99 sermouse->count = 0;
100}
101
102/*
103 * sermouse_process_ms() anlyzes the incoming MS(Z/+/++) bytestream and
104 * generates events. With prediction it gets 80 updates/sec, assuming
105 * standard 3-byte packets and 1200 bps.
106 */
107
108static void sermouse_process_ms(struct sermouse *sermouse, signed char data, struct pt_regs *regs)
109{
110 struct input_dev *dev = &sermouse->dev;
111 signed char *buf = sermouse->buf;
112
113 if (data & 0x40) sermouse->count = 0;
114
115 input_regs(dev, regs);
116
117 switch (sermouse->count) {
118
119 case 0:
120 buf[1] = data;
121 input_report_key(dev, BTN_LEFT, (data >> 5) & 1);
122 input_report_key(dev, BTN_RIGHT, (data >> 4) & 1);
123 break;
124
125 case 1:
126 buf[2] = data;
127 data = (signed char) (((buf[1] << 6) & 0xc0) | (data & 0x3f));
128 input_report_rel(dev, REL_X, data / 2);
129 input_report_rel(dev, REL_Y, buf[4]);
130 buf[3] = data - data / 2;
131 break;
132
133 case 2:
134 /* Guessing the state of the middle button on 3-button MS-protocol mice - ugly. */
135 if ((sermouse->type == SERIO_MS) && !data && !buf[2] && !((buf[0] & 0xf0) ^ buf[1]))
136 input_report_key(dev, BTN_MIDDLE, !test_bit(BTN_MIDDLE, dev->key));
137 buf[0] = buf[1];
138
139 data = (signed char) (((buf[1] << 4) & 0xc0) | (data & 0x3f));
140 input_report_rel(dev, REL_X, buf[3]);
141 input_report_rel(dev, REL_Y, data - buf[4]);
142 buf[4] = data / 2;
143 break;
144
145 case 3:
146
147 switch (sermouse->type) {
148
149 case SERIO_MS:
150 sermouse->type = SERIO_MP;
151
152 case SERIO_MP:
153 if ((data >> 2) & 3) break; /* M++ Wireless Extension packet. */
154 input_report_key(dev, BTN_MIDDLE, (data >> 5) & 1);
155 input_report_key(dev, BTN_SIDE, (data >> 4) & 1);
156 break;
157
158 case SERIO_MZP:
159 case SERIO_MZPP:
160 input_report_key(dev, BTN_SIDE, (data >> 5) & 1);
161
162 case SERIO_MZ:
163 input_report_key(dev, BTN_MIDDLE, (data >> 4) & 1);
164 input_report_rel(dev, REL_WHEEL, (data & 8) - (data & 7));
165 break;
166 }
167
168 break;
169
170 case 4:
171 case 6: /* MZ++ packet type. We can get these bytes for M++ too but we ignore them later. */
172 buf[1] = (data >> 2) & 0x0f;
173 break;
174
175 case 5:
176 case 7: /* Ignore anything besides MZ++ */
177 if (sermouse->type != SERIO_MZPP) break;
178
179 switch (buf[1]) {
180
181 case 1: /* Extra mouse info */
182
183 input_report_key(dev, BTN_SIDE, (data >> 4) & 1);
184 input_report_key(dev, BTN_EXTRA, (data >> 5) & 1);
185 input_report_rel(dev, data & 0x80 ? REL_HWHEEL : REL_WHEEL, (data & 7) - (data & 8));
186
187 break;
188
189 default: /* We don't decode anything else yet. */
190
191 printk(KERN_WARNING
192 "sermouse.c: Received MZ++ packet %x, don't know how to handle.\n", buf[1]);
193 break;
194 }
195
196 break;
197 }
198
199 input_sync(dev);
200
201 sermouse->count++;
202}
203
204/*
205 * sermouse_interrupt() handles incoming characters, either gathering them into
206 * packets or passing them to the command routine as command output.
207 */
208
209static irqreturn_t sermouse_interrupt(struct serio *serio,
210 unsigned char data, unsigned int flags, struct pt_regs *regs)
211{
212 struct sermouse *sermouse = serio_get_drvdata(serio);
213
214 if (time_after(jiffies, sermouse->last + HZ/10)) sermouse->count = 0;
215 sermouse->last = jiffies;
216
217 if (sermouse->type > SERIO_SUN)
218 sermouse_process_ms(sermouse, data, regs);
219 else
220 sermouse_process_msc(sermouse, data, regs);
221 return IRQ_HANDLED;
222}
223
224/*
225 * sermouse_disconnect() cleans up after we don't want talk
226 * to the mouse anymore.
227 */
228
229static void sermouse_disconnect(struct serio *serio)
230{
231 struct sermouse *sermouse = serio_get_drvdata(serio);
232
233 input_unregister_device(&sermouse->dev);
234 serio_close(serio);
235 serio_set_drvdata(serio, NULL);
236 kfree(sermouse);
237}
238
239/*
240 * sermouse_connect() is a callback form the serio module when
241 * an unhandled serio port is found.
242 */
243
244static int sermouse_connect(struct serio *serio, struct serio_driver *drv)
245{
246 struct sermouse *sermouse;
247 unsigned char c;
248 int err;
249
250 if (!serio->id.proto || serio->id.proto > SERIO_MZPP)
251 return -ENODEV;
252
253 if (!(sermouse = kmalloc(sizeof(struct sermouse), GFP_KERNEL)))
254 return -ENOMEM;
255
256 memset(sermouse, 0, sizeof(struct sermouse));
257
258 init_input_dev(&sermouse->dev);
259 sermouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
260 sermouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
261 sermouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
262 sermouse->dev.private = sermouse;
263
264 sermouse->type = serio->id.proto;
265 c = serio->id.extra;
266
267 if (c & 0x01) set_bit(BTN_MIDDLE, sermouse->dev.keybit);
268 if (c & 0x02) set_bit(BTN_SIDE, sermouse->dev.keybit);
269 if (c & 0x04) set_bit(BTN_EXTRA, sermouse->dev.keybit);
270 if (c & 0x10) set_bit(REL_WHEEL, sermouse->dev.relbit);
271 if (c & 0x20) set_bit(REL_HWHEEL, sermouse->dev.relbit);
272
273 sprintf(sermouse->phys, "%s/input0", serio->phys);
274
275 sermouse->dev.name = sermouse_protocols[sermouse->type];
276 sermouse->dev.phys = sermouse->phys;
277 sermouse->dev.id.bustype = BUS_RS232;
278 sermouse->dev.id.vendor = sermouse->type;
279 sermouse->dev.id.product = c;
280 sermouse->dev.id.version = 0x0100;
281 sermouse->dev.dev = &serio->dev;
282
283 serio_set_drvdata(serio, sermouse);
284
285 err = serio_open(serio, drv);
286 if (err) {
287 serio_set_drvdata(serio, NULL);
288 kfree(sermouse);
289 return err;
290 }
291
292 input_register_device(&sermouse->dev);
293
294 printk(KERN_INFO "input: %s on %s\n", sermouse_protocols[sermouse->type], serio->phys);
295
296 return 0;
297}
298
299static struct serio_device_id sermouse_serio_ids[] = {
300 {
301 .type = SERIO_RS232,
302 .proto = SERIO_MSC,
303 .id = SERIO_ANY,
304 .extra = SERIO_ANY,
305 },
306 {
307 .type = SERIO_RS232,
308 .proto = SERIO_SUN,
309 .id = SERIO_ANY,
310 .extra = SERIO_ANY,
311 },
312 {
313 .type = SERIO_RS232,
314 .proto = SERIO_MS,
315 .id = SERIO_ANY,
316 .extra = SERIO_ANY,
317 },
318 {
319 .type = SERIO_RS232,
320 .proto = SERIO_MP,
321 .id = SERIO_ANY,
322 .extra = SERIO_ANY,
323 },
324 {
325 .type = SERIO_RS232,
326 .proto = SERIO_MZ,
327 .id = SERIO_ANY,
328 .extra = SERIO_ANY,
329 },
330 {
331 .type = SERIO_RS232,
332 .proto = SERIO_MZP,
333 .id = SERIO_ANY,
334 .extra = SERIO_ANY,
335 },
336 {
337 .type = SERIO_RS232,
338 .proto = SERIO_MZPP,
339 .id = SERIO_ANY,
340 .extra = SERIO_ANY,
341 },
342 { 0 }
343};
344
345MODULE_DEVICE_TABLE(serio, sermouse_serio_ids);
346
347static struct serio_driver sermouse_drv = {
348 .driver = {
349 .name = "sermouse",
350 },
351 .description = DRIVER_DESC,
352 .id_table = sermouse_serio_ids,
353 .interrupt = sermouse_interrupt,
354 .connect = sermouse_connect,
355 .disconnect = sermouse_disconnect,
356};
357
358static int __init sermouse_init(void)
359{
360 serio_register_driver(&sermouse_drv);
361 return 0;
362}
363
364static void __exit sermouse_exit(void)
365{
366 serio_unregister_driver(&sermouse_drv);
367}
368
369module_init(sermouse_init);
370module_exit(sermouse_exit);
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
new file mode 100644
index 000000000000..69832f8fb720
--- /dev/null
+++ b/drivers/input/mouse/synaptics.c
@@ -0,0 +1,700 @@
1/*
2 * Synaptics TouchPad PS/2 mouse driver
3 *
4 * 2003 Dmitry Torokhov <dtor@mail.ru>
5 * Added support for pass-through port. Special thanks to Peter Berg Larsen
6 * for explaining various Synaptics quirks.
7 *
8 * 2003 Peter Osterlund <petero2@telia.com>
9 * Ported to 2.5 input device infrastructure.
10 *
11 * Copyright (C) 2001 Stefan Gmeiner <riddlebox@freesurf.ch>
12 * start merging tpconfig and gpm code to a xfree-input module
13 * adding some changes and extensions (ex. 3rd and 4th button)
14 *
15 * Copyright (c) 1997 C. Scott Ananian <cananian@alumni.priceton.edu>
16 * Copyright (c) 1998-2000 Bruce Kalk <kall@compass.com>
17 * code for the special synaptics commands (from the tpconfig-source)
18 *
19 * This program is free software; you can redistribute it and/or modify it
20 * under the terms of the GNU General Public License version 2 as published by
21 * the Free Software Foundation.
22 *
23 * Trademarks are the property of their respective owners.
24 */
25
26#include <linux/module.h>
27#include <linux/input.h>
28#include <linux/serio.h>
29#include <linux/libps2.h>
30#include "psmouse.h"
31#include "synaptics.h"
32
33/*
34 * The x/y limits are taken from the Synaptics TouchPad interfacing Guide,
35 * section 2.3.2, which says that they should be valid regardless of the
36 * actual size of the sensor.
37 */
38#define XMIN_NOMINAL 1472
39#define XMAX_NOMINAL 5472
40#define YMIN_NOMINAL 1408
41#define YMAX_NOMINAL 4448
42
43/*****************************************************************************
44 * Synaptics communications functions
45 ****************************************************************************/
46
47/*
48 * Send a command to the synpatics touchpad by special commands
49 */
50static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, unsigned char *param)
51{
52 if (psmouse_sliced_command(psmouse, c))
53 return -1;
54 if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO))
55 return -1;
56 return 0;
57}
58
59/*
60 * Set the synaptics touchpad mode byte by special commands
61 */
62static int synaptics_mode_cmd(struct psmouse *psmouse, unsigned char mode)
63{
64 unsigned char param[1];
65
66 if (psmouse_sliced_command(psmouse, mode))
67 return -1;
68 param[0] = SYN_PS_SET_MODE2;
69 if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_SETRATE))
70 return -1;
71 return 0;
72}
73
74/*
75 * Read the model-id bytes from the touchpad
76 * see also SYN_MODEL_* macros
77 */
78static int synaptics_model_id(struct psmouse *psmouse)
79{
80 struct synaptics_data *priv = psmouse->private;
81 unsigned char mi[3];
82
83 if (synaptics_send_cmd(psmouse, SYN_QUE_MODEL, mi))
84 return -1;
85 priv->model_id = (mi[0]<<16) | (mi[1]<<8) | mi[2];
86 return 0;
87}
88
89/*
90 * Read the capability-bits from the touchpad
91 * see also the SYN_CAP_* macros
92 */
93static int synaptics_capability(struct psmouse *psmouse)
94{
95 struct synaptics_data *priv = psmouse->private;
96 unsigned char cap[3];
97
98 if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap))
99 return -1;
100 priv->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2];
101 priv->ext_cap = 0;
102 if (!SYN_CAP_VALID(priv->capabilities))
103 return -1;
104
105 /*
106 * Unless capExtended is set the rest of the flags should be ignored
107 */
108 if (!SYN_CAP_EXTENDED(priv->capabilities))
109 priv->capabilities = 0;
110
111 if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) {
112 if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) {
113 printk(KERN_ERR "Synaptics claims to have extended capabilities,"
114 " but I'm not able to read them.");
115 } else {
116 priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2];
117
118 /*
119 * if nExtBtn is greater than 8 it should be considered
120 * invalid and treated as 0
121 */
122 if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) > 8)
123 priv->ext_cap &= 0xff0fff;
124 }
125 }
126 return 0;
127}
128
129/*
130 * Identify Touchpad
131 * See also the SYN_ID_* macros
132 */
133static int synaptics_identify(struct psmouse *psmouse)
134{
135 struct synaptics_data *priv = psmouse->private;
136 unsigned char id[3];
137
138 if (synaptics_send_cmd(psmouse, SYN_QUE_IDENTIFY, id))
139 return -1;
140 priv->identity = (id[0]<<16) | (id[1]<<8) | id[2];
141 if (SYN_ID_IS_SYNAPTICS(priv->identity))
142 return 0;
143 return -1;
144}
145
146static void print_ident(struct synaptics_data *priv)
147{
148 printk(KERN_INFO "Synaptics Touchpad, model: %ld\n", SYN_ID_MODEL(priv->identity));
149 printk(KERN_INFO " Firmware: %ld.%ld\n", SYN_ID_MAJOR(priv->identity),
150 SYN_ID_MINOR(priv->identity));
151 if (SYN_MODEL_ROT180(priv->model_id))
152 printk(KERN_INFO " 180 degree mounted touchpad\n");
153 if (SYN_MODEL_PORTRAIT(priv->model_id))
154 printk(KERN_INFO " portrait touchpad\n");
155 printk(KERN_INFO " Sensor: %ld\n", SYN_MODEL_SENSOR(priv->model_id));
156 if (SYN_MODEL_NEWABS(priv->model_id))
157 printk(KERN_INFO " new absolute packet format\n");
158 if (SYN_MODEL_PEN(priv->model_id))
159 printk(KERN_INFO " pen detection\n");
160
161 if (SYN_CAP_EXTENDED(priv->capabilities)) {
162 printk(KERN_INFO " Touchpad has extended capability bits\n");
163 if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap))
164 printk(KERN_INFO " -> %d multi-buttons, i.e. besides standard buttons\n",
165 (int)(SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)));
166 if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
167 printk(KERN_INFO " -> middle button\n");
168 if (SYN_CAP_FOUR_BUTTON(priv->capabilities))
169 printk(KERN_INFO " -> four buttons\n");
170 if (SYN_CAP_MULTIFINGER(priv->capabilities))
171 printk(KERN_INFO " -> multifinger detection\n");
172 if (SYN_CAP_PALMDETECT(priv->capabilities))
173 printk(KERN_INFO " -> palm detection\n");
174 if (SYN_CAP_PASS_THROUGH(priv->capabilities))
175 printk(KERN_INFO " -> pass-through port\n");
176 }
177}
178
179static int synaptics_query_hardware(struct psmouse *psmouse)
180{
181 int retries = 0;
182
183 while ((retries++ < 3) && psmouse_reset(psmouse))
184 printk(KERN_ERR "synaptics reset failed\n");
185
186 if (synaptics_identify(psmouse))
187 return -1;
188 if (synaptics_model_id(psmouse))
189 return -1;
190 if (synaptics_capability(psmouse))
191 return -1;
192
193 return 0;
194}
195
196static int synaptics_set_absolute_mode(struct psmouse *psmouse)
197{
198 struct synaptics_data *priv = psmouse->private;
199
200 priv->mode = SYN_BIT_ABSOLUTE_MODE;
201 if (SYN_ID_MAJOR(priv->identity) >= 4)
202 priv->mode |= SYN_BIT_DISABLE_GESTURE;
203 if (SYN_CAP_EXTENDED(priv->capabilities))
204 priv->mode |= SYN_BIT_W_MODE;
205
206 if (synaptics_mode_cmd(psmouse, priv->mode))
207 return -1;
208
209 return 0;
210}
211
212static void synaptics_set_rate(struct psmouse *psmouse, unsigned int rate)
213{
214 struct synaptics_data *priv = psmouse->private;
215
216 if (rate >= 80) {
217 priv->mode |= SYN_BIT_HIGH_RATE;
218 psmouse->rate = 80;
219 } else {
220 priv->mode &= ~SYN_BIT_HIGH_RATE;
221 psmouse->rate = 40;
222 }
223
224 synaptics_mode_cmd(psmouse, priv->mode);
225}
226
227/*****************************************************************************
228 * Synaptics pass-through PS/2 port support
229 ****************************************************************************/
230static int synaptics_pt_write(struct serio *serio, unsigned char c)
231{
232 struct psmouse *parent = serio_get_drvdata(serio->parent);
233 char rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */
234
235 if (psmouse_sliced_command(parent, c))
236 return -1;
237 if (ps2_command(&parent->ps2dev, &rate_param, PSMOUSE_CMD_SETRATE))
238 return -1;
239 return 0;
240}
241
242static inline int synaptics_is_pt_packet(unsigned char *buf)
243{
244 return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4;
245}
246
247static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet)
248{
249 struct psmouse *child = serio_get_drvdata(ptport);
250
251 if (child && child->state == PSMOUSE_ACTIVATED) {
252 serio_interrupt(ptport, packet[1], 0, NULL);
253 serio_interrupt(ptport, packet[4], 0, NULL);
254 serio_interrupt(ptport, packet[5], 0, NULL);
255 if (child->type >= PSMOUSE_GENPS)
256 serio_interrupt(ptport, packet[2], 0, NULL);
257 } else
258 serio_interrupt(ptport, packet[1], 0, NULL);
259}
260
261static void synaptics_pt_activate(struct psmouse *psmouse)
262{
263 struct serio *ptport = psmouse->ps2dev.serio->child;
264 struct psmouse *child = serio_get_drvdata(ptport);
265 struct synaptics_data *priv = psmouse->private;
266
267 /* adjust the touchpad to child's choice of protocol */
268 if (child) {
269 if (child->type >= PSMOUSE_GENPS)
270 priv->mode |= SYN_BIT_FOUR_BYTE_CLIENT;
271 else
272 priv->mode &= ~SYN_BIT_FOUR_BYTE_CLIENT;
273
274 if (synaptics_mode_cmd(psmouse, priv->mode))
275 printk(KERN_INFO "synaptics: failed to switch guest protocol\n");
276 }
277}
278
279static void synaptics_pt_create(struct psmouse *psmouse)
280{
281 struct serio *serio;
282
283 serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
284 if (!serio) {
285 printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n");
286 return;
287 }
288
289 memset(serio, 0, sizeof(struct serio));
290
291 serio->id.type = SERIO_PS_PSTHRU;
292 strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
293 strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name));
294 serio->write = synaptics_pt_write;
295 serio->parent = psmouse->ps2dev.serio;
296
297 psmouse->pt_activate = synaptics_pt_activate;
298
299 printk(KERN_INFO "serio: %s port at %s\n", serio->name, psmouse->phys);
300 serio_register_port(serio);
301}
302
303/*****************************************************************************
304 * Functions to interpret the absolute mode packets
305 ****************************************************************************/
306
307static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data *priv, struct synaptics_hw_state *hw)
308{
309 memset(hw, 0, sizeof(struct synaptics_hw_state));
310
311 if (SYN_MODEL_NEWABS(priv->model_id)) {
312 hw->x = (((buf[3] & 0x10) << 8) |
313 ((buf[1] & 0x0f) << 8) |
314 buf[4]);
315 hw->y = (((buf[3] & 0x20) << 7) |
316 ((buf[1] & 0xf0) << 4) |
317 buf[5]);
318
319 hw->z = buf[2];
320 hw->w = (((buf[0] & 0x30) >> 2) |
321 ((buf[0] & 0x04) >> 1) |
322 ((buf[3] & 0x04) >> 2));
323
324 hw->left = (buf[0] & 0x01) ? 1 : 0;
325 hw->right = (buf[0] & 0x02) ? 1 : 0;
326
327 if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) {
328 hw->middle = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
329 if (hw->w == 2)
330 hw->scroll = (signed char)(buf[1]);
331 }
332
333 if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
334 hw->up = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
335 hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
336 }
337
338 if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) &&
339 ((buf[0] ^ buf[3]) & 0x02)) {
340 switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
341 default:
342 /*
343 * if nExtBtn is greater than 8 it should be
344 * considered invalid and treated as 0
345 */
346 break;
347 case 8:
348 hw->ext_buttons |= ((buf[5] & 0x08)) ? 0x80 : 0;
349 hw->ext_buttons |= ((buf[4] & 0x08)) ? 0x40 : 0;
350 case 6:
351 hw->ext_buttons |= ((buf[5] & 0x04)) ? 0x20 : 0;
352 hw->ext_buttons |= ((buf[4] & 0x04)) ? 0x10 : 0;
353 case 4:
354 hw->ext_buttons |= ((buf[5] & 0x02)) ? 0x08 : 0;
355 hw->ext_buttons |= ((buf[4] & 0x02)) ? 0x04 : 0;
356 case 2:
357 hw->ext_buttons |= ((buf[5] & 0x01)) ? 0x02 : 0;
358 hw->ext_buttons |= ((buf[4] & 0x01)) ? 0x01 : 0;
359 }
360 }
361 } else {
362 hw->x = (((buf[1] & 0x1f) << 8) | buf[2]);
363 hw->y = (((buf[4] & 0x1f) << 8) | buf[5]);
364
365 hw->z = (((buf[0] & 0x30) << 2) | (buf[3] & 0x3F));
366 hw->w = (((buf[1] & 0x80) >> 4) | ((buf[0] & 0x04) >> 1));
367
368 hw->left = (buf[0] & 0x01) ? 1 : 0;
369 hw->right = (buf[0] & 0x02) ? 1 : 0;
370 }
371}
372
373/*
374 * called for each full received packet from the touchpad
375 */
376static void synaptics_process_packet(struct psmouse *psmouse)
377{
378 struct input_dev *dev = &psmouse->dev;
379 struct synaptics_data *priv = psmouse->private;
380 struct synaptics_hw_state hw;
381 int num_fingers;
382 int finger_width;
383 int i;
384
385 synaptics_parse_hw_state(psmouse->packet, priv, &hw);
386
387 if (hw.scroll) {
388 priv->scroll += hw.scroll;
389
390 while (priv->scroll >= 4) {
391 input_report_key(dev, BTN_BACK, !hw.down);
392 input_sync(dev);
393 input_report_key(dev, BTN_BACK, hw.down);
394 input_sync(dev);
395 priv->scroll -= 4;
396 }
397 while (priv->scroll <= -4) {
398 input_report_key(dev, BTN_FORWARD, !hw.up);
399 input_sync(dev);
400 input_report_key(dev, BTN_FORWARD, hw.up);
401 input_sync(dev);
402 priv->scroll += 4;
403 }
404 return;
405 }
406
407 if (hw.z > 0) {
408 num_fingers = 1;
409 finger_width = 5;
410 if (SYN_CAP_EXTENDED(priv->capabilities)) {
411 switch (hw.w) {
412 case 0 ... 1:
413 if (SYN_CAP_MULTIFINGER(priv->capabilities))
414 num_fingers = hw.w + 2;
415 break;
416 case 2:
417 if (SYN_MODEL_PEN(priv->model_id))
418 ; /* Nothing, treat a pen as a single finger */
419 break;
420 case 4 ... 15:
421 if (SYN_CAP_PALMDETECT(priv->capabilities))
422 finger_width = hw.w;
423 break;
424 }
425 }
426 } else {
427 num_fingers = 0;
428 finger_width = 0;
429 }
430
431 /* Post events
432 * BTN_TOUCH has to be first as mousedev relies on it when doing
433 * absolute -> relative conversion
434 */
435 if (hw.z > 30) input_report_key(dev, BTN_TOUCH, 1);
436 if (hw.z < 25) input_report_key(dev, BTN_TOUCH, 0);
437
438 if (hw.z > 0) {
439 input_report_abs(dev, ABS_X, hw.x);
440 input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw.y);
441 }
442 input_report_abs(dev, ABS_PRESSURE, hw.z);
443
444 input_report_abs(dev, ABS_TOOL_WIDTH, finger_width);
445 input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1);
446 input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
447 input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3);
448
449 input_report_key(dev, BTN_LEFT, hw.left);
450 input_report_key(dev, BTN_RIGHT, hw.right);
451
452 if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
453 input_report_key(dev, BTN_MIDDLE, hw.middle);
454
455 if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
456 input_report_key(dev, BTN_FORWARD, hw.up);
457 input_report_key(dev, BTN_BACK, hw.down);
458 }
459
460 for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
461 input_report_key(dev, BTN_0 + i, hw.ext_buttons & (1 << i));
462
463 input_sync(dev);
464}
465
466static int synaptics_validate_byte(unsigned char packet[], int idx, unsigned char pkt_type)
467{
468 static unsigned char newabs_mask[] = { 0xC8, 0x00, 0x00, 0xC8, 0x00 };
469 static unsigned char newabs_rel_mask[] = { 0xC0, 0x00, 0x00, 0xC0, 0x00 };
470 static unsigned char newabs_rslt[] = { 0x80, 0x00, 0x00, 0xC0, 0x00 };
471 static unsigned char oldabs_mask[] = { 0xC0, 0x60, 0x00, 0xC0, 0x60 };
472 static unsigned char oldabs_rslt[] = { 0xC0, 0x00, 0x00, 0x80, 0x00 };
473
474 if (idx < 0 || idx > 4)
475 return 0;
476
477 switch (pkt_type) {
478 case SYN_NEWABS:
479 case SYN_NEWABS_RELAXED:
480 return (packet[idx] & newabs_rel_mask[idx]) == newabs_rslt[idx];
481
482 case SYN_NEWABS_STRICT:
483 return (packet[idx] & newabs_mask[idx]) == newabs_rslt[idx];
484
485 case SYN_OLDABS:
486 return (packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx];
487
488 default:
489 printk(KERN_ERR "synaptics: unknown packet type %d\n", pkt_type);
490 return 0;
491 }
492}
493
494static unsigned char synaptics_detect_pkt_type(struct psmouse *psmouse)
495{
496 int i;
497
498 for (i = 0; i < 5; i++)
499 if (!synaptics_validate_byte(psmouse->packet, i, SYN_NEWABS_STRICT)) {
500 printk(KERN_INFO "synaptics: using relaxed packet validation\n");
501 return SYN_NEWABS_RELAXED;
502 }
503
504 return SYN_NEWABS_STRICT;
505}
506
507static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
508{
509 struct input_dev *dev = &psmouse->dev;
510 struct synaptics_data *priv = psmouse->private;
511
512 input_regs(dev, regs);
513
514 if (psmouse->pktcnt >= 6) { /* Full packet received */
515 if (unlikely(priv->pkt_type == SYN_NEWABS))
516 priv->pkt_type = synaptics_detect_pkt_type(psmouse);
517
518 if (SYN_CAP_PASS_THROUGH(priv->capabilities) && synaptics_is_pt_packet(psmouse->packet)) {
519 if (psmouse->ps2dev.serio->child)
520 synaptics_pass_pt_packet(psmouse->ps2dev.serio->child, psmouse->packet);
521 } else
522 synaptics_process_packet(psmouse);
523
524 return PSMOUSE_FULL_PACKET;
525 }
526
527 return synaptics_validate_byte(psmouse->packet, psmouse->pktcnt - 1, priv->pkt_type) ?
528 PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
529}
530
531/*****************************************************************************
532 * Driver initialization/cleanup functions
533 ****************************************************************************/
534static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
535{
536 int i;
537
538 set_bit(EV_ABS, dev->evbit);
539 input_set_abs_params(dev, ABS_X, XMIN_NOMINAL, XMAX_NOMINAL, 0, 0);
540 input_set_abs_params(dev, ABS_Y, YMIN_NOMINAL, YMAX_NOMINAL, 0, 0);
541 input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
542 set_bit(ABS_TOOL_WIDTH, dev->absbit);
543
544 set_bit(EV_KEY, dev->evbit);
545 set_bit(BTN_TOUCH, dev->keybit);
546 set_bit(BTN_TOOL_FINGER, dev->keybit);
547 set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
548 set_bit(BTN_TOOL_TRIPLETAP, dev->keybit);
549
550 set_bit(BTN_LEFT, dev->keybit);
551 set_bit(BTN_RIGHT, dev->keybit);
552
553 if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
554 set_bit(BTN_MIDDLE, dev->keybit);
555
556 if (SYN_CAP_FOUR_BUTTON(priv->capabilities) ||
557 SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) {
558 set_bit(BTN_FORWARD, dev->keybit);
559 set_bit(BTN_BACK, dev->keybit);
560 }
561
562 for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
563 set_bit(BTN_0 + i, dev->keybit);
564
565 clear_bit(EV_REL, dev->evbit);
566 clear_bit(REL_X, dev->relbit);
567 clear_bit(REL_Y, dev->relbit);
568}
569
570void synaptics_reset(struct psmouse *psmouse)
571{
572 /* reset touchpad back to relative mode, gestures enabled */
573 synaptics_mode_cmd(psmouse, 0);
574}
575
576static void synaptics_disconnect(struct psmouse *psmouse)
577{
578 synaptics_reset(psmouse);
579 kfree(psmouse->private);
580 psmouse->private = NULL;
581}
582
583static int synaptics_reconnect(struct psmouse *psmouse)
584{
585 struct synaptics_data *priv = psmouse->private;
586 struct synaptics_data old_priv = *priv;
587
588 if (synaptics_detect(psmouse, 0))
589 return -1;
590
591 if (synaptics_query_hardware(psmouse)) {
592 printk(KERN_ERR "Unable to query Synaptics hardware.\n");
593 return -1;
594 }
595
596 if (old_priv.identity != priv->identity ||
597 old_priv.model_id != priv->model_id ||
598 old_priv.capabilities != priv->capabilities ||
599 old_priv.ext_cap != priv->ext_cap)
600 return -1;
601
602 if (synaptics_set_absolute_mode(psmouse)) {
603 printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
604 return -1;
605 }
606
607 return 0;
608}
609
610int synaptics_detect(struct psmouse *psmouse, int set_properties)
611{
612 struct ps2dev *ps2dev = &psmouse->ps2dev;
613 unsigned char param[4];
614
615 param[0] = 0;
616
617 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
618 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
619 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
620 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
621 ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
622
623 if (param[1] != 0x47)
624 return -1;
625
626 if (set_properties) {
627 psmouse->vendor = "Synaptics";
628 psmouse->name = "TouchPad";
629 }
630
631 return 0;
632}
633
634#if defined(__i386__)
635#include <linux/dmi.h>
636static struct dmi_system_id toshiba_dmi_table[] = {
637 {
638 .ident = "Toshiba Satellite",
639 .matches = {
640 DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
641 DMI_MATCH(DMI_PRODUCT_NAME , "Satellite"),
642 },
643 },
644 { }
645};
646#endif
647
648int synaptics_init(struct psmouse *psmouse)
649{
650 struct synaptics_data *priv;
651
652 psmouse->private = priv = kmalloc(sizeof(struct synaptics_data), GFP_KERNEL);
653 if (!priv)
654 return -1;
655 memset(priv, 0, sizeof(struct synaptics_data));
656
657 if (synaptics_query_hardware(psmouse)) {
658 printk(KERN_ERR "Unable to query Synaptics hardware.\n");
659 goto init_fail;
660 }
661
662 if (synaptics_set_absolute_mode(psmouse)) {
663 printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
664 goto init_fail;
665 }
666
667 priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;
668
669 print_ident(priv);
670 set_input_params(&psmouse->dev, priv);
671
672 psmouse->protocol_handler = synaptics_process_byte;
673 psmouse->set_rate = synaptics_set_rate;
674 psmouse->disconnect = synaptics_disconnect;
675 psmouse->reconnect = synaptics_reconnect;
676 psmouse->pktsize = 6;
677
678 if (SYN_CAP_PASS_THROUGH(priv->capabilities))
679 synaptics_pt_create(psmouse);
680
681#if defined(__i386__)
682 /*
683 * Toshiba's KBC seems to have trouble handling data from
684 * Synaptics as full rate, switch to lower rate which is roughly
685 * thye same as rate of standard PS/2 mouse.
686 */
687 if (psmouse->rate >= 80 && dmi_check_system(toshiba_dmi_table)) {
688 printk(KERN_INFO "synaptics: Toshiba Satellite detected, limiting rate to 40pps.\n");
689 psmouse->rate = 40;
690 }
691#endif
692
693 return 0;
694
695 init_fail:
696 kfree(priv);
697 return -1;
698}
699
700
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
new file mode 100644
index 000000000000..68fff1dcd7de
--- /dev/null
+++ b/drivers/input/mouse/synaptics.h
@@ -0,0 +1,110 @@
1/*
2 * Synaptics TouchPad PS/2 mouse driver
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 as published by
6 * the Free Software Foundation.
7 */
8
9#ifndef _SYNAPTICS_H
10#define _SYNAPTICS_H
11
12extern int synaptics_detect(struct psmouse *psmouse, int set_properties);
13extern int synaptics_init(struct psmouse *psmouse);
14extern void synaptics_reset(struct psmouse *psmouse);
15
16/* synaptics queries */
17#define SYN_QUE_IDENTIFY 0x00
18#define SYN_QUE_MODES 0x01
19#define SYN_QUE_CAPABILITIES 0x02
20#define SYN_QUE_MODEL 0x03
21#define SYN_QUE_SERIAL_NUMBER_PREFIX 0x06
22#define SYN_QUE_SERIAL_NUMBER_SUFFIX 0x07
23#define SYN_QUE_RESOLUTION 0x08
24#define SYN_QUE_EXT_CAPAB 0x09
25
26/* synatics modes */
27#define SYN_BIT_ABSOLUTE_MODE (1 << 7)
28#define SYN_BIT_HIGH_RATE (1 << 6)
29#define SYN_BIT_SLEEP_MODE (1 << 3)
30#define SYN_BIT_DISABLE_GESTURE (1 << 2)
31#define SYN_BIT_FOUR_BYTE_CLIENT (1 << 1)
32#define SYN_BIT_W_MODE (1 << 0)
33
34/* synaptics model ID bits */
35#define SYN_MODEL_ROT180(m) ((m) & (1 << 23))
36#define SYN_MODEL_PORTRAIT(m) ((m) & (1 << 22))
37#define SYN_MODEL_SENSOR(m) (((m) >> 16) & 0x3f)
38#define SYN_MODEL_HARDWARE(m) (((m) >> 9) & 0x7f)
39#define SYN_MODEL_NEWABS(m) ((m) & (1 << 7))
40#define SYN_MODEL_PEN(m) ((m) & (1 << 6))
41#define SYN_MODEL_SIMPLIC(m) ((m) & (1 << 5))
42#define SYN_MODEL_GEOMETRY(m) ((m) & 0x0f)
43
44/* synaptics capability bits */
45#define SYN_CAP_EXTENDED(c) ((c) & (1 << 23))
46#define SYN_CAP_MIDDLE_BUTTON(c) ((c) & (1 << 18))
47#define SYN_CAP_PASS_THROUGH(c) ((c) & (1 << 7))
48#define SYN_CAP_SLEEP(c) ((c) & (1 << 4))
49#define SYN_CAP_FOUR_BUTTON(c) ((c) & (1 << 3))
50#define SYN_CAP_MULTIFINGER(c) ((c) & (1 << 1))
51#define SYN_CAP_PALMDETECT(c) ((c) & (1 << 0))
52#define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47)
53#define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20)
54#define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12)
55
56/* synaptics modes query bits */
57#define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7))
58#define SYN_MODE_RATE(m) ((m) & (1 << 6))
59#define SYN_MODE_BAUD_SLEEP(m) ((m) & (1 << 3))
60#define SYN_MODE_DISABLE_GESTURE(m) ((m) & (1 << 2))
61#define SYN_MODE_PACKSIZE(m) ((m) & (1 << 1))
62#define SYN_MODE_WMODE(m) ((m) & (1 << 0))
63
64/* synaptics identify query bits */
65#define SYN_ID_MODEL(i) (((i) >> 4) & 0x0f)
66#define SYN_ID_MAJOR(i) ((i) & 0x0f)
67#define SYN_ID_MINOR(i) (((i) >> 16) & 0xff)
68#define SYN_ID_IS_SYNAPTICS(i) ((((i) >> 8) & 0xff) == 0x47)
69
70/* synaptics special commands */
71#define SYN_PS_SET_MODE2 0x14
72#define SYN_PS_CLIENT_CMD 0x28
73
74/* synaptics packet types */
75#define SYN_NEWABS 0
76#define SYN_NEWABS_STRICT 1
77#define SYN_NEWABS_RELAXED 2
78#define SYN_OLDABS 3
79
80/*
81 * A structure to describe the state of the touchpad hardware (buttons and pad)
82 */
83
84struct synaptics_hw_state {
85 int x;
86 int y;
87 int z;
88 int w;
89 unsigned int left:1;
90 unsigned int right:1;
91 unsigned int middle:1;
92 unsigned int up:1;
93 unsigned int down:1;
94 unsigned char ext_buttons;
95 signed char scroll;
96};
97
98struct synaptics_data {
99 /* Data read from the touchpad */
100 unsigned long int model_id; /* Model-ID */
101 unsigned long int capabilities; /* Capabilities */
102 unsigned long int ext_cap; /* Extended Capabilities */
103 unsigned long int identity; /* Identification */
104
105 unsigned char pkt_type; /* packet type - old, new, etc */
106 unsigned char mode; /* current mode byte */
107 int scroll;
108};
109
110#endif /* _SYNAPTICS_H */
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c
new file mode 100644
index 000000000000..b2cb101c8110
--- /dev/null
+++ b/drivers/input/mouse/vsxxxaa.c
@@ -0,0 +1,591 @@
1/*
2 * Driver for DEC VSXXX-AA mouse (hockey-puck mouse, ball or two rollers)
3 * DEC VSXXX-GA mouse (rectangular mouse, with ball)
4 * DEC VSXXX-AB tablet (digitizer with hair cross or stylus)
5 *
6 * Copyright (C) 2003-2004 by Jan-Benedict Glaw <jbglaw@lug-owl.de>
7 *
8 * The packet format was initially taken from a patch to GPM which is (C) 2001
9 * by Karsten Merker <merker@linuxtag.org>
10 * and Maciej W. Rozycki <macro@ds2.pg.gda.pl>
11 * Later on, I had access to the device's documentation (referenced below).
12 */
13
14/*
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30/*
31 * Building an adaptor to DE9 / DB25 RS232
32 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
33 *
34 * DISCLAIMER: Use this description AT YOUR OWN RISK! I'll not pay for
35 * anything if you break your mouse, your computer or whatever!
36 *
37 * In theory, this mouse is a simple RS232 device. In practice, it has got
38 * a quite uncommon plug and the requirement to additionally get a power
39 * supply at +5V and -12V.
40 *
41 * If you look at the socket/jack (_not_ at the plug), we use this pin
42 * numbering:
43 * _______
44 * / 7 6 5 \
45 * | 4 --- 3 |
46 * \ 2 1 /
47 * -------
48 *
49 * DEC socket DE9 DB25 Note
50 * 1 (GND) 5 7 -
51 * 2 (RxD) 2 3 -
52 * 3 (TxD) 3 2 -
53 * 4 (-12V) - - Somewhere from the PSU. At ATX, it's
54 * the thin blue wire at pin 12 of the
55 * ATX power connector. Only required for
56 * VSXXX-AA/-GA mice.
57 * 5 (+5V) - - PSU (red wires of ATX power connector
58 * on pin 4, 6, 19 or 20) or HDD power
59 * connector (also red wire).
60 * 6 (+12V) - - HDD power connector, yellow wire. Only
61 * required for VSXXX-AB digitizer.
62 * 7 (dev. avail.) - - The mouse shorts this one to pin 1.
63 * This way, the host computer can detect
64 * the mouse. To use it with the adaptor,
65 * simply don't connect this pin.
66 *
67 * So to get a working adaptor, you need to connect the mouse with three
68 * wires to a RS232 port and two or three additional wires for +5V, +12V and
69 * -12V to the PSU.
70 *
71 * Flow specification for the link is 4800, 8o1.
72 *
73 * The mice and tablet are described in "VCB02 Video Subsystem - Technical
74 * Manual", DEC EK-104AA-TM-001. You'll find it at MANX, a search engine
75 * specific for DEC documentation. Try
76 * http://www.vt100.net/manx/details?pn=EK-104AA-TM-001;id=21;cp=1
77 */
78
79#include <linux/delay.h>
80#include <linux/module.h>
81#include <linux/slab.h>
82#include <linux/interrupt.h>
83#include <linux/input.h>
84#include <linux/config.h>
85#include <linux/serio.h>
86#include <linux/init.h>
87
88#define DRIVER_DESC "Driver for DEC VSXXX-AA and -GA mice and VSXXX-AB tablet"
89
90MODULE_AUTHOR ("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
91MODULE_DESCRIPTION (DRIVER_DESC);
92MODULE_LICENSE ("GPL");
93
94#undef VSXXXAA_DEBUG
95#ifdef VSXXXAA_DEBUG
96#define DBG(x...) printk (x)
97#else
98#define DBG(x...) do {} while (0)
99#endif
100
101#define VSXXXAA_INTRO_MASK 0x80
102#define VSXXXAA_INTRO_HEAD 0x80
103#define IS_HDR_BYTE(x) (((x) & VSXXXAA_INTRO_MASK) \
104 == VSXXXAA_INTRO_HEAD)
105
106#define VSXXXAA_PACKET_MASK 0xe0
107#define VSXXXAA_PACKET_REL 0x80
108#define VSXXXAA_PACKET_ABS 0xc0
109#define VSXXXAA_PACKET_POR 0xa0
110#define MATCH_PACKET_TYPE(data, type) (((data) & VSXXXAA_PACKET_MASK) == (type))
111
112
113
114struct vsxxxaa {
115 struct input_dev dev;
116 struct serio *serio;
117#define BUFLEN 15 /* At least 5 is needed for a full tablet packet */
118 unsigned char buf[BUFLEN];
119 unsigned char count;
120 unsigned char version;
121 unsigned char country;
122 unsigned char type;
123 char name[64];
124 char phys[32];
125};
126
127static void
128vsxxxaa_drop_bytes (struct vsxxxaa *mouse, int num)
129{
130 if (num >= mouse->count)
131 mouse->count = 0;
132 else {
133 memmove (mouse->buf, mouse->buf + num - 1, BUFLEN - num);
134 mouse->count -= num;
135 }
136}
137
138static void
139vsxxxaa_queue_byte (struct vsxxxaa *mouse, unsigned char byte)
140{
141 if (mouse->count == BUFLEN) {
142 printk (KERN_ERR "%s on %s: Dropping a byte of full buffer.\n",
143 mouse->name, mouse->phys);
144 vsxxxaa_drop_bytes (mouse, 1);
145 }
146 DBG (KERN_INFO "Queueing byte 0x%02x\n", byte);
147
148 mouse->buf[mouse->count++] = byte;
149}
150
151static void
152vsxxxaa_detection_done (struct vsxxxaa *mouse)
153{
154 switch (mouse->type) {
155 case 0x02:
156 sprintf (mouse->name, "DEC VSXXX-AA/-GA mouse");
157 break;
158
159 case 0x04:
160 sprintf (mouse->name, "DEC VSXXX-AB digitizer");
161 break;
162
163 default:
164 sprintf (mouse->name, "unknown DEC pointer device "
165 "(type = 0x%02x)", mouse->type);
166 break;
167 }
168
169 printk (KERN_INFO "Found %s version 0x%02x from country 0x%02x "
170 "on port %s\n", mouse->name, mouse->version,
171 mouse->country, mouse->phys);
172}
173
174/*
175 * Returns number of bytes to be dropped, 0 if packet is okay.
176 */
177static int
178vsxxxaa_check_packet (struct vsxxxaa *mouse, int packet_len)
179{
180 int i;
181
182 /* First byte must be a header byte */
183 if (!IS_HDR_BYTE (mouse->buf[0])) {
184 DBG ("vsck: len=%d, 1st=0x%02x\n", packet_len, mouse->buf[0]);
185 return 1;
186 }
187
188 /* Check all following bytes */
189 if (packet_len > 1) {
190 for (i = 1; i < packet_len; i++) {
191 if (IS_HDR_BYTE (mouse->buf[i])) {
192 printk (KERN_ERR "Need to drop %d bytes "
193 "of a broken packet.\n",
194 i - 1);
195 DBG (KERN_INFO "check: len=%d, b[%d]=0x%02x\n",
196 packet_len, i, mouse->buf[i]);
197 return i - 1;
198 }
199 }
200 }
201
202 return 0;
203}
204
205static __inline__ int
206vsxxxaa_smells_like_packet (struct vsxxxaa *mouse, unsigned char type, size_t len)
207{
208 return (mouse->count >= len) && MATCH_PACKET_TYPE (mouse->buf[0], type);
209}
210
211static void
212vsxxxaa_handle_REL_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
213{
214 struct input_dev *dev = &mouse->dev;
215 unsigned char *buf = mouse->buf;
216 int left, middle, right;
217 int dx, dy;
218
219 /*
220 * Check for normal stream packets. This is three bytes,
221 * with the first byte's 3 MSB set to 100.
222 *
223 * [0]: 1 0 0 SignX SignY Left Middle Right
224 * [1]: 0 dx dx dx dx dx dx dx
225 * [2]: 0 dy dy dy dy dy dy dy
226 */
227
228 /*
229 * Low 7 bit of byte 1 are abs(dx), bit 7 is
230 * 0, bit 4 of byte 0 is direction.
231 */
232 dx = buf[1] & 0x7f;
233 dx *= ((buf[0] >> 4) & 0x01)? 1: -1;
234
235 /*
236 * Low 7 bit of byte 2 are abs(dy), bit 7 is
237 * 0, bit 3 of byte 0 is direction.
238 */
239 dy = buf[2] & 0x7f;
240 dy *= ((buf[0] >> 3) & 0x01)? -1: 1;
241
242 /*
243 * Get button state. It's the low three bits
244 * (for three buttons) of byte 0.
245 */
246 left = (buf[0] & 0x04)? 1: 0;
247 middle = (buf[0] & 0x02)? 1: 0;
248 right = (buf[0] & 0x01)? 1: 0;
249
250 vsxxxaa_drop_bytes (mouse, 3);
251
252 DBG (KERN_INFO "%s on %s: dx=%d, dy=%d, buttons=%s%s%s\n",
253 mouse->name, mouse->phys, dx, dy,
254 left? "L": "l", middle? "M": "m", right? "R": "r");
255
256 /*
257 * Report what we've found so far...
258 */
259 input_regs (dev, regs);
260 input_report_key (dev, BTN_LEFT, left);
261 input_report_key (dev, BTN_MIDDLE, middle);
262 input_report_key (dev, BTN_RIGHT, right);
263 input_report_key (dev, BTN_TOUCH, 0);
264 input_report_rel (dev, REL_X, dx);
265 input_report_rel (dev, REL_Y, dy);
266 input_sync (dev);
267}
268
269static void
270vsxxxaa_handle_ABS_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
271{
272 struct input_dev *dev = &mouse->dev;
273 unsigned char *buf = mouse->buf;
274 int left, middle, right, touch;
275 int x, y;
276
277 /*
278 * Tablet position / button packet
279 *
280 * [0]: 1 1 0 B4 B3 B2 B1 Pr
281 * [1]: 0 0 X5 X4 X3 X2 X1 X0
282 * [2]: 0 0 X11 X10 X9 X8 X7 X6
283 * [3]: 0 0 Y5 Y4 Y3 Y2 Y1 Y0
284 * [4]: 0 0 Y11 Y10 Y9 Y8 Y7 Y6
285 */
286
287 /*
288 * Get X/Y position. Y axis needs to be inverted since VSXXX-AB
289 * counts down->top while monitor counts top->bottom.
290 */
291 x = ((buf[2] & 0x3f) << 6) | (buf[1] & 0x3f);
292 y = ((buf[4] & 0x3f) << 6) | (buf[3] & 0x3f);
293 y = 1023 - y;
294
295 /*
296 * Get button state. It's bits <4..1> of byte 0.
297 */
298 left = (buf[0] & 0x02)? 1: 0;
299 middle = (buf[0] & 0x04)? 1: 0;
300 right = (buf[0] & 0x08)? 1: 0;
301 touch = (buf[0] & 0x10)? 1: 0;
302
303 vsxxxaa_drop_bytes (mouse, 5);
304
305 DBG (KERN_INFO "%s on %s: x=%d, y=%d, buttons=%s%s%s%s\n",
306 mouse->name, mouse->phys, x, y,
307 left? "L": "l", middle? "M": "m",
308 right? "R": "r", touch? "T": "t");
309
310 /*
311 * Report what we've found so far...
312 */
313 input_regs (dev, regs);
314 input_report_key (dev, BTN_LEFT, left);
315 input_report_key (dev, BTN_MIDDLE, middle);
316 input_report_key (dev, BTN_RIGHT, right);
317 input_report_key (dev, BTN_TOUCH, touch);
318 input_report_abs (dev, ABS_X, x);
319 input_report_abs (dev, ABS_Y, y);
320 input_sync (dev);
321}
322
323static void
324vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
325{
326 struct input_dev *dev = &mouse->dev;
327 unsigned char *buf = mouse->buf;
328 int left, middle, right;
329 unsigned char error;
330
331 /*
332 * Check for Power-On-Reset packets. These are sent out
333 * after plugging the mouse in, or when explicitely
334 * requested by sending 'T'.
335 *
336 * [0]: 1 0 1 0 R3 R2 R1 R0
337 * [1]: 0 M2 M1 M0 D3 D2 D1 D0
338 * [2]: 0 E6 E5 E4 E3 E2 E1 E0
339 * [3]: 0 0 0 0 0 Left Middle Right
340 *
341 * M: manufacturer location code
342 * R: revision code
343 * E: Error code. If it's in the range of 0x00..0x1f, only some
344 * minor problem occured. Errors >= 0x20 are considered bad
345 * and the device may not work properly...
346 * D: <0010> == mouse, <0100> == tablet
347 */
348
349 mouse->version = buf[0] & 0x0f;
350 mouse->country = (buf[1] >> 4) & 0x07;
351 mouse->type = buf[1] & 0x0f;
352 error = buf[2] & 0x7f;
353
354 /*
355 * Get button state. It's the low three bits
356 * (for three buttons) of byte 0. Maybe even the bit <3>
357 * has some meaning if a tablet is attached.
358 */
359 left = (buf[0] & 0x04)? 1: 0;
360 middle = (buf[0] & 0x02)? 1: 0;
361 right = (buf[0] & 0x01)? 1: 0;
362
363 vsxxxaa_drop_bytes (mouse, 4);
364 vsxxxaa_detection_done (mouse);
365
366 if (error <= 0x1f) {
367 /* No (serious) error. Report buttons */
368 input_regs (dev, regs);
369 input_report_key (dev, BTN_LEFT, left);
370 input_report_key (dev, BTN_MIDDLE, middle);
371 input_report_key (dev, BTN_RIGHT, right);
372 input_report_key (dev, BTN_TOUCH, 0);
373 input_sync (dev);
374
375 if (error != 0)
376 printk (KERN_INFO "Your %s on %s reports error=0x%02x\n",
377 mouse->name, mouse->phys, error);
378
379 }
380
381 /*
382 * If the mouse was hot-plugged, we need to force differential mode
383 * now... However, give it a second to recover from it's reset.
384 */
385 printk (KERN_NOTICE "%s on %s: Forceing standard packet format, "
386 "incremental streaming mode and 72 samples/sec\n",
387 mouse->name, mouse->phys);
388 mouse->serio->write (mouse->serio, 'S'); /* Standard format */
389 mdelay (50);
390 mouse->serio->write (mouse->serio, 'R'); /* Incremental */
391 mdelay (50);
392 mouse->serio->write (mouse->serio, 'L'); /* 72 samples/sec */
393}
394
395static void
396vsxxxaa_parse_buffer (struct vsxxxaa *mouse, struct pt_regs *regs)
397{
398 unsigned char *buf = mouse->buf;
399 int stray_bytes;
400
401 /*
402 * Parse buffer to death...
403 */
404 do {
405 /*
406 * Out of sync? Throw away what we don't understand. Each
407 * packet starts with a byte whose bit 7 is set. Unhandled
408 * packets (ie. which we don't know about or simply b0rk3d
409 * data...) will get shifted out of the buffer after some
410 * activity on the mouse.
411 */
412 while (mouse->count > 0 && !IS_HDR_BYTE(buf[0])) {
413 printk (KERN_ERR "%s on %s: Dropping a byte to regain "
414 "sync with mouse data stream...\n",
415 mouse->name, mouse->phys);
416 vsxxxaa_drop_bytes (mouse, 1);
417 }
418
419 /*
420 * Check for packets we know about.
421 */
422
423 if (vsxxxaa_smells_like_packet (mouse, VSXXXAA_PACKET_REL, 3)) {
424 /* Check for broken packet */
425 stray_bytes = vsxxxaa_check_packet (mouse, 3);
426 if (stray_bytes > 0) {
427 printk (KERN_ERR "Dropping %d bytes now...\n",
428 stray_bytes);
429 vsxxxaa_drop_bytes (mouse, stray_bytes);
430 continue;
431 }
432
433 vsxxxaa_handle_REL_packet (mouse, regs);
434 continue; /* More to parse? */
435 }
436
437 if (vsxxxaa_smells_like_packet (mouse, VSXXXAA_PACKET_ABS, 5)) {
438 /* Check for broken packet */
439 stray_bytes = vsxxxaa_check_packet (mouse, 5);
440 if (stray_bytes > 0) {
441 printk (KERN_ERR "Dropping %d bytes now...\n",
442 stray_bytes);
443 vsxxxaa_drop_bytes (mouse, stray_bytes);
444 continue;
445 }
446
447 vsxxxaa_handle_ABS_packet (mouse, regs);
448 continue; /* More to parse? */
449 }
450
451 if (vsxxxaa_smells_like_packet (mouse, VSXXXAA_PACKET_POR, 4)) {
452 /* Check for broken packet */
453 stray_bytes = vsxxxaa_check_packet (mouse, 4);
454 if (stray_bytes > 0) {
455 printk (KERN_ERR "Dropping %d bytes now...\n",
456 stray_bytes);
457 vsxxxaa_drop_bytes (mouse, stray_bytes);
458 continue;
459 }
460
461 vsxxxaa_handle_POR_packet (mouse, regs);
462 continue; /* More to parse? */
463 }
464
465 break; /* No REL, ABS or POR packet found */
466 } while (1);
467}
468
469static irqreturn_t
470vsxxxaa_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
471 struct pt_regs *regs)
472{
473 struct vsxxxaa *mouse = serio_get_drvdata (serio);
474
475 vsxxxaa_queue_byte (mouse, data);
476 vsxxxaa_parse_buffer (mouse, regs);
477
478 return IRQ_HANDLED;
479}
480
481static void
482vsxxxaa_disconnect (struct serio *serio)
483{
484 struct vsxxxaa *mouse = serio_get_drvdata (serio);
485
486 input_unregister_device (&mouse->dev);
487 serio_close (serio);
488 serio_set_drvdata (serio, NULL);
489 kfree (mouse);
490}
491
492static int
493vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
494{
495 struct vsxxxaa *mouse;
496 int err;
497
498 if (!(mouse = kmalloc (sizeof (struct vsxxxaa), GFP_KERNEL)))
499 return -ENOMEM;
500
501 memset (mouse, 0, sizeof (struct vsxxxaa));
502
503 init_input_dev (&mouse->dev);
504 set_bit (EV_KEY, mouse->dev.evbit); /* We have buttons */
505 set_bit (EV_REL, mouse->dev.evbit);
506 set_bit (EV_ABS, mouse->dev.evbit);
507 set_bit (BTN_LEFT, mouse->dev.keybit); /* We have 3 buttons */
508 set_bit (BTN_MIDDLE, mouse->dev.keybit);
509 set_bit (BTN_RIGHT, mouse->dev.keybit);
510 set_bit (BTN_TOUCH, mouse->dev.keybit); /* ...and Tablet */
511 set_bit (REL_X, mouse->dev.relbit);
512 set_bit (REL_Y, mouse->dev.relbit);
513 set_bit (ABS_X, mouse->dev.absbit);
514 set_bit (ABS_Y, mouse->dev.absbit);
515
516 mouse->dev.absmin[ABS_X] = 0;
517 mouse->dev.absmax[ABS_X] = 1023;
518 mouse->dev.absmin[ABS_Y] = 0;
519 mouse->dev.absmax[ABS_Y] = 1023;
520
521 mouse->dev.private = mouse;
522
523 sprintf (mouse->name, "DEC VSXXX-AA/-GA mouse or VSXXX-AB digitizer");
524 sprintf (mouse->phys, "%s/input0", serio->phys);
525 mouse->dev.name = mouse->name;
526 mouse->dev.phys = mouse->phys;
527 mouse->dev.id.bustype = BUS_RS232;
528 mouse->dev.dev = &serio->dev;
529 mouse->serio = serio;
530
531 serio_set_drvdata (serio, mouse);
532
533 err = serio_open (serio, drv);
534 if (err) {
535 serio_set_drvdata (serio, NULL);
536 kfree (mouse);
537 return err;
538 }
539
540 /*
541 * Request selftest. Standard packet format and differential
542 * mode will be requested after the device ID'ed successfully.
543 */
544 mouse->serio->write (mouse->serio, 'T'); /* Test */
545
546 input_register_device (&mouse->dev);
547
548 printk (KERN_INFO "input: %s on %s\n", mouse->name, mouse->phys);
549
550 return 0;
551}
552
553static struct serio_device_id vsxxaa_serio_ids[] = {
554 {
555 .type = SERIO_RS232,
556 .proto = SERIO_VSXXXAA,
557 .id = SERIO_ANY,
558 .extra = SERIO_ANY,
559 },
560 { 0 }
561};
562
563MODULE_DEVICE_TABLE(serio, vsxxaa_serio_ids);
564
565static struct serio_driver vsxxxaa_drv = {
566 .driver = {
567 .name = "vsxxxaa",
568 },
569 .description = DRIVER_DESC,
570 .id_table = vsxxaa_serio_ids,
571 .connect = vsxxxaa_connect,
572 .interrupt = vsxxxaa_interrupt,
573 .disconnect = vsxxxaa_disconnect,
574};
575
576static int __init
577vsxxxaa_init (void)
578{
579 serio_register_driver(&vsxxxaa_drv);
580 return 0;
581}
582
583static void __exit
584vsxxxaa_exit (void)
585{
586 serio_unregister_driver(&vsxxxaa_drv);
587}
588
589module_init (vsxxxaa_init);
590module_exit (vsxxxaa_exit);
591
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
new file mode 100644
index 000000000000..564974ce5793
--- /dev/null
+++ b/drivers/input/mousedev.c
@@ -0,0 +1,758 @@
1/*
2 * Input driver to ExplorerPS/2 device driver module.
3 *
4 * Copyright (c) 1999-2002 Vojtech Pavlik
5 * Copyright (c) 2004 Dmitry Torokhov
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 */
11
12#define MOUSEDEV_MINOR_BASE 32
13#define MOUSEDEV_MINORS 32
14#define MOUSEDEV_MIX 31
15
16#include <linux/slab.h>
17#include <linux/poll.h>
18#include <linux/module.h>
19#include <linux/moduleparam.h>
20#include <linux/init.h>
21#include <linux/input.h>
22#include <linux/config.h>
23#include <linux/smp_lock.h>
24#include <linux/random.h>
25#include <linux/major.h>
26#include <linux/device.h>
27#include <linux/devfs_fs_kernel.h>
28#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
29#include <linux/miscdevice.h>
30#endif
31
32MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
33MODULE_DESCRIPTION("Mouse (ExplorerPS/2) device interfaces");
34MODULE_LICENSE("GPL");
35
36#ifndef CONFIG_INPUT_MOUSEDEV_SCREEN_X
37#define CONFIG_INPUT_MOUSEDEV_SCREEN_X 1024
38#endif
39#ifndef CONFIG_INPUT_MOUSEDEV_SCREEN_Y
40#define CONFIG_INPUT_MOUSEDEV_SCREEN_Y 768
41#endif
42
43static int xres = CONFIG_INPUT_MOUSEDEV_SCREEN_X;
44module_param(xres, uint, 0);
45MODULE_PARM_DESC(xres, "Horizontal screen resolution");
46
47static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y;
48module_param(yres, uint, 0);
49MODULE_PARM_DESC(yres, "Vertical screen resolution");
50
51static unsigned tap_time = 200;
52module_param(tap_time, uint, 0);
53MODULE_PARM_DESC(tap_time, "Tap time for touchpads in absolute mode (msecs)");
54
55struct mousedev_hw_data {
56 int dx, dy, dz;
57 int x, y;
58 int abs_event;
59 unsigned long buttons;
60};
61
62struct mousedev {
63 int exist;
64 int open;
65 int minor;
66 char name[16];
67 wait_queue_head_t wait;
68 struct list_head list;
69 struct input_handle handle;
70
71 struct mousedev_hw_data packet;
72 unsigned int pkt_count;
73 int old_x[4], old_y[4];
74 int frac_dx, frac_dy;
75 unsigned long touch;
76};
77
78enum mousedev_emul {
79 MOUSEDEV_EMUL_PS2,
80 MOUSEDEV_EMUL_IMPS,
81 MOUSEDEV_EMUL_EXPS
82};
83
84struct mousedev_motion {
85 int dx, dy, dz;
86 unsigned long buttons;
87};
88
89#define PACKET_QUEUE_LEN 16
90struct mousedev_list {
91 struct fasync_struct *fasync;
92 struct mousedev *mousedev;
93 struct list_head node;
94
95 struct mousedev_motion packets[PACKET_QUEUE_LEN];
96 unsigned int head, tail;
97 spinlock_t packet_lock;
98 int pos_x, pos_y;
99
100 signed char ps2[6];
101 unsigned char ready, buffer, bufsiz;
102 unsigned char imexseq, impsseq;
103 enum mousedev_emul mode;
104};
105
106#define MOUSEDEV_SEQ_LEN 6
107
108static unsigned char mousedev_imps_seq[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 };
109static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 };
110
111static struct input_handler mousedev_handler;
112
113static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
114static struct mousedev mousedev_mix;
115
116#define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
117#define fy(i) (mousedev->old_y[(mousedev->pkt_count - (i)) & 03])
118
119static void mousedev_touchpad_event(struct input_dev *dev, struct mousedev *mousedev, unsigned int code, int value)
120{
121 int size, tmp;
122 enum { FRACTION_DENOM = 128 };
123
124 if (mousedev->touch) {
125 size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
126 if (size == 0) size = 256 * 2;
127 switch (code) {
128 case ABS_X:
129 fx(0) = value;
130 if (mousedev->pkt_count >= 2) {
131 tmp = ((value - fx(2)) * (256 * FRACTION_DENOM)) / size;
132 tmp += mousedev->frac_dx;
133 mousedev->packet.dx = tmp / FRACTION_DENOM;
134 mousedev->frac_dx = tmp - mousedev->packet.dx * FRACTION_DENOM;
135 }
136 break;
137
138 case ABS_Y:
139 fy(0) = value;
140 if (mousedev->pkt_count >= 2) {
141 tmp = -((value - fy(2)) * (256 * FRACTION_DENOM)) / size;
142 tmp += mousedev->frac_dy;
143 mousedev->packet.dy = tmp / FRACTION_DENOM;
144 mousedev->frac_dy = tmp - mousedev->packet.dy * FRACTION_DENOM;
145 }
146 break;
147 }
148 }
149}
150
151static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, unsigned int code, int value)
152{
153 int size;
154
155 switch (code) {
156 case ABS_X:
157 size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
158 if (size == 0) size = xres;
159 if (value > dev->absmax[ABS_X]) value = dev->absmax[ABS_X];
160 if (value < dev->absmin[ABS_X]) value = dev->absmin[ABS_X];
161 mousedev->packet.x = ((value - dev->absmin[ABS_X]) * xres) / size;
162 mousedev->packet.abs_event = 1;
163 break;
164
165 case ABS_Y:
166 size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y];
167 if (size == 0) size = yres;
168 if (value > dev->absmax[ABS_Y]) value = dev->absmax[ABS_Y];
169 if (value < dev->absmin[ABS_Y]) value = dev->absmin[ABS_Y];
170 mousedev->packet.y = yres - ((value - dev->absmin[ABS_Y]) * yres) / size;
171 mousedev->packet.abs_event = 1;
172 break;
173 }
174}
175
176static void mousedev_rel_event(struct mousedev *mousedev, unsigned int code, int value)
177{
178 switch (code) {
179 case REL_X: mousedev->packet.dx += value; break;
180 case REL_Y: mousedev->packet.dy -= value; break;
181 case REL_WHEEL: mousedev->packet.dz -= value; break;
182 }
183}
184
185static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int value)
186{
187 int index;
188
189 switch (code) {
190 case BTN_TOUCH:
191 case BTN_0:
192 case BTN_FORWARD:
193 case BTN_LEFT: index = 0; break;
194 case BTN_STYLUS:
195 case BTN_1:
196 case BTN_RIGHT: index = 1; break;
197 case BTN_2:
198 case BTN_STYLUS2:
199 case BTN_MIDDLE: index = 2; break;
200 case BTN_3:
201 case BTN_BACK:
202 case BTN_SIDE: index = 3; break;
203 case BTN_4:
204 case BTN_EXTRA: index = 4; break;
205 default: return;
206 }
207
208 if (value) {
209 set_bit(index, &mousedev->packet.buttons);
210 set_bit(index, &mousedev_mix.packet.buttons);
211 } else {
212 clear_bit(index, &mousedev->packet.buttons);
213 clear_bit(index, &mousedev_mix.packet.buttons);
214 }
215}
216
217static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_hw_data *packet)
218{
219 struct mousedev_list *list;
220 struct mousedev_motion *p;
221 unsigned long flags;
222
223 list_for_each_entry(list, &mousedev->list, node) {
224 spin_lock_irqsave(&list->packet_lock, flags);
225
226 p = &list->packets[list->head];
227 if (list->ready && p->buttons != packet->buttons) {
228 unsigned int new_head = (list->head + 1) % PACKET_QUEUE_LEN;
229 if (new_head != list->tail) {
230 p = &list->packets[list->head = new_head];
231 memset(p, 0, sizeof(struct mousedev_motion));
232 }
233 }
234
235 if (packet->abs_event) {
236 p->dx += packet->x - list->pos_x;
237 p->dy += packet->y - list->pos_y;
238 list->pos_x = packet->x;
239 list->pos_y = packet->y;
240 }
241
242 list->pos_x += packet->dx;
243 list->pos_x = list->pos_x < 0 ? 0 : (list->pos_x >= xres ? xres : list->pos_x);
244 list->pos_y += packet->dy;
245 list->pos_y = list->pos_y < 0 ? 0 : (list->pos_y >= yres ? yres : list->pos_y);
246
247 p->dx += packet->dx;
248 p->dy += packet->dy;
249 p->dz += packet->dz;
250 p->buttons = mousedev->packet.buttons;
251
252 list->ready = 1;
253
254 spin_unlock_irqrestore(&list->packet_lock, flags);
255 kill_fasync(&list->fasync, SIGIO, POLL_IN);
256 }
257
258 wake_up_interruptible(&mousedev->wait);
259}
260
261static void mousedev_touchpad_touch(struct mousedev *mousedev, int value)
262{
263 if (!value) {
264 if (mousedev->touch &&
265 time_before(jiffies, mousedev->touch + msecs_to_jiffies(tap_time))) {
266 /*
267 * Toggle left button to emulate tap.
268 * We rely on the fact that mousedev_mix always has 0
269 * motion packet so we won't mess current position.
270 */
271 set_bit(0, &mousedev->packet.buttons);
272 set_bit(0, &mousedev_mix.packet.buttons);
273 mousedev_notify_readers(mousedev, &mousedev_mix.packet);
274 mousedev_notify_readers(&mousedev_mix, &mousedev_mix.packet);
275 clear_bit(0, &mousedev->packet.buttons);
276 clear_bit(0, &mousedev_mix.packet.buttons);
277 }
278 mousedev->touch = mousedev->pkt_count = 0;
279 mousedev->frac_dx = 0;
280 mousedev->frac_dy = 0;
281 }
282 else
283 if (!mousedev->touch)
284 mousedev->touch = jiffies;
285}
286
287static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
288{
289 struct mousedev *mousedev = handle->private;
290
291 switch (type) {
292 case EV_ABS:
293 /* Ignore joysticks */
294 if (test_bit(BTN_TRIGGER, handle->dev->keybit))
295 return;
296
297 if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit))
298 mousedev_touchpad_event(handle->dev, mousedev, code, value);
299 else
300 mousedev_abs_event(handle->dev, mousedev, code, value);
301
302 break;
303
304 case EV_REL:
305 mousedev_rel_event(mousedev, code, value);
306 break;
307
308 case EV_KEY:
309 if (value != 2) {
310 if (code == BTN_TOUCH && test_bit(BTN_TOOL_FINGER, handle->dev->keybit))
311 mousedev_touchpad_touch(mousedev, value);
312 else
313 mousedev_key_event(mousedev, code, value);
314 }
315 break;
316
317 case EV_SYN:
318 if (code == SYN_REPORT) {
319 if (mousedev->touch) {
320 mousedev->pkt_count++;
321 /* Input system eats duplicate events, but we need all of them
322 * to do correct averaging so apply present one forward
323 */
324 fx(0) = fx(1);
325 fy(0) = fy(1);
326 }
327
328 mousedev_notify_readers(mousedev, &mousedev->packet);
329 mousedev_notify_readers(&mousedev_mix, &mousedev->packet);
330
331 mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0;
332 mousedev->packet.abs_event = 0;
333 }
334 break;
335 }
336}
337
338static int mousedev_fasync(int fd, struct file *file, int on)
339{
340 int retval;
341 struct mousedev_list *list = file->private_data;
342 retval = fasync_helper(fd, file, on, &list->fasync);
343 return retval < 0 ? retval : 0;
344}
345
346static void mousedev_free(struct mousedev *mousedev)
347{
348 mousedev_table[mousedev->minor] = NULL;
349 kfree(mousedev);
350}
351
352static int mixdev_release(void)
353{
354 struct input_handle *handle;
355
356 list_for_each_entry(handle, &mousedev_handler.h_list, h_node) {
357 struct mousedev *mousedev = handle->private;
358
359 if (!mousedev->open) {
360 if (mousedev->exist)
361 input_close_device(&mousedev->handle);
362 else
363 mousedev_free(mousedev);
364 }
365 }
366
367 return 0;
368}
369
370static int mousedev_release(struct inode * inode, struct file * file)
371{
372 struct mousedev_list *list = file->private_data;
373
374 mousedev_fasync(-1, file, 0);
375
376 list_del(&list->node);
377
378 if (!--list->mousedev->open) {
379 if (list->mousedev->minor == MOUSEDEV_MIX)
380 return mixdev_release();
381
382 if (!mousedev_mix.open) {
383 if (list->mousedev->exist)
384 input_close_device(&list->mousedev->handle);
385 else
386 mousedev_free(list->mousedev);
387 }
388 }
389
390 kfree(list);
391 return 0;
392}
393
394static int mousedev_open(struct inode * inode, struct file * file)
395{
396 struct mousedev_list *list;
397 struct input_handle *handle;
398 struct mousedev *mousedev;
399 int i;
400
401#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
402 if (imajor(inode) == MISC_MAJOR)
403 i = MOUSEDEV_MIX;
404 else
405#endif
406 i = iminor(inode) - MOUSEDEV_MINOR_BASE;
407
408 if (i >= MOUSEDEV_MINORS || !mousedev_table[i])
409 return -ENODEV;
410
411 if (!(list = kmalloc(sizeof(struct mousedev_list), GFP_KERNEL)))
412 return -ENOMEM;
413 memset(list, 0, sizeof(struct mousedev_list));
414
415 spin_lock_init(&list->packet_lock);
416 list->pos_x = xres / 2;
417 list->pos_y = yres / 2;
418 list->mousedev = mousedev_table[i];
419 list_add_tail(&list->node, &mousedev_table[i]->list);
420 file->private_data = list;
421
422 if (!list->mousedev->open++) {
423 if (list->mousedev->minor == MOUSEDEV_MIX) {
424 list_for_each_entry(handle, &mousedev_handler.h_list, h_node) {
425 mousedev = handle->private;
426 if (!mousedev->open && mousedev->exist)
427 input_open_device(handle);
428 }
429 } else
430 if (!mousedev_mix.open && list->mousedev->exist)
431 input_open_device(&list->mousedev->handle);
432 }
433
434 return 0;
435}
436
437static inline int mousedev_limit_delta(int delta, int limit)
438{
439 return delta > limit ? limit : (delta < -limit ? -limit : delta);
440}
441
442static void mousedev_packet(struct mousedev_list *list, signed char *ps2_data)
443{
444 struct mousedev_motion *p;
445 unsigned long flags;
446
447 spin_lock_irqsave(&list->packet_lock, flags);
448 p = &list->packets[list->tail];
449
450 ps2_data[0] = 0x08 | ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07);
451 ps2_data[1] = mousedev_limit_delta(p->dx, 127);
452 ps2_data[2] = mousedev_limit_delta(p->dy, 127);
453 p->dx -= ps2_data[1];
454 p->dy -= ps2_data[2];
455
456 switch (list->mode) {
457 case MOUSEDEV_EMUL_EXPS:
458 ps2_data[3] = mousedev_limit_delta(p->dz, 7);
459 p->dz -= ps2_data[3];
460 ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1);
461 list->bufsiz = 4;
462 break;
463
464 case MOUSEDEV_EMUL_IMPS:
465 ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
466 ps2_data[3] = mousedev_limit_delta(p->dz, 127);
467 p->dz -= ps2_data[3];
468 list->bufsiz = 4;
469 break;
470
471 case MOUSEDEV_EMUL_PS2:
472 default:
473 ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
474 p->dz = 0;
475 list->bufsiz = 3;
476 break;
477 }
478
479 if (!p->dx && !p->dy && !p->dz) {
480 if (list->tail == list->head)
481 list->ready = 0;
482 else
483 list->tail = (list->tail + 1) % PACKET_QUEUE_LEN;
484 }
485
486 spin_unlock_irqrestore(&list->packet_lock, flags);
487}
488
489
490static ssize_t mousedev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
491{
492 struct mousedev_list *list = file->private_data;
493 unsigned char c;
494 unsigned int i;
495
496 for (i = 0; i < count; i++) {
497
498 if (get_user(c, buffer + i))
499 return -EFAULT;
500
501 if (c == mousedev_imex_seq[list->imexseq]) {
502 if (++list->imexseq == MOUSEDEV_SEQ_LEN) {
503 list->imexseq = 0;
504 list->mode = MOUSEDEV_EMUL_EXPS;
505 }
506 } else list->imexseq = 0;
507
508 if (c == mousedev_imps_seq[list->impsseq]) {
509 if (++list->impsseq == MOUSEDEV_SEQ_LEN) {
510 list->impsseq = 0;
511 list->mode = MOUSEDEV_EMUL_IMPS;
512 }
513 } else list->impsseq = 0;
514
515 list->ps2[0] = 0xfa;
516
517 switch (c) {
518
519 case 0xeb: /* Poll */
520 mousedev_packet(list, &list->ps2[1]);
521 list->bufsiz++; /* account for leading ACK */
522 break;
523
524 case 0xf2: /* Get ID */
525 switch (list->mode) {
526 case MOUSEDEV_EMUL_PS2: list->ps2[1] = 0; break;
527 case MOUSEDEV_EMUL_IMPS: list->ps2[1] = 3; break;
528 case MOUSEDEV_EMUL_EXPS: list->ps2[1] = 4; break;
529 }
530 list->bufsiz = 2;
531 break;
532
533 case 0xe9: /* Get info */
534 list->ps2[1] = 0x60; list->ps2[2] = 3; list->ps2[3] = 200;
535 list->bufsiz = 4;
536 break;
537
538 case 0xff: /* Reset */
539 list->impsseq = list->imexseq = 0;
540 list->mode = MOUSEDEV_EMUL_PS2;
541 list->ps2[1] = 0xaa; list->ps2[2] = 0x00;
542 list->bufsiz = 3;
543 break;
544
545 default:
546 list->bufsiz = 1;
547 break;
548 }
549
550 list->buffer = list->bufsiz;
551 }
552
553 kill_fasync(&list->fasync, SIGIO, POLL_IN);
554
555 wake_up_interruptible(&list->mousedev->wait);
556
557 return count;
558}
559
560static ssize_t mousedev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
561{
562 struct mousedev_list *list = file->private_data;
563 int retval = 0;
564
565 if (!list->ready && !list->buffer && (file->f_flags & O_NONBLOCK))
566 return -EAGAIN;
567
568 retval = wait_event_interruptible(list->mousedev->wait,
569 !list->mousedev->exist || list->ready || list->buffer);
570
571 if (retval)
572 return retval;
573
574 if (!list->mousedev->exist)
575 return -ENODEV;
576
577 if (!list->buffer && list->ready) {
578 mousedev_packet(list, list->ps2);
579 list->buffer = list->bufsiz;
580 }
581
582 if (count > list->buffer)
583 count = list->buffer;
584
585 list->buffer -= count;
586
587 if (copy_to_user(buffer, list->ps2 + list->bufsiz - list->buffer - count, count))
588 return -EFAULT;
589
590 return count;
591}
592
593/* No kernel lock - fine */
594static unsigned int mousedev_poll(struct file *file, poll_table *wait)
595{
596 struct mousedev_list *list = file->private_data;
597 poll_wait(file, &list->mousedev->wait, wait);
598 return ((list->ready || list->buffer) ? (POLLIN | POLLRDNORM) : 0) |
599 (list->mousedev->exist ? 0 : (POLLHUP | POLLERR));
600}
601
602static struct file_operations mousedev_fops = {
603 .owner = THIS_MODULE,
604 .read = mousedev_read,
605 .write = mousedev_write,
606 .poll = mousedev_poll,
607 .open = mousedev_open,
608 .release = mousedev_release,
609 .fasync = mousedev_fasync,
610};
611
612static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
613{
614 struct mousedev *mousedev;
615 int minor = 0;
616
617 for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
618 if (minor == MOUSEDEV_MINORS) {
619 printk(KERN_ERR "mousedev: no more free mousedev devices\n");
620 return NULL;
621 }
622
623 if (!(mousedev = kmalloc(sizeof(struct mousedev), GFP_KERNEL)))
624 return NULL;
625 memset(mousedev, 0, sizeof(struct mousedev));
626
627 INIT_LIST_HEAD(&mousedev->list);
628 init_waitqueue_head(&mousedev->wait);
629
630 mousedev->minor = minor;
631 mousedev->exist = 1;
632 mousedev->handle.dev = dev;
633 mousedev->handle.name = mousedev->name;
634 mousedev->handle.handler = handler;
635 mousedev->handle.private = mousedev;
636 sprintf(mousedev->name, "mouse%d", minor);
637
638 if (mousedev_mix.open)
639 input_open_device(&mousedev->handle);
640
641 mousedev_table[minor] = mousedev;
642
643 devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
644 S_IFCHR|S_IRUGO|S_IWUSR, "input/mouse%d", minor);
645 class_simple_device_add(input_class,
646 MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
647 dev->dev, "mouse%d", minor);
648
649 return &mousedev->handle;
650}
651
652static void mousedev_disconnect(struct input_handle *handle)
653{
654 struct mousedev *mousedev = handle->private;
655 struct mousedev_list *list;
656
657 class_simple_device_remove(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
658 devfs_remove("input/mouse%d", mousedev->minor);
659 mousedev->exist = 0;
660
661 if (mousedev->open) {
662 input_close_device(handle);
663 wake_up_interruptible(&mousedev->wait);
664 list_for_each_entry(list, &mousedev->list, node)
665 kill_fasync(&list->fasync, SIGIO, POLL_HUP);
666 } else {
667 if (mousedev_mix.open)
668 input_close_device(handle);
669 mousedev_free(mousedev);
670 }
671}
672
673static struct input_device_id mousedev_ids[] = {
674 {
675 .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT,
676 .evbit = { BIT(EV_KEY) | BIT(EV_REL) },
677 .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) },
678 .relbit = { BIT(REL_X) | BIT(REL_Y) },
679 }, /* A mouse like device, at least one button, two relative axes */
680 {
681 .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_RELBIT,
682 .evbit = { BIT(EV_KEY) | BIT(EV_REL) },
683 .relbit = { BIT(REL_WHEEL) },
684 }, /* A separate scrollwheel */
685 {
686 .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
687 .evbit = { BIT(EV_KEY) | BIT(EV_ABS) },
688 .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
689 .absbit = { BIT(ABS_X) | BIT(ABS_Y) },
690 }, /* A tablet like device, at least touch detection, two absolute axes */
691 {
692 .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
693 .evbit = { BIT(EV_KEY) | BIT(EV_ABS) },
694 .keybit = { [LONG(BTN_TOOL_FINGER)] = BIT(BTN_TOOL_FINGER) },
695 .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_TOOL_WIDTH) },
696 }, /* A touchpad */
697
698 { }, /* Terminating entry */
699};
700
701MODULE_DEVICE_TABLE(input, mousedev_ids);
702
703static struct input_handler mousedev_handler = {
704 .event = mousedev_event,
705 .connect = mousedev_connect,
706 .disconnect = mousedev_disconnect,
707 .fops = &mousedev_fops,
708 .minor = MOUSEDEV_MINOR_BASE,
709 .name = "mousedev",
710 .id_table = mousedev_ids,
711};
712
713#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
714static struct miscdevice psaux_mouse = {
715 PSMOUSE_MINOR, "psaux", &mousedev_fops
716};
717static int psaux_registered;
718#endif
719
720static int __init mousedev_init(void)
721{
722 input_register_handler(&mousedev_handler);
723
724 memset(&mousedev_mix, 0, sizeof(struct mousedev));
725 INIT_LIST_HEAD(&mousedev_mix.list);
726 init_waitqueue_head(&mousedev_mix.wait);
727 mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
728 mousedev_mix.exist = 1;
729 mousedev_mix.minor = MOUSEDEV_MIX;
730
731 devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX),
732 S_IFCHR|S_IRUGO|S_IWUSR, "input/mice");
733 class_simple_device_add(input_class, MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX),
734 NULL, "mice");
735
736#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
737 if (!(psaux_registered = !misc_register(&psaux_mouse)))
738 printk(KERN_WARNING "mice: could not misc_register the device\n");
739#endif
740
741 printk(KERN_INFO "mice: PS/2 mouse device common for all mice\n");
742
743 return 0;
744}
745
746static void __exit mousedev_exit(void)
747{
748#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
749 if (psaux_registered)
750 misc_deregister(&psaux_mouse);
751#endif
752 devfs_remove("input/mice");
753 class_simple_device_remove(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX));
754 input_unregister_handler(&mousedev_handler);
755}
756
757module_init(mousedev_init);
758module_exit(mousedev_exit);
diff --git a/drivers/input/power.c b/drivers/input/power.c
new file mode 100644
index 000000000000..bfc5c63ebffe
--- /dev/null
+++ b/drivers/input/power.c
@@ -0,0 +1,169 @@
1/*
2 * $Id: power.c,v 1.10 2001/09/25 09:17:15 vojtech Exp $
3 *
4 * Copyright (c) 2001 "Crazy" James Simmons
5 *
6 * Input driver Power Management.
7 *
8 * Sponsored by Transvirtual Technology.
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so by
27 * e-mail - mail your message to <jsimmons@transvirtual.com>.
28 */
29
30#include <linux/module.h>
31#include <linux/config.h>
32#include <linux/input.h>
33#include <linux/slab.h>
34#include <linux/init.h>
35#include <linux/tty.h>
36#include <linux/delay.h>
37#include <linux/pm.h>
38
39static struct input_handler power_handler;
40
41/*
42 * Power management can't be done in a interrupt context. So we have to
43 * use keventd.
44 */
45static int suspend_button_pushed = 0;
46static void suspend_button_task_handler(void *data)
47{
48 udelay(200); /* debounce */
49 suspend_button_pushed = 0;
50}
51
52static DECLARE_WORK(suspend_button_task, suspend_button_task_handler, NULL);
53
54static void power_event(struct input_handle *handle, unsigned int type,
55 unsigned int code, int down)
56{
57 struct input_dev *dev = handle->dev;
58
59 printk("Entering power_event\n");
60
61 if (type == EV_PWR) {
62 switch (code) {
63 case KEY_SUSPEND:
64 printk("Powering down entire device\n");
65
66 if (!suspend_button_pushed) {
67 suspend_button_pushed = 1;
68 schedule_work(&suspend_button_task);
69 }
70 break;
71 case KEY_POWER:
72 /* Hum power down the machine. */
73 break;
74 default:
75 return;
76 }
77 }
78
79 if (type == EV_KEY) {
80 switch (code) {
81 case KEY_SUSPEND:
82 printk("Powering down input device\n");
83 /* This is risky. See pm.h for details. */
84 if (dev->state != PM_RESUME)
85 dev->state = PM_RESUME;
86 else
87 dev->state = PM_SUSPEND;
88 pm_send(dev->pm_dev, dev->state, dev);
89 break;
90 case KEY_POWER:
91 /* Turn the input device off completely ? */
92 break;
93 default:
94 return;
95 }
96 }
97 return;
98}
99
100static struct input_handle *power_connect(struct input_handler *handler,
101 struct input_dev *dev,
102 struct input_device_id *id)
103{
104 struct input_handle *handle;
105
106 if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
107 return NULL;
108 memset(handle, 0, sizeof(struct input_handle));
109
110 handle->dev = dev;
111 handle->handler = handler;
112
113 input_open_device(handle);
114
115 printk(KERN_INFO "power.c: Adding power management to input layer\n");
116 return handle;
117}
118
119static void power_disconnect(struct input_handle *handle)
120{
121 input_close_device(handle);
122 kfree(handle);
123}
124
125static struct input_device_id power_ids[] = {
126 {
127 .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
128 .evbit = { BIT(EV_KEY) },
129 .keybit = { [LONG(KEY_SUSPEND)] = BIT(KEY_SUSPEND) }
130 },
131 {
132 .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
133 .evbit = { BIT(EV_KEY) },
134 .keybit = { [LONG(KEY_POWER)] = BIT(KEY_POWER) }
135 },
136 {
137 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
138 .evbit = { BIT(EV_PWR) },
139 },
140 { }, /* Terminating entry */
141};
142
143MODULE_DEVICE_TABLE(input, power_ids);
144
145static struct input_handler power_handler = {
146 .event = power_event,
147 .connect = power_connect,
148 .disconnect = power_disconnect,
149 .name = "power",
150 .id_table = power_ids,
151};
152
153static int __init power_init(void)
154{
155 input_register_handler(&power_handler);
156 return 0;
157}
158
159static void __exit power_exit(void)
160{
161 input_unregister_handler(&power_handler);
162}
163
164module_init(power_init);
165module_exit(power_exit);
166
167MODULE_AUTHOR("James Simmons <jsimmons@transvirtual.com>");
168MODULE_DESCRIPTION("Input Power Management driver");
169MODULE_LICENSE("GPL");
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
new file mode 100644
index 000000000000..b3710733b36b
--- /dev/null
+++ b/drivers/input/serio/Kconfig
@@ -0,0 +1,183 @@
1#
2# Input core configuration
3#
4config SERIO
5 tristate "Serial I/O support" if EMBEDDED || !X86
6 default y
7 ---help---
8 Say Yes here if you have any input device that uses serial I/O to
9 communicate with the system. This includes the
10 * standard AT keyboard and PS/2 mouse *
11 as well as serial mice, Sun keyboards, some joysticks and 6dof
12 devices and more.
13
14 If unsure, say Y.
15
16 To compile this driver as a module, choose M here: the
17 module will be called serio.
18
19if SERIO
20
21config SERIO_I8042
22 tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86
23 default y
24 depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && !M68K
25 ---help---
26 i8042 is the chip over which the standard AT keyboard and PS/2
27 mouse are connected to the computer. If you use these devices,
28 you'll need to say Y here.
29
30 If unsure, say Y.
31
32 To compile this driver as a module, choose M here: the
33 module will be called i8042.
34
35config SERIO_SERPORT
36 tristate "Serial port line discipline"
37 default y
38 ---help---
39 Say Y here if you plan to use an input device (mouse, joystick,
40 tablet, 6dof) that communicates over the RS232 serial (COM) port.
41
42 More information is available: <file:Documentation/input/input.txt>
43
44 If unsure, say Y.
45
46 To compile this driver as a module, choose M here: the
47 module will be called serport.
48
49config SERIO_CT82C710
50 tristate "ct82c710 Aux port controller"
51 depends on X86
52 ---help---
53 Say Y here if you have a Texas Instruments TravelMate notebook
54 equipped with the ct82c710 chip and want to use a mouse connected
55 to the "QuickPort".
56
57 If unsure, say N.
58
59 To compile this driver as a module, choose M here: the
60 module will be called ct82c710.
61
62config SERIO_Q40KBD
63 tristate "Q40 keyboard controller"
64 depends on Q40
65
66config SERIO_PARKBD
67 tristate "Parallel port keyboard adapter"
68 depends on PARPORT
69 ---help---
70 Say Y here if you built a simple parallel port adapter to attach
71 an additional AT keyboard, XT keyboard or PS/2 mouse.
72
73 More information is available: <file:Documentation/input/input.txt>
74
75 If unsure, say N.
76
77 To compile this driver as a module, choose M here: the
78 module will be called parkbd.
79
80config SERIO_RPCKBD
81 tristate "Acorn RiscPC keyboard controller"
82 depends on ARCH_ACORN || ARCH_CLPS7500
83 default y
84 help
85 Say Y here if you have the Acorn RiscPC and want to use an AT
86 keyboard connected to its keyboard controller.
87
88 To compile this driver as a module, choose M here: the
89 module will be called rpckbd.
90
91config SERIO_AMBAKMI
92 tristate "AMBA KMI keyboard controller"
93 depends on ARM_AMBA
94
95config SERIO_SA1111
96 tristate "Intel SA1111 keyboard controller"
97 depends on SA1111
98
99config SERIO_GSCPS2
100 tristate "HP GSC PS/2 keyboard and PS/2 mouse controller"
101 depends on GSC
102 default y
103 help
104 This driver provides support for the PS/2 ports on PA-RISC machines
105 over which HP PS/2 keyboards and PS/2 mice may be connected.
106 If you use these devices, you'll need to say Y here.
107
108 It's safe to enable this driver, so if unsure, say Y.
109
110 To compile this driver as a module, choose M here: the
111 module will be called gscps2.
112
113config HP_SDC
114 tristate "HP System Device Controller i8042 Support"
115 depends on GSC && SERIO
116 default y
117 ---help---
118 This option enables supports for the the "System Device
119 Controller", an i8042 carrying microcode to manage a
120 few miscellanous devices on some Hewlett Packard systems.
121 The SDC itself contains a 10ms resolution timer/clock capable
122 of delivering interrupts on a periodic and one-shot basis.
123 The SDC may also be connected to a battery-backed real-time
124 clock, a basic audio waveform generator, and an HP-HIL Master
125 Link Controller serving up to seven input devices.
126
127 By itself this option is rather useless, but enabling it will
128 enable selection of drivers for the abovementioned devices.
129 It is, however, incompatible with the old, reliable HIL keyboard
130 driver, and the new HIL driver is experimental, so if you plan
131 to use a HIL keyboard as your primary keyboard, you may wish
132 to keep using that driver until the new HIL drivers have had
133 more testing.
134
135config HIL_MLC
136 tristate "HIL MLC Support (needed for HIL input devices)"
137 depends on HP_SDC
138
139config SERIO_PCIPS2
140 tristate "PCI PS/2 keyboard and PS/2 mouse controller"
141 depends on PCI
142 help
143 Say Y here if you have a Mobility Docking station with PS/2
144 keyboard and mice ports.
145
146 To compile this driver as a module, choose M here: the
147 module will be called pcips2.
148
149config SERIO_MACEPS2
150 tristate "SGI O2 MACE PS/2 controller"
151 depends on SGI_IP32
152 help
153 Say Y here if you have SGI O2 workstation and want to use its
154 PS/2 ports.
155
156 To compile this driver as a module, choose M here: the
157 module will be called maceps2.
158
159config SERIO_LIBPS2
160 tristate "PS/2 driver library" if EMBEDDED
161 help
162 Say Y here if you are using a driver for device connected
163 to a PS/2 port, such as PS/2 mouse or standard AT keyboard.
164
165 To compile this driver as a module, choose M here: the
166 module will be called libps2.
167
168config SERIO_RAW
169 tristate "Raw access to serio ports"
170 help
171 Say Y here if you want to have raw access to serio ports, such as
172 AUX ports on i8042 keyboard controller. Each serio port that is
173 bound to this driver will be accessible via a char device with
174 major 10 and dynamically allocated minor. The driver will try
175 allocating minor 1 (that historically corresponds to /dev/psaux)
176 first. To bind this driver to a serio port use sysfs interface:
177
178 echo -n "serio_raw" > /sys/bus/serio/devices/serioX/driver
179
180 To compile this driver as a module, choose M here: the
181 module will be called serio_raw.
182
183endif
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
new file mode 100644
index 000000000000..678a8599f9ff
--- /dev/null
+++ b/drivers/input/serio/Makefile
@@ -0,0 +1,23 @@
1#
2# Makefile for the input core drivers.
3#
4
5# Each configuration option enables a list of files.
6
7obj-$(CONFIG_SERIO) += serio.o
8obj-$(CONFIG_SERIO_I8042) += i8042.o
9obj-$(CONFIG_SERIO_PARKBD) += parkbd.o
10obj-$(CONFIG_SERIO_SERPORT) += serport.o
11obj-$(CONFIG_SERIO_CT82C710) += ct82c710.o
12obj-$(CONFIG_SERIO_RPCKBD) += rpckbd.o
13obj-$(CONFIG_SERIO_SA1111) += sa1111ps2.o
14obj-$(CONFIG_SERIO_AMBAKMI) += ambakmi.o
15obj-$(CONFIG_SERIO_Q40KBD) += q40kbd.o
16obj-$(CONFIG_SERIO_98KBD) += 98kbd-io.o
17obj-$(CONFIG_SERIO_GSCPS2) += gscps2.o
18obj-$(CONFIG_HP_SDC) += hp_sdc.o
19obj-$(CONFIG_HIL_MLC) += hp_sdc_mlc.o hil_mlc.o
20obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o
21obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o
22obj-$(CONFIG_SERIO_LIBPS2) += libps2.o
23obj-$(CONFIG_SERIO_RAW) += serio_raw.o
diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c
new file mode 100644
index 000000000000..9b1ab5e7a98d
--- /dev/null
+++ b/drivers/input/serio/ambakmi.c
@@ -0,0 +1,231 @@
1/*
2 * linux/drivers/input/serio/ambakmi.c
3 *
4 * Copyright (C) 2000-2003 Deep Blue Solutions Ltd.
5 * Copyright (C) 2002 Russell King.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/serio.h>
15#include <linux/errno.h>
16#include <linux/interrupt.h>
17#include <linux/ioport.h>
18#include <linux/device.h>
19#include <linux/delay.h>
20#include <linux/slab.h>
21#include <linux/err.h>
22
23#include <asm/io.h>
24#include <asm/irq.h>
25#include <asm/hardware/amba.h>
26#include <asm/hardware/amba_kmi.h>
27#include <asm/hardware/clock.h>
28
29#define KMI_BASE (kmi->base)
30
31struct amba_kmi_port {
32 struct serio *io;
33 struct clk *clk;
34 void __iomem *base;
35 unsigned int irq;
36 unsigned int divisor;
37 unsigned int open;
38};
39
40static irqreturn_t amba_kmi_int(int irq, void *dev_id, struct pt_regs *regs)
41{
42 struct amba_kmi_port *kmi = dev_id;
43 unsigned int status = readb(KMIIR);
44 int handled = IRQ_NONE;
45
46 while (status & KMIIR_RXINTR) {
47 serio_interrupt(kmi->io, readb(KMIDATA), 0, regs);
48 status = readb(KMIIR);
49 handled = IRQ_HANDLED;
50 }
51
52 return handled;
53}
54
55static int amba_kmi_write(struct serio *io, unsigned char val)
56{
57 struct amba_kmi_port *kmi = io->port_data;
58 unsigned int timeleft = 10000; /* timeout in 100ms */
59
60 while ((readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && timeleft--)
61 udelay(10);
62
63 if (timeleft)
64 writeb(val, KMIDATA);
65
66 return timeleft ? 0 : SERIO_TIMEOUT;
67}
68
69static int amba_kmi_open(struct serio *io)
70{
71 struct amba_kmi_port *kmi = io->port_data;
72 unsigned int divisor;
73 int ret;
74
75 ret = clk_use(kmi->clk);
76 if (ret)
77 goto out;
78
79 ret = clk_enable(kmi->clk);
80 if (ret)
81 goto clk_unuse;
82
83 divisor = clk_get_rate(kmi->clk) / 8000000 - 1;
84 writeb(divisor, KMICLKDIV);
85 writeb(KMICR_EN, KMICR);
86
87 ret = request_irq(kmi->irq, amba_kmi_int, 0, "kmi-pl050", kmi);
88 if (ret) {
89 printk(KERN_ERR "kmi: failed to claim IRQ%d\n", kmi->irq);
90 writeb(0, KMICR);
91 goto clk_disable;
92 }
93
94 writeb(KMICR_EN | KMICR_RXINTREN, KMICR);
95
96 return 0;
97
98 clk_disable:
99 clk_disable(kmi->clk);
100 clk_unuse:
101 clk_unuse(kmi->clk);
102 out:
103 return ret;
104}
105
106static void amba_kmi_close(struct serio *io)
107{
108 struct amba_kmi_port *kmi = io->port_data;
109
110 writeb(0, KMICR);
111
112 free_irq(kmi->irq, kmi);
113 clk_disable(kmi->clk);
114 clk_unuse(kmi->clk);
115}
116
117static int amba_kmi_probe(struct amba_device *dev, void *id)
118{
119 struct amba_kmi_port *kmi;
120 struct serio *io;
121 int ret;
122
123 ret = amba_request_regions(dev, NULL);
124 if (ret)
125 return ret;
126
127 kmi = kmalloc(sizeof(struct amba_kmi_port), GFP_KERNEL);
128 io = kmalloc(sizeof(struct serio), GFP_KERNEL);
129 if (!kmi || !io) {
130 ret = -ENOMEM;
131 goto out;
132 }
133
134 memset(kmi, 0, sizeof(struct amba_kmi_port));
135 memset(io, 0, sizeof(struct serio));
136
137 io->id.type = SERIO_8042;
138 io->write = amba_kmi_write;
139 io->open = amba_kmi_open;
140 io->close = amba_kmi_close;
141 strlcpy(io->name, dev->dev.bus_id, sizeof(io->name));
142 strlcpy(io->phys, dev->dev.bus_id, sizeof(io->phys));
143 io->port_data = kmi;
144 io->dev.parent = &dev->dev;
145
146 kmi->io = io;
147 kmi->base = ioremap(dev->res.start, KMI_SIZE);
148 if (!kmi->base) {
149 ret = -ENOMEM;
150 goto out;
151 }
152
153 kmi->clk = clk_get(&dev->dev, "KMIREFCLK");
154 if (IS_ERR(kmi->clk)) {
155 ret = PTR_ERR(kmi->clk);
156 goto unmap;
157 }
158
159 kmi->irq = dev->irq[0];
160 amba_set_drvdata(dev, kmi);
161
162 serio_register_port(kmi->io);
163 return 0;
164
165 unmap:
166 iounmap(kmi->base);
167 out:
168 kfree(kmi);
169 kfree(io);
170 amba_release_regions(dev);
171 return ret;
172}
173
174static int amba_kmi_remove(struct amba_device *dev)
175{
176 struct amba_kmi_port *kmi = amba_get_drvdata(dev);
177
178 amba_set_drvdata(dev, NULL);
179
180 serio_unregister_port(kmi->io);
181 clk_put(kmi->clk);
182 iounmap(kmi->base);
183 kfree(kmi);
184 amba_release_regions(dev);
185 return 0;
186}
187
188static int amba_kmi_resume(struct amba_device *dev)
189{
190 struct amba_kmi_port *kmi = amba_get_drvdata(dev);
191
192 /* kick the serio layer to rescan this port */
193 serio_reconnect(kmi->io);
194
195 return 0;
196}
197
198static struct amba_id amba_kmi_idtable[] = {
199 {
200 .id = 0x00041050,
201 .mask = 0x000fffff,
202 },
203 { 0, 0 }
204};
205
206static struct amba_driver ambakmi_driver = {
207 .drv = {
208 .name = "kmi-pl050",
209 },
210 .id_table = amba_kmi_idtable,
211 .probe = amba_kmi_probe,
212 .remove = amba_kmi_remove,
213 .resume = amba_kmi_resume,
214};
215
216static int __init amba_kmi_init(void)
217{
218 return amba_driver_register(&ambakmi_driver);
219}
220
221static void __exit amba_kmi_exit(void)
222{
223 amba_driver_unregister(&ambakmi_driver);
224}
225
226module_init(amba_kmi_init);
227module_exit(amba_kmi_exit);
228
229MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
230MODULE_DESCRIPTION("AMBA KMI controller driver");
231MODULE_LICENSE("GPL");
diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c
new file mode 100644
index 000000000000..dd0f5bd90241
--- /dev/null
+++ b/drivers/input/serio/ct82c710.c
@@ -0,0 +1,225 @@
1/*
2 * $Id: ct82c710.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
3 *
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 */
6
7/*
8 * 82C710 C&T mouse port chip driver for Linux
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/delay.h>
32#include <linux/module.h>
33#include <linux/ioport.h>
34#include <linux/config.h>
35#include <linux/init.h>
36#include <linux/interrupt.h>
37#include <linux/serio.h>
38#include <linux/errno.h>
39#include <linux/err.h>
40
41#include <asm/io.h>
42
43MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
44MODULE_DESCRIPTION("82C710 C&T mouse port chip driver");
45MODULE_LICENSE("GPL");
46
47/*
48 * ct82c710 interface
49 */
50
51#define CT82C710_DEV_IDLE 0x01 /* Device Idle */
52#define CT82C710_RX_FULL 0x02 /* Device Char received */
53#define CT82C710_TX_IDLE 0x04 /* Device XMIT Idle */
54#define CT82C710_RESET 0x08 /* Device Reset */
55#define CT82C710_INTS_ON 0x10 /* Device Interrupt On */
56#define CT82C710_ERROR_FLAG 0x20 /* Device Error */
57#define CT82C710_CLEAR 0x40 /* Device Clear */
58#define CT82C710_ENABLE 0x80 /* Device Enable */
59
60#define CT82C710_IRQ 12
61
62#define CT82C710_DATA ct82c710_iores.start
63#define CT82C710_STATUS (ct82c710_iores.start + 1)
64
65static struct serio *ct82c710_port;
66static struct platform_device *ct82c710_device;
67static struct resource ct82c710_iores;
68
69/*
70 * Interrupt handler for the 82C710 mouse port. A character
71 * is waiting in the 82C710.
72 */
73
74static irqreturn_t ct82c710_interrupt(int cpl, void *dev_id, struct pt_regs * regs)
75{
76 return serio_interrupt(ct82c710_port, inb(CT82C710_DATA), 0, regs);
77}
78
79/*
80 * Wait for device to send output char and flush any input char.
81 */
82
83static int ct82c170_wait(void)
84{
85 int timeout = 60000;
86
87 while ((inb(CT82C710_STATUS) & (CT82C710_RX_FULL | CT82C710_TX_IDLE | CT82C710_DEV_IDLE))
88 != (CT82C710_DEV_IDLE | CT82C710_TX_IDLE) && timeout) {
89
90 if (inb_p(CT82C710_STATUS) & CT82C710_RX_FULL) inb_p(CT82C710_DATA);
91
92 udelay(1);
93 timeout--;
94 }
95
96 return !timeout;
97}
98
99static void ct82c710_close(struct serio *serio)
100{
101 if (ct82c170_wait())
102 printk(KERN_WARNING "ct82c710.c: Device busy in close()\n");
103
104 outb_p(inb_p(CT82C710_STATUS) & ~(CT82C710_ENABLE | CT82C710_INTS_ON), CT82C710_STATUS);
105
106 if (ct82c170_wait())
107 printk(KERN_WARNING "ct82c710.c: Device busy in close()\n");
108
109 free_irq(CT82C710_IRQ, NULL);
110}
111
112static int ct82c710_open(struct serio *serio)
113{
114 unsigned char status;
115
116 if (request_irq(CT82C710_IRQ, ct82c710_interrupt, 0, "ct82c710", NULL))
117 return -1;
118
119 status = inb_p(CT82C710_STATUS);
120
121 status |= (CT82C710_ENABLE | CT82C710_RESET);
122 outb_p(status, CT82C710_STATUS);
123
124 status &= ~(CT82C710_RESET);
125 outb_p(status, CT82C710_STATUS);
126
127 status |= CT82C710_INTS_ON;
128 outb_p(status, CT82C710_STATUS); /* Enable interrupts */
129
130 while (ct82c170_wait()) {
131 printk(KERN_ERR "ct82c710: Device busy in open()\n");
132 status &= ~(CT82C710_ENABLE | CT82C710_INTS_ON);
133 outb_p(status, CT82C710_STATUS);
134 free_irq(CT82C710_IRQ, NULL);
135 return -1;
136 }
137
138 return 0;
139}
140
141/*
142 * Write to the 82C710 mouse device.
143 */
144
145static int ct82c710_write(struct serio *port, unsigned char c)
146{
147 if (ct82c170_wait()) return -1;
148 outb_p(c, CT82C710_DATA);
149 return 0;
150}
151
152/*
153 * See if we can find a 82C710 device. Read mouse address.
154 */
155
156static int __init ct82c710_probe(void)
157{
158 outb_p(0x55, 0x2fa); /* Any value except 9, ff or 36 */
159 outb_p(0xaa, 0x3fa); /* Inverse of 55 */
160 outb_p(0x36, 0x3fa); /* Address the chip */
161 outb_p(0xe4, 0x3fa); /* 390/4; 390 = config address */
162 outb_p(0x1b, 0x2fa); /* Inverse of e4 */
163 outb_p(0x0f, 0x390); /* Write index */
164 if (inb_p(0x391) != 0xe4) /* Config address found? */
165 return -1; /* No: no 82C710 here */
166
167 outb_p(0x0d, 0x390); /* Write index */
168 ct82c710_iores.start = inb_p(0x391) << 2; /* Get mouse I/O address */
169 ct82c710_iores.end = ct82c710_iores.start + 1;
170 ct82c710_iores.flags = IORESOURCE_IO;
171 outb_p(0x0f, 0x390);
172 outb_p(0x0f, 0x391); /* Close config mode */
173
174 return 0;
175}
176
177static struct serio * __init ct82c710_allocate_port(void)
178{
179 struct serio *serio;
180
181 serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
182 if (serio) {
183 memset(serio, 0, sizeof(struct serio));
184 serio->id.type = SERIO_8042;
185 serio->open = ct82c710_open;
186 serio->close = ct82c710_close;
187 serio->write = ct82c710_write;
188 serio->dev.parent = &ct82c710_device->dev;
189 strlcpy(serio->name, "C&T 82c710 mouse port", sizeof(serio->name));
190 snprintf(serio->phys, sizeof(serio->phys), "isa%04lx/serio0", CT82C710_DATA);
191 }
192
193 return serio;
194}
195
196static int __init ct82c710_init(void)
197{
198 if (ct82c710_probe())
199 return -ENODEV;
200
201 ct82c710_device = platform_device_register_simple("ct82c710", -1, &ct82c710_iores, 1);
202 if (IS_ERR(ct82c710_device))
203 return PTR_ERR(ct82c710_device);
204
205 if (!(ct82c710_port = ct82c710_allocate_port())) {
206 platform_device_unregister(ct82c710_device);
207 return -ENOMEM;
208 }
209
210 serio_register_port(ct82c710_port);
211
212 printk(KERN_INFO "serio: C&T 82c710 mouse port at %#lx irq %d\n",
213 CT82C710_DATA, CT82C710_IRQ);
214
215 return 0;
216}
217
218static void __exit ct82c710_exit(void)
219{
220 serio_unregister_port(ct82c710_port);
221 platform_device_unregister(ct82c710_device);
222}
223
224module_init(ct82c710_init);
225module_exit(ct82c710_exit);
diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
new file mode 100644
index 000000000000..897e4c12b642
--- /dev/null
+++ b/drivers/input/serio/gscps2.c
@@ -0,0 +1,467 @@
1/*
2 * drivers/input/serio/gscps2.c
3 *
4 * Copyright (c) 2004 Helge Deller <deller@gmx.de>
5 * Copyright (c) 2002 Laurent Canet <canetl@esiee.fr>
6 * Copyright (c) 2002 Thibaut Varene <varenet@parisc-linux.org>
7 *
8 * Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c
9 * Copyright (c) 1999 Alex deVries <alex@onefishtwo.ca>
10 * Copyright (c) 1999-2000 Philipp Rumpf <prumpf@tux.org>
11 * Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr>
12 * Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr>
13 *
14 * HP GSC PS/2 port driver, found in PA/RISC Workstations
15 *
16 * This file is subject to the terms and conditions of the GNU General Public
17 * License. See the file "COPYING" in the main directory of this archive
18 * for more details.
19 *
20 * TODO:
21 * - Dino testing (did HP ever shipped a machine on which this port
22 * was usable/enabled ?)
23 */
24
25#include <linux/config.h>
26#include <linux/init.h>
27#include <linux/module.h>
28#include <linux/serio.h>
29#include <linux/input.h>
30#include <linux/interrupt.h>
31#include <linux/spinlock.h>
32#include <linux/delay.h>
33#include <linux/ioport.h>
34#include <linux/pci_ids.h>
35
36#include <asm/irq.h>
37#include <asm/io.h>
38#include <asm/parisc-device.h>
39
40MODULE_AUTHOR("Laurent Canet <canetl@esiee.fr>, Thibaut Varene <varenet@parisc-linux.org>, Helge Deller <deller@gmx.de>");
41MODULE_DESCRIPTION("HP GSC PS2 port driver");
42MODULE_LICENSE("GPL");
43MODULE_DEVICE_TABLE(parisc, gscps2_device_tbl);
44
45#define PFX "gscps2.c: "
46
47/*
48 * Driver constants
49 */
50
51/* various constants */
52#define ENABLE 1
53#define DISABLE 0
54
55#define GSC_DINO_OFFSET 0x0800 /* offset for DINO controller versus LASI one */
56
57/* PS/2 IO port offsets */
58#define GSC_ID 0x00 /* device ID offset (see: GSC_ID_XXX) */
59#define GSC_RESET 0x00 /* reset port offset */
60#define GSC_RCVDATA 0x04 /* receive port offset */
61#define GSC_XMTDATA 0x04 /* transmit port offset */
62#define GSC_CONTROL 0x08 /* see: Control register bits */
63#define GSC_STATUS 0x0C /* see: Status register bits */
64
65/* Control register bits */
66#define GSC_CTRL_ENBL 0x01 /* enable interface */
67#define GSC_CTRL_LPBXR 0x02 /* loopback operation */
68#define GSC_CTRL_DIAG 0x20 /* directly control clock/data line */
69#define GSC_CTRL_DATDIR 0x40 /* data line direct control */
70#define GSC_CTRL_CLKDIR 0x80 /* clock line direct control */
71
72/* Status register bits */
73#define GSC_STAT_RBNE 0x01 /* Receive Buffer Not Empty */
74#define GSC_STAT_TBNE 0x02 /* Transmit Buffer Not Empty */
75#define GSC_STAT_TERR 0x04 /* Timeout Error */
76#define GSC_STAT_PERR 0x08 /* Parity Error */
77#define GSC_STAT_CMPINTR 0x10 /* Composite Interrupt = irq on any port */
78#define GSC_STAT_DATSHD 0x40 /* Data Line Shadow */
79#define GSC_STAT_CLKSHD 0x80 /* Clock Line Shadow */
80
81/* IDs returned by GSC_ID port register */
82#define GSC_ID_KEYBOARD 0 /* device ID values */
83#define GSC_ID_MOUSE 1
84
85
86static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs);
87
88#define BUFFER_SIZE 0x0f
89
90/* GSC PS/2 port device struct */
91struct gscps2port {
92 struct list_head node;
93 struct parisc_device *padev;
94 struct serio *port;
95 spinlock_t lock;
96 char *addr;
97 u8 act, append; /* position in buffer[] */
98 struct {
99 u8 data;
100 u8 str;
101 } buffer[BUFFER_SIZE+1];
102 int id;
103};
104
105/*
106 * Various HW level routines
107 */
108
109#define gscps2_readb_input(x) readb((x)+GSC_RCVDATA)
110#define gscps2_readb_control(x) readb((x)+GSC_CONTROL)
111#define gscps2_readb_status(x) readb((x)+GSC_STATUS)
112#define gscps2_writeb_control(x, y) writeb((x), (y)+GSC_CONTROL)
113
114
115/*
116 * wait_TBE() - wait for Transmit Buffer Empty
117 */
118
119static int wait_TBE(char *addr)
120{
121 int timeout = 25000; /* device is expected to react within 250 msec */
122 while (gscps2_readb_status(addr) & GSC_STAT_TBNE) {
123 if (!--timeout)
124 return 0; /* This should not happen */
125 udelay(10);
126 }
127 return 1;
128}
129
130
131/*
132 * gscps2_flush() - flush the receive buffer
133 */
134
135static void gscps2_flush(struct gscps2port *ps2port)
136{
137 while (gscps2_readb_status(ps2port->addr) & GSC_STAT_RBNE)
138 gscps2_readb_input(ps2port->addr);
139 ps2port->act = ps2port->append = 0;
140}
141
142/*
143 * gscps2_writeb_output() - write a byte to the port
144 *
145 * returns 1 on sucess, 0 on error
146 */
147
148static inline int gscps2_writeb_output(struct gscps2port *ps2port, u8 data)
149{
150 unsigned long flags;
151 char *addr = ps2port->addr;
152
153 if (!wait_TBE(addr)) {
154 printk(KERN_DEBUG PFX "timeout - could not write byte %#x\n", data);
155 return 0;
156 }
157
158 while (gscps2_readb_status(ps2port->addr) & GSC_STAT_RBNE)
159 /* wait */;
160
161 spin_lock_irqsave(&ps2port->lock, flags);
162 writeb(data, addr+GSC_XMTDATA);
163 spin_unlock_irqrestore(&ps2port->lock, flags);
164
165 /* this is ugly, but due to timing of the port it seems to be necessary. */
166 mdelay(6);
167
168 /* make sure any received data is returned as fast as possible */
169 /* this is important e.g. when we set the LEDs on the keyboard */
170 gscps2_interrupt(0, NULL, NULL);
171
172 return 1;
173}
174
175
176/*
177 * gscps2_enable() - enables or disables the port
178 */
179
180static void gscps2_enable(struct gscps2port *ps2port, int enable)
181{
182 unsigned long flags;
183 u8 data;
184
185 /* now enable/disable the port */
186 spin_lock_irqsave(&ps2port->lock, flags);
187 gscps2_flush(ps2port);
188 data = gscps2_readb_control(ps2port->addr);
189 if (enable)
190 data |= GSC_CTRL_ENBL;
191 else
192 data &= ~GSC_CTRL_ENBL;
193 gscps2_writeb_control(data, ps2port->addr);
194 spin_unlock_irqrestore(&ps2port->lock, flags);
195 wait_TBE(ps2port->addr);
196 gscps2_flush(ps2port);
197}
198
199/*
200 * gscps2_reset() - resets the PS/2 port
201 */
202
203static void gscps2_reset(struct gscps2port *ps2port)
204{
205 char *addr = ps2port->addr;
206 unsigned long flags;
207
208 /* reset the interface */
209 spin_lock_irqsave(&ps2port->lock, flags);
210 gscps2_flush(ps2port);
211 writeb(0xff, addr+GSC_RESET);
212 gscps2_flush(ps2port);
213 spin_unlock_irqrestore(&ps2port->lock, flags);
214
215 /* enable it */
216 gscps2_enable(ps2port, ENABLE);
217}
218
219static LIST_HEAD(ps2port_list);
220
221/**
222 * gscps2_interrupt() - Interruption service routine
223 *
224 * This function reads received PS/2 bytes and processes them on
225 * all interfaces.
226 * The problematic part here is, that the keyboard and mouse PS/2 port
227 * share the same interrupt and it's not possible to send data if any
228 * one of them holds input data. To solve this problem we try to receive
229 * the data as fast as possible and handle the reporting to the upper layer
230 * later.
231 */
232
233static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs)
234{
235 struct gscps2port *ps2port;
236
237 list_for_each_entry(ps2port, &ps2port_list, node) {
238
239 unsigned long flags;
240 spin_lock_irqsave(&ps2port->lock, flags);
241
242 while ( (ps2port->buffer[ps2port->append].str =
243 gscps2_readb_status(ps2port->addr)) & GSC_STAT_RBNE ) {
244 ps2port->buffer[ps2port->append].data =
245 gscps2_readb_input(ps2port->addr);
246 ps2port->append = ((ps2port->append+1) & BUFFER_SIZE);
247 }
248
249 spin_unlock_irqrestore(&ps2port->lock, flags);
250
251 } /* list_for_each_entry */
252
253 /* all data was read from the ports - now report the data to upper layer */
254
255 list_for_each_entry(ps2port, &ps2port_list, node) {
256
257 while (ps2port->act != ps2port->append) {
258
259 unsigned int rxflags;
260 u8 data, status;
261
262 /* Did new data arrived while we read existing data ?
263 If yes, exit now and let the new irq handler start over again */
264 if (gscps2_readb_status(ps2port->addr) & GSC_STAT_CMPINTR)
265 return IRQ_HANDLED;
266
267 status = ps2port->buffer[ps2port->act].str;
268 data = ps2port->buffer[ps2port->act].data;
269
270 ps2port->act = ((ps2port->act+1) & BUFFER_SIZE);
271 rxflags = ((status & GSC_STAT_TERR) ? SERIO_TIMEOUT : 0 ) |
272 ((status & GSC_STAT_PERR) ? SERIO_PARITY : 0 );
273
274 serio_interrupt(ps2port->port, data, rxflags, regs);
275
276 } /* while() */
277
278 } /* list_for_each_entry */
279
280 return IRQ_HANDLED;
281}
282
283
284/*
285 * gscps2_write() - send a byte out through the aux interface.
286 */
287
288static int gscps2_write(struct serio *port, unsigned char data)
289{
290 struct gscps2port *ps2port = port->port_data;
291
292 if (!gscps2_writeb_output(ps2port, data)) {
293 printk(KERN_DEBUG PFX "sending byte %#x failed.\n", data);
294 return -1;
295 }
296 return 0;
297}
298
299/*
300 * gscps2_open() is called when a port is opened by the higher layer.
301 * It resets and enables the port.
302 */
303
304static int gscps2_open(struct serio *port)
305{
306 struct gscps2port *ps2port = port->port_data;
307
308 gscps2_reset(ps2port);
309
310 gscps2_interrupt(0, NULL, NULL);
311
312 return 0;
313}
314
315/*
316 * gscps2_close() disables the port
317 */
318
319static void gscps2_close(struct serio *port)
320{
321 struct gscps2port *ps2port = port->port_data;
322 gscps2_enable(ps2port, DISABLE);
323}
324
325/**
326 * gscps2_probe() - Probes PS2 devices
327 * @return: success/error report
328 */
329
330static int __init gscps2_probe(struct parisc_device *dev)
331{
332 struct gscps2port *ps2port;
333 struct serio *serio;
334 unsigned long hpa = dev->hpa;
335 int ret;
336
337 if (!dev->irq)
338 return -ENODEV;
339
340 /* Offset for DINO PS/2. Works with LASI even */
341 if (dev->id.sversion == 0x96)
342 hpa += GSC_DINO_OFFSET;
343
344 ps2port = kmalloc(sizeof(struct gscps2port), GFP_KERNEL);
345 serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
346 if (!ps2port || !serio) {
347 ret = -ENOMEM;
348 goto fail_nomem;
349 }
350
351 dev_set_drvdata(&dev->dev, ps2port);
352
353 memset(ps2port, 0, sizeof(struct gscps2port));
354 memset(serio, 0, sizeof(struct serio));
355 ps2port->port = serio;
356 ps2port->padev = dev;
357 ps2port->addr = ioremap(hpa, GSC_STATUS + 4);
358 spin_lock_init(&ps2port->lock);
359
360 gscps2_reset(ps2port);
361 ps2port->id = readb(ps2port->addr + GSC_ID) & 0x0f;
362
363 snprintf(serio->name, sizeof(serio->name), "GSC PS/2 %s",
364 (ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse");
365 strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
366 serio->id.type = SERIO_8042;
367 serio->write = gscps2_write;
368 serio->open = gscps2_open;
369 serio->close = gscps2_close;
370 serio->port_data = ps2port;
371 serio->dev.parent = &dev->dev;
372
373 list_add_tail(&ps2port->node, &ps2port_list);
374
375 ret = -EBUSY;
376 if (request_irq(dev->irq, gscps2_interrupt, SA_SHIRQ, ps2port->port->name, ps2port))
377 goto fail_miserably;
378
379 if (ps2port->id != GSC_ID_KEYBOARD && ps2port->id != GSC_ID_MOUSE) {
380 printk(KERN_WARNING PFX "Unsupported PS/2 port at 0x%08lx (id=%d) ignored\n",
381 hpa, ps2port->id);
382 ret = -ENODEV;
383 goto fail;
384 }
385
386#if 0
387 if (!request_mem_region(hpa, GSC_STATUS + 4, ps2port->port.name))
388 goto fail;
389#endif
390
391 printk(KERN_INFO "serio: %s port at 0x%p irq %d @ %s\n",
392 ps2port->port->name,
393 ps2port->addr,
394 ps2port->padev->irq,
395 ps2port->port->phys);
396
397 serio_register_port(ps2port->port);
398
399 return 0;
400
401fail:
402 free_irq(dev->irq, ps2port);
403
404fail_miserably:
405 list_del(&ps2port->node);
406 iounmap(ps2port->addr);
407 release_mem_region(dev->hpa, GSC_STATUS + 4);
408
409fail_nomem:
410 kfree(ps2port);
411 kfree(serio);
412 return ret;
413}
414
415/**
416 * gscps2_remove() - Removes PS2 devices
417 * @return: success/error report
418 */
419
420static int __devexit gscps2_remove(struct parisc_device *dev)
421{
422 struct gscps2port *ps2port = dev_get_drvdata(&dev->dev);
423
424 serio_unregister_port(ps2port->port);
425 free_irq(dev->irq, ps2port);
426 gscps2_flush(ps2port);
427 list_del(&ps2port->node);
428 iounmap(ps2port->addr);
429#if 0
430 release_mem_region(dev->hpa, GSC_STATUS + 4);
431#endif
432 dev_set_drvdata(&dev->dev, NULL);
433 kfree(ps2port);
434 return 0;
435}
436
437
438static struct parisc_device_id gscps2_device_tbl[] = {
439 { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00084 }, /* LASI PS/2 */
440#ifdef DINO_TESTED
441 { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00096 }, /* DINO PS/2 */
442#endif
443 { 0, } /* 0 terminated list */
444};
445
446static struct parisc_driver parisc_ps2_driver = {
447 .name = "GSC PS2",
448 .id_table = gscps2_device_tbl,
449 .probe = gscps2_probe,
450 .remove = gscps2_remove,
451};
452
453static int __init gscps2_init(void)
454{
455 register_parisc_driver(&parisc_ps2_driver);
456 return 0;
457}
458
459static void __exit gscps2_exit(void)
460{
461 unregister_parisc_driver(&parisc_ps2_driver);
462}
463
464
465module_init(gscps2_init);
466module_exit(gscps2_exit);
467
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
new file mode 100644
index 000000000000..c243cb6fdfc4
--- /dev/null
+++ b/drivers/input/serio/hil_mlc.c
@@ -0,0 +1,949 @@
1/*
2 * HIL MLC state machine and serio interface driver
3 *
4 * Copyright (c) 2001 Brian S. Julin
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * Alternatively, this software may be distributed under the terms of the
17 * GNU General Public License ("GPL").
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 *
29 * References:
30 * HP-HIL Technical Reference Manual. Hewlett Packard Product No. 45918A
31 *
32 *
33 * Driver theory of operation:
34 *
35 * Some access methods and an ISR is defined by the sub-driver
36 * (e.g. hp_sdc_mlc.c). These methods are expected to provide a
37 * few bits of logic in addition to raw access to the HIL MLC,
38 * specifically, the ISR, which is entirely registered by the
39 * sub-driver and invoked directly, must check for record
40 * termination or packet match, at which point a semaphore must
41 * be cleared and then the hil_mlcs_tasklet must be scheduled.
42 *
43 * The hil_mlcs_tasklet processes the state machine for all MLCs
44 * each time it runs, checking each MLC's progress at the current
45 * node in the state machine, and moving the MLC to subsequent nodes
46 * in the state machine when appropriate. It will reschedule
47 * itself if output is pending. (This rescheduling should be replaced
48 * at some point with a sub-driver-specific mechanism.)
49 *
50 * A timer task prods the tasklet once per second to prevent
51 * hangups when attached devices do not return expected data
52 * and to initiate probes of the loop for new devices.
53 */
54
55#include <linux/hil_mlc.h>
56#include <linux/errno.h>
57#include <linux/kernel.h>
58#include <linux/module.h>
59#include <linux/init.h>
60#include <linux/interrupt.h>
61#include <linux/timer.h>
62#include <linux/sched.h>
63#include <linux/list.h>
64
65MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
66MODULE_DESCRIPTION("HIL MLC serio");
67MODULE_LICENSE("Dual BSD/GPL");
68
69EXPORT_SYMBOL(hil_mlc_register);
70EXPORT_SYMBOL(hil_mlc_unregister);
71
72#define PREFIX "HIL MLC: "
73
74static LIST_HEAD(hil_mlcs);
75static DEFINE_RWLOCK(hil_mlcs_lock);
76static struct timer_list hil_mlcs_kicker;
77static int hil_mlcs_probe;
78
79static void hil_mlcs_process(unsigned long unused);
80DECLARE_TASKLET_DISABLED(hil_mlcs_tasklet, hil_mlcs_process, 0);
81
82
83/* #define HIL_MLC_DEBUG */
84
85/********************** Device info/instance management **********************/
86
87static void hil_mlc_clear_di_map (hil_mlc *mlc, int val) {
88 int j;
89 for (j = val; j < 7 ; j++) {
90 mlc->di_map[j] = -1;
91 }
92}
93
94static void hil_mlc_clear_di_scratch (hil_mlc *mlc) {
95 memset(&(mlc->di_scratch), 0, sizeof(mlc->di_scratch));
96}
97
98static void hil_mlc_copy_di_scratch (hil_mlc *mlc, int idx) {
99 memcpy(&(mlc->di[idx]), &(mlc->di_scratch), sizeof(mlc->di_scratch));
100}
101
102static int hil_mlc_match_di_scratch (hil_mlc *mlc) {
103 int idx;
104
105 for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
106 int j, found;
107
108 /* In-use slots are not eligible. */
109 found = 0;
110 for (j = 0; j < 7 ; j++) {
111 if (mlc->di_map[j] == idx) found++;
112 }
113 if (found) continue;
114 if (!memcmp(mlc->di + idx,
115 &(mlc->di_scratch),
116 sizeof(mlc->di_scratch))) break;
117 }
118 return((idx >= HIL_MLC_DEVMEM) ? -1 : idx);
119}
120
121static int hil_mlc_find_free_di(hil_mlc *mlc) {
122 int idx;
123 /* TODO: Pick all-zero slots first, failing that,
124 * randomize the slot picked among those eligible.
125 */
126 for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
127 int j, found;
128 found = 0;
129 for (j = 0; j < 7 ; j++) {
130 if (mlc->di_map[j] == idx) found++;
131 }
132 if (!found) break;
133 }
134 return(idx); /* Note: It is guaranteed at least one above will match */
135}
136
137static inline void hil_mlc_clean_serio_map(hil_mlc *mlc) {
138 int idx;
139 for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
140 int j, found;
141 found = 0;
142 for (j = 0; j < 7 ; j++) {
143 if (mlc->di_map[j] == idx) found++;
144 }
145 if (!found) mlc->serio_map[idx].di_revmap = -1;
146 }
147}
148
149static void hil_mlc_send_polls(hil_mlc *mlc) {
150 int did, i, cnt;
151 struct serio *serio;
152 struct serio_driver *drv;
153
154 i = cnt = 0;
155 did = (mlc->ipacket[0] & HIL_PKT_ADDR_MASK) >> 8;
156 serio = did ? mlc->serio[mlc->di_map[did - 1]] : NULL;
157 drv = (serio != NULL) ? serio->drv : NULL;
158
159 while (mlc->icount < 15 - i) {
160 hil_packet p;
161 p = mlc->ipacket[i];
162 if (did != (p & HIL_PKT_ADDR_MASK) >> 8) {
163 if (drv == NULL || drv->interrupt == NULL) goto skip;
164
165 drv->interrupt(serio, 0, 0, NULL);
166 drv->interrupt(serio, HIL_ERR_INT >> 16, 0, NULL);
167 drv->interrupt(serio, HIL_PKT_CMD >> 8, 0, NULL);
168 drv->interrupt(serio, HIL_CMD_POL + cnt, 0, NULL);
169 skip:
170 did = (p & HIL_PKT_ADDR_MASK) >> 8;
171 serio = did ? mlc->serio[mlc->di_map[did-1]] : NULL;
172 drv = (serio != NULL) ? serio->drv : NULL;
173 cnt = 0;
174 }
175 cnt++; i++;
176 if (drv == NULL || drv->interrupt == NULL) continue;
177 drv->interrupt(serio, (p >> 24), 0, NULL);
178 drv->interrupt(serio, (p >> 16) & 0xff, 0, NULL);
179 drv->interrupt(serio, (p >> 8) & ~HIL_PKT_ADDR_MASK, 0, NULL);
180 drv->interrupt(serio, p & 0xff, 0, NULL);
181 }
182}
183
184/*************************** State engine *********************************/
185
186#define HILSEN_SCHED 0x000100 /* Schedule the tasklet */
187#define HILSEN_BREAK 0x000200 /* Wait until next pass */
188#define HILSEN_UP 0x000400 /* relative node#, decrement */
189#define HILSEN_DOWN 0x000800 /* relative node#, increment */
190#define HILSEN_FOLLOW 0x001000 /* use retval as next node# */
191
192#define HILSEN_MASK 0x0000ff
193#define HILSEN_START 0
194#define HILSEN_RESTART 1
195#define HILSEN_DHR 9
196#define HILSEN_DHR2 10
197#define HILSEN_IFC 14
198#define HILSEN_HEAL0 16
199#define HILSEN_HEAL 18
200#define HILSEN_ACF 21
201#define HILSEN_ACF2 22
202#define HILSEN_DISC0 25
203#define HILSEN_DISC 27
204#define HILSEN_MATCH 40
205#define HILSEN_OPERATE 41
206#define HILSEN_PROBE 44
207#define HILSEN_DSR 52
208#define HILSEN_REPOLL 55
209#define HILSEN_IFCACF 58
210#define HILSEN_END 60
211
212#define HILSEN_NEXT (HILSEN_DOWN | 1)
213#define HILSEN_SAME (HILSEN_DOWN | 0)
214#define HILSEN_LAST (HILSEN_UP | 1)
215
216#define HILSEN_DOZE (HILSEN_SAME | HILSEN_SCHED | HILSEN_BREAK)
217#define HILSEN_SLEEP (HILSEN_SAME | HILSEN_BREAK)
218
219static int hilse_match(hil_mlc *mlc, int unused) {
220 int rc;
221 rc = hil_mlc_match_di_scratch(mlc);
222 if (rc == -1) {
223 rc = hil_mlc_find_free_di(mlc);
224 if (rc == -1) goto err;
225#ifdef HIL_MLC_DEBUG
226 printk(KERN_DEBUG PREFIX "new in slot %i\n", rc);
227#endif
228 hil_mlc_copy_di_scratch(mlc, rc);
229 mlc->di_map[mlc->ddi] = rc;
230 mlc->serio_map[rc].di_revmap = mlc->ddi;
231 hil_mlc_clean_serio_map(mlc);
232 serio_rescan(mlc->serio[rc]);
233 return -1;
234 }
235 mlc->di_map[mlc->ddi] = rc;
236#ifdef HIL_MLC_DEBUG
237 printk(KERN_DEBUG PREFIX "same in slot %i\n", rc);
238#endif
239 mlc->serio_map[rc].di_revmap = mlc->ddi;
240 hil_mlc_clean_serio_map(mlc);
241 return 0;
242 err:
243 printk(KERN_ERR PREFIX "Residual device slots exhausted, close some serios!\n");
244 return 1;
245}
246
247/* An LCV used to prevent runaway loops, forces 5 second sleep when reset. */
248static int hilse_init_lcv(hil_mlc *mlc, int unused) {
249 struct timeval tv;
250
251 do_gettimeofday(&tv);
252
253 if(mlc->lcv == 0) goto restart; /* First init, no need to dally */
254 if(tv.tv_sec - mlc->lcv_tv.tv_sec < 5) return -1;
255 restart:
256 mlc->lcv_tv = tv;
257 mlc->lcv = 0;
258 return 0;
259}
260
261static int hilse_inc_lcv(hil_mlc *mlc, int lim) {
262 if (mlc->lcv++ >= lim) return -1;
263 return 0;
264}
265
266#if 0
267static int hilse_set_lcv(hil_mlc *mlc, int val) {
268 mlc->lcv = val;
269 return 0;
270}
271#endif
272
273/* Management of the discovered device index (zero based, -1 means no devs) */
274static int hilse_set_ddi(hil_mlc *mlc, int val) {
275 mlc->ddi = val;
276 hil_mlc_clear_di_map(mlc, val + 1);
277 return 0;
278}
279
280static int hilse_dec_ddi(hil_mlc *mlc, int unused) {
281 mlc->ddi--;
282 if (mlc->ddi <= -1) {
283 mlc->ddi = -1;
284 hil_mlc_clear_di_map(mlc, 0);
285 return -1;
286 }
287 hil_mlc_clear_di_map(mlc, mlc->ddi + 1);
288 return 0;
289}
290
291static int hilse_inc_ddi(hil_mlc *mlc, int unused) {
292 if (mlc->ddi >= 6) {
293 BUG();
294 return -1;
295 }
296 mlc->ddi++;
297 return 0;
298}
299
300static int hilse_take_idd(hil_mlc *mlc, int unused) {
301 int i;
302
303 /* Help the state engine:
304 * Is this a real IDD response or just an echo?
305 *
306 * Real IDD response does not start with a command.
307 */
308 if (mlc->ipacket[0] & HIL_PKT_CMD) goto bail;
309 /* Should have the command echoed further down. */
310 for (i = 1; i < 16; i++) {
311 if (((mlc->ipacket[i] & HIL_PKT_ADDR_MASK) ==
312 (mlc->ipacket[0] & HIL_PKT_ADDR_MASK)) &&
313 (mlc->ipacket[i] & HIL_PKT_CMD) &&
314 ((mlc->ipacket[i] & HIL_PKT_DATA_MASK) == HIL_CMD_IDD))
315 break;
316 }
317 if (i > 15) goto bail;
318 /* And the rest of the packets should still be clear. */
319 while (++i < 16) {
320 if (mlc->ipacket[i]) break;
321 }
322 if (i < 16) goto bail;
323 for (i = 0; i < 16; i++) {
324 mlc->di_scratch.idd[i] =
325 mlc->ipacket[i] & HIL_PKT_DATA_MASK;
326 }
327 /* Next step is to see if RSC supported */
328 if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_RSC)
329 return HILSEN_NEXT;
330 if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD)
331 return HILSEN_DOWN | 4;
332 return 0;
333 bail:
334 mlc->ddi--;
335 return -1; /* This should send us off to ACF */
336}
337
338static int hilse_take_rsc(hil_mlc *mlc, int unused) {
339 int i;
340
341 for (i = 0; i < 16; i++) {
342 mlc->di_scratch.rsc[i] =
343 mlc->ipacket[i] & HIL_PKT_DATA_MASK;
344 }
345 /* Next step is to see if EXD supported (IDD has already been read) */
346 if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD)
347 return HILSEN_NEXT;
348 return 0;
349}
350
351static int hilse_take_exd(hil_mlc *mlc, int unused) {
352 int i;
353
354 for (i = 0; i < 16; i++) {
355 mlc->di_scratch.exd[i] =
356 mlc->ipacket[i] & HIL_PKT_DATA_MASK;
357 }
358 /* Next step is to see if RNM supported. */
359 if (mlc->di_scratch.exd[0] & HIL_EXD_HEADER_RNM)
360 return HILSEN_NEXT;
361 return 0;
362}
363
364static int hilse_take_rnm(hil_mlc *mlc, int unused) {
365 int i;
366
367 for (i = 0; i < 16; i++) {
368 mlc->di_scratch.rnm[i] =
369 mlc->ipacket[i] & HIL_PKT_DATA_MASK;
370 }
371 do {
372 char nam[17];
373 snprintf(nam, 16, "%s", mlc->di_scratch.rnm);
374 nam[16] = '\0';
375 printk(KERN_INFO PREFIX "Device name gotten: %s\n", nam);
376 } while (0);
377 return 0;
378}
379
380static int hilse_operate(hil_mlc *mlc, int repoll) {
381
382 if (mlc->opercnt == 0) hil_mlcs_probe = 0;
383 mlc->opercnt = 1;
384
385 hil_mlc_send_polls(mlc);
386
387 if (!hil_mlcs_probe) return 0;
388 hil_mlcs_probe = 0;
389 mlc->opercnt = 0;
390 return 1;
391}
392
393#define FUNC(funct, funct_arg, zero_rc, neg_rc, pos_rc) \
394{ HILSE_FUNC, { func: &funct }, funct_arg, zero_rc, neg_rc, pos_rc },
395#define OUT(pack) \
396{ HILSE_OUT, { packet: pack }, 0, HILSEN_NEXT, HILSEN_DOZE, 0 },
397#define CTS \
398{ HILSE_CTS, { packet: 0 }, 0, HILSEN_NEXT | HILSEN_SCHED | HILSEN_BREAK, HILSEN_DOZE, 0 },
399#define EXPECT(comp, to, got, got_wrong, timed_out) \
400{ HILSE_EXPECT, { packet: comp }, to, got, got_wrong, timed_out },
401#define EXPECT_LAST(comp, to, got, got_wrong, timed_out) \
402{ HILSE_EXPECT_LAST, { packet: comp }, to, got, got_wrong, timed_out },
403#define EXPECT_DISC(comp, to, got, got_wrong, timed_out) \
404{ HILSE_EXPECT_DISC, { packet: comp }, to, got, got_wrong, timed_out },
405#define IN(to, got, got_error, timed_out) \
406{ HILSE_IN, { packet: 0 }, to, got, got_error, timed_out },
407#define OUT_DISC(pack) \
408{ HILSE_OUT_DISC, { packet: pack }, 0, 0, 0, 0 },
409#define OUT_LAST(pack) \
410{ HILSE_OUT_LAST, { packet: pack }, 0, 0, 0, 0 },
411
412struct hilse_node hil_mlc_se[HILSEN_END] = {
413
414 /* 0 HILSEN_START */
415 FUNC(hilse_init_lcv, 0, HILSEN_NEXT, HILSEN_SLEEP, 0)
416
417 /* 1 HILSEN_RESTART */
418 FUNC(hilse_inc_lcv, 10, HILSEN_NEXT, HILSEN_START, 0)
419 OUT(HIL_CTRL_ONLY) /* Disable APE */
420 CTS
421
422#define TEST_PACKET(x) \
423(HIL_PKT_CMD | (x << HIL_PKT_ADDR_SHIFT) | x << 4 | x)
424
425 OUT(HIL_DO_ALTER_CTRL | HIL_CTRL_TEST | TEST_PACKET(0x5))
426 EXPECT(HIL_ERR_INT | TEST_PACKET(0x5),
427 2000, HILSEN_NEXT, HILSEN_RESTART, HILSEN_RESTART)
428 OUT(HIL_DO_ALTER_CTRL | HIL_CTRL_TEST | TEST_PACKET(0xa))
429 EXPECT(HIL_ERR_INT | TEST_PACKET(0xa),
430 2000, HILSEN_NEXT, HILSEN_RESTART, HILSEN_RESTART)
431 OUT(HIL_CTRL_ONLY | 0) /* Disable test mode */
432
433 /* 9 HILSEN_DHR */
434 FUNC(hilse_init_lcv, 0, HILSEN_NEXT, HILSEN_SLEEP, 0)
435
436 /* 10 HILSEN_DHR2 */
437 FUNC(hilse_inc_lcv, 10, HILSEN_NEXT, HILSEN_START, 0)
438 FUNC(hilse_set_ddi, -1, HILSEN_NEXT, 0, 0)
439 OUT(HIL_PKT_CMD | HIL_CMD_DHR)
440 IN(300000, HILSEN_DHR2, HILSEN_DHR2, HILSEN_NEXT)
441
442 /* 14 HILSEN_IFC */
443 OUT(HIL_PKT_CMD | HIL_CMD_IFC)
444 EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT,
445 20000, HILSEN_DISC, HILSEN_DHR2, HILSEN_NEXT )
446
447 /* If devices are there, they weren't in PUP or other loopback mode.
448 * We're more concerned at this point with restoring operation
449 * to devices than discovering new ones, so we try to salvage
450 * the loop configuration by closing off the loop.
451 */
452
453 /* 16 HILSEN_HEAL0 */
454 FUNC(hilse_dec_ddi, 0, HILSEN_NEXT, HILSEN_ACF, 0)
455 FUNC(hilse_inc_ddi, 0, HILSEN_NEXT, 0, 0)
456
457 /* 18 HILSEN_HEAL */
458 OUT_LAST(HIL_CMD_ELB)
459 EXPECT_LAST(HIL_CMD_ELB | HIL_ERR_INT,
460 20000, HILSEN_REPOLL, HILSEN_DSR, HILSEN_NEXT)
461 FUNC(hilse_dec_ddi, 0, HILSEN_HEAL, HILSEN_NEXT, 0)
462
463 /* 21 HILSEN_ACF */
464 FUNC(hilse_init_lcv, 0, HILSEN_NEXT, HILSEN_DOZE, 0)
465
466 /* 22 HILSEN_ACF2 */
467 FUNC(hilse_inc_lcv, 10, HILSEN_NEXT, HILSEN_START, 0)
468 OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1)
469 IN(20000, HILSEN_NEXT, HILSEN_DSR, HILSEN_NEXT)
470
471 /* 25 HILSEN_DISC0 */
472 OUT_DISC(HIL_PKT_CMD | HIL_CMD_ELB)
473 EXPECT_DISC(HIL_PKT_CMD | HIL_CMD_ELB | HIL_ERR_INT,
474 20000, HILSEN_NEXT, HILSEN_DSR, HILSEN_DSR)
475
476 /* Only enter here if response just received */
477 /* 27 HILSEN_DISC */
478 OUT_DISC(HIL_PKT_CMD | HIL_CMD_IDD)
479 EXPECT_DISC(HIL_PKT_CMD | HIL_CMD_IDD | HIL_ERR_INT,
480 20000, HILSEN_NEXT, HILSEN_DSR, HILSEN_START)
481 FUNC(hilse_inc_ddi, 0, HILSEN_NEXT, HILSEN_START, 0)
482 FUNC(hilse_take_idd, 0, HILSEN_MATCH, HILSEN_IFCACF, HILSEN_FOLLOW)
483 OUT_LAST(HIL_PKT_CMD | HIL_CMD_RSC)
484 EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_RSC | HIL_ERR_INT,
485 30000, HILSEN_NEXT, HILSEN_DSR, HILSEN_DSR)
486 FUNC(hilse_take_rsc, 0, HILSEN_MATCH, 0, HILSEN_FOLLOW)
487 OUT_LAST(HIL_PKT_CMD | HIL_CMD_EXD)
488 EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_EXD | HIL_ERR_INT,
489 30000, HILSEN_NEXT, HILSEN_DSR, HILSEN_DSR)
490 FUNC(hilse_take_exd, 0, HILSEN_MATCH, 0, HILSEN_FOLLOW)
491 OUT_LAST(HIL_PKT_CMD | HIL_CMD_RNM)
492 EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_RNM | HIL_ERR_INT,
493 30000, HILSEN_NEXT, HILSEN_DSR, HILSEN_DSR)
494 FUNC(hilse_take_rnm, 0, HILSEN_MATCH, 0, 0)
495
496 /* 40 HILSEN_MATCH */
497 FUNC(hilse_match, 0, HILSEN_NEXT, HILSEN_NEXT, /* TODO */ 0)
498
499 /* 41 HILSEN_OPERATE */
500 OUT(HIL_PKT_CMD | HIL_CMD_POL)
501 EXPECT(HIL_PKT_CMD | HIL_CMD_POL | HIL_ERR_INT,
502 20000, HILSEN_NEXT, HILSEN_DSR, HILSEN_NEXT)
503 FUNC(hilse_operate, 0, HILSEN_OPERATE, HILSEN_IFC, HILSEN_NEXT)
504
505 /* 44 HILSEN_PROBE */
506 OUT_LAST(HIL_PKT_CMD | HIL_CMD_EPT)
507 IN(10000, HILSEN_DISC, HILSEN_DSR, HILSEN_NEXT)
508 OUT_DISC(HIL_PKT_CMD | HIL_CMD_ELB)
509 IN(10000, HILSEN_DISC, HILSEN_DSR, HILSEN_NEXT)
510 OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1)
511 IN(10000, HILSEN_DISC0, HILSEN_DSR, HILSEN_NEXT)
512 OUT_LAST(HIL_PKT_CMD | HIL_CMD_ELB)
513 IN(10000, HILSEN_OPERATE, HILSEN_DSR, HILSEN_DSR)
514
515 /* 52 HILSEN_DSR */
516 FUNC(hilse_set_ddi, -1, HILSEN_NEXT, 0, 0)
517 OUT(HIL_PKT_CMD | HIL_CMD_DSR)
518 IN(20000, HILSEN_DHR, HILSEN_DHR, HILSEN_IFC)
519
520 /* 55 HILSEN_REPOLL */
521 OUT(HIL_PKT_CMD | HIL_CMD_RPL)
522 EXPECT(HIL_PKT_CMD | HIL_CMD_RPL | HIL_ERR_INT,
523 20000, HILSEN_NEXT, HILSEN_DSR, HILSEN_NEXT)
524 FUNC(hilse_operate, 1, HILSEN_OPERATE, HILSEN_IFC, HILSEN_PROBE)
525
526 /* 58 HILSEN_IFCACF */
527 OUT(HIL_PKT_CMD | HIL_CMD_IFC)
528 EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT,
529 20000, HILSEN_ACF2, HILSEN_DHR2, HILSEN_HEAL)
530
531 /* 60 HILSEN_END */
532};
533
534static inline void hilse_setup_input(hil_mlc *mlc, struct hilse_node *node) {
535
536 switch (node->act) {
537 case HILSE_EXPECT_DISC:
538 mlc->imatch = node->object.packet;
539 mlc->imatch |= ((mlc->ddi + 2) << HIL_PKT_ADDR_SHIFT);
540 break;
541 case HILSE_EXPECT_LAST:
542 mlc->imatch = node->object.packet;
543 mlc->imatch |= ((mlc->ddi + 1) << HIL_PKT_ADDR_SHIFT);
544 break;
545 case HILSE_EXPECT:
546 mlc->imatch = node->object.packet;
547 break;
548 case HILSE_IN:
549 mlc->imatch = 0;
550 break;
551 default:
552 BUG();
553 }
554 mlc->istarted = 1;
555 mlc->intimeout = node->arg;
556 do_gettimeofday(&(mlc->instart));
557 mlc->icount = 15;
558 memset(mlc->ipacket, 0, 16 * sizeof(hil_packet));
559 if (down_trylock(&(mlc->isem))) BUG();
560
561 return;
562}
563
564#ifdef HIL_MLC_DEBUG
565static int doze = 0;
566static int seidx; /* For debug */
567static int kick = 1;
568#endif
569
570static int hilse_donode (hil_mlc *mlc) {
571 struct hilse_node *node;
572 int nextidx = 0;
573 int sched_long = 0;
574 unsigned long flags;
575
576#ifdef HIL_MLC_DEBUG
577 if (mlc->seidx && (mlc->seidx != seidx) && mlc->seidx != 41 && mlc->seidx != 42 && mlc->seidx != 43) {
578 printk(KERN_DEBUG PREFIX "z%i \n%s {%i}", doze, kick ? "K" : "", mlc->seidx);
579 doze = 0;
580 }
581 kick = 0;
582
583 seidx = mlc->seidx;
584#endif
585 node = hil_mlc_se + mlc->seidx;
586
587 switch (node->act) {
588 int rc;
589 hil_packet pack;
590
591 case HILSE_FUNC:
592 if (node->object.func == NULL) break;
593 rc = node->object.func(mlc, node->arg);
594 nextidx = (rc > 0) ? node->ugly :
595 ((rc < 0) ? node->bad : node->good);
596 if (nextidx == HILSEN_FOLLOW) nextidx = rc;
597 break;
598 case HILSE_EXPECT_LAST:
599 case HILSE_EXPECT_DISC:
600 case HILSE_EXPECT:
601 case HILSE_IN:
602 /* Already set up from previous HILSE_OUT_* */
603 write_lock_irqsave(&(mlc->lock), flags);
604 rc = mlc->in(mlc, node->arg);
605 if (rc == 2) {
606 nextidx = HILSEN_DOZE;
607 sched_long = 1;
608 write_unlock_irqrestore(&(mlc->lock), flags);
609 break;
610 }
611 if (rc == 1) nextidx = node->ugly;
612 else if (rc == 0) nextidx = node->good;
613 else nextidx = node->bad;
614 mlc->istarted = 0;
615 write_unlock_irqrestore(&(mlc->lock), flags);
616 break;
617 case HILSE_OUT_LAST:
618 write_lock_irqsave(&(mlc->lock), flags);
619 pack = node->object.packet;
620 pack |= ((mlc->ddi + 1) << HIL_PKT_ADDR_SHIFT);
621 goto out;
622 case HILSE_OUT_DISC:
623 write_lock_irqsave(&(mlc->lock), flags);
624 pack = node->object.packet;
625 pack |= ((mlc->ddi + 2) << HIL_PKT_ADDR_SHIFT);
626 goto out;
627 case HILSE_OUT:
628 write_lock_irqsave(&(mlc->lock), flags);
629 pack = node->object.packet;
630 out:
631 if (mlc->istarted) goto out2;
632 /* Prepare to receive input */
633 if ((node + 1)->act & HILSE_IN)
634 hilse_setup_input(mlc, node + 1);
635
636 out2:
637 write_unlock_irqrestore(&(mlc->lock), flags);
638
639 if (down_trylock(&mlc->osem)) {
640 nextidx = HILSEN_DOZE;
641 break;
642 }
643 up(&mlc->osem);
644
645 write_lock_irqsave(&(mlc->lock), flags);
646 if (!(mlc->ostarted)) {
647 mlc->ostarted = 1;
648 mlc->opacket = pack;
649 mlc->out(mlc);
650 nextidx = HILSEN_DOZE;
651 write_unlock_irqrestore(&(mlc->lock), flags);
652 break;
653 }
654 mlc->ostarted = 0;
655 do_gettimeofday(&(mlc->instart));
656 write_unlock_irqrestore(&(mlc->lock), flags);
657 nextidx = HILSEN_NEXT;
658 break;
659 case HILSE_CTS:
660 nextidx = mlc->cts(mlc) ? node->bad : node->good;
661 break;
662 default:
663 BUG();
664 nextidx = 0;
665 break;
666 }
667
668#ifdef HIL_MLC_DEBUG
669 if (nextidx == HILSEN_DOZE) doze++;
670#endif
671
672 while (nextidx & HILSEN_SCHED) {
673 struct timeval tv;
674
675 if (!sched_long) goto sched;
676
677 do_gettimeofday(&tv);
678 tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec);
679 tv.tv_usec -= mlc->instart.tv_usec;
680 if (tv.tv_usec >= mlc->intimeout) goto sched;
681 tv.tv_usec = (mlc->intimeout - tv.tv_usec) * HZ / 1000000;
682 if (!tv.tv_usec) goto sched;
683 mod_timer(&hil_mlcs_kicker, jiffies + tv.tv_usec);
684 break;
685 sched:
686 tasklet_schedule(&hil_mlcs_tasklet);
687 break;
688 }
689 if (nextidx & HILSEN_DOWN) mlc->seidx += nextidx & HILSEN_MASK;
690 else if (nextidx & HILSEN_UP) mlc->seidx -= nextidx & HILSEN_MASK;
691 else mlc->seidx = nextidx & HILSEN_MASK;
692
693 if (nextidx & HILSEN_BREAK) return 1;
694 return 0;
695}
696
697/******************** tasklet context functions **************************/
698static void hil_mlcs_process(unsigned long unused) {
699 struct list_head *tmp;
700
701 read_lock(&hil_mlcs_lock);
702 list_for_each(tmp, &hil_mlcs) {
703 struct hil_mlc *mlc = list_entry(tmp, hil_mlc, list);
704 while (hilse_donode(mlc) == 0) {
705#ifdef HIL_MLC_DEBUG
706 if (mlc->seidx != 41 &&
707 mlc->seidx != 42 &&
708 mlc->seidx != 43)
709 printk(KERN_DEBUG PREFIX " + ");
710#endif
711 };
712 }
713 read_unlock(&hil_mlcs_lock);
714}
715
716/************************* Keepalive timer task *********************/
717
718void hil_mlcs_timer (unsigned long data) {
719 hil_mlcs_probe = 1;
720 tasklet_schedule(&hil_mlcs_tasklet);
721 /* Re-insert the periodic task. */
722 if (!timer_pending(&hil_mlcs_kicker))
723 mod_timer(&hil_mlcs_kicker, jiffies + HZ);
724}
725
726/******************** user/kernel context functions **********************/
727
728static int hil_mlc_serio_write(struct serio *serio, unsigned char c) {
729 struct hil_mlc_serio_map *map;
730 struct hil_mlc *mlc;
731 struct serio_driver *drv;
732 uint8_t *idx, *last;
733
734 map = serio->port_data;
735 if (map == NULL) {
736 BUG();
737 return -EIO;
738 }
739 mlc = map->mlc;
740 if (mlc == NULL) {
741 BUG();
742 return -EIO;
743 }
744 mlc->serio_opacket[map->didx] |=
745 ((hil_packet)c) << (8 * (3 - mlc->serio_oidx[map->didx]));
746
747 if (mlc->serio_oidx[map->didx] >= 3) {
748 /* for now only commands */
749 if (!(mlc->serio_opacket[map->didx] & HIL_PKT_CMD))
750 return -EIO;
751 switch (mlc->serio_opacket[map->didx] & HIL_PKT_DATA_MASK) {
752 case HIL_CMD_IDD:
753 idx = mlc->di[map->didx].idd;
754 goto emu;
755 case HIL_CMD_RSC:
756 idx = mlc->di[map->didx].rsc;
757 goto emu;
758 case HIL_CMD_EXD:
759 idx = mlc->di[map->didx].exd;
760 goto emu;
761 case HIL_CMD_RNM:
762 idx = mlc->di[map->didx].rnm;
763 goto emu;
764 default:
765 break;
766 }
767 mlc->serio_oidx[map->didx] = 0;
768 mlc->serio_opacket[map->didx] = 0;
769 }
770
771 mlc->serio_oidx[map->didx]++;
772 return -EIO;
773 emu:
774 drv = serio->drv;
775 if (drv == NULL) {
776 BUG();
777 return -EIO;
778 }
779 last = idx + 15;
780 while ((last != idx) && (*last == 0)) last--;
781
782 while (idx != last) {
783 drv->interrupt(serio, 0, 0, NULL);
784 drv->interrupt(serio, HIL_ERR_INT >> 16, 0, NULL);
785 drv->interrupt(serio, 0, 0, NULL);
786 drv->interrupt(serio, *idx, 0, NULL);
787 idx++;
788 }
789 drv->interrupt(serio, 0, 0, NULL);
790 drv->interrupt(serio, HIL_ERR_INT >> 16, 0, NULL);
791 drv->interrupt(serio, HIL_PKT_CMD >> 8, 0, NULL);
792 drv->interrupt(serio, *idx, 0, NULL);
793
794 mlc->serio_oidx[map->didx] = 0;
795 mlc->serio_opacket[map->didx] = 0;
796
797 return 0;
798}
799
800static int hil_mlc_serio_open(struct serio *serio) {
801 struct hil_mlc_serio_map *map;
802 struct hil_mlc *mlc;
803
804 if (serio->private != NULL) return -EBUSY;
805
806 map = serio->port_data;
807 if (map == NULL) {
808 BUG();
809 return -ENODEV;
810 }
811 mlc = map->mlc;
812 if (mlc == NULL) {
813 BUG();
814 return -ENODEV;
815 }
816
817 return 0;
818}
819
820static void hil_mlc_serio_close(struct serio *serio) {
821 struct hil_mlc_serio_map *map;
822 struct hil_mlc *mlc;
823
824 map = serio->port_data;
825 if (map == NULL) {
826 BUG();
827 return;
828 }
829 mlc = map->mlc;
830 if (mlc == NULL) {
831 BUG();
832 return;
833 }
834
835 serio->private = NULL;
836 serio->drv = NULL;
837 /* TODO wake up interruptable */
838}
839
840int hil_mlc_register(hil_mlc *mlc) {
841 int i;
842 unsigned long flags;
843
844 if (mlc == NULL) {
845 return -EINVAL;
846 }
847
848 mlc->istarted = 0;
849 mlc->ostarted = 0;
850
851 rwlock_init(&mlc->lock);
852 init_MUTEX(&(mlc->osem));
853
854 init_MUTEX(&(mlc->isem));
855 mlc->icount = -1;
856 mlc->imatch = 0;
857
858 mlc->opercnt = 0;
859
860 init_MUTEX_LOCKED(&(mlc->csem));
861
862 hil_mlc_clear_di_scratch(mlc);
863 hil_mlc_clear_di_map(mlc, 0);
864 for (i = 0; i < HIL_MLC_DEVMEM; i++) {
865 struct serio *mlc_serio;
866 hil_mlc_copy_di_scratch(mlc, i);
867 mlc_serio = kmalloc(sizeof(*mlc_serio), GFP_KERNEL);
868 mlc->serio[i] = mlc_serio;
869 memset(mlc_serio, 0, sizeof(*mlc_serio));
870 mlc_serio->type = SERIO_HIL | SERIO_HIL_MLC;
871 mlc_serio->write = hil_mlc_serio_write;
872 mlc_serio->open = hil_mlc_serio_open;
873 mlc_serio->close = hil_mlc_serio_close;
874 mlc_serio->port_data = &(mlc->serio_map[i]);
875 mlc->serio_map[i].mlc = mlc;
876 mlc->serio_map[i].didx = i;
877 mlc->serio_map[i].di_revmap = -1;
878 mlc->serio_opacket[i] = 0;
879 mlc->serio_oidx[i] = 0;
880 serio_register_port(mlc_serio);
881 }
882
883 mlc->tasklet = &hil_mlcs_tasklet;
884
885 write_lock_irqsave(&hil_mlcs_lock, flags);
886 list_add_tail(&mlc->list, &hil_mlcs);
887 mlc->seidx = HILSEN_START;
888 write_unlock_irqrestore(&hil_mlcs_lock, flags);
889
890 tasklet_schedule(&hil_mlcs_tasklet);
891 return 0;
892}
893
894int hil_mlc_unregister(hil_mlc *mlc) {
895 struct list_head *tmp;
896 unsigned long flags;
897 int i;
898
899 if (mlc == NULL)
900 return -EINVAL;
901
902 write_lock_irqsave(&hil_mlcs_lock, flags);
903 list_for_each(tmp, &hil_mlcs) {
904 if (list_entry(tmp, hil_mlc, list) == mlc)
905 goto found;
906 }
907
908 /* not found in list */
909 write_unlock_irqrestore(&hil_mlcs_lock, flags);
910 tasklet_schedule(&hil_mlcs_tasklet);
911 return -ENODEV;
912
913 found:
914 list_del(tmp);
915 write_unlock_irqrestore(&hil_mlcs_lock, flags);
916
917 for (i = 0; i < HIL_MLC_DEVMEM; i++) {
918 serio_unregister_port(mlc->serio[i]);
919 mlc->serio[i] = NULL;
920 }
921
922 tasklet_schedule(&hil_mlcs_tasklet);
923 return 0;
924}
925
926/**************************** Module interface *************************/
927
928static int __init hil_mlc_init(void)
929{
930 init_timer(&hil_mlcs_kicker);
931 hil_mlcs_kicker.expires = jiffies + HZ;
932 hil_mlcs_kicker.function = &hil_mlcs_timer;
933 add_timer(&hil_mlcs_kicker);
934
935 tasklet_enable(&hil_mlcs_tasklet);
936
937 return 0;
938}
939
940static void __exit hil_mlc_exit(void)
941{
942 del_timer(&hil_mlcs_kicker);
943
944 tasklet_disable(&hil_mlcs_tasklet);
945 tasklet_kill(&hil_mlcs_tasklet);
946}
947
948module_init(hil_mlc_init);
949module_exit(hil_mlc_exit);
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
new file mode 100644
index 000000000000..7629452dd64b
--- /dev/null
+++ b/drivers/input/serio/hp_sdc.c
@@ -0,0 +1,1054 @@
1/*
2 * HP i8042-based System Device Controller driver.
3 *
4 * Copyright (c) 2001 Brian S. Julin
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * Alternatively, this software may be distributed under the terms of the
17 * GNU General Public License ("GPL").
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 *
29 * References:
30 * System Device Controller Microprocessor Firmware Theory of Operation
31 * for Part Number 1820-4784 Revision B. Dwg No. A-1820-4784-2
32 * Helge Deller's original hilkbd.c port for PA-RISC.
33 *
34 *
35 * Driver theory of operation:
36 *
37 * hp_sdc_put does all writing to the SDC. ISR can run on a different
38 * CPU than hp_sdc_put, but only one CPU runs hp_sdc_put at a time
39 * (it cannot really benefit from SMP anyway.) A tasket fit this perfectly.
40 *
41 * All data coming back from the SDC is sent via interrupt and can be read
42 * fully in the ISR, so there are no latency/throughput problems there.
43 * The problem is with output, due to the slow clock speed of the SDC
44 * compared to the CPU. This should not be too horrible most of the time,
45 * but if used with HIL devices that support the multibyte transfer command,
46 * keeping outbound throughput flowing at the 6500KBps that the HIL is
47 * capable of is more than can be done at HZ=100.
48 *
49 * Busy polling for IBF clear wastes CPU cycles and bus cycles. hp_sdc.ibf
50 * is set to 0 when the IBF flag in the status register has cleared. ISR
51 * may do this, and may also access the parts of queued transactions related
52 * to reading data back from the SDC, but otherwise will not touch the
53 * hp_sdc state. Whenever a register is written hp_sdc.ibf is set to 1.
54 *
55 * The i8042 write index and the values in the 4-byte input buffer
56 * starting at 0x70 are kept track of in hp_sdc.wi, and .r7[], respectively,
57 * to minimize the amount of IO needed to the SDC. However these values
58 * do not need to be locked since they are only ever accessed by hp_sdc_put.
59 *
60 * A timer task schedules the tasklet once per second just to make
61 * sure it doesn't freeze up and to allow for bad reads to time out.
62 */
63
64#include <linux/hp_sdc.h>
65#include <linux/sched.h>
66#include <linux/errno.h>
67#include <linux/init.h>
68#include <linux/module.h>
69#include <linux/ioport.h>
70#include <linux/time.h>
71#include <linux/slab.h>
72#include <linux/hil.h>
73#include <asm/io.h>
74#include <asm/system.h>
75
76/* Machine-specific abstraction */
77
78#if defined(__hppa__)
79# include <asm/parisc-device.h>
80# define sdc_readb(p) gsc_readb(p)
81# define sdc_writeb(v,p) gsc_writeb((v),(p))
82#elif defined(__mc68000__)
83# include <asm/uaccess.h>
84# define sdc_readb(p) in_8(p)
85# define sdc_writeb(v,p) out_8((p),(v))
86#else
87# error "HIL is not supported on this platform"
88#endif
89
90#define PREFIX "HP SDC: "
91
92MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
93MODULE_DESCRIPTION("HP i8042-based SDC Driver");
94MODULE_LICENSE("Dual BSD/GPL");
95
96EXPORT_SYMBOL(hp_sdc_request_timer_irq);
97EXPORT_SYMBOL(hp_sdc_request_hil_irq);
98EXPORT_SYMBOL(hp_sdc_request_cooked_irq);
99
100EXPORT_SYMBOL(hp_sdc_release_timer_irq);
101EXPORT_SYMBOL(hp_sdc_release_hil_irq);
102EXPORT_SYMBOL(hp_sdc_release_cooked_irq);
103
104EXPORT_SYMBOL(hp_sdc_enqueue_transaction);
105EXPORT_SYMBOL(hp_sdc_dequeue_transaction);
106
107static hp_i8042_sdc hp_sdc; /* All driver state is kept in here. */
108
109/*************** primitives for use in any context *********************/
110static inline uint8_t hp_sdc_status_in8 (void) {
111 uint8_t status;
112 unsigned long flags;
113
114 write_lock_irqsave(&hp_sdc.ibf_lock, flags);
115 status = sdc_readb(hp_sdc.status_io);
116 if (!(status & HP_SDC_STATUS_IBF)) hp_sdc.ibf = 0;
117 write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
118
119 return status;
120}
121
122static inline uint8_t hp_sdc_data_in8 (void) {
123 return sdc_readb(hp_sdc.data_io);
124}
125
126static inline void hp_sdc_status_out8 (uint8_t val) {
127 unsigned long flags;
128
129 write_lock_irqsave(&hp_sdc.ibf_lock, flags);
130 hp_sdc.ibf = 1;
131 if ((val & 0xf0) == 0xe0) hp_sdc.wi = 0xff;
132 sdc_writeb(val, hp_sdc.status_io);
133 write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
134}
135
136static inline void hp_sdc_data_out8 (uint8_t val) {
137 unsigned long flags;
138
139 write_lock_irqsave(&hp_sdc.ibf_lock, flags);
140 hp_sdc.ibf = 1;
141 sdc_writeb(val, hp_sdc.data_io);
142 write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
143}
144
145/* Care must be taken to only invoke hp_sdc_spin_ibf when
146 * absolutely needed, or in rarely invoked subroutines.
147 * Not only does it waste CPU cycles, it also wastes bus cycles.
148 */
149static inline void hp_sdc_spin_ibf(void) {
150 unsigned long flags;
151 rwlock_t *lock;
152
153 lock = &hp_sdc.ibf_lock;
154
155 read_lock_irqsave(lock, flags);
156 if (!hp_sdc.ibf) {
157 read_unlock_irqrestore(lock, flags);
158 return;
159 }
160 read_unlock(lock);
161 write_lock(lock);
162 while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF) {};
163 hp_sdc.ibf = 0;
164 write_unlock_irqrestore(lock, flags);
165}
166
167
168/************************ Interrupt context functions ************************/
169static void hp_sdc_take (int irq, void *dev_id, uint8_t status, uint8_t data) {
170 hp_sdc_transaction *curr;
171
172 read_lock(&hp_sdc.rtq_lock);
173 if (hp_sdc.rcurr < 0) {
174 read_unlock(&hp_sdc.rtq_lock);
175 return;
176 }
177 curr = hp_sdc.tq[hp_sdc.rcurr];
178 read_unlock(&hp_sdc.rtq_lock);
179
180 curr->seq[curr->idx++] = status;
181 curr->seq[curr->idx++] = data;
182 hp_sdc.rqty -= 2;
183 do_gettimeofday(&hp_sdc.rtv);
184
185 if (hp_sdc.rqty <= 0) {
186 /* All data has been gathered. */
187 if(curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE) {
188 if (curr->act.semaphore) up(curr->act.semaphore);
189 }
190 if(curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK) {
191 if (curr->act.irqhook)
192 curr->act.irqhook(irq, dev_id, status, data);
193 }
194 curr->actidx = curr->idx;
195 curr->idx++;
196 /* Return control of this transaction */
197 write_lock(&hp_sdc.rtq_lock);
198 hp_sdc.rcurr = -1;
199 hp_sdc.rqty = 0;
200 write_unlock(&hp_sdc.rtq_lock);
201 tasklet_schedule(&hp_sdc.task);
202 }
203}
204
205static irqreturn_t hp_sdc_isr(int irq, void *dev_id, struct pt_regs * regs) {
206 uint8_t status, data;
207
208 status = hp_sdc_status_in8();
209 /* Read data unconditionally to advance i8042. */
210 data = hp_sdc_data_in8();
211
212 /* For now we are ignoring these until we get the SDC to behave. */
213 if (((status & 0xf1) == 0x51) && data == 0x82) {
214 return IRQ_HANDLED;
215 }
216
217 switch(status & HP_SDC_STATUS_IRQMASK) {
218 case 0: /* This case is not documented. */
219 break;
220 case HP_SDC_STATUS_USERTIMER:
221 case HP_SDC_STATUS_PERIODIC:
222 case HP_SDC_STATUS_TIMER:
223 read_lock(&hp_sdc.hook_lock);
224 if (hp_sdc.timer != NULL)
225 hp_sdc.timer(irq, dev_id, status, data);
226 read_unlock(&hp_sdc.hook_lock);
227 break;
228 case HP_SDC_STATUS_REG:
229 hp_sdc_take(irq, dev_id, status, data);
230 break;
231 case HP_SDC_STATUS_HILCMD:
232 case HP_SDC_STATUS_HILDATA:
233 read_lock(&hp_sdc.hook_lock);
234 if (hp_sdc.hil != NULL)
235 hp_sdc.hil(irq, dev_id, status, data);
236 read_unlock(&hp_sdc.hook_lock);
237 break;
238 case HP_SDC_STATUS_PUP:
239 read_lock(&hp_sdc.hook_lock);
240 if (hp_sdc.pup != NULL)
241 hp_sdc.pup(irq, dev_id, status, data);
242 else printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n");
243 read_unlock(&hp_sdc.hook_lock);
244 break;
245 default:
246 read_lock(&hp_sdc.hook_lock);
247 if (hp_sdc.cooked != NULL)
248 hp_sdc.cooked(irq, dev_id, status, data);
249 read_unlock(&hp_sdc.hook_lock);
250 break;
251 }
252 return IRQ_HANDLED;
253}
254
255
256static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id, struct pt_regs * regs) {
257 int status;
258
259 status = hp_sdc_status_in8();
260 printk(KERN_WARNING PREFIX "NMI !\n");
261
262#if 0
263 if (status & HP_SDC_NMISTATUS_FHS) {
264 read_lock(&hp_sdc.hook_lock);
265 if (hp_sdc.timer != NULL)
266 hp_sdc.timer(irq, dev_id, status, 0);
267 read_unlock(&hp_sdc.hook_lock);
268 }
269 else {
270 /* TODO: pass this on to the HIL handler, or do SAK here? */
271 printk(KERN_WARNING PREFIX "HIL NMI\n");
272 }
273#endif
274 return IRQ_HANDLED;
275}
276
277
278/***************** Kernel (tasklet) context functions ****************/
279
280unsigned long hp_sdc_put(void);
281
282static void hp_sdc_tasklet(unsigned long foo) {
283
284 write_lock_irq(&hp_sdc.rtq_lock);
285 if (hp_sdc.rcurr >= 0) {
286 struct timeval tv;
287 do_gettimeofday(&tv);
288 if (tv.tv_sec > hp_sdc.rtv.tv_sec) tv.tv_usec += 1000000;
289 if (tv.tv_usec - hp_sdc.rtv.tv_usec > HP_SDC_MAX_REG_DELAY) {
290 hp_sdc_transaction *curr;
291 uint8_t tmp;
292
293 curr = hp_sdc.tq[hp_sdc.rcurr];
294 /* If this turns out to be a normal failure mode
295 * we'll need to figure out a way to communicate
296 * it back to the application. and be less verbose.
297 */
298 printk(KERN_WARNING PREFIX "read timeout (%ius)!\n",
299 tv.tv_usec - hp_sdc.rtv.tv_usec);
300 curr->idx += hp_sdc.rqty;
301 hp_sdc.rqty = 0;
302 tmp = curr->seq[curr->actidx];
303 curr->seq[curr->actidx] |= HP_SDC_ACT_DEAD;
304 if(tmp & HP_SDC_ACT_SEMAPHORE) {
305 if (curr->act.semaphore)
306 up(curr->act.semaphore);
307 }
308 if(tmp & HP_SDC_ACT_CALLBACK) {
309 /* Note this means that irqhooks may be called
310 * in tasklet/bh context.
311 */
312 if (curr->act.irqhook)
313 curr->act.irqhook(0, 0, 0, 0);
314 }
315 curr->actidx = curr->idx;
316 curr->idx++;
317 hp_sdc.rcurr = -1;
318 }
319 }
320 write_unlock_irq(&hp_sdc.rtq_lock);
321 hp_sdc_put();
322}
323
324unsigned long hp_sdc_put(void) {
325 hp_sdc_transaction *curr;
326 uint8_t act;
327 int idx, curridx;
328
329 int limit = 0;
330
331 write_lock(&hp_sdc.lock);
332
333 /* If i8042 buffers are full, we cannot do anything that
334 requires output, so we skip to the administrativa. */
335 if (hp_sdc.ibf) {
336 hp_sdc_status_in8();
337 if (hp_sdc.ibf) goto finish;
338 }
339
340 anew:
341 /* See if we are in the middle of a sequence. */
342 if (hp_sdc.wcurr < 0) hp_sdc.wcurr = 0;
343 read_lock_irq(&hp_sdc.rtq_lock);
344 if (hp_sdc.rcurr == hp_sdc.wcurr) hp_sdc.wcurr++;
345 read_unlock_irq(&hp_sdc.rtq_lock);
346 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
347 curridx = hp_sdc.wcurr;
348
349 if (hp_sdc.tq[curridx] != NULL) goto start;
350
351 while (++curridx != hp_sdc.wcurr) {
352 if (curridx >= HP_SDC_QUEUE_LEN) {
353 curridx = -1; /* Wrap to top */
354 continue;
355 }
356 read_lock_irq(&hp_sdc.rtq_lock);
357 if (hp_sdc.rcurr == curridx) {
358 read_unlock_irq(&hp_sdc.rtq_lock);
359 continue;
360 }
361 read_unlock_irq(&hp_sdc.rtq_lock);
362 if (hp_sdc.tq[curridx] != NULL) break; /* Found one. */
363 }
364 if (curridx == hp_sdc.wcurr) { /* There's nothing queued to do. */
365 curridx = -1;
366 }
367 hp_sdc.wcurr = curridx;
368
369 start:
370
371 /* Check to see if the interrupt mask needs to be set. */
372 if (hp_sdc.set_im) {
373 hp_sdc_status_out8(hp_sdc.im | HP_SDC_CMD_SET_IM);
374 hp_sdc.set_im = 0;
375 goto finish;
376 }
377
378 if (hp_sdc.wcurr == -1) goto done;
379
380 curr = hp_sdc.tq[curridx];
381 idx = curr->actidx;
382
383 if (curr->actidx >= curr->endidx) {
384 hp_sdc.tq[curridx] = NULL;
385 /* Interleave outbound data between the transactions. */
386 hp_sdc.wcurr++;
387 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
388 goto finish;
389 }
390
391 act = curr->seq[idx];
392 idx++;
393
394 if (curr->idx >= curr->endidx) {
395 if (act & HP_SDC_ACT_DEALLOC) kfree(curr);
396 hp_sdc.tq[curridx] = NULL;
397 /* Interleave outbound data between the transactions. */
398 hp_sdc.wcurr++;
399 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
400 goto finish;
401 }
402
403 while (act & HP_SDC_ACT_PRECMD) {
404 if (curr->idx != idx) {
405 idx++;
406 act &= ~HP_SDC_ACT_PRECMD;
407 break;
408 }
409 hp_sdc_status_out8(curr->seq[idx]);
410 curr->idx++;
411 /* act finished? */
412 if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_PRECMD)
413 goto actdone;
414 /* skip quantity field if data-out sequence follows. */
415 if (act & HP_SDC_ACT_DATAOUT) curr->idx++;
416 goto finish;
417 }
418 if (act & HP_SDC_ACT_DATAOUT) {
419 int qty;
420
421 qty = curr->seq[idx];
422 idx++;
423 if (curr->idx - idx < qty) {
424 hp_sdc_data_out8(curr->seq[curr->idx]);
425 curr->idx++;
426 /* act finished? */
427 if ((curr->idx - idx >= qty) &&
428 ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT))
429 goto actdone;
430 goto finish;
431 }
432 idx += qty;
433 act &= ~HP_SDC_ACT_DATAOUT;
434 }
435 else while (act & HP_SDC_ACT_DATAREG) {
436 int mask;
437 uint8_t w7[4];
438
439 mask = curr->seq[idx];
440 if (idx != curr->idx) {
441 idx++;
442 idx += !!(mask & 1);
443 idx += !!(mask & 2);
444 idx += !!(mask & 4);
445 idx += !!(mask & 8);
446 act &= ~HP_SDC_ACT_DATAREG;
447 break;
448 }
449
450 w7[0] = (mask & 1) ? curr->seq[++idx] : hp_sdc.r7[0];
451 w7[1] = (mask & 2) ? curr->seq[++idx] : hp_sdc.r7[1];
452 w7[2] = (mask & 4) ? curr->seq[++idx] : hp_sdc.r7[2];
453 w7[3] = (mask & 8) ? curr->seq[++idx] : hp_sdc.r7[3];
454
455 if (hp_sdc.wi > 0x73 || hp_sdc.wi < 0x70 ||
456 w7[hp_sdc.wi-0x70] == hp_sdc.r7[hp_sdc.wi-0x70]) {
457 int i = 0;
458
459 /* Need to point the write index register */
460 while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++;
461 if (i < 4) {
462 hp_sdc_status_out8(HP_SDC_CMD_SET_D0 + i);
463 hp_sdc.wi = 0x70 + i;
464 goto finish;
465 }
466 idx++;
467 if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAREG)
468 goto actdone;
469 curr->idx = idx;
470 act &= ~HP_SDC_ACT_DATAREG;
471 break;
472 }
473
474 hp_sdc_data_out8(w7[hp_sdc.wi - 0x70]);
475 hp_sdc.r7[hp_sdc.wi - 0x70] = w7[hp_sdc.wi - 0x70];
476 hp_sdc.wi++; /* write index register autoincrements */
477 {
478 int i = 0;
479
480 while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++;
481 if (i >= 4) {
482 curr->idx = idx + 1;
483 if ((act & HP_SDC_ACT_DURING) ==
484 HP_SDC_ACT_DATAREG)
485 goto actdone;
486 }
487 }
488 goto finish;
489 }
490 /* We don't go any further in the command if there is a pending read,
491 because we don't want interleaved results. */
492 read_lock_irq(&hp_sdc.rtq_lock);
493 if (hp_sdc.rcurr >= 0) {
494 read_unlock_irq(&hp_sdc.rtq_lock);
495 goto finish;
496 }
497 read_unlock_irq(&hp_sdc.rtq_lock);
498
499
500 if (act & HP_SDC_ACT_POSTCMD) {
501 uint8_t postcmd;
502
503 /* curr->idx should == idx at this point. */
504 postcmd = curr->seq[idx];
505 curr->idx++;
506 if (act & HP_SDC_ACT_DATAIN) {
507
508 /* Start a new read */
509 hp_sdc.rqty = curr->seq[curr->idx];
510 do_gettimeofday(&hp_sdc.rtv);
511 curr->idx++;
512 /* Still need to lock here in case of spurious irq. */
513 write_lock_irq(&hp_sdc.rtq_lock);
514 hp_sdc.rcurr = curridx;
515 write_unlock_irq(&hp_sdc.rtq_lock);
516 hp_sdc_status_out8(postcmd);
517 goto finish;
518 }
519 hp_sdc_status_out8(postcmd);
520 goto actdone;
521 }
522
523actdone:
524 if (act & HP_SDC_ACT_SEMAPHORE) {
525 up(curr->act.semaphore);
526 }
527 else if (act & HP_SDC_ACT_CALLBACK) {
528 curr->act.irqhook(0,0,0,0);
529 }
530 if (curr->idx >= curr->endidx) { /* This transaction is over. */
531 if (act & HP_SDC_ACT_DEALLOC) kfree(curr);
532 hp_sdc.tq[curridx] = NULL;
533 }
534 else {
535 curr->actidx = idx + 1;
536 curr->idx = idx + 2;
537 }
538 /* Interleave outbound data between the transactions. */
539 hp_sdc.wcurr++;
540 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
541
542 finish:
543 /* If by some quirk IBF has cleared and our ISR has run to
544 see that that has happened, do it all again. */
545 if (!hp_sdc.ibf && limit++ < 20) goto anew;
546
547 done:
548 if (hp_sdc.wcurr >= 0) tasklet_schedule(&hp_sdc.task);
549 write_unlock(&hp_sdc.lock);
550 return 0;
551}
552
553/******* Functions called in either user or kernel context ****/
554int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) {
555 unsigned long flags;
556 int i;
557
558 if (this == NULL) {
559 tasklet_schedule(&hp_sdc.task);
560 return -EINVAL;
561 };
562
563 write_lock_irqsave(&hp_sdc.lock, flags);
564
565 /* Can't have same transaction on queue twice */
566 for (i=0; i < HP_SDC_QUEUE_LEN; i++)
567 if (hp_sdc.tq[i] == this) goto fail;
568
569 this->actidx = 0;
570 this->idx = 1;
571
572 /* Search for empty slot */
573 for (i=0; i < HP_SDC_QUEUE_LEN; i++) {
574 if (hp_sdc.tq[i] == NULL) {
575 hp_sdc.tq[i] = this;
576 write_unlock_irqrestore(&hp_sdc.lock, flags);
577 tasklet_schedule(&hp_sdc.task);
578 return 0;
579 }
580 }
581 write_unlock_irqrestore(&hp_sdc.lock, flags);
582 printk(KERN_WARNING PREFIX "No free slot to add transaction.\n");
583 return -EBUSY;
584
585 fail:
586 write_unlock_irqrestore(&hp_sdc.lock,flags);
587 printk(KERN_WARNING PREFIX "Transaction add failed: transaction already queued?\n");
588 return -EINVAL;
589}
590
591int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) {
592 unsigned long flags;
593 int i;
594
595 write_lock_irqsave(&hp_sdc.lock, flags);
596
597 /* TODO: don't remove it if it's not done. */
598
599 for (i=0; i < HP_SDC_QUEUE_LEN; i++)
600 if (hp_sdc.tq[i] == this) hp_sdc.tq[i] = NULL;
601
602 write_unlock_irqrestore(&hp_sdc.lock, flags);
603 return 0;
604}
605
606
607
608/********************** User context functions **************************/
609int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback) {
610
611 if (callback == NULL || hp_sdc.dev == NULL) {
612 return -EINVAL;
613 }
614 write_lock_irq(&hp_sdc.hook_lock);
615 if (hp_sdc.timer != NULL) {
616 write_unlock_irq(&hp_sdc.hook_lock);
617 return -EBUSY;
618 }
619
620 hp_sdc.timer = callback;
621 /* Enable interrupts from the timers */
622 hp_sdc.im &= ~HP_SDC_IM_FH;
623 hp_sdc.im &= ~HP_SDC_IM_PT;
624 hp_sdc.im &= ~HP_SDC_IM_TIMERS;
625 hp_sdc.set_im = 1;
626 write_unlock_irq(&hp_sdc.hook_lock);
627
628 tasklet_schedule(&hp_sdc.task);
629
630 return 0;
631}
632
633int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback) {
634
635 if (callback == NULL || hp_sdc.dev == NULL) {
636 return -EINVAL;
637 }
638 write_lock_irq(&hp_sdc.hook_lock);
639 if (hp_sdc.hil != NULL) {
640 write_unlock_irq(&hp_sdc.hook_lock);
641 return -EBUSY;
642 }
643
644 hp_sdc.hil = callback;
645 hp_sdc.im &= ~(HP_SDC_IM_HIL | HP_SDC_IM_RESET);
646 hp_sdc.set_im = 1;
647 write_unlock_irq(&hp_sdc.hook_lock);
648
649 tasklet_schedule(&hp_sdc.task);
650
651 return 0;
652}
653
654int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback) {
655
656 if (callback == NULL || hp_sdc.dev == NULL) {
657 return -EINVAL;
658 }
659 write_lock_irq(&hp_sdc.hook_lock);
660 if (hp_sdc.cooked != NULL) {
661 write_unlock_irq(&hp_sdc.hook_lock);
662 return -EBUSY;
663 }
664
665 /* Enable interrupts from the HIL MLC */
666 hp_sdc.cooked = callback;
667 hp_sdc.im &= ~(HP_SDC_IM_HIL | HP_SDC_IM_RESET);
668 hp_sdc.set_im = 1;
669 write_unlock_irq(&hp_sdc.hook_lock);
670
671 tasklet_schedule(&hp_sdc.task);
672
673 return 0;
674}
675
676int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback) {
677
678
679 write_lock_irq(&hp_sdc.hook_lock);
680 if ((callback != hp_sdc.timer) ||
681 (hp_sdc.timer == NULL)) {
682 write_unlock_irq(&hp_sdc.hook_lock);
683 return -EINVAL;
684 }
685
686 /* Disable interrupts from the timers */
687 hp_sdc.timer = NULL;
688 hp_sdc.im |= HP_SDC_IM_TIMERS;
689 hp_sdc.im |= HP_SDC_IM_FH;
690 hp_sdc.im |= HP_SDC_IM_PT;
691 hp_sdc.set_im = 1;
692 write_unlock_irq(&hp_sdc.hook_lock);
693 tasklet_schedule(&hp_sdc.task);
694
695 return 0;
696}
697
698int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback) {
699
700 write_lock_irq(&hp_sdc.hook_lock);
701 if ((callback != hp_sdc.hil) ||
702 (hp_sdc.hil == NULL)) {
703 write_unlock_irq(&hp_sdc.hook_lock);
704 return -EINVAL;
705 }
706
707 hp_sdc.hil = NULL;
708 /* Disable interrupts from HIL only if there is no cooked driver. */
709 if(hp_sdc.cooked == NULL) {
710 hp_sdc.im |= (HP_SDC_IM_HIL | HP_SDC_IM_RESET);
711 hp_sdc.set_im = 1;
712 }
713 write_unlock_irq(&hp_sdc.hook_lock);
714 tasklet_schedule(&hp_sdc.task);
715
716 return 0;
717}
718
719int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) {
720
721 write_lock_irq(&hp_sdc.hook_lock);
722 if ((callback != hp_sdc.cooked) ||
723 (hp_sdc.cooked == NULL)) {
724 write_unlock_irq(&hp_sdc.hook_lock);
725 return -EINVAL;
726 }
727
728 hp_sdc.cooked = NULL;
729 /* Disable interrupts from HIL only if there is no raw HIL driver. */
730 if(hp_sdc.hil == NULL) {
731 hp_sdc.im |= (HP_SDC_IM_HIL | HP_SDC_IM_RESET);
732 hp_sdc.set_im = 1;
733 }
734 write_unlock_irq(&hp_sdc.hook_lock);
735 tasklet_schedule(&hp_sdc.task);
736
737 return 0;
738}
739
740/************************* Keepalive timer task *********************/
741
742void hp_sdc_kicker (unsigned long data) {
743 tasklet_schedule(&hp_sdc.task);
744 /* Re-insert the periodic task. */
745 mod_timer(&hp_sdc.kicker, jiffies + HZ);
746}
747
748/************************** Module Initialization ***************************/
749
750#if defined(__hppa__)
751
752static struct parisc_device_id hp_sdc_tbl[] = {
753 {
754 .hw_type = HPHW_FIO,
755 .hversion_rev = HVERSION_REV_ANY_ID,
756 .hversion = HVERSION_ANY_ID,
757 .sversion = 0x73,
758 },
759 { 0, }
760};
761
762MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl);
763
764static int __init hp_sdc_init_hppa(struct parisc_device *d);
765
766static struct parisc_driver hp_sdc_driver = {
767 .name = "HP SDC",
768 .id_table = hp_sdc_tbl,
769 .probe = hp_sdc_init_hppa,
770};
771
772#endif /* __hppa__ */
773
774static int __init hp_sdc_init(void)
775{
776 int i;
777 char *errstr;
778 hp_sdc_transaction t_sync;
779 uint8_t ts_sync[6];
780 struct semaphore s_sync;
781
782 rwlock_init(&hp_sdc.lock);
783 rwlock_init(&hp_sdc.ibf_lock);
784 rwlock_init(&hp_sdc.rtq_lock);
785 rwlock_init(&hp_sdc.hook_lock);
786
787 hp_sdc.timer = NULL;
788 hp_sdc.hil = NULL;
789 hp_sdc.pup = NULL;
790 hp_sdc.cooked = NULL;
791 hp_sdc.im = HP_SDC_IM_MASK; /* Mask maskable irqs */
792 hp_sdc.set_im = 1;
793 hp_sdc.wi = 0xff;
794 hp_sdc.r7[0] = 0xff;
795 hp_sdc.r7[1] = 0xff;
796 hp_sdc.r7[2] = 0xff;
797 hp_sdc.r7[3] = 0xff;
798 hp_sdc.ibf = 1;
799
800 for (i = 0; i < HP_SDC_QUEUE_LEN; i++) hp_sdc.tq[i] = NULL;
801 hp_sdc.wcurr = -1;
802 hp_sdc.rcurr = -1;
803 hp_sdc.rqty = 0;
804
805 hp_sdc.dev_err = -ENODEV;
806
807 errstr = "IO not found for";
808 if (!hp_sdc.base_io) goto err0;
809
810 errstr = "IRQ not found for";
811 if (!hp_sdc.irq) goto err0;
812
813 hp_sdc.dev_err = -EBUSY;
814
815#if defined(__hppa__)
816 errstr = "IO not available for";
817 if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name)) goto err0;
818#endif
819
820 errstr = "IRQ not available for";
821 if(request_irq(hp_sdc.irq, &hp_sdc_isr, 0, "HP SDC",
822 (void *) hp_sdc.base_io)) goto err1;
823
824 errstr = "NMI not available for";
825 if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, 0, "HP SDC NMI",
826 (void *) hp_sdc.base_io)) goto err2;
827
828 printk(KERN_INFO PREFIX "HP SDC at 0x%p, IRQ %d (NMI IRQ %d)\n",
829 (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
830
831 hp_sdc_status_in8();
832 hp_sdc_data_in8();
833
834 tasklet_init(&hp_sdc.task, hp_sdc_tasklet, 0);
835
836 /* Sync the output buffer registers, thus scheduling hp_sdc_tasklet. */
837 t_sync.actidx = 0;
838 t_sync.idx = 1;
839 t_sync.endidx = 6;
840 t_sync.seq = ts_sync;
841 ts_sync[0] = HP_SDC_ACT_DATAREG | HP_SDC_ACT_SEMAPHORE;
842 ts_sync[1] = 0x0f;
843 ts_sync[2] = ts_sync[3] = ts_sync[4] = ts_sync[5] = 0;
844 t_sync.act.semaphore = &s_sync;
845 init_MUTEX_LOCKED(&s_sync);
846 hp_sdc_enqueue_transaction(&t_sync);
847 down(&s_sync); /* Wait for t_sync to complete */
848
849 /* Create the keepalive task */
850 init_timer(&hp_sdc.kicker);
851 hp_sdc.kicker.expires = jiffies + HZ;
852 hp_sdc.kicker.function = &hp_sdc_kicker;
853 add_timer(&hp_sdc.kicker);
854
855 hp_sdc.dev_err = 0;
856 return 0;
857 err2:
858 free_irq(hp_sdc.irq, NULL);
859 err1:
860 release_region(hp_sdc.data_io, 2);
861 err0:
862 printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n",
863 errstr, (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
864 hp_sdc.dev = NULL;
865 return hp_sdc.dev_err;
866}
867
868#if defined(__hppa__)
869
870static int __init hp_sdc_init_hppa(struct parisc_device *d)
871{
872 if (!d) return 1;
873 if (hp_sdc.dev != NULL) return 1; /* We only expect one SDC */
874
875 hp_sdc.dev = d;
876 hp_sdc.irq = d->irq;
877 hp_sdc.nmi = d->aux_irq;
878 hp_sdc.base_io = d->hpa;
879 hp_sdc.data_io = d->hpa + 0x800;
880 hp_sdc.status_io = d->hpa + 0x801;
881
882 return hp_sdc_init();
883}
884
885#endif /* __hppa__ */
886
887#if !defined(__mc68000__) /* Link error on m68k! */
888static void __exit hp_sdc_exit(void)
889#else
890static void hp_sdc_exit(void)
891#endif
892{
893 write_lock_irq(&hp_sdc.lock);
894
895 /* Turn off all maskable "sub-function" irq's. */
896 hp_sdc_spin_ibf();
897 sdc_writeb(HP_SDC_CMD_SET_IM | HP_SDC_IM_MASK, hp_sdc.status_io);
898
899 /* Wait until we know this has been processed by the i8042 */
900 hp_sdc_spin_ibf();
901
902 free_irq(hp_sdc.nmi, NULL);
903 free_irq(hp_sdc.irq, NULL);
904 write_unlock_irq(&hp_sdc.lock);
905
906 del_timer(&hp_sdc.kicker);
907
908 tasklet_kill(&hp_sdc.task);
909
910/* release_region(hp_sdc.data_io, 2); */
911
912#if defined(__hppa__)
913 if (unregister_parisc_driver(&hp_sdc_driver))
914 printk(KERN_WARNING PREFIX "Error unregistering HP SDC");
915#endif
916}
917
918static int __init hp_sdc_register(void)
919{
920 hp_sdc_transaction tq_init;
921 uint8_t tq_init_seq[5];
922 struct semaphore tq_init_sem;
923#if defined(__mc68000__)
924 mm_segment_t fs;
925 unsigned char i;
926#endif
927
928 hp_sdc.dev = NULL;
929 hp_sdc.dev_err = 0;
930#if defined(__hppa__)
931 if (register_parisc_driver(&hp_sdc_driver)) {
932 printk(KERN_WARNING PREFIX "Error registering SDC with system bus tree.\n");
933 return -ENODEV;
934 }
935#elif defined(__mc68000__)
936 if (!MACH_IS_HP300)
937 return -ENODEV;
938
939 hp_sdc.irq = 1;
940 hp_sdc.nmi = 7;
941 hp_sdc.base_io = (unsigned long) 0xf0428000;
942 hp_sdc.data_io = (unsigned long) hp_sdc.base_io + 1;
943 hp_sdc.status_io = (unsigned long) hp_sdc.base_io + 3;
944 fs = get_fs();
945 set_fs(KERNEL_DS);
946 if (!get_user(i, (unsigned char *)hp_sdc.data_io))
947 hp_sdc.dev = (void *)1;
948 set_fs(fs);
949 hp_sdc.dev_err = hp_sdc_init();
950#endif
951 if (hp_sdc.dev == NULL) {
952 printk(KERN_WARNING PREFIX "No SDC found.\n");
953 return hp_sdc.dev_err;
954 }
955
956 init_MUTEX_LOCKED(&tq_init_sem);
957
958 tq_init.actidx = 0;
959 tq_init.idx = 1;
960 tq_init.endidx = 5;
961 tq_init.seq = tq_init_seq;
962 tq_init.act.semaphore = &tq_init_sem;
963
964 tq_init_seq[0] =
965 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
966 tq_init_seq[1] = HP_SDC_CMD_READ_KCC;
967 tq_init_seq[2] = 1;
968 tq_init_seq[3] = 0;
969 tq_init_seq[4] = 0;
970
971 hp_sdc_enqueue_transaction(&tq_init);
972
973 down(&tq_init_sem);
974 up(&tq_init_sem);
975
976 if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) {
977 printk(KERN_WARNING PREFIX "Error reading config byte.\n");
978 hp_sdc_exit();
979 return -ENODEV;
980 }
981 hp_sdc.r11 = tq_init_seq[4];
982 if (hp_sdc.r11 & HP_SDC_CFG_NEW) {
983 char *str;
984 printk(KERN_INFO PREFIX "New style SDC\n");
985 tq_init_seq[1] = HP_SDC_CMD_READ_XTD;
986 tq_init.actidx = 0;
987 tq_init.idx = 1;
988 down(&tq_init_sem);
989 hp_sdc_enqueue_transaction(&tq_init);
990 down(&tq_init_sem);
991 up(&tq_init_sem);
992 if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) {
993 printk(KERN_WARNING PREFIX "Error reading extended config byte.\n");
994 return -ENODEV;
995 }
996 hp_sdc.r7e = tq_init_seq[4];
997 HP_SDC_XTD_REV_STRINGS(hp_sdc.r7e & HP_SDC_XTD_REV, str)
998 printk(KERN_INFO PREFIX "Revision: %s\n", str);
999 if (hp_sdc.r7e & HP_SDC_XTD_BEEPER) {
1000 printk(KERN_INFO PREFIX "TI SN76494 beeper present\n");
1001 }
1002 if (hp_sdc.r7e & HP_SDC_XTD_BBRTC) {
1003 printk(KERN_INFO PREFIX "OKI MSM-58321 BBRTC present\n");
1004 }
1005 printk(KERN_INFO PREFIX "Spunking the self test register to force PUP "
1006 "on next firmware reset.\n");
1007 tq_init_seq[0] = HP_SDC_ACT_PRECMD |
1008 HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE;
1009 tq_init_seq[1] = HP_SDC_CMD_SET_STR;
1010 tq_init_seq[2] = 1;
1011 tq_init_seq[3] = 0;
1012 tq_init.actidx = 0;
1013 tq_init.idx = 1;
1014 tq_init.endidx = 4;
1015 down(&tq_init_sem);
1016 hp_sdc_enqueue_transaction(&tq_init);
1017 down(&tq_init_sem);
1018 up(&tq_init_sem);
1019 }
1020 else {
1021 printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n",
1022 (hp_sdc.r11 & HP_SDC_CFG_REV) ? "3300" : "2564/3087");
1023 }
1024
1025 return 0;
1026}
1027
1028module_init(hp_sdc_register);
1029module_exit(hp_sdc_exit);
1030
1031/* Timing notes: These measurements taken on my 64MHz 7100-LC (715/64)
1032 * cycles cycles-adj time
1033 * between two consecutive mfctl(16)'s: 4 n/a 63ns
1034 * hp_sdc_spin_ibf when idle: 119 115 1.7us
1035 * gsc_writeb status register: 83 79 1.2us
1036 * IBF to clear after sending SET_IM: 6204 6006 93us
1037 * IBF to clear after sending LOAD_RT: 4467 4352 68us
1038 * IBF to clear after sending two LOAD_RTs: 18974 18859 295us
1039 * READ_T1, read status/data, IRQ, call handler: 35564 n/a 556us
1040 * cmd to ~IBF READ_T1 2nd time right after: 5158403 n/a 81ms
1041 * between IRQ received and ~IBF for above: 2578877 n/a 40ms
1042 *
1043 * Performance stats after a run of this module configuring HIL and
1044 * receiving a few mouse events:
1045 *
1046 * status in8 282508 cycles 7128 calls
1047 * status out8 8404 cycles 341 calls
1048 * data out8 1734 cycles 78 calls
1049 * isr 174324 cycles 617 calls (includes take)
1050 * take 1241 cycles 2 calls
1051 * put 1411504 cycles 6937 calls
1052 * task 1655209 cycles 6937 calls (includes put)
1053 *
1054 */
diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c
new file mode 100644
index 000000000000..e3c44ffae674
--- /dev/null
+++ b/drivers/input/serio/hp_sdc_mlc.c
@@ -0,0 +1,358 @@
1/*
2 * Access to HP-HIL MLC through HP System Device Controller.
3 *
4 * Copyright (c) 2001 Brian S. Julin
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * Alternatively, this software may be distributed under the terms of the
17 * GNU General Public License ("GPL").
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 *
29 * References:
30 * HP-HIL Technical Reference Manual. Hewlett Packard Product No. 45918A
31 * System Device Controller Microprocessor Firmware Theory of Operation
32 * for Part Number 1820-4784 Revision B. Dwg No. A-1820-4784-2
33 *
34 */
35
36#include <linux/hil_mlc.h>
37#include <linux/hp_sdc.h>
38#include <linux/errno.h>
39#include <linux/kernel.h>
40#include <linux/module.h>
41#include <linux/init.h>
42#include <linux/string.h>
43
44#define PREFIX "HP SDC MLC: "
45
46static hil_mlc hp_sdc_mlc;
47
48MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
49MODULE_DESCRIPTION("Glue for onboard HIL MLC in HP-PARISC machines");
50MODULE_LICENSE("Dual BSD/GPL");
51
52struct hp_sdc_mlc_priv_s {
53 int emtestmode;
54 hp_sdc_transaction trans;
55 u8 tseq[16];
56 int got5x;
57} hp_sdc_mlc_priv;
58
59/************************* Interrupt context ******************************/
60static void hp_sdc_mlc_isr (int irq, void *dev_id,
61 uint8_t status, uint8_t data) {
62 int idx;
63 hil_mlc *mlc = &hp_sdc_mlc;
64
65 write_lock(&(mlc->lock));
66 if (mlc->icount < 0) {
67 printk(KERN_WARNING PREFIX "HIL Overflow!\n");
68 up(&mlc->isem);
69 goto out;
70 }
71 idx = 15 - mlc->icount;
72 if ((status & HP_SDC_STATUS_IRQMASK) == HP_SDC_STATUS_HILDATA) {
73 mlc->ipacket[idx] |= data | HIL_ERR_INT;
74 mlc->icount--;
75 if (hp_sdc_mlc_priv.got5x) goto check;
76 if (!idx) goto check;
77 if ((mlc->ipacket[idx-1] & HIL_PKT_ADDR_MASK) !=
78 (mlc->ipacket[idx] & HIL_PKT_ADDR_MASK)) {
79 mlc->ipacket[idx] &= ~HIL_PKT_ADDR_MASK;
80 mlc->ipacket[idx] |= (mlc->ipacket[idx-1]
81 & HIL_PKT_ADDR_MASK);
82 }
83 goto check;
84 }
85 /* We know status is 5X */
86 if (data & HP_SDC_HIL_ISERR) goto err;
87 mlc->ipacket[idx] =
88 (data & HP_SDC_HIL_R1MASK) << HIL_PKT_ADDR_SHIFT;
89 hp_sdc_mlc_priv.got5x = 1;
90 goto out;
91
92 check:
93 hp_sdc_mlc_priv.got5x = 0;
94 if (mlc->imatch == 0) goto done;
95 if ((mlc->imatch == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL))
96 && (mlc->ipacket[idx] == (mlc->imatch | idx))) goto done;
97 if (mlc->ipacket[idx] == mlc->imatch) goto done;
98 goto out;
99
100 err:
101 printk(KERN_DEBUG PREFIX "err code %x\n", data);
102 switch (data) {
103 case HP_SDC_HIL_RC_DONE:
104 printk(KERN_WARNING PREFIX "Bastard SDC reconfigured loop!\n");
105 break;
106 case HP_SDC_HIL_ERR:
107 mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_PERR |
108 HIL_ERR_FERR | HIL_ERR_FOF;
109 break;
110 case HP_SDC_HIL_TO:
111 mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_LERR;
112 break;
113 case HP_SDC_HIL_RC:
114 printk(KERN_WARNING PREFIX "Bastard SDC decided to reconfigure loop!\n");
115 break;
116 default:
117 printk(KERN_WARNING PREFIX "Unkown HIL Error status (%x)!\n", data);
118 break;
119 }
120 /* No more data will be coming due to an error. */
121 done:
122 tasklet_schedule(mlc->tasklet);
123 up(&(mlc->isem));
124 out:
125 write_unlock(&(mlc->lock));
126}
127
128
129/******************** Tasklet or userspace context functions ****************/
130
131static int hp_sdc_mlc_in (hil_mlc *mlc, suseconds_t timeout) {
132 unsigned long flags;
133 struct hp_sdc_mlc_priv_s *priv;
134 int rc = 2;
135
136 priv = mlc->priv;
137
138 write_lock_irqsave(&(mlc->lock), flags);
139
140 /* Try to down the semaphore */
141 if (down_trylock(&(mlc->isem))) {
142 struct timeval tv;
143 if (priv->emtestmode) {
144 mlc->ipacket[0] =
145 HIL_ERR_INT | (mlc->opacket &
146 (HIL_PKT_CMD |
147 HIL_PKT_ADDR_MASK |
148 HIL_PKT_DATA_MASK));
149 mlc->icount = 14;
150 /* printk(KERN_DEBUG PREFIX ">[%x]\n", mlc->ipacket[0]); */
151 goto wasup;
152 }
153 do_gettimeofday(&tv);
154 tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec);
155 if (tv.tv_usec - mlc->instart.tv_usec > mlc->intimeout) {
156 /* printk("!%i %i",
157 tv.tv_usec - mlc->instart.tv_usec,
158 mlc->intimeout);
159 */
160 rc = 1;
161 up(&(mlc->isem));
162 }
163 goto done;
164 }
165 wasup:
166 up(&(mlc->isem));
167 rc = 0;
168 goto done;
169 done:
170 write_unlock_irqrestore(&(mlc->lock), flags);
171 return rc;
172}
173
174static int hp_sdc_mlc_cts (hil_mlc *mlc) {
175 struct hp_sdc_mlc_priv_s *priv;
176 unsigned long flags;
177
178 priv = mlc->priv;
179
180 write_lock_irqsave(&(mlc->lock), flags);
181
182 /* Try to down the semaphores -- they should be up. */
183 if (down_trylock(&(mlc->isem))) {
184 BUG();
185 goto busy;
186 }
187 if (down_trylock(&(mlc->osem))) {
188 BUG();
189 up(&(mlc->isem));
190 goto busy;
191 }
192 up(&(mlc->isem));
193 up(&(mlc->osem));
194
195 if (down_trylock(&(mlc->csem))) {
196 if (priv->trans.act.semaphore != &(mlc->csem)) goto poll;
197 goto busy;
198 }
199 if (!(priv->tseq[4] & HP_SDC_USE_LOOP)) goto done;
200
201 poll:
202 priv->trans.act.semaphore = &(mlc->csem);
203 priv->trans.actidx = 0;
204 priv->trans.idx = 1;
205 priv->trans.endidx = 5;
206 priv->tseq[0] =
207 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
208 priv->tseq[1] = HP_SDC_CMD_READ_USE;
209 priv->tseq[2] = 1;
210 priv->tseq[3] = 0;
211 priv->tseq[4] = 0;
212 hp_sdc_enqueue_transaction(&(priv->trans));
213 busy:
214 write_unlock_irqrestore(&(mlc->lock), flags);
215 return 1;
216 done:
217 priv->trans.act.semaphore = &(mlc->osem);
218 up(&(mlc->csem));
219 write_unlock_irqrestore(&(mlc->lock), flags);
220 return 0;
221}
222
223static void hp_sdc_mlc_out (hil_mlc *mlc) {
224 struct hp_sdc_mlc_priv_s *priv;
225 unsigned long flags;
226
227 priv = mlc->priv;
228
229 write_lock_irqsave(&(mlc->lock), flags);
230
231 /* Try to down the semaphore -- it should be up. */
232 if (down_trylock(&(mlc->osem))) {
233 BUG();
234 goto done;
235 }
236
237 if (mlc->opacket & HIL_DO_ALTER_CTRL) goto do_control;
238
239 do_data:
240 if (priv->emtestmode) {
241 up(&(mlc->osem));
242 goto done;
243 }
244 /* Shouldn't be sending commands when loop may be busy */
245 if (down_trylock(&(mlc->csem))) {
246 BUG();
247 goto done;
248 }
249 up(&(mlc->csem));
250
251 priv->trans.actidx = 0;
252 priv->trans.idx = 1;
253 priv->trans.act.semaphore = &(mlc->osem);
254 priv->trans.endidx = 6;
255 priv->tseq[0] =
256 HP_SDC_ACT_DATAREG | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_SEMAPHORE;
257 priv->tseq[1] = 0x7;
258 priv->tseq[2] =
259 (mlc->opacket &
260 (HIL_PKT_ADDR_MASK | HIL_PKT_CMD))
261 >> HIL_PKT_ADDR_SHIFT;
262 priv->tseq[3] =
263 (mlc->opacket & HIL_PKT_DATA_MASK)
264 >> HIL_PKT_DATA_SHIFT;
265 priv->tseq[4] = 0; /* No timeout */
266 if (priv->tseq[3] == HIL_CMD_DHR) priv->tseq[4] = 1;
267 priv->tseq[5] = HP_SDC_CMD_DO_HIL;
268 goto enqueue;
269
270 do_control:
271 priv->emtestmode = mlc->opacket & HIL_CTRL_TEST;
272 if ((mlc->opacket & (HIL_CTRL_APE | HIL_CTRL_IPF)) == HIL_CTRL_APE) {
273 BUG(); /* we cannot emulate this, it should not be used. */
274 }
275 if ((mlc->opacket & HIL_CTRL_ONLY) == HIL_CTRL_ONLY) goto control_only;
276 if (mlc->opacket & HIL_CTRL_APE) {
277 BUG(); /* Should not send command/data after engaging APE */
278 goto done;
279 }
280 /* Disengaging APE this way would not be valid either since
281 * the loop must be allowed to idle.
282 *
283 * So, it works out that we really never actually send control
284 * and data when using SDC, we just send the data.
285 */
286 goto do_data;
287
288 control_only:
289 priv->trans.actidx = 0;
290 priv->trans.idx = 1;
291 priv->trans.act.semaphore = &(mlc->osem);
292 priv->trans.endidx = 4;
293 priv->tseq[0] =
294 HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE;
295 priv->tseq[1] = HP_SDC_CMD_SET_LPC;
296 priv->tseq[2] = 1;
297 // priv->tseq[3] = (mlc->ddc + 1) | HP_SDC_LPS_ACSUCC;
298 priv->tseq[3] = 0;
299 if (mlc->opacket & HIL_CTRL_APE) {
300 priv->tseq[3] |= HP_SDC_LPC_APE_IPF;
301 down_trylock(&(mlc->csem));
302 }
303 enqueue:
304 hp_sdc_enqueue_transaction(&(priv->trans));
305 done:
306 write_unlock_irqrestore(&(mlc->lock), flags);
307}
308
309static int __init hp_sdc_mlc_init(void)
310{
311 hil_mlc *mlc = &hp_sdc_mlc;
312
313 printk(KERN_INFO PREFIX "Registering the System Domain Controller's HIL MLC.\n");
314
315 hp_sdc_mlc_priv.emtestmode = 0;
316 hp_sdc_mlc_priv.trans.seq = hp_sdc_mlc_priv.tseq;
317 hp_sdc_mlc_priv.trans.act.semaphore = &(mlc->osem);
318 hp_sdc_mlc_priv.got5x = 0;
319
320 mlc->cts = &hp_sdc_mlc_cts;
321 mlc->in = &hp_sdc_mlc_in;
322 mlc->out = &hp_sdc_mlc_out;
323
324 if (hil_mlc_register(mlc)) {
325 printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n");
326 goto err0;
327 }
328 mlc->priv = &hp_sdc_mlc_priv;
329
330 if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) {
331 printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n");
332 goto err1;
333 }
334 return 0;
335 err1:
336 if (hil_mlc_unregister(mlc)) {
337 printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n"
338 "This is bad. Could cause an oops.\n");
339 }
340 err0:
341 return -EBUSY;
342}
343
344static void __exit hp_sdc_mlc_exit(void)
345{
346 hil_mlc *mlc = &hp_sdc_mlc;
347 if (hp_sdc_release_hil_irq(&hp_sdc_mlc_isr)) {
348 printk(KERN_ERR PREFIX "Failed to release the raw HIL ISR hook.\n"
349 "This is bad. Could cause an oops.\n");
350 }
351 if (hil_mlc_unregister(mlc)) {
352 printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n"
353 "This is bad. Could cause an oops.\n");
354 }
355}
356
357module_init(hp_sdc_mlc_init);
358module_exit(hp_sdc_mlc_exit);
diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h
new file mode 100644
index 000000000000..c9e633d21d90
--- /dev/null
+++ b/drivers/input/serio/i8042-io.h
@@ -0,0 +1,93 @@
1#ifndef _I8042_IO_H
2#define _I8042_IO_H
3
4/*
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 */
9
10/*
11 * Names.
12 */
13
14#define I8042_KBD_PHYS_DESC "isa0060/serio0"
15#define I8042_AUX_PHYS_DESC "isa0060/serio1"
16#define I8042_MUX_PHYS_DESC "isa0060/serio%d"
17
18/*
19 * IRQs.
20 */
21
22#ifdef __alpha__
23# define I8042_KBD_IRQ 1
24# define I8042_AUX_IRQ (RTC_PORT(0) == 0x170 ? 9 : 12) /* Jensen is special */
25#elif defined(__arm__)
26/* defined in include/asm-arm/arch-xxx/irqs.h */
27#include <asm/irq.h>
28#elif defined(CONFIG_SUPERH64)
29#include <asm/irq.h>
30#else
31# define I8042_KBD_IRQ 1
32# define I8042_AUX_IRQ 12
33#endif
34
35
36/*
37 * Register numbers.
38 */
39
40#define I8042_COMMAND_REG 0x64
41#define I8042_STATUS_REG 0x64
42#define I8042_DATA_REG 0x60
43
44static inline int i8042_read_data(void)
45{
46 return inb(I8042_DATA_REG);
47}
48
49static inline int i8042_read_status(void)
50{
51 return inb(I8042_STATUS_REG);
52}
53
54static inline void i8042_write_data(int val)
55{
56 outb(val, I8042_DATA_REG);
57}
58
59static inline void i8042_write_command(int val)
60{
61 outb(val, I8042_COMMAND_REG);
62}
63
64static inline int i8042_platform_init(void)
65{
66/*
67 * On some platforms touching the i8042 data register region can do really
68 * bad things. Because of this the region is always reserved on such boxes.
69 */
70#if !defined(__sh__) && !defined(__alpha__) && !defined(__mips__) && !defined(CONFIG_PPC64)
71 if (!request_region(I8042_DATA_REG, 16, "i8042"))
72 return -1;
73#endif
74
75 i8042_reset = 1;
76
77#if defined(CONFIG_PPC64)
78 if (check_legacy_ioport(I8042_DATA_REG))
79 return -1;
80 if (!request_region(I8042_DATA_REG, 16, "i8042"))
81 return -1;
82#endif
83 return 0;
84}
85
86static inline void i8042_platform_exit(void)
87{
88#if !defined(__sh__) && !defined(__alpha__) && !defined(CONFIG_PPC64)
89 release_region(I8042_DATA_REG, 16);
90#endif
91}
92
93#endif /* _I8042_IO_H */
diff --git a/drivers/input/serio/i8042-ip22io.h b/drivers/input/serio/i8042-ip22io.h
new file mode 100644
index 000000000000..863b9c95fbb8
--- /dev/null
+++ b/drivers/input/serio/i8042-ip22io.h
@@ -0,0 +1,76 @@
1#ifndef _I8042_IP22_H
2#define _I8042_IP22_H
3
4#include <asm/sgi/ioc.h>
5#include <asm/sgi/ip22.h>
6
7/*
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 */
12
13/*
14 * Names.
15 */
16
17#define I8042_KBD_PHYS_DESC "hpc3ps2/serio0"
18#define I8042_AUX_PHYS_DESC "hpc3ps2/serio1"
19#define I8042_MUX_PHYS_DESC "hpc3ps2/serio%d"
20
21/*
22 * IRQs.
23 */
24
25#define I8042_KBD_IRQ SGI_KEYBD_IRQ
26#define I8042_AUX_IRQ SGI_KEYBD_IRQ
27
28/*
29 * Register numbers.
30 */
31
32#define I8042_COMMAND_REG ((unsigned long)&sgioc->kbdmouse.command)
33#define I8042_STATUS_REG ((unsigned long)&sgioc->kbdmouse.command)
34#define I8042_DATA_REG ((unsigned long)&sgioc->kbdmouse.data)
35
36static inline int i8042_read_data(void)
37{
38 return sgioc->kbdmouse.data;
39}
40
41static inline int i8042_read_status(void)
42{
43 return sgioc->kbdmouse.command;
44}
45
46static inline void i8042_write_data(int val)
47{
48 sgioc->kbdmouse.data = val;
49}
50
51static inline void i8042_write_command(int val)
52{
53 sgioc->kbdmouse.command = val;
54}
55
56static inline int i8042_platform_init(void)
57{
58#if 0
59 /* XXX sgi_kh is a virtual address */
60 if (!request_mem_region(sgi_kh, sizeof(struct hpc_keyb), "i8042"))
61 return 1;
62#endif
63
64 i8042_reset = 1;
65
66 return 0;
67}
68
69static inline void i8042_platform_exit(void)
70{
71#if 0
72 release_mem_region(JAZZ_KEYBOARD_ADDRESS, sizeof(struct hpc_keyb));
73#endif
74}
75
76#endif /* _I8042_IP22_H */
diff --git a/drivers/input/serio/i8042-jazzio.h b/drivers/input/serio/i8042-jazzio.h
new file mode 100644
index 000000000000..5c20ab131488
--- /dev/null
+++ b/drivers/input/serio/i8042-jazzio.h
@@ -0,0 +1,69 @@
1#ifndef _I8042_JAZZ_H
2#define _I8042_JAZZ_H
3
4#include <asm/jazz.h>
5
6/*
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 */
11
12/*
13 * Names.
14 */
15
16#define I8042_KBD_PHYS_DESC "R4030/serio0"
17#define I8042_AUX_PHYS_DESC "R4030/serio1"
18#define I8042_MUX_PHYS_DESC "R4030/serio%d"
19
20/*
21 * IRQs.
22 */
23
24#define I8042_KBD_IRQ JAZZ_KEYBOARD_IRQ
25#define I8042_AUX_IRQ JAZZ_MOUSE_IRQ
26
27#define I8042_COMMAND_REG ((unsigned long)&jazz_kh->command)
28#define I8042_STATUS_REG ((unsigned long)&jazz_kh->command)
29#define I8042_DATA_REG ((unsigned long)&jazz_kh->data)
30
31static inline int i8042_read_data(void)
32{
33 return jazz_kh->data;
34}
35
36static inline int i8042_read_status(void)
37{
38 return jazz_kh->command;
39}
40
41static inline void i8042_write_data(int val)
42{
43 jazz_kh->data = val;
44}
45
46static inline void i8042_write_command(int val)
47{
48 jazz_kh->command = val;
49}
50
51static inline int i8042_platform_init(void)
52{
53#if 0
54 /* XXX JAZZ_KEYBOARD_ADDRESS is a virtual address */
55 if (!request_mem_region(JAZZ_KEYBOARD_ADDRESS, 2, "i8042"))
56 return 1;
57#endif
58
59 return 0;
60}
61
62static inline void i8042_platform_exit(void)
63{
64#if 0
65 release_mem_region(JAZZ_KEYBOARD_ADDRESS, 2);
66#endif
67}
68
69#endif /* _I8042_JAZZ_H */
diff --git a/drivers/input/serio/i8042-ppcio.h b/drivers/input/serio/i8042-ppcio.h
new file mode 100644
index 000000000000..2906e1b60c04
--- /dev/null
+++ b/drivers/input/serio/i8042-ppcio.h
@@ -0,0 +1,136 @@
1#ifndef _I8042_PPCIO_H
2#define _I8042_PPCIO_H
3
4/*
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 */
9
10#if defined(CONFIG_WALNUT)
11
12#define I8042_KBD_IRQ 25
13#define I8042_AUX_IRQ 26
14
15#define I8042_KBD_PHYS_DESC "walnutps2/serio0"
16#define I8042_AUX_PHYS_DESC "walnutps2/serio1"
17#define I8042_MUX_PHYS_DESC "walnutps2/serio%d"
18
19extern void *kb_cs;
20extern void *kb_data;
21
22#define I8042_COMMAND_REG (*(int *)kb_cs)
23#define I8042_DATA_REG (*(int *)kb_data)
24
25static inline int i8042_read_data(void)
26{
27 return readb(kb_data);
28}
29
30static inline int i8042_read_status(void)
31{
32 return readb(kb_cs);
33}
34
35static inline void i8042_write_data(int val)
36{
37 writeb(val, kb_data);
38}
39
40static inline void i8042_write_command(int val)
41{
42 writeb(val, kb_cs);
43}
44
45static inline int i8042_platform_init(void)
46{
47 i8042_reset = 1;
48 return 0;
49}
50
51static inline void i8042_platform_exit(void)
52{
53}
54
55#elif defined(CONFIG_SPRUCE)
56
57#define I8042_KBD_IRQ 22
58#define I8042_AUX_IRQ 21
59
60#define I8042_KBD_PHYS_DESC "spruceps2/serio0"
61#define I8042_AUX_PHYS_DESC "spruceps2/serio1"
62#define I8042_MUX_PHYS_DESC "spruceps2/serio%d"
63
64#define I8042_COMMAND_REG 0xff810000
65#define I8042_DATA_REG 0xff810001
66
67static inline int i8042_read_data(void)
68{
69 unsigned long kbd_data;
70
71 __raw_writel(0x00000088, 0xff500008);
72 eieio();
73
74 __raw_writel(0x03000000, 0xff50000c);
75 eieio();
76
77 asm volatile("lis 7,0xff88 \n\
78 lswi 6,7,0x8 \n\
79 mr %0,6"
80 : "=r" (kbd_data) :: "6", "7");
81
82 __raw_writel(0x00000000, 0xff50000c);
83 eieio();
84
85 return (unsigned char)(kbd_data >> 24);
86}
87
88static inline int i8042_read_status(void)
89{
90 unsigned long kbd_status;
91
92 __raw_writel(0x00000088, 0xff500008);
93 eieio();
94
95 __raw_writel(0x03000000, 0xff50000c);
96 eieio();
97
98 asm volatile("lis 7,0xff88 \n\
99 ori 7,7,0x8 \n\
100 lswi 6,7,0x8 \n\
101 mr %0,6"
102 : "=r" (kbd_status) :: "6", "7");
103
104 __raw_writel(0x00000000, 0xff50000c);
105 eieio();
106
107 return (unsigned char)(kbd_status >> 24);
108}
109
110static inline void i8042_write_data(int val)
111{
112 *((unsigned char *)0xff810000) = (char)val;
113}
114
115static inline void i8042_write_command(int val)
116{
117 *((unsigned char *)0xff810001) = (char)val;
118}
119
120static inline int i8042_platform_init(void)
121{
122 i8042_reset = 1;
123 return 0;
124}
125
126static inline void i8042_platform_exit(void)
127{
128}
129
130#else
131
132#include "i8042-io.h"
133
134#endif
135
136#endif /* _I8042_PPCIO_H */
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h
new file mode 100644
index 000000000000..da2a19812485
--- /dev/null
+++ b/drivers/input/serio/i8042-sparcio.h
@@ -0,0 +1,116 @@
1#ifndef _I8042_SPARCIO_H
2#define _I8042_SPARCIO_H
3
4#include <linux/config.h>
5#include <asm/io.h>
6
7#ifdef CONFIG_PCI
8#include <asm/oplib.h>
9#include <asm/ebus.h>
10#endif
11
12static int i8042_kbd_irq = -1;
13static int i8042_aux_irq = -1;
14#define I8042_KBD_IRQ i8042_kbd_irq
15#define I8042_AUX_IRQ i8042_aux_irq
16
17#define I8042_KBD_PHYS_DESC "sparcps2/serio0"
18#define I8042_AUX_PHYS_DESC "sparcps2/serio1"
19#define I8042_MUX_PHYS_DESC "sparcps2/serio%d"
20
21static void __iomem *kbd_iobase;
22
23#define I8042_COMMAND_REG (kbd_iobase + 0x64UL)
24#define I8042_DATA_REG (kbd_iobase + 0x60UL)
25
26static inline int i8042_read_data(void)
27{
28 return readb(kbd_iobase + 0x60UL);
29}
30
31static inline int i8042_read_status(void)
32{
33 return readb(kbd_iobase + 0x64UL);
34}
35
36static inline void i8042_write_data(int val)
37{
38 writeb(val, kbd_iobase + 0x60UL);
39}
40
41static inline void i8042_write_command(int val)
42{
43 writeb(val, kbd_iobase + 0x64UL);
44}
45
46#define OBP_PS2KBD_NAME1 "kb_ps2"
47#define OBP_PS2KBD_NAME2 "keyboard"
48#define OBP_PS2MS_NAME1 "kdmouse"
49#define OBP_PS2MS_NAME2 "mouse"
50
51static int i8042_platform_init(void)
52{
53#ifndef CONFIG_PCI
54 return -1;
55#else
56 char prop[128];
57 int len;
58
59 len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop));
60 if (len < 0) {
61 printk("i8042: Cannot get name property of root OBP node.\n");
62 return -1;
63 }
64 if (strncmp(prop, "SUNW,JavaStation-1", len) == 0) {
65 /* Hardcoded values for MrCoffee. */
66 i8042_kbd_irq = i8042_aux_irq = 13 | 0x20;
67 kbd_iobase = ioremap(0x71300060, 8);
68 if (!kbd_iobase)
69 return -1;
70 } else {
71 struct linux_ebus *ebus;
72 struct linux_ebus_device *edev;
73 struct linux_ebus_child *child;
74
75 for_each_ebus(ebus) {
76 for_each_ebusdev(edev, ebus) {
77 if (!strcmp(edev->prom_name, "8042"))
78 goto edev_found;
79 }
80 }
81 return -1;
82
83 edev_found:
84 for_each_edevchild(edev, child) {
85 if (!strcmp(child->prom_name, OBP_PS2KBD_NAME1) ||
86 !strcmp(child->prom_name, OBP_PS2KBD_NAME2)) {
87 i8042_kbd_irq = child->irqs[0];
88 kbd_iobase =
89 ioremap(child->resource[0].start, 8);
90 }
91 if (!strcmp(child->prom_name, OBP_PS2MS_NAME1) ||
92 !strcmp(child->prom_name, OBP_PS2MS_NAME2))
93 i8042_aux_irq = child->irqs[0];
94 }
95 if (i8042_kbd_irq == -1 ||
96 i8042_aux_irq == -1) {
97 printk("i8042: Error, 8042 device lacks both kbd and "
98 "mouse nodes.\n");
99 return -1;
100 }
101 }
102
103 i8042_reset = 1;
104
105 return 0;
106#endif /* CONFIG_PCI */
107}
108
109static inline void i8042_platform_exit(void)
110{
111#ifdef CONFIG_PCI
112 iounmap(kbd_iobase);
113#endif
114}
115
116#endif /* _I8042_SPARCIO_H */
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
new file mode 100644
index 000000000000..f64867808fea
--- /dev/null
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -0,0 +1,333 @@
1#ifndef _I8042_X86IA64IO_H
2#define _I8042_X86IA64IO_H
3
4/*
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 */
9
10/*
11 * Names.
12 */
13
14#define I8042_KBD_PHYS_DESC "isa0060/serio0"
15#define I8042_AUX_PHYS_DESC "isa0060/serio1"
16#define I8042_MUX_PHYS_DESC "isa0060/serio%d"
17
18/*
19 * IRQs.
20 */
21
22#if defined(__ia64__)
23# define I8042_MAP_IRQ(x) isa_irq_to_vector((x))
24#else
25# define I8042_MAP_IRQ(x) (x)
26#endif
27
28#define I8042_KBD_IRQ i8042_kbd_irq
29#define I8042_AUX_IRQ i8042_aux_irq
30
31static int i8042_kbd_irq;
32static int i8042_aux_irq;
33
34/*
35 * Register numbers.
36 */
37
38#define I8042_COMMAND_REG i8042_command_reg
39#define I8042_STATUS_REG i8042_command_reg
40#define I8042_DATA_REG i8042_data_reg
41
42static int i8042_command_reg = 0x64;
43static int i8042_data_reg = 0x60;
44
45
46static inline int i8042_read_data(void)
47{
48 return inb(I8042_DATA_REG);
49}
50
51static inline int i8042_read_status(void)
52{
53 return inb(I8042_STATUS_REG);
54}
55
56static inline void i8042_write_data(int val)
57{
58 outb(val, I8042_DATA_REG);
59}
60
61static inline void i8042_write_command(int val)
62{
63 outb(val, I8042_COMMAND_REG);
64}
65
66#if defined(__i386__)
67
68#include <linux/dmi.h>
69
70static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
71 {
72 .ident = "Compaq Proliant 8500",
73 .matches = {
74 DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
75 DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"),
76 DMI_MATCH(DMI_PRODUCT_VERSION, "8500"),
77 },
78 },
79 {
80 .ident = "Compaq Proliant DL760",
81 .matches = {
82 DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
83 DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"),
84 DMI_MATCH(DMI_PRODUCT_VERSION, "DL760"),
85 },
86 },
87 { }
88};
89
90/*
91 * Some Fujitsu notebooks are ahving trouble with touhcpads if
92 * active multiplexing mode is activated. Luckily they don't have
93 * external PS/2 ports so we can safely disable it.
94 */
95static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
96 {
97 .ident = "Fujitsu Lifebook P7010/P7010D",
98 .matches = {
99 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
100 DMI_MATCH(DMI_PRODUCT_NAME, "P7010"),
101 },
102 },
103 {
104 .ident = "Fujitsu Lifebook P5020D",
105 .matches = {
106 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
107 DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P Series"),
108 },
109 },
110 {
111 .ident = "Fujitsu Lifebook S2000",
112 .matches = {
113 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
114 DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S Series"),
115 },
116 },
117 {
118 .ident = "Fujitsu T70H",
119 .matches = {
120 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
121 DMI_MATCH(DMI_PRODUCT_NAME, "FMVLT70H"),
122 },
123 },
124 { }
125};
126
127
128
129#endif
130
131
132#ifdef CONFIG_PNP
133#include <linux/pnp.h>
134
135static int i8042_pnp_kbd_registered;
136static int i8042_pnp_aux_registered;
137
138static int i8042_pnp_command_reg;
139static int i8042_pnp_data_reg;
140static int i8042_pnp_kbd_irq;
141static int i8042_pnp_aux_irq;
142
143static char i8042_pnp_kbd_name[32];
144static char i8042_pnp_aux_name[32];
145
146static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *did)
147{
148 if (pnp_port_valid(dev, 0) && pnp_port_len(dev, 0) == 1)
149 i8042_pnp_data_reg = pnp_port_start(dev,0);
150
151 if (pnp_port_valid(dev, 1) && pnp_port_len(dev, 1) == 1)
152 i8042_pnp_command_reg = pnp_port_start(dev, 1);
153
154 if (pnp_irq_valid(dev,0))
155 i8042_pnp_kbd_irq = pnp_irq(dev, 0);
156
157 strncpy(i8042_pnp_kbd_name, did->id, sizeof(i8042_pnp_kbd_name));
158 if (strlen(pnp_dev_name(dev))) {
159 strncat(i8042_pnp_kbd_name, ":", sizeof(i8042_pnp_kbd_name));
160 strncat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name));
161 }
162
163 return 0;
164}
165
166static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id *did)
167{
168 if (pnp_port_valid(dev, 0) && pnp_port_len(dev, 0) == 1)
169 i8042_pnp_data_reg = pnp_port_start(dev,0);
170
171 if (pnp_port_valid(dev, 1) && pnp_port_len(dev, 1) == 1)
172 i8042_pnp_command_reg = pnp_port_start(dev, 1);
173
174 if (pnp_irq_valid(dev, 0))
175 i8042_pnp_aux_irq = pnp_irq(dev, 0);
176
177 strncpy(i8042_pnp_aux_name, did->id, sizeof(i8042_pnp_aux_name));
178 if (strlen(pnp_dev_name(dev))) {
179 strncat(i8042_pnp_aux_name, ":", sizeof(i8042_pnp_aux_name));
180 strncat(i8042_pnp_aux_name, pnp_dev_name(dev), sizeof(i8042_pnp_aux_name));
181 }
182
183 return 0;
184}
185
186static struct pnp_device_id pnp_kbd_devids[] = {
187 { .id = "PNP0303", .driver_data = 0 },
188 { .id = "PNP030b", .driver_data = 0 },
189 { .id = "", },
190};
191
192static struct pnp_driver i8042_pnp_kbd_driver = {
193 .name = "i8042 kbd",
194 .id_table = pnp_kbd_devids,
195 .probe = i8042_pnp_kbd_probe,
196};
197
198static struct pnp_device_id pnp_aux_devids[] = {
199 { .id = "PNP0f03", .driver_data = 0 },
200 { .id = "PNP0f0b", .driver_data = 0 },
201 { .id = "PNP0f0e", .driver_data = 0 },
202 { .id = "PNP0f12", .driver_data = 0 },
203 { .id = "PNP0f13", .driver_data = 0 },
204 { .id = "PNP0f19", .driver_data = 0 },
205 { .id = "PNP0f1c", .driver_data = 0 },
206 { .id = "SYN0801", .driver_data = 0 },
207 { .id = "", },
208};
209
210static struct pnp_driver i8042_pnp_aux_driver = {
211 .name = "i8042 aux",
212 .id_table = pnp_aux_devids,
213 .probe = i8042_pnp_aux_probe,
214};
215
216static void i8042_pnp_exit(void)
217{
218 if (i8042_pnp_kbd_registered)
219 pnp_unregister_driver(&i8042_pnp_kbd_driver);
220
221 if (i8042_pnp_aux_registered)
222 pnp_unregister_driver(&i8042_pnp_aux_driver);
223}
224
225static int i8042_pnp_init(void)
226{
227 int result_kbd, result_aux;
228
229 if (i8042_nopnp) {
230 printk("i8042: PNP detection disabled\n");
231 return 0;
232 }
233
234 if ((result_kbd = pnp_register_driver(&i8042_pnp_kbd_driver)) >= 0)
235 i8042_pnp_kbd_registered = 1;
236 if ((result_aux = pnp_register_driver(&i8042_pnp_aux_driver)) >= 0)
237 i8042_pnp_aux_registered = 1;
238
239 if (result_kbd <= 0 && result_aux <= 0) {
240 i8042_pnp_exit();
241#if defined(__ia64__)
242 return -ENODEV;
243#else
244 printk(KERN_WARNING "PNP: No PS/2 controller found. Probing ports directly.\n");
245 return 0;
246#endif
247 }
248
249 if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) &&
250 i8042_pnp_data_reg != i8042_data_reg) || !i8042_pnp_data_reg) {
251 printk(KERN_WARNING "PNP: PS/2 controller has invalid data port %#x; using default %#x\n",
252 i8042_pnp_data_reg, i8042_data_reg);
253 i8042_pnp_data_reg = i8042_data_reg;
254 }
255
256 if (((i8042_pnp_command_reg & ~0xf) == (i8042_command_reg & ~0xf) &&
257 i8042_pnp_command_reg != i8042_command_reg) || !i8042_pnp_command_reg) {
258 printk(KERN_WARNING "PNP: PS/2 controller has invalid command port %#x; using default %#x\n",
259 i8042_pnp_command_reg, i8042_command_reg);
260 i8042_pnp_command_reg = i8042_command_reg;
261 }
262
263 if (!i8042_pnp_kbd_irq) {
264 printk(KERN_WARNING "PNP: PS/2 controller doesn't have KBD irq; using default %#x\n", i8042_kbd_irq);
265 i8042_pnp_kbd_irq = i8042_kbd_irq;
266 }
267
268 if (result_aux > 0 && !i8042_pnp_aux_irq) {
269 printk(KERN_WARNING "PNP: PS/2 controller doesn't have AUX irq; using default %#x\n", i8042_aux_irq);
270 i8042_pnp_aux_irq = i8042_aux_irq;
271 }
272
273#if defined(__ia64__)
274 if (result_aux <= 0)
275 i8042_noaux = 1;
276#endif
277
278 i8042_data_reg = i8042_pnp_data_reg;
279 i8042_command_reg = i8042_pnp_command_reg;
280 i8042_kbd_irq = i8042_pnp_kbd_irq;
281 i8042_aux_irq = i8042_pnp_aux_irq;
282
283 printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %d%s%d\n",
284 i8042_pnp_kbd_name, (result_kbd > 0 && result_aux > 0) ? "," : "", i8042_pnp_aux_name,
285 i8042_data_reg, i8042_command_reg, i8042_kbd_irq,
286 (result_aux > 0) ? "," : "", i8042_aux_irq);
287
288 return 0;
289}
290
291#endif
292
293static inline int i8042_platform_init(void)
294{
295/*
296 * On ix86 platforms touching the i8042 data register region can do really
297 * bad things. Because of this the region is always reserved on ix86 boxes.
298 *
299 * if (!request_region(I8042_DATA_REG, 16, "i8042"))
300 * return -1;
301 */
302
303 i8042_kbd_irq = I8042_MAP_IRQ(1);
304 i8042_aux_irq = I8042_MAP_IRQ(12);
305
306#ifdef CONFIG_PNP
307 if (i8042_pnp_init())
308 return -1;
309#endif
310
311#if defined(__ia64__)
312 i8042_reset = 1;
313#endif
314
315#if defined(__i386__)
316 if (dmi_check_system(i8042_dmi_noloop_table))
317 i8042_noloop = 1;
318
319 if (dmi_check_system(i8042_dmi_nomux_table))
320 i8042_nomux = 1;
321#endif
322
323 return 0;
324}
325
326static inline void i8042_platform_exit(void)
327{
328#ifdef CONFIG_PNP
329 i8042_pnp_exit();
330#endif
331}
332
333#endif /* _I8042_X86IA64IO_H */
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
new file mode 100644
index 000000000000..8e63e464d361
--- /dev/null
+++ b/drivers/input/serio/i8042.c
@@ -0,0 +1,1116 @@
1/*
2 * i8042 keyboard and mouse controller driver for Linux
3 *
4 * Copyright (c) 1999-2004 Vojtech Pavlik
5 */
6
7/*
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 */
12
13#include <linux/delay.h>
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/interrupt.h>
17#include <linux/ioport.h>
18#include <linux/config.h>
19#include <linux/init.h>
20#include <linux/serio.h>
21#include <linux/err.h>
22#include <linux/rcupdate.h>
23
24#include <asm/io.h>
25
26MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
27MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver");
28MODULE_LICENSE("GPL");
29
30static unsigned int i8042_noaux;
31module_param_named(noaux, i8042_noaux, bool, 0);
32MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port.");
33
34static unsigned int i8042_nomux;
35module_param_named(nomux, i8042_nomux, bool, 0);
36MODULE_PARM_DESC(nomux, "Do not check whether an active multiplexing conrtoller is present.");
37
38static unsigned int i8042_unlock;
39module_param_named(unlock, i8042_unlock, bool, 0);
40MODULE_PARM_DESC(unlock, "Ignore keyboard lock.");
41
42static unsigned int i8042_reset;
43module_param_named(reset, i8042_reset, bool, 0);
44MODULE_PARM_DESC(reset, "Reset controller during init and cleanup.");
45
46static unsigned int i8042_direct;
47module_param_named(direct, i8042_direct, bool, 0);
48MODULE_PARM_DESC(direct, "Put keyboard port into non-translated mode.");
49
50static unsigned int i8042_dumbkbd;
51module_param_named(dumbkbd, i8042_dumbkbd, bool, 0);
52MODULE_PARM_DESC(dumbkbd, "Pretend that controller can only read data from keyboard");
53
54static unsigned int i8042_noloop;
55module_param_named(noloop, i8042_noloop, bool, 0);
56MODULE_PARM_DESC(noloop, "Disable the AUX Loopback command while probing for the AUX port");
57
58static unsigned int i8042_blink_frequency = 500;
59module_param_named(panicblink, i8042_blink_frequency, uint, 0600);
60MODULE_PARM_DESC(panicblink, "Frequency with which keyboard LEDs should blink when kernel panics");
61
62#ifdef CONFIG_PNP
63static int i8042_nopnp;
64module_param_named(nopnp, i8042_nopnp, bool, 0);
65MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings");
66#endif
67
68#define DEBUG
69#ifdef DEBUG
70static int i8042_debug;
71module_param_named(debug, i8042_debug, bool, 0600);
72MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off");
73#endif
74
75__obsolete_setup("i8042_noaux");
76__obsolete_setup("i8042_nomux");
77__obsolete_setup("i8042_unlock");
78__obsolete_setup("i8042_reset");
79__obsolete_setup("i8042_direct");
80__obsolete_setup("i8042_dumbkbd");
81
82#include "i8042.h"
83
84static DEFINE_SPINLOCK(i8042_lock);
85
86struct i8042_port {
87 struct serio *serio;
88 int irq;
89 unsigned char disable;
90 unsigned char irqen;
91 unsigned char exists;
92 signed char mux;
93 char name[8];
94};
95
96#define I8042_KBD_PORT_NO 0
97#define I8042_AUX_PORT_NO 1
98#define I8042_MUX_PORT_NO 2
99#define I8042_NUM_PORTS (I8042_NUM_MUX_PORTS + 2)
100static struct i8042_port i8042_ports[I8042_NUM_PORTS] = {
101 {
102 .disable = I8042_CTR_KBDDIS,
103 .irqen = I8042_CTR_KBDINT,
104 .mux = -1,
105 .name = "KBD",
106 },
107 {
108 .disable = I8042_CTR_AUXDIS,
109 .irqen = I8042_CTR_AUXINT,
110 .mux = -1,
111 .name = "AUX",
112 }
113};
114
115static unsigned char i8042_initial_ctr;
116static unsigned char i8042_ctr;
117static unsigned char i8042_mux_open;
118static unsigned char i8042_mux_present;
119static struct timer_list i8042_timer;
120static struct platform_device *i8042_platform_device;
121
122
123/*
124 * Shared IRQ's require a device pointer, but this driver doesn't support
125 * multiple devices
126 */
127#define i8042_request_irq_cookie (&i8042_timer)
128
129static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs);
130
131/*
132 * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to
133 * be ready for reading values from it / writing values to it.
134 * Called always with i8042_lock held.
135 */
136
137static int i8042_wait_read(void)
138{
139 int i = 0;
140 while ((~i8042_read_status() & I8042_STR_OBF) && (i < I8042_CTL_TIMEOUT)) {
141 udelay(50);
142 i++;
143 }
144 return -(i == I8042_CTL_TIMEOUT);
145}
146
147static int i8042_wait_write(void)
148{
149 int i = 0;
150 while ((i8042_read_status() & I8042_STR_IBF) && (i < I8042_CTL_TIMEOUT)) {
151 udelay(50);
152 i++;
153 }
154 return -(i == I8042_CTL_TIMEOUT);
155}
156
157/*
158 * i8042_flush() flushes all data that may be in the keyboard and mouse buffers
159 * of the i8042 down the toilet.
160 */
161
162static int i8042_flush(void)
163{
164 unsigned long flags;
165 unsigned char data, str;
166 int i = 0;
167
168 spin_lock_irqsave(&i8042_lock, flags);
169
170 while (((str = i8042_read_status()) & I8042_STR_OBF) && (i < I8042_BUFFER_SIZE)) {
171 udelay(50);
172 data = i8042_read_data();
173 i++;
174 dbg("%02x <- i8042 (flush, %s)", data,
175 str & I8042_STR_AUXDATA ? "aux" : "kbd");
176 }
177
178 spin_unlock_irqrestore(&i8042_lock, flags);
179
180 return i;
181}
182
183/*
184 * i8042_command() executes a command on the i8042. It also sends the input
185 * parameter(s) of the commands to it, and receives the output value(s). The
186 * parameters are to be stored in the param array, and the output is placed
187 * into the same array. The number of the parameters and output values is
188 * encoded in bits 8-11 of the command number.
189 */
190
191static int i8042_command(unsigned char *param, int command)
192{
193 unsigned long flags;
194 int retval = 0, i = 0;
195
196 if (i8042_noloop && command == I8042_CMD_AUX_LOOP)
197 return -1;
198
199 spin_lock_irqsave(&i8042_lock, flags);
200
201 retval = i8042_wait_write();
202 if (!retval) {
203 dbg("%02x -> i8042 (command)", command & 0xff);
204 i8042_write_command(command & 0xff);
205 }
206
207 if (!retval)
208 for (i = 0; i < ((command >> 12) & 0xf); i++) {
209 if ((retval = i8042_wait_write())) break;
210 dbg("%02x -> i8042 (parameter)", param[i]);
211 i8042_write_data(param[i]);
212 }
213
214 if (!retval)
215 for (i = 0; i < ((command >> 8) & 0xf); i++) {
216 if ((retval = i8042_wait_read())) break;
217 if (i8042_read_status() & I8042_STR_AUXDATA)
218 param[i] = ~i8042_read_data();
219 else
220 param[i] = i8042_read_data();
221 dbg("%02x <- i8042 (return)", param[i]);
222 }
223
224 spin_unlock_irqrestore(&i8042_lock, flags);
225
226 if (retval)
227 dbg(" -- i8042 (timeout)");
228
229 return retval;
230}
231
232/*
233 * i8042_kbd_write() sends a byte out through the keyboard interface.
234 */
235
236static int i8042_kbd_write(struct serio *port, unsigned char c)
237{
238 unsigned long flags;
239 int retval = 0;
240
241 spin_lock_irqsave(&i8042_lock, flags);
242
243 if(!(retval = i8042_wait_write())) {
244 dbg("%02x -> i8042 (kbd-data)", c);
245 i8042_write_data(c);
246 }
247
248 spin_unlock_irqrestore(&i8042_lock, flags);
249
250 return retval;
251}
252
253/*
254 * i8042_aux_write() sends a byte out through the aux interface.
255 */
256
257static int i8042_aux_write(struct serio *serio, unsigned char c)
258{
259 struct i8042_port *port = serio->port_data;
260 int retval;
261
262/*
263 * Send the byte out.
264 */
265
266 if (port->mux == -1)
267 retval = i8042_command(&c, I8042_CMD_AUX_SEND);
268 else
269 retval = i8042_command(&c, I8042_CMD_MUX_SEND + port->mux);
270
271/*
272 * Make sure the interrupt happens and the character is received even
273 * in the case the IRQ isn't wired, so that we can receive further
274 * characters later.
275 */
276
277 i8042_interrupt(0, NULL, NULL);
278 return retval;
279}
280
281/*
282 * i8042_activate_port() enables port on a chip.
283 */
284
285static int i8042_activate_port(struct i8042_port *port)
286{
287 if (!port->serio)
288 return -1;
289
290 i8042_flush();
291
292 /*
293 * Enable port again here because it is disabled if we are
294 * resuming (normally it is enabled already).
295 */
296 i8042_ctr &= ~port->disable;
297
298 i8042_ctr |= port->irqen;
299
300 if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
301 i8042_ctr &= ~port->irqen;
302 return -1;
303 }
304
305 return 0;
306}
307
308
309/*
310 * i8042_open() is called when a port is open by the higher layer.
311 * It allocates the interrupt and calls i8042_enable_port.
312 */
313
314static int i8042_open(struct serio *serio)
315{
316 struct i8042_port *port = serio->port_data;
317
318 if (port->mux != -1)
319 if (i8042_mux_open++)
320 return 0;
321
322 if (request_irq(port->irq, i8042_interrupt,
323 SA_SHIRQ, "i8042", i8042_request_irq_cookie)) {
324 printk(KERN_ERR "i8042.c: Can't get irq %d for %s, unregistering the port.\n", port->irq, port->name);
325 goto irq_fail;
326 }
327
328 if (i8042_activate_port(port)) {
329 printk(KERN_ERR "i8042.c: Can't activate %s, unregistering the port\n", port->name);
330 goto activate_fail;
331 }
332
333 i8042_interrupt(0, NULL, NULL);
334
335 return 0;
336
337activate_fail:
338 free_irq(port->irq, i8042_request_irq_cookie);
339
340irq_fail:
341 serio_unregister_port_delayed(serio);
342
343 return -1;
344}
345
346/*
347 * i8042_close() frees the interrupt, so that it can possibly be used
348 * by another driver. We never know - if the user doesn't have a mouse,
349 * the BIOS could have used the AUX interrupt for PCI.
350 */
351
352static void i8042_close(struct serio *serio)
353{
354 struct i8042_port *port = serio->port_data;
355
356 if (port->mux != -1)
357 if (--i8042_mux_open)
358 return;
359
360 i8042_ctr &= ~port->irqen;
361
362 if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
363 printk(KERN_WARNING "i8042.c: Can't write CTR while closing %s.\n", port->name);
364/*
365 * We still want to continue and free IRQ so if more data keeps coming in
366 * kernel will just ignore the irq.
367 */
368 }
369
370 free_irq(port->irq, i8042_request_irq_cookie);
371
372 i8042_flush();
373}
374
375/*
376 * i8042_start() is called by serio core when port is about to finish
377 * registering. It will mark port as existing so i8042_interrupt can
378 * start sending data through it.
379 */
380static int i8042_start(struct serio *serio)
381{
382 struct i8042_port *port = serio->port_data;
383
384 port->exists = 1;
385 mb();
386 return 0;
387}
388
389/*
390 * i8042_stop() marks serio port as non-existing so i8042_interrupt
391 * will not try to send data to the port that is about to go away.
392 * The function is called by serio core as part of unregister procedure.
393 */
394static void i8042_stop(struct serio *serio)
395{
396 struct i8042_port *port = serio->port_data;
397
398 port->exists = 0;
399 synchronize_kernel();
400 port->serio = NULL;
401}
402
403/*
404 * i8042_interrupt() is the most important function in this driver -
405 * it handles the interrupts from the i8042, and sends incoming bytes
406 * to the upper layers.
407 */
408
409static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
410{
411 struct i8042_port *port;
412 unsigned long flags;
413 unsigned char str, data;
414 unsigned int dfl;
415 unsigned int port_no;
416 int ret;
417
418 mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
419
420 spin_lock_irqsave(&i8042_lock, flags);
421 str = i8042_read_status();
422 if (unlikely(~str & I8042_STR_OBF)) {
423 spin_unlock_irqrestore(&i8042_lock, flags);
424 if (irq) dbg("Interrupt %d, without any data", irq);
425 ret = 0;
426 goto out;
427 }
428 data = i8042_read_data();
429 spin_unlock_irqrestore(&i8042_lock, flags);
430
431 if (i8042_mux_present && (str & I8042_STR_AUXDATA)) {
432 static unsigned long last_transmit;
433 static unsigned char last_str;
434
435 dfl = 0;
436 if (str & I8042_STR_MUXERR) {
437 dbg("MUX error, status is %02x, data is %02x", str, data);
438 switch (data) {
439 default:
440/*
441 * When MUXERR condition is signalled the data register can only contain
442 * 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately
443 * it is not always the case. Some KBC just get confused which port the
444 * data came from and signal error leaving the data intact. They _do not_
445 * revert to legacy mode (actually I've never seen KBC reverting to legacy
446 * mode yet, when we see one we'll add proper handling).
447 * Anyway, we will assume that the data came from the same serio last byte
448 * was transmitted (if transmission happened not too long ago).
449 */
450 if (time_before(jiffies, last_transmit + HZ/10)) {
451 str = last_str;
452 break;
453 }
454 /* fall through - report timeout */
455 case 0xfd:
456 case 0xfe: dfl = SERIO_TIMEOUT; data = 0xfe; break;
457 case 0xff: dfl = SERIO_PARITY; data = 0xfe; break;
458 }
459 }
460
461 port_no = I8042_MUX_PORT_NO + ((str >> 6) & 3);
462 last_str = str;
463 last_transmit = jiffies;
464 } else {
465
466 dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) |
467 ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0);
468
469 port_no = (str & I8042_STR_AUXDATA) ?
470 I8042_AUX_PORT_NO : I8042_KBD_PORT_NO;
471 }
472
473 port = &i8042_ports[port_no];
474
475 dbg("%02x <- i8042 (interrupt, %s, %d%s%s)",
476 data, port->name, irq,
477 dfl & SERIO_PARITY ? ", bad parity" : "",
478 dfl & SERIO_TIMEOUT ? ", timeout" : "");
479
480 if (likely(port->exists))
481 serio_interrupt(port->serio, data, dfl, regs);
482
483 ret = 1;
484out:
485 return IRQ_RETVAL(ret);
486}
487
488/*
489 * i8042_set_mux_mode checks whether the controller has an active
490 * multiplexor and puts the chip into Multiplexed (1) or Legacy (0) mode.
491 */
492
493static int i8042_set_mux_mode(unsigned int mode, unsigned char *mux_version)
494{
495
496 unsigned char param;
497/*
498 * Get rid of bytes in the queue.
499 */
500
501 i8042_flush();
502
503/*
504 * Internal loopback test - send three bytes, they should come back from the
505 * mouse interface, the last should be version. Note that we negate mouseport
506 * command responses for the i8042_check_aux() routine.
507 */
508
509 param = 0xf0;
510 if (i8042_command(&param, I8042_CMD_AUX_LOOP) || param != 0x0f)
511 return -1;
512 param = mode ? 0x56 : 0xf6;
513 if (i8042_command(&param, I8042_CMD_AUX_LOOP) || param != (mode ? 0xa9 : 0x09))
514 return -1;
515 param = mode ? 0xa4 : 0xa5;
516 if (i8042_command(&param, I8042_CMD_AUX_LOOP) || param == (mode ? 0x5b : 0x5a))
517 return -1;
518
519 if (mux_version)
520 *mux_version = ~param;
521
522 return 0;
523}
524
525
526/*
527 * i8042_enable_mux_ports enables 4 individual AUX ports after
528 * the controller has been switched into Multiplexed mode
529 */
530
531static int i8042_enable_mux_ports(void)
532{
533 unsigned char param;
534 int i;
535/*
536 * Disable all muxed ports by disabling AUX.
537 */
538
539 i8042_ctr |= I8042_CTR_AUXDIS;
540 i8042_ctr &= ~I8042_CTR_AUXINT;
541
542 if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
543 printk(KERN_ERR "i8042.c: Failed to disable AUX port, can't use MUX.\n");
544 return -1;
545 }
546
547/*
548 * Enable all muxed ports.
549 */
550
551 for (i = 0; i < 4; i++) {
552 i8042_command(&param, I8042_CMD_MUX_PFX + i);
553 i8042_command(&param, I8042_CMD_AUX_ENABLE);
554 }
555
556 return 0;
557}
558
559
560/*
561 * i8042_check_mux() checks whether the controller supports the PS/2 Active
562 * Multiplexing specification by Synaptics, Phoenix, Insyde and
563 * LCS/Telegraphics.
564 */
565
566static int __init i8042_check_mux(void)
567{
568 unsigned char mux_version;
569
570 if (i8042_set_mux_mode(1, &mux_version))
571 return -1;
572
573 /* Workaround for interference with USB Legacy emulation */
574 /* that causes a v10.12 MUX to be found. */
575 if (mux_version == 0xAC)
576 return -1;
577
578 printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n",
579 (mux_version >> 4) & 0xf, mux_version & 0xf);
580
581 if (i8042_enable_mux_ports())
582 return -1;
583
584 i8042_mux_present = 1;
585 return 0;
586}
587
588
589/*
590 * i8042_check_aux() applies as much paranoia as it can at detecting
591 * the presence of an AUX interface.
592 */
593
594static int __init i8042_check_aux(void)
595{
596 unsigned char param;
597 static int i8042_check_aux_cookie;
598
599/*
600 * Check if AUX irq is available. If it isn't, then there is no point
601 * in trying to detect AUX presence.
602 */
603
604 if (request_irq(i8042_ports[I8042_AUX_PORT_NO].irq, i8042_interrupt,
605 SA_SHIRQ, "i8042", &i8042_check_aux_cookie))
606 return -1;
607 free_irq(i8042_ports[I8042_AUX_PORT_NO].irq, &i8042_check_aux_cookie);
608
609/*
610 * Get rid of bytes in the queue.
611 */
612
613 i8042_flush();
614
615/*
616 * Internal loopback test - filters out AT-type i8042's. Unfortunately
617 * SiS screwed up and their 5597 doesn't support the LOOP command even
618 * though it has an AUX port.
619 */
620
621 param = 0x5a;
622 if (i8042_command(&param, I8042_CMD_AUX_LOOP) || param != 0xa5) {
623
624/*
625 * External connection test - filters out AT-soldered PS/2 i8042's
626 * 0x00 - no error, 0x01-0x03 - clock/data stuck, 0xff - general error
627 * 0xfa - no error on some notebooks which ignore the spec
628 * Because it's common for chipsets to return error on perfectly functioning
629 * AUX ports, we test for this only when the LOOP command failed.
630 */
631
632 if (i8042_command(&param, I8042_CMD_AUX_TEST)
633 || (param && param != 0xfa && param != 0xff))
634 return -1;
635 }
636
637/*
638 * Bit assignment test - filters out PS/2 i8042's in AT mode
639 */
640
641 if (i8042_command(&param, I8042_CMD_AUX_DISABLE))
642 return -1;
643 if (i8042_command(&param, I8042_CMD_CTL_RCTR) || (~param & I8042_CTR_AUXDIS)) {
644 printk(KERN_WARNING "Failed to disable AUX port, but continuing anyway... Is this a SiS?\n");
645 printk(KERN_WARNING "If AUX port is really absent please use the 'i8042.noaux' option.\n");
646 }
647
648 if (i8042_command(&param, I8042_CMD_AUX_ENABLE))
649 return -1;
650 if (i8042_command(&param, I8042_CMD_CTL_RCTR) || (param & I8042_CTR_AUXDIS))
651 return -1;
652
653/*
654 * Disable the interface.
655 */
656
657 i8042_ctr |= I8042_CTR_AUXDIS;
658 i8042_ctr &= ~I8042_CTR_AUXINT;
659
660 if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR))
661 return -1;
662
663 return 0;
664}
665
666
667/*
668 * i8042_port_register() marks the device as existing,
669 * registers it, and reports to the user.
670 */
671
672static int __init i8042_port_register(struct i8042_port *port)
673{
674 i8042_ctr &= ~port->disable;
675
676 if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
677 printk(KERN_WARNING "i8042.c: Can't write CTR while registering.\n");
678 kfree(port->serio);
679 port->serio = NULL;
680 i8042_ctr |= port->disable;
681 return -1;
682 }
683
684 printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n",
685 port->name,
686 (unsigned long) I8042_DATA_REG,
687 (unsigned long) I8042_COMMAND_REG,
688 port->irq);
689
690 serio_register_port(port->serio);
691
692 return 0;
693}
694
695
696static void i8042_timer_func(unsigned long data)
697{
698 i8042_interrupt(0, NULL, NULL);
699}
700
701
702/*
703 * i8042_controller init initializes the i8042 controller, and,
704 * most importantly, sets it into non-xlated mode if that's
705 * desired.
706 */
707
708static int i8042_controller_init(void)
709{
710 unsigned long flags;
711
712/*
713 * Test the i8042. We need to know if it thinks it's working correctly
714 * before doing anything else.
715 */
716
717 if (i8042_flush() == I8042_BUFFER_SIZE) {
718 printk(KERN_ERR "i8042.c: No controller found.\n");
719 return -1;
720 }
721
722 if (i8042_reset) {
723
724 unsigned char param;
725
726 if (i8042_command(&param, I8042_CMD_CTL_TEST)) {
727 printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n");
728 return -1;
729 }
730
731 if (param != I8042_RET_CTL_TEST) {
732 printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n",
733 param, I8042_RET_CTL_TEST);
734 return -1;
735 }
736 }
737
738/*
739 * Save the CTR for restoral on unload / reboot.
740 */
741
742 if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) {
743 printk(KERN_ERR "i8042.c: Can't read CTR while initializing i8042.\n");
744 return -1;
745 }
746
747 i8042_initial_ctr = i8042_ctr;
748
749/*
750 * Disable the keyboard interface and interrupt.
751 */
752
753 i8042_ctr |= I8042_CTR_KBDDIS;
754 i8042_ctr &= ~I8042_CTR_KBDINT;
755
756/*
757 * Handle keylock.
758 */
759
760 spin_lock_irqsave(&i8042_lock, flags);
761 if (~i8042_read_status() & I8042_STR_KEYLOCK) {
762 if (i8042_unlock)
763 i8042_ctr |= I8042_CTR_IGNKEYLOCK;
764 else
765 printk(KERN_WARNING "i8042.c: Warning: Keylock active.\n");
766 }
767 spin_unlock_irqrestore(&i8042_lock, flags);
768
769/*
770 * If the chip is configured into nontranslated mode by the BIOS, don't
771 * bother enabling translating and be happy.
772 */
773
774 if (~i8042_ctr & I8042_CTR_XLATE)
775 i8042_direct = 1;
776
777/*
778 * Set nontranslated mode for the kbd interface if requested by an option.
779 * After this the kbd interface becomes a simple serial in/out, like the aux
780 * interface is. We don't do this by default, since it can confuse notebook
781 * BIOSes.
782 */
783
784 if (i8042_direct)
785 i8042_ctr &= ~I8042_CTR_XLATE;
786
787/*
788 * Write CTR back.
789 */
790
791 if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
792 printk(KERN_ERR "i8042.c: Can't write CTR while initializing i8042.\n");
793 return -1;
794 }
795
796 return 0;
797}
798
799
800/*
801 * Reset the controller.
802 */
803static void i8042_controller_reset(void)
804{
805 unsigned char param;
806
807/*
808 * Reset the controller if requested.
809 */
810
811 if (i8042_reset)
812 if (i8042_command(&param, I8042_CMD_CTL_TEST))
813 printk(KERN_ERR "i8042.c: i8042 controller reset timeout.\n");
814
815/*
816 * Disable MUX mode if present.
817 */
818
819 if (i8042_mux_present)
820 i8042_set_mux_mode(0, NULL);
821
822/*
823 * Restore the original control register setting.
824 */
825
826 i8042_ctr = i8042_initial_ctr;
827
828 if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR))
829 printk(KERN_WARNING "i8042.c: Can't restore CTR.\n");
830}
831
832
833/*
834 * Here we try to reset everything back to a state in which the BIOS will be
835 * able to talk to the hardware when rebooting.
836 */
837
838static void i8042_controller_cleanup(void)
839{
840 int i;
841
842 i8042_flush();
843
844/*
845 * Reset anything that is connected to the ports.
846 */
847
848 for (i = 0; i < I8042_NUM_PORTS; i++)
849 if (i8042_ports[i].exists)
850 serio_cleanup(i8042_ports[i].serio);
851
852 i8042_controller_reset();
853}
854
855
856/*
857 * i8042_panic_blink() will flash the keyboard LEDs and is called when
858 * kernel panics. Flashing LEDs is useful for users running X who may
859 * not see the console and will help distingushing panics from "real"
860 * lockups.
861 *
862 * Note that DELAY has a limit of 10ms so we will not get stuck here
863 * waiting for KBC to free up even if KBD interrupt is off
864 */
865
866#define DELAY do { mdelay(1); if (++delay > 10) return delay; } while(0)
867
868static long i8042_panic_blink(long count)
869{
870 long delay = 0;
871 static long last_blink;
872 static char led;
873
874 /*
875 * We expect frequency to be about 1/2s. KDB uses about 1s.
876 * Make sure they are different.
877 */
878 if (!i8042_blink_frequency)
879 return 0;
880 if (count - last_blink < i8042_blink_frequency)
881 return 0;
882
883 led ^= 0x01 | 0x04;
884 while (i8042_read_status() & I8042_STR_IBF)
885 DELAY;
886 i8042_write_data(0xed); /* set leds */
887 DELAY;
888 while (i8042_read_status() & I8042_STR_IBF)
889 DELAY;
890 DELAY;
891 i8042_write_data(led);
892 DELAY;
893 last_blink = count;
894 return delay;
895}
896
897#undef DELAY
898
899/*
900 * Here we try to restore the original BIOS settings
901 */
902
903static int i8042_suspend(struct device *dev, pm_message_t state, u32 level)
904{
905 if (level == SUSPEND_DISABLE) {
906 del_timer_sync(&i8042_timer);
907 i8042_controller_reset();
908 }
909
910 return 0;
911}
912
913
914/*
915 * Here we try to reset everything back to a state in which suspended
916 */
917
918static int i8042_resume(struct device *dev, u32 level)
919{
920 int i;
921
922 if (level != RESUME_ENABLE)
923 return 0;
924
925 if (i8042_controller_init()) {
926 printk(KERN_ERR "i8042: resume failed\n");
927 return -1;
928 }
929
930 if (i8042_mux_present)
931 if (i8042_set_mux_mode(1, NULL) || i8042_enable_mux_ports())
932 printk(KERN_WARNING "i8042: failed to resume active multiplexor, mouse won't work.\n");
933
934/*
935 * Activate all ports.
936 */
937
938 for (i = 0; i < I8042_NUM_PORTS; i++)
939 i8042_activate_port(&i8042_ports[i]);
940
941/*
942 * Restart timer (for polling "stuck" data)
943 */
944 mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
945
946 panic_blink = i8042_panic_blink;
947
948 return 0;
949
950}
951
952/*
953 * We need to reset the 8042 back to original mode on system shutdown,
954 * because otherwise BIOSes will be confused.
955 */
956
957static void i8042_shutdown(struct device *dev)
958{
959 i8042_controller_cleanup();
960}
961
962static struct device_driver i8042_driver = {
963 .name = "i8042",
964 .bus = &platform_bus_type,
965 .suspend = i8042_suspend,
966 .resume = i8042_resume,
967 .shutdown = i8042_shutdown,
968};
969
970static void __init i8042_create_kbd_port(void)
971{
972 struct serio *serio;
973 struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO];
974
975 serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
976 if (serio) {
977 memset(serio, 0, sizeof(struct serio));
978 serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL;
979 serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write;
980 serio->open = i8042_open;
981 serio->close = i8042_close;
982 serio->start = i8042_start;
983 serio->stop = i8042_stop;
984 serio->port_data = port;
985 serio->dev.parent = &i8042_platform_device->dev;
986 strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name));
987 strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys));
988
989 port->serio = serio;
990 i8042_port_register(port);
991 }
992}
993
994static void __init i8042_create_aux_port(void)
995{
996 struct serio *serio;
997 struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO];
998
999 serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
1000 if (serio) {
1001 memset(serio, 0, sizeof(struct serio));
1002 serio->id.type = SERIO_8042;
1003 serio->write = i8042_aux_write;
1004 serio->open = i8042_open;
1005 serio->close = i8042_close;
1006 serio->start = i8042_start;
1007 serio->stop = i8042_stop;
1008 serio->port_data = port;
1009 serio->dev.parent = &i8042_platform_device->dev;
1010 strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name));
1011 strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys));
1012
1013 port->serio = serio;
1014 i8042_port_register(port);
1015 }
1016}
1017
1018static void __init i8042_create_mux_port(int index)
1019{
1020 struct serio *serio;
1021 struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index];
1022
1023 serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
1024 if (serio) {
1025 memset(serio, 0, sizeof(struct serio));
1026 serio->id.type = SERIO_8042;
1027 serio->write = i8042_aux_write;
1028 serio->open = i8042_open;
1029 serio->close = i8042_close;
1030 serio->start = i8042_start;
1031 serio->stop = i8042_stop;
1032 serio->port_data = port;
1033 serio->dev.parent = &i8042_platform_device->dev;
1034 snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index);
1035 snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1);
1036
1037 *port = i8042_ports[I8042_AUX_PORT_NO];
1038 port->exists = 0;
1039 snprintf(port->name, sizeof(port->name), "AUX%d", index);
1040 port->mux = index;
1041 port->serio = serio;
1042 i8042_port_register(port);
1043 }
1044}
1045
1046static int __init i8042_init(void)
1047{
1048 int i;
1049 int err;
1050
1051 dbg_init();
1052
1053 init_timer(&i8042_timer);
1054 i8042_timer.function = i8042_timer_func;
1055
1056 if (i8042_platform_init())
1057 return -EBUSY;
1058
1059 i8042_ports[I8042_AUX_PORT_NO].irq = I8042_AUX_IRQ;
1060 i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ;
1061
1062 if (i8042_controller_init()) {
1063 i8042_platform_exit();
1064 return -ENODEV;
1065 }
1066
1067 err = driver_register(&i8042_driver);
1068 if (err) {
1069 i8042_platform_exit();
1070 return err;
1071 }
1072
1073 i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0);
1074 if (IS_ERR(i8042_platform_device)) {
1075 driver_unregister(&i8042_driver);
1076 i8042_platform_exit();
1077 return PTR_ERR(i8042_platform_device);
1078 }
1079
1080 if (!i8042_noaux && !i8042_check_aux()) {
1081 if (!i8042_nomux && !i8042_check_mux())
1082 for (i = 0; i < I8042_NUM_MUX_PORTS; i++)
1083 i8042_create_mux_port(i);
1084 else
1085 i8042_create_aux_port();
1086 }
1087
1088 i8042_create_kbd_port();
1089
1090 mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
1091
1092 return 0;
1093}
1094
1095static void __exit i8042_exit(void)
1096{
1097 int i;
1098
1099 i8042_controller_cleanup();
1100
1101 for (i = 0; i < I8042_NUM_PORTS; i++)
1102 if (i8042_ports[i].exists)
1103 serio_unregister_port(i8042_ports[i].serio);
1104
1105 del_timer_sync(&i8042_timer);
1106
1107 platform_device_unregister(i8042_platform_device);
1108 driver_unregister(&i8042_driver);
1109
1110 i8042_platform_exit();
1111
1112 panic_blink = NULL;
1113}
1114
1115module_init(i8042_init);
1116module_exit(i8042_exit);
diff --git a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h
new file mode 100644
index 000000000000..13835039a2a7
--- /dev/null
+++ b/drivers/input/serio/i8042.h
@@ -0,0 +1,133 @@
1#ifndef _I8042_H
2#define _I8042_H
3
4#include <linux/config.h>
5
6/*
7 * Copyright (c) 1999-2002 Vojtech Pavlik
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published by
11 * the Free Software Foundation.
12 */
13
14/*
15 * Arch-dependent inline functions and defines.
16 */
17
18#if defined(CONFIG_MACH_JAZZ)
19#include "i8042-jazzio.h"
20#elif defined(CONFIG_SGI_IP22)
21#include "i8042-ip22io.h"
22#elif defined(CONFIG_PPC)
23#include "i8042-ppcio.h"
24#elif defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64)
25#include "i8042-sparcio.h"
26#elif defined(CONFIG_X86) || defined(CONFIG_IA64)
27#include "i8042-x86ia64io.h"
28#else
29#include "i8042-io.h"
30#endif
31
32/*
33 * This is in 50us units, the time we wait for the i8042 to react. This
34 * has to be long enough for the i8042 itself to timeout on sending a byte
35 * to a non-existent mouse.
36 */
37
38#define I8042_CTL_TIMEOUT 10000
39
40/*
41 * When the device isn't opened and it's interrupts aren't used, we poll it at
42 * regular intervals to see if any characters arrived. If yes, we can start
43 * probing for any mouse / keyboard connected. This is the period of the
44 * polling.
45 */
46
47#define I8042_POLL_PERIOD HZ/20
48
49/*
50 * Status register bits.
51 */
52
53#define I8042_STR_PARITY 0x80
54#define I8042_STR_TIMEOUT 0x40
55#define I8042_STR_AUXDATA 0x20
56#define I8042_STR_KEYLOCK 0x10
57#define I8042_STR_CMDDAT 0x08
58#define I8042_STR_MUXERR 0x04
59#define I8042_STR_IBF 0x02
60#define I8042_STR_OBF 0x01
61
62/*
63 * Control register bits.
64 */
65
66#define I8042_CTR_KBDINT 0x01
67#define I8042_CTR_AUXINT 0x02
68#define I8042_CTR_IGNKEYLOCK 0x08
69#define I8042_CTR_KBDDIS 0x10
70#define I8042_CTR_AUXDIS 0x20
71#define I8042_CTR_XLATE 0x40
72
73/*
74 * Commands.
75 */
76
77#define I8042_CMD_CTL_RCTR 0x0120
78#define I8042_CMD_CTL_WCTR 0x1060
79#define I8042_CMD_CTL_TEST 0x01aa
80
81#define I8042_CMD_KBD_DISABLE 0x00ad
82#define I8042_CMD_KBD_ENABLE 0x00ae
83#define I8042_CMD_KBD_TEST 0x01ab
84#define I8042_CMD_KBD_LOOP 0x11d2
85
86#define I8042_CMD_AUX_DISABLE 0x00a7
87#define I8042_CMD_AUX_ENABLE 0x00a8
88#define I8042_CMD_AUX_TEST 0x01a9
89#define I8042_CMD_AUX_SEND 0x10d4
90#define I8042_CMD_AUX_LOOP 0x11d3
91
92#define I8042_CMD_MUX_PFX 0x0090
93#define I8042_CMD_MUX_SEND 0x1090
94
95/*
96 * Return codes.
97 */
98
99#define I8042_RET_CTL_TEST 0x55
100
101/*
102 * Expected maximum internal i8042 buffer size. This is used for flushing
103 * the i8042 buffers.
104 */
105
106#define I8042_BUFFER_SIZE 16
107
108/*
109 * Number of AUX ports on controllers supporting active multiplexing
110 * specification
111 */
112
113#define I8042_NUM_MUX_PORTS 4
114
115/*
116 * Debug.
117 */
118
119#ifdef DEBUG
120static unsigned long i8042_start_time;
121#define dbg_init() do { i8042_start_time = jiffies; } while (0)
122#define dbg(format, arg...) \
123 do { \
124 if (i8042_debug) \
125 printk(KERN_DEBUG __FILE__ ": " format " [%d]\n" , \
126 ## arg, (int) (jiffies - i8042_start_time)); \
127 } while (0)
128#else
129#define dbg_init() do { } while (0)
130#define dbg(format, arg...) do {} while (0)
131#endif
132
133#endif /* _I8042_H */
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
new file mode 100644
index 000000000000..c978657068c5
--- /dev/null
+++ b/drivers/input/serio/libps2.c
@@ -0,0 +1,305 @@
1/*
2 * PS/2 driver library
3 *
4 * Copyright (c) 1999-2002 Vojtech Pavlik
5 * Copyright (c) 2004 Dmitry Torokhov
6 */
7
8/*
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published by
11 * the Free Software Foundation.
12 */
13
14#include <linux/delay.h>
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/slab.h>
18#include <linux/interrupt.h>
19#include <linux/input.h>
20#include <linux/serio.h>
21#include <linux/init.h>
22#include <linux/libps2.h>
23
24#define DRIVER_DESC "PS/2 driver library"
25
26MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
27MODULE_DESCRIPTION("PS/2 driver library");
28MODULE_LICENSE("GPL");
29
30EXPORT_SYMBOL(ps2_init);
31EXPORT_SYMBOL(ps2_sendbyte);
32EXPORT_SYMBOL(ps2_command);
33EXPORT_SYMBOL(ps2_schedule_command);
34EXPORT_SYMBOL(ps2_handle_ack);
35EXPORT_SYMBOL(ps2_handle_response);
36EXPORT_SYMBOL(ps2_cmd_aborted);
37
38/* Work structure to schedule execution of a command */
39struct ps2work {
40 struct work_struct work;
41 struct ps2dev *ps2dev;
42 int command;
43 unsigned char param[0];
44};
45
46
47/*
48 * ps2_sendbyte() sends a byte to the mouse, and waits for acknowledge.
49 * It doesn't handle retransmission, though it could - because when there would
50 * be need for retransmissions, the mouse has to be replaced anyway.
51 *
52 * ps2_sendbyte() can only be called from a process context
53 */
54
55int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout)
56{
57 serio_pause_rx(ps2dev->serio);
58 ps2dev->nak = 1;
59 ps2dev->flags |= PS2_FLAG_ACK;
60 serio_continue_rx(ps2dev->serio);
61
62 if (serio_write(ps2dev->serio, byte) == 0)
63 wait_event_timeout(ps2dev->wait,
64 !(ps2dev->flags & PS2_FLAG_ACK),
65 msecs_to_jiffies(timeout));
66
67 serio_pause_rx(ps2dev->serio);
68 ps2dev->flags &= ~PS2_FLAG_ACK;
69 serio_continue_rx(ps2dev->serio);
70
71 return -ps2dev->nak;
72}
73
74/*
75 * ps2_command() sends a command and its parameters to the mouse,
76 * then waits for the response and puts it in the param array.
77 *
78 * ps2_command() can only be called from a process context
79 */
80
81int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
82{
83 int timeout;
84 int send = (command >> 12) & 0xf;
85 int receive = (command >> 8) & 0xf;
86 int rc = -1;
87 int i;
88
89 down(&ps2dev->cmd_sem);
90
91 serio_pause_rx(ps2dev->serio);
92 ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0;
93 ps2dev->cmdcnt = receive;
94 if (receive && param)
95 for (i = 0; i < receive; i++)
96 ps2dev->cmdbuf[(receive - 1) - i] = param[i];
97 serio_continue_rx(ps2dev->serio);
98
99 /*
100 * Some devices (Synaptics) peform the reset before
101 * ACKing the reset command, and so it can take a long
102 * time before the ACK arrrives.
103 */
104 if (command & 0xff)
105 if (ps2_sendbyte(ps2dev, command & 0xff,
106 command == PS2_CMD_RESET_BAT ? 1000 : 200))
107 goto out;
108
109 for (i = 0; i < send; i++)
110 if (ps2_sendbyte(ps2dev, param[i], 200))
111 goto out;
112
113 /*
114 * The reset command takes a long time to execute.
115 */
116 timeout = msecs_to_jiffies(command == PS2_CMD_RESET_BAT ? 4000 : 500);
117
118 timeout = wait_event_timeout(ps2dev->wait,
119 !(ps2dev->flags & PS2_FLAG_CMD1), timeout);
120
121 if (ps2dev->cmdcnt && timeout > 0) {
122
123 if (command == PS2_CMD_RESET_BAT && timeout > msecs_to_jiffies(100)) {
124 /*
125 * Device has sent the first response byte
126 * after a reset command, reset is thus done,
127 * shorten the timeout. The next byte will come
128 * soon (keyboard) or not at all (mouse).
129 */
130 timeout = msecs_to_jiffies(100);
131 }
132
133 if (command == PS2_CMD_GETID &&
134 ps2dev->cmdbuf[receive - 1] != 0xab && /* Regular keyboards */
135 ps2dev->cmdbuf[receive - 1] != 0xac && /* NCD Sun keyboard */
136 ps2dev->cmdbuf[receive - 1] != 0x2b && /* Trust keyboard, translated */
137 ps2dev->cmdbuf[receive - 1] != 0x5d && /* Trust keyboard */
138 ps2dev->cmdbuf[receive - 1] != 0x60 && /* NMB SGI keyboard, translated */
139 ps2dev->cmdbuf[receive - 1] != 0x47) { /* NMB SGI keyboard */
140 /*
141 * Device behind the port is not a keyboard
142 * so we don't need to wait for the 2nd byte
143 * of ID response.
144 */
145 serio_pause_rx(ps2dev->serio);
146 ps2dev->flags = ps2dev->cmdcnt = 0;
147 serio_continue_rx(ps2dev->serio);
148 }
149
150 wait_event_timeout(ps2dev->wait,
151 !(ps2dev->flags & PS2_FLAG_CMD), timeout);
152 }
153
154 if (param)
155 for (i = 0; i < receive; i++)
156 param[i] = ps2dev->cmdbuf[(receive - 1) - i];
157
158 if (ps2dev->cmdcnt && (command != PS2_CMD_RESET_BAT || ps2dev->cmdcnt != 1))
159 goto out;
160
161 rc = 0;
162
163out:
164 serio_pause_rx(ps2dev->serio);
165 ps2dev->flags = 0;
166 serio_continue_rx(ps2dev->serio);
167
168 up(&ps2dev->cmd_sem);
169 return rc;
170}
171
172/*
173 * ps2_execute_scheduled_command() sends a command, previously scheduled by
174 * ps2_schedule_command(), to a PS/2 device (keyboard, mouse, etc.)
175 */
176
177static void ps2_execute_scheduled_command(void *data)
178{
179 struct ps2work *ps2work = data;
180
181 ps2_command(ps2work->ps2dev, ps2work->param, ps2work->command);
182 kfree(ps2work);
183}
184
185/*
186 * ps2_schedule_command() allows to schedule delayed execution of a PS/2
187 * command and can be used to issue a command from an interrupt or softirq
188 * context.
189 */
190
191int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int command)
192{
193 struct ps2work *ps2work;
194 int send = (command >> 12) & 0xf;
195 int receive = (command >> 8) & 0xf;
196
197 if (!(ps2work = kmalloc(sizeof(struct ps2work) + max(send, receive), GFP_ATOMIC)))
198 return -1;
199
200 memset(ps2work, 0, sizeof(struct ps2work));
201 ps2work->ps2dev = ps2dev;
202 ps2work->command = command;
203 memcpy(ps2work->param, param, send);
204 INIT_WORK(&ps2work->work, ps2_execute_scheduled_command, ps2work);
205
206 if (!schedule_work(&ps2work->work)) {
207 kfree(ps2work);
208 return -1;
209 }
210
211 return 0;
212}
213
214/*
215 * ps2_init() initializes ps2dev structure
216 */
217
218void ps2_init(struct ps2dev *ps2dev, struct serio *serio)
219{
220 init_MUTEX(&ps2dev->cmd_sem);
221 init_waitqueue_head(&ps2dev->wait);
222 ps2dev->serio = serio;
223}
224
225/*
226 * ps2_handle_ack() is supposed to be used in interrupt handler
227 * to properly process ACK/NAK of a command from a PS/2 device.
228 */
229
230int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data)
231{
232 switch (data) {
233 case PS2_RET_ACK:
234 ps2dev->nak = 0;
235 break;
236
237 case PS2_RET_NAK:
238 ps2dev->nak = 1;
239 break;
240
241 /*
242 * Workaround for mice which don't ACK the Get ID command.
243 * These are valid mouse IDs that we recognize.
244 */
245 case 0x00:
246 case 0x03:
247 case 0x04:
248 if (ps2dev->flags & PS2_FLAG_WAITID) {
249 ps2dev->nak = 0;
250 break;
251 }
252 /* Fall through */
253 default:
254 return 0;
255 }
256
257
258 if (!ps2dev->nak && ps2dev->cmdcnt)
259 ps2dev->flags |= PS2_FLAG_CMD | PS2_FLAG_CMD1;
260
261 ps2dev->flags &= ~PS2_FLAG_ACK;
262 wake_up(&ps2dev->wait);
263
264 if (data != PS2_RET_ACK)
265 ps2_handle_response(ps2dev, data);
266
267 return 1;
268}
269
270/*
271 * ps2_handle_response() is supposed to be used in interrupt handler
272 * to properly store device's response to a command and notify process
273 * waiting for completion of the command.
274 */
275
276int ps2_handle_response(struct ps2dev *ps2dev, unsigned char data)
277{
278 if (ps2dev->cmdcnt)
279 ps2dev->cmdbuf[--ps2dev->cmdcnt] = data;
280
281 if (ps2dev->flags & PS2_FLAG_CMD1) {
282 ps2dev->flags &= ~PS2_FLAG_CMD1;
283 if (ps2dev->cmdcnt)
284 wake_up(&ps2dev->wait);
285 }
286
287 if (!ps2dev->cmdcnt) {
288 ps2dev->flags &= ~PS2_FLAG_CMD;
289 wake_up(&ps2dev->wait);
290 }
291
292 return 1;
293}
294
295void ps2_cmd_aborted(struct ps2dev *ps2dev)
296{
297 if (ps2dev->flags & PS2_FLAG_ACK)
298 ps2dev->nak = 1;
299
300 if (ps2dev->flags & (PS2_FLAG_ACK | PS2_FLAG_CMD))
301 wake_up(&ps2dev->wait);
302
303 ps2dev->flags = 0;
304}
305
diff --git a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c
new file mode 100644
index 000000000000..9880fc145d90
--- /dev/null
+++ b/drivers/input/serio/maceps2.c
@@ -0,0 +1,176 @@
1/*
2 * SGI O2 MACE PS2 controller driver for linux
3 *
4 * Copyright (C) 2002 Vivien Chappelier
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation
9 */
10#include <linux/module.h>
11#include <linux/init.h>
12#include <linux/serio.h>
13#include <linux/errno.h>
14#include <linux/interrupt.h>
15#include <linux/ioport.h>
16#include <linux/delay.h>
17#include <linux/device.h>
18#include <linux/slab.h>
19#include <linux/spinlock.h>
20#include <linux/err.h>
21
22#include <asm/io.h>
23#include <asm/irq.h>
24#include <asm/system.h>
25#include <asm/ip32/mace.h>
26#include <asm/ip32/ip32_ints.h>
27
28MODULE_AUTHOR("Vivien Chappelier <vivien.chappelier@linux-mips.org");
29MODULE_DESCRIPTION("SGI O2 MACE PS2 controller driver");
30MODULE_LICENSE("GPL");
31
32#define MACE_PS2_TIMEOUT 10000 /* in 50us unit */
33
34#define PS2_STATUS_CLOCK_SIGNAL BIT(0) /* external clock signal */
35#define PS2_STATUS_CLOCK_INHIBIT BIT(1) /* clken output signal */
36#define PS2_STATUS_TX_INPROGRESS BIT(2) /* transmission in progress */
37#define PS2_STATUS_TX_EMPTY BIT(3) /* empty transmit buffer */
38#define PS2_STATUS_RX_FULL BIT(4) /* full receive buffer */
39#define PS2_STATUS_RX_INPROGRESS BIT(5) /* reception in progress */
40#define PS2_STATUS_ERROR_PARITY BIT(6) /* parity error */
41#define PS2_STATUS_ERROR_FRAMING BIT(7) /* framing error */
42
43#define PS2_CONTROL_TX_CLOCK_DISABLE BIT(0) /* inhibit clock signal after TX */
44#define PS2_CONTROL_TX_ENABLE BIT(1) /* transmit enable */
45#define PS2_CONTROL_TX_INT_ENABLE BIT(2) /* enable transmit interrupt */
46#define PS2_CONTROL_RX_INT_ENABLE BIT(3) /* enable receive interrupt */
47#define PS2_CONTROL_RX_CLOCK_ENABLE BIT(4) /* pause reception if set to 0 */
48#define PS2_CONTROL_RESET BIT(5) /* reset */
49
50struct maceps2_data {
51 struct mace_ps2port *port;
52 int irq;
53};
54
55static struct maceps2_data port_data[2];
56static struct serio *maceps2_port[2];
57static struct platform_device *maceps2_device;
58
59static int maceps2_write(struct serio *dev, unsigned char val)
60{
61 struct mace_ps2port *port = ((struct maceps2_data *)dev->port_data)->port;
62 unsigned int timeout = MACE_PS2_TIMEOUT;
63
64 do {
65 if (port->status & PS2_STATUS_TX_EMPTY) {
66 port->tx = val;
67 return 0;
68 }
69 udelay(50);
70 } while (timeout--);
71
72 return -1;
73}
74
75static irqreturn_t maceps2_interrupt(int irq, void *dev_id,
76 struct pt_regs *regs)
77{
78 struct serio *dev = dev_id;
79 struct mace_ps2port *port = ((struct maceps2_data *)dev->port_data)->port;
80 unsigned long byte;
81
82 if (port->status & PS2_STATUS_RX_FULL) {
83 byte = port->rx;
84 serio_interrupt(dev, byte & 0xff, 0, regs);
85 }
86
87 return IRQ_HANDLED;
88}
89
90static int maceps2_open(struct serio *dev)
91{
92 struct maceps2_data *data = (struct maceps2_data *)dev->port_data;
93
94 if (request_irq(data->irq, maceps2_interrupt, 0, "PS2 port", dev)) {
95 printk(KERN_ERR "Could not allocate PS/2 IRQ\n");
96 return -EBUSY;
97 }
98
99 /* Reset port */
100 data->port->control = PS2_CONTROL_TX_CLOCK_DISABLE | PS2_CONTROL_RESET;
101 udelay(100);
102
103 /* Enable interrupts */
104 data->port->control = PS2_CONTROL_RX_CLOCK_ENABLE |
105 PS2_CONTROL_TX_ENABLE |
106 PS2_CONTROL_RX_INT_ENABLE;
107
108 return 0;
109}
110
111static void maceps2_close(struct serio *dev)
112{
113 struct maceps2_data *data = (struct maceps2_data *)dev->port_data;
114
115 data->port->control = PS2_CONTROL_TX_CLOCK_DISABLE | PS2_CONTROL_RESET;
116 udelay(100);
117 free_irq(data->irq, dev);
118}
119
120
121static struct serio * __init maceps2_allocate_port(int idx)
122{
123 struct serio *serio;
124
125 serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
126 if (serio) {
127 memset(serio, 0, sizeof(struct serio));
128 serio->id.type = SERIO_8042;
129 serio->write = maceps2_write;
130 serio->open = maceps2_open;
131 serio->close = maceps2_close;
132 snprintf(serio->name, sizeof(serio->name), "MACE PS/2 port%d", idx);
133 snprintf(serio->phys, sizeof(serio->phys), "mace/serio%d", idx);
134 serio->port_data = &port_data[idx];
135 serio->dev.parent = &maceps2_device->dev;
136 }
137
138 return serio;
139}
140
141
142static int __init maceps2_init(void)
143{
144 maceps2_device = platform_device_register_simple("maceps2", -1, NULL, 0);
145 if (IS_ERR(maceps2_device))
146 return PTR_ERR(maceps2_device);
147
148 port_data[0].port = &mace->perif.ps2.keyb;
149 port_data[0].irq = MACEISA_KEYB_IRQ;
150 port_data[1].port = &mace->perif.ps2.mouse;
151 port_data[1].irq = MACEISA_MOUSE_IRQ;
152
153 maceps2_port[0] = maceps2_allocate_port(0);
154 maceps2_port[1] = maceps2_allocate_port(1);
155 if (!maceps2_port[0] || !maceps2_port[1]) {
156 kfree(maceps2_port[0]);
157 kfree(maceps2_port[1]);
158 platform_device_unregister(maceps2_device);
159 return -ENOMEM;
160 }
161
162 serio_register_port(maceps2_port[0]);
163 serio_register_port(maceps2_port[1]);
164
165 return 0;
166}
167
168static void __exit maceps2_exit(void)
169{
170 serio_unregister_port(maceps2_port[0]);
171 serio_unregister_port(maceps2_port[1]);
172 platform_device_unregister(maceps2_device);
173}
174
175module_init(maceps2_init);
176module_exit(maceps2_exit);
diff --git a/drivers/input/serio/parkbd.c b/drivers/input/serio/parkbd.c
new file mode 100644
index 000000000000..1d15c2819818
--- /dev/null
+++ b/drivers/input/serio/parkbd.c
@@ -0,0 +1,218 @@
1/*
2 * Parallel port to Keyboard port adapter driver for Linux
3 *
4 * Copyright (c) 1999-2004 Vojtech Pavlik
5 */
6
7/*
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 */
12
13/*
14 * To connect an AT or XT keyboard to the parallel port, a fairly simple adapter
15 * can be made:
16 *
17 * Parallel port Keyboard port
18 *
19 * +5V --------------------- +5V (4)
20 *
21 * ______
22 * +5V -------|______|--.
23 * |
24 * ACK (10) ------------|
25 * |--- KBD CLOCK (5)
26 * STROBE (1) ---|<|----'
27 *
28 * ______
29 * +5V -------|______|--.
30 * |
31 * BUSY (11) -----------|
32 * |--- KBD DATA (1)
33 * AUTOFD (14) --|<|----'
34 *
35 * GND (18-25) ------------- GND (3)
36 *
37 * The diodes can be fairly any type, and the resistors should be somewhere
38 * around 5 kOhm, but the adapter will likely work without the resistors,
39 * too.
40 *
41 * The +5V source can be taken either from USB, from mouse or keyboard ports,
42 * or from a joystick port. Unfortunately, the parallel port of a PC doesn't
43 * have a +5V pin, and feeding the keyboard from signal pins is out of question
44 * with 300 mA power reqirement of a typical AT keyboard.
45 */
46
47#include <linux/module.h>
48#include <linux/parport.h>
49#include <linux/init.h>
50#include <linux/serio.h>
51
52MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
53MODULE_DESCRIPTION("Parallel port to Keyboard port adapter driver");
54MODULE_LICENSE("GPL");
55
56static unsigned int parkbd_pp_no;
57module_param_named(port, parkbd_pp_no, int, 0);
58MODULE_PARM_DESC(port, "Parallel port the adapter is connected to (default is 0)");
59
60static unsigned int parkbd_mode = SERIO_8042;
61module_param_named(mode, parkbd_mode, uint, 0);
62MODULE_PARM_DESC(mode, "Mode of operation: XT = 0/AT = 1 (default)");
63
64#define PARKBD_CLOCK 0x01 /* Strobe & Ack */
65#define PARKBD_DATA 0x02 /* AutoFd & Busy */
66
67static int parkbd_buffer;
68static int parkbd_counter;
69static unsigned long parkbd_last;
70static int parkbd_writing;
71static unsigned long parkbd_start;
72
73static struct pardevice *parkbd_dev;
74static struct serio *parkbd_port;
75
76static int parkbd_readlines(void)
77{
78 return (parport_read_status(parkbd_dev->port) >> 6) ^ 2;
79}
80
81static void parkbd_writelines(int data)
82{
83 parport_write_control(parkbd_dev->port, (~data & 3) | 0x10);
84}
85
86static int parkbd_write(struct serio *port, unsigned char c)
87{
88 unsigned char p;
89
90 if (!parkbd_mode) return -1;
91
92 p = c ^ (c >> 4);
93 p = p ^ (p >> 2);
94 p = p ^ (p >> 1);
95
96 parkbd_counter = 0;
97 parkbd_writing = 1;
98 parkbd_buffer = c | (((int) (~p & 1)) << 8) | 0x600;
99
100 parkbd_writelines(2);
101
102 return 0;
103}
104
105static void parkbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
106{
107
108 if (parkbd_writing) {
109
110 if (parkbd_counter && ((parkbd_counter == 11) || time_after(jiffies, parkbd_last + HZ/100))) {
111 parkbd_counter = 0;
112 parkbd_buffer = 0;
113 parkbd_writing = 0;
114 parkbd_writelines(3);
115 return;
116 }
117
118 parkbd_writelines(((parkbd_buffer >> parkbd_counter++) & 1) | 2);
119
120 if (parkbd_counter == 11) {
121 parkbd_counter = 0;
122 parkbd_buffer = 0;
123 parkbd_writing = 0;
124 parkbd_writelines(3);
125 }
126
127 } else {
128
129 if ((parkbd_counter == parkbd_mode + 10) || time_after(jiffies, parkbd_last + HZ/100)) {
130 parkbd_counter = 0;
131 parkbd_buffer = 0;
132 }
133
134 parkbd_buffer |= (parkbd_readlines() >> 1) << parkbd_counter++;
135
136 if (parkbd_counter == parkbd_mode + 10)
137 serio_interrupt(parkbd_port, (parkbd_buffer >> (2 - parkbd_mode)) & 0xff, 0, regs);
138 }
139
140 parkbd_last = jiffies;
141}
142
143static int parkbd_getport(void)
144{
145 struct parport *pp;
146
147 pp = parport_find_number(parkbd_pp_no);
148
149 if (pp == NULL) {
150 printk(KERN_ERR "parkbd: no such parport\n");
151 return -ENODEV;
152 }
153
154 parkbd_dev = parport_register_device(pp, "parkbd", NULL, NULL, parkbd_interrupt, PARPORT_DEV_EXCL, NULL);
155 parport_put_port(pp);
156
157 if (!parkbd_dev)
158 return -ENODEV;
159
160 if (parport_claim(parkbd_dev)) {
161 parport_unregister_device(parkbd_dev);
162 return -EBUSY;
163 }
164
165 parkbd_start = jiffies;
166
167 return 0;
168}
169
170static struct serio * __init parkbd_allocate_serio(void)
171{
172 struct serio *serio;
173
174 serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
175 if (serio) {
176 memset(serio, 0, sizeof(struct serio));
177 serio->id.type = parkbd_mode;
178 serio->write = parkbd_write,
179 strlcpy(serio->name, "PARKBD AT/XT keyboard adapter", sizeof(serio->name));
180 snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", parkbd_dev->port->name);
181 }
182
183 return serio;
184}
185
186static int __init parkbd_init(void)
187{
188 int err;
189
190 err = parkbd_getport();
191 if (err)
192 return err;
193
194 parkbd_port = parkbd_allocate_serio();
195 if (!parkbd_port) {
196 parport_release(parkbd_dev);
197 return -ENOMEM;
198 }
199
200 parkbd_writelines(3);
201
202 serio_register_port(parkbd_port);
203
204 printk(KERN_INFO "serio: PARKBD %s adapter on %s\n",
205 parkbd_mode ? "AT" : "XT", parkbd_dev->port->name);
206
207 return 0;
208}
209
210static void __exit parkbd_exit(void)
211{
212 parport_release(parkbd_dev);
213 serio_unregister_port(parkbd_port);
214 parport_unregister_device(parkbd_dev);
215}
216
217module_init(parkbd_init);
218module_exit(parkbd_exit);
diff --git a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c
new file mode 100644
index 000000000000..1e139c5e59de
--- /dev/null
+++ b/drivers/input/serio/pcips2.c
@@ -0,0 +1,234 @@
1/*
2 * linux/drivers/input/serio/pcips2.c
3 *
4 * Copyright (C) 2003 Russell King, All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License.
9 *
10 * I'm not sure if this is a generic PS/2 PCI interface or specific to
11 * the Mobility Electronics docking station.
12 */
13#include <linux/module.h>
14#include <linux/interrupt.h>
15#include <linux/ioport.h>
16#include <linux/input.h>
17#include <linux/pci.h>
18#include <linux/init.h>
19#include <linux/serio.h>
20#include <linux/delay.h>
21#include <asm/io.h>
22
23#define PS2_CTRL (0)
24#define PS2_STATUS (1)
25#define PS2_DATA (2)
26
27#define PS2_CTRL_CLK (1<<0)
28#define PS2_CTRL_DAT (1<<1)
29#define PS2_CTRL_TXIRQ (1<<2)
30#define PS2_CTRL_ENABLE (1<<3)
31#define PS2_CTRL_RXIRQ (1<<4)
32
33#define PS2_STAT_CLK (1<<0)
34#define PS2_STAT_DAT (1<<1)
35#define PS2_STAT_PARITY (1<<2)
36#define PS2_STAT_RXFULL (1<<5)
37#define PS2_STAT_TXBUSY (1<<6)
38#define PS2_STAT_TXEMPTY (1<<7)
39
40struct pcips2_data {
41 struct serio *io;
42 unsigned int base;
43 struct pci_dev *dev;
44};
45
46static int pcips2_write(struct serio *io, unsigned char val)
47{
48 struct pcips2_data *ps2if = io->port_data;
49 unsigned int stat;
50
51 do {
52 stat = inb(ps2if->base + PS2_STATUS);
53 cpu_relax();
54 } while (!(stat & PS2_STAT_TXEMPTY));
55
56 outb(val, ps2if->base + PS2_DATA);
57
58 return 0;
59}
60
61static irqreturn_t pcips2_interrupt(int irq, void *devid, struct pt_regs *regs)
62{
63 struct pcips2_data *ps2if = devid;
64 unsigned char status, scancode;
65 int handled = 0;
66
67 do {
68 unsigned int flag;
69
70 status = inb(ps2if->base + PS2_STATUS);
71 if (!(status & PS2_STAT_RXFULL))
72 break;
73 handled = 1;
74 scancode = inb(ps2if->base + PS2_DATA);
75 if (status == 0xff && scancode == 0xff)
76 break;
77
78 flag = (status & PS2_STAT_PARITY) ? 0 : SERIO_PARITY;
79
80 if (hweight8(scancode) & 1)
81 flag ^= SERIO_PARITY;
82
83 serio_interrupt(ps2if->io, scancode, flag, regs);
84 } while (1);
85 return IRQ_RETVAL(handled);
86}
87
88static void pcips2_flush_input(struct pcips2_data *ps2if)
89{
90 unsigned char status, scancode;
91
92 do {
93 status = inb(ps2if->base + PS2_STATUS);
94 if (!(status & PS2_STAT_RXFULL))
95 break;
96 scancode = inb(ps2if->base + PS2_DATA);
97 if (status == 0xff && scancode == 0xff)
98 break;
99 } while (1);
100}
101
102static int pcips2_open(struct serio *io)
103{
104 struct pcips2_data *ps2if = io->port_data;
105 int ret, val = 0;
106
107 outb(PS2_CTRL_ENABLE, ps2if->base);
108 pcips2_flush_input(ps2if);
109
110 ret = request_irq(ps2if->dev->irq, pcips2_interrupt, SA_SHIRQ,
111 "pcips2", ps2if);
112 if (ret == 0)
113 val = PS2_CTRL_ENABLE | PS2_CTRL_RXIRQ;
114
115 outb(val, ps2if->base);
116
117 return ret;
118}
119
120static void pcips2_close(struct serio *io)
121{
122 struct pcips2_data *ps2if = io->port_data;
123
124 outb(0, ps2if->base);
125
126 free_irq(ps2if->dev->irq, ps2if);
127}
128
129static int __devinit pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id)
130{
131 struct pcips2_data *ps2if;
132 struct serio *serio;
133 int ret;
134
135 ret = pci_enable_device(dev);
136 if (ret)
137 goto out;
138
139 ret = pci_request_regions(dev, "pcips2");
140 if (ret)
141 goto disable;
142
143 ps2if = kmalloc(sizeof(struct pcips2_data), GFP_KERNEL);
144 serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
145 if (!ps2if || !serio) {
146 ret = -ENOMEM;
147 goto release;
148 }
149
150 memset(ps2if, 0, sizeof(struct pcips2_data));
151 memset(serio, 0, sizeof(struct serio));
152
153 serio->id.type = SERIO_8042;
154 serio->write = pcips2_write;
155 serio->open = pcips2_open;
156 serio->close = pcips2_close;
157 strlcpy(serio->name, pci_name(dev), sizeof(serio->name));
158 strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
159 serio->port_data = ps2if;
160 serio->dev.parent = &dev->dev;
161 ps2if->io = serio;
162 ps2if->dev = dev;
163 ps2if->base = pci_resource_start(dev, 0);
164
165 pci_set_drvdata(dev, ps2if);
166
167 serio_register_port(ps2if->io);
168 return 0;
169
170 release:
171 kfree(ps2if);
172 kfree(serio);
173 pci_release_regions(dev);
174 disable:
175 pci_disable_device(dev);
176 out:
177 return ret;
178}
179
180static void __devexit pcips2_remove(struct pci_dev *dev)
181{
182 struct pcips2_data *ps2if = pci_get_drvdata(dev);
183
184 serio_unregister_port(ps2if->io);
185 pci_set_drvdata(dev, NULL);
186 kfree(ps2if);
187 pci_release_regions(dev);
188 pci_disable_device(dev);
189}
190
191static struct pci_device_id pcips2_ids[] = {
192 {
193 .vendor = 0x14f2, /* MOBILITY */
194 .device = 0x0123, /* Keyboard */
195 .subvendor = PCI_ANY_ID,
196 .subdevice = PCI_ANY_ID,
197 .class = PCI_CLASS_INPUT_KEYBOARD << 8,
198 .class_mask = 0xffff00,
199 },
200 {
201 .vendor = 0x14f2, /* MOBILITY */
202 .device = 0x0124, /* Mouse */
203 .subvendor = PCI_ANY_ID,
204 .subdevice = PCI_ANY_ID,
205 .class = PCI_CLASS_INPUT_MOUSE << 8,
206 .class_mask = 0xffff00,
207 },
208 { 0, }
209};
210
211static struct pci_driver pcips2_driver = {
212 .name = "pcips2",
213 .id_table = pcips2_ids,
214 .probe = pcips2_probe,
215 .remove = __devexit_p(pcips2_remove),
216};
217
218static int __init pcips2_init(void)
219{
220 return pci_register_driver(&pcips2_driver);
221}
222
223static void __exit pcips2_exit(void)
224{
225 pci_unregister_driver(&pcips2_driver);
226}
227
228module_init(pcips2_init);
229module_exit(pcips2_exit);
230
231MODULE_LICENSE("GPL");
232MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
233MODULE_DESCRIPTION("PCI PS/2 keyboard/mouse driver");
234MODULE_DEVICE_TABLE(pci, pcips2_ids);
diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c
new file mode 100644
index 000000000000..46093c507988
--- /dev/null
+++ b/drivers/input/serio/q40kbd.c
@@ -0,0 +1,163 @@
1/*
2 * $Id: q40kbd.c,v 1.12 2002/02/02 22:26:44 vojtech Exp $
3 *
4 * Copyright (c) 2000-2001 Vojtech Pavlik
5 *
6 * Based on the work of:
7 * Richard Zidlicky <Richard.Zidlicky@stud.informatik.uni-erlangen.de>
8 */
9
10/*
11 * Q40 PS/2 keyboard controller driver for Linux/m68k
12 */
13
14/*
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 * Should you need to contact me, the author, you can do so either by
30 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
31 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
32 */
33
34#include <linux/module.h>
35#include <linux/init.h>
36#include <linux/serio.h>
37#include <linux/interrupt.h>
38#include <linux/err.h>
39#include <linux/bitops.h>
40
41#include <asm/io.h>
42#include <asm/uaccess.h>
43#include <asm/q40_master.h>
44#include <asm/irq.h>
45#include <asm/q40ints.h>
46
47MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
48MODULE_DESCRIPTION("Q40 PS/2 keyboard controller driver");
49MODULE_LICENSE("GPL");
50
51DEFINE_SPINLOCK(q40kbd_lock);
52static struct serio *q40kbd_port;
53static struct platform_device *q40kbd_device;
54
55static irqreturn_t q40kbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
56{
57 unsigned long flags;
58
59 spin_lock_irqsave(&q40kbd_lock, flags);
60
61 if (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG))
62 serio_interrupt(q40kbd_port, master_inb(KEYCODE_REG), 0, regs);
63
64 master_outb(-1, KEYBOARD_UNLOCK_REG);
65
66 spin_unlock_irqrestore(&q40kbd_lock, flags);
67
68 return IRQ_HANDLED;
69}
70
71/*
72 * q40kbd_flush() flushes all data that may be in the keyboard buffers
73 */
74
75static void q40kbd_flush(void)
76{
77 int maxread = 100;
78 unsigned long flags;
79
80 spin_lock_irqsave(&q40kbd_lock, flags);
81
82 while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)))
83 master_inb(KEYCODE_REG);
84
85 spin_unlock_irqrestore(&q40kbd_lock, flags);
86}
87
88/*
89 * q40kbd_open() is called when a port is open by the higher layer.
90 * It allocates the interrupt and enables in in the chip.
91 */
92
93static int q40kbd_open(struct serio *port)
94{
95 q40kbd_flush();
96
97 if (request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, "q40kbd", NULL)) {
98 printk(KERN_ERR "q40kbd.c: Can't get irq %d.\n", Q40_IRQ_KEYBOARD);
99 return -1;
100 }
101
102 /* off we go */
103 master_outb(-1, KEYBOARD_UNLOCK_REG);
104 master_outb(1, KEY_IRQ_ENABLE_REG);
105
106 return 0;
107}
108
109static void q40kbd_close(struct serio *port)
110{
111 master_outb(0, KEY_IRQ_ENABLE_REG);
112 master_outb(-1, KEYBOARD_UNLOCK_REG);
113 free_irq(Q40_IRQ_KEYBOARD, NULL);
114
115 q40kbd_flush();
116}
117
118static struct serio * __init q40kbd_allocate_port(void)
119{
120 struct serio *serio;
121
122 serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
123 if (serio) {
124 memset(serio, 0, sizeof(struct serio));
125 serio->id.type = SERIO_8042;
126 serio->open = q40kbd_open;
127 serio->close = q40kbd_close;
128 serio->dev.parent = &q40kbd_device->dev;
129 strlcpy(serio->name, "Q40 Kbd Port", sizeof(serio->name));
130 strlcpy(serio->phys, "Q40", sizeof(serio->phys));
131 }
132
133 return serio;
134}
135
136static int __init q40kbd_init(void)
137{
138 if (!MACH_IS_Q40)
139 return -EIO;
140
141 q40kbd_device = platform_device_register_simple("q40kbd", -1, NULL, 0);
142 if (IS_ERR(q40kbd_device))
143 return PTR_ERR(q40kbd_device);
144
145 if (!(q40kbd_port = q40kbd_allocate_port())) {
146 platform_device_unregister(q40kbd_device);
147 return -ENOMEM;
148 }
149
150 serio_register_port(q40kbd_port);
151 printk(KERN_INFO "serio: Q40 kbd registered\n");
152
153 return 0;
154}
155
156static void __exit q40kbd_exit(void)
157{
158 serio_unregister_port(q40kbd_port);
159 platform_device_unregister(q40kbd_device);
160}
161
162module_init(q40kbd_init);
163module_exit(q40kbd_exit);
diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
new file mode 100644
index 000000000000..106f5eefd89a
--- /dev/null
+++ b/drivers/input/serio/rpckbd.c
@@ -0,0 +1,156 @@
1/*
2 * $Id: rpckbd.c,v 1.7 2001/09/25 10:12:07 vojtech Exp $
3 *
4 * Copyright (c) 2000-2001 Vojtech Pavlik
5 * Copyright (c) 2002 Russell King
6 */
7
8/*
9 * Acorn RiscPC PS/2 keyboard controller driver for Linux/ARM
10 */
11
12/*
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27 * Should you need to contact me, the author, you can do so either by
28 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
29 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
30 */
31
32#include <linux/module.h>
33#include <linux/interrupt.h>
34#include <linux/init.h>
35#include <linux/serio.h>
36#include <linux/err.h>
37
38#include <asm/irq.h>
39#include <asm/hardware.h>
40#include <asm/io.h>
41#include <asm/hardware/iomd.h>
42#include <asm/system.h>
43
44MODULE_AUTHOR("Vojtech Pavlik, Russell King");
45MODULE_DESCRIPTION("Acorn RiscPC PS/2 keyboard controller driver");
46MODULE_LICENSE("GPL");
47
48static int rpckbd_write(struct serio *port, unsigned char val)
49{
50 while (!(iomd_readb(IOMD_KCTRL) & (1 << 7)))
51 cpu_relax();
52
53 iomd_writeb(val, IOMD_KARTTX);
54
55 return 0;
56}
57
58static irqreturn_t rpckbd_rx(int irq, void *dev_id, struct pt_regs *regs)
59{
60 struct serio *port = dev_id;
61 unsigned int byte;
62 int handled = IRQ_NONE;
63
64 while (iomd_readb(IOMD_KCTRL) & (1 << 5)) {
65 byte = iomd_readb(IOMD_KARTRX);
66
67 serio_interrupt(port, byte, 0, regs);
68 handled = IRQ_HANDLED;
69 }
70 return handled;
71}
72
73static irqreturn_t rpckbd_tx(int irq, void *dev_id, struct pt_regs *regs)
74{
75 return IRQ_HANDLED;
76}
77
78static int rpckbd_open(struct serio *port)
79{
80 /* Reset the keyboard state machine. */
81 iomd_writeb(0, IOMD_KCTRL);
82 iomd_writeb(8, IOMD_KCTRL);
83 iomd_readb(IOMD_KARTRX);
84
85 if (request_irq(IRQ_KEYBOARDRX, rpckbd_rx, 0, "rpckbd", port) != 0) {
86 printk(KERN_ERR "rpckbd.c: Could not allocate keyboard receive IRQ\n");
87 return -EBUSY;
88 }
89
90 if (request_irq(IRQ_KEYBOARDTX, rpckbd_tx, 0, "rpckbd", port) != 0) {
91 printk(KERN_ERR "rpckbd.c: Could not allocate keyboard transmit IRQ\n");
92 free_irq(IRQ_KEYBOARDRX, NULL);
93 return -EBUSY;
94 }
95
96 return 0;
97}
98
99static void rpckbd_close(struct serio *port)
100{
101 free_irq(IRQ_KEYBOARDRX, port);
102 free_irq(IRQ_KEYBOARDTX, port);
103}
104
105/*
106 * Allocate and initialize serio structure for subsequent registration
107 * with serio core.
108 */
109static int __devinit rpckbd_probe(struct device *dev)
110{
111 struct serio *serio;
112
113 serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
114 if (!serio)
115 return -ENOMEM;
116
117 memset(serio, 0, sizeof(struct serio));
118 serio->id.type = SERIO_8042;
119 serio->write = rpckbd_write;
120 serio->open = rpckbd_open;
121 serio->close = rpckbd_close;
122 serio->dev.parent = dev;
123 strlcpy(serio->name, "RiscPC PS/2 kbd port", sizeof(serio->name));
124 strlcpy(serio->phys, "rpckbd/serio0", sizeof(serio->phys));
125
126 dev_set_drvdata(dev, serio);
127 serio_register_port(serio);
128 return 0;
129}
130
131static int __devexit rpckbd_remove(struct device *dev)
132{
133 struct serio *serio = dev_get_drvdata(dev);
134 serio_unregister_port(serio);
135 return 0;
136}
137
138static struct device_driver rpckbd_driver = {
139 .name = "kart",
140 .bus = &platform_bus_type,
141 .probe = rpckbd_probe,
142 .remove = __devexit_p(rpckbd_remove),
143};
144
145static int __init rpckbd_init(void)
146{
147 return driver_register(&rpckbd_driver);
148}
149
150static void __exit rpckbd_exit(void)
151{
152 driver_unregister(&rpckbd_driver);
153}
154
155module_init(rpckbd_init);
156module_exit(rpckbd_exit);
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
new file mode 100644
index 000000000000..3f0df3330fb2
--- /dev/null
+++ b/drivers/input/serio/sa1111ps2.c
@@ -0,0 +1,359 @@
1/*
2 * linux/drivers/input/serio/sa1111ps2.c
3 *
4 * Copyright (C) 2002 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License.
9 */
10#include <linux/module.h>
11#include <linux/init.h>
12#include <linux/input.h>
13#include <linux/serio.h>
14#include <linux/errno.h>
15#include <linux/interrupt.h>
16#include <linux/ioport.h>
17#include <linux/delay.h>
18#include <linux/device.h>
19#include <linux/slab.h>
20#include <linux/spinlock.h>
21
22#include <asm/io.h>
23#include <asm/irq.h>
24#include <asm/system.h>
25
26#include <asm/hardware/sa1111.h>
27
28struct ps2if {
29 struct serio *io;
30 struct sa1111_dev *dev;
31 void __iomem *base;
32 unsigned int open;
33 spinlock_t lock;
34 unsigned int head;
35 unsigned int tail;
36 unsigned char buf[4];
37};
38
39/*
40 * Read all bytes waiting in the PS2 port. There should be
41 * at the most one, but we loop for safety. If there was a
42 * framing error, we have to manually clear the status.
43 */
44static irqreturn_t ps2_rxint(int irq, void *dev_id, struct pt_regs *regs)
45{
46 struct ps2if *ps2if = dev_id;
47 unsigned int scancode, flag, status;
48
49 status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
50 while (status & PS2STAT_RXF) {
51 if (status & PS2STAT_STP)
52 sa1111_writel(PS2STAT_STP, ps2if->base + SA1111_PS2STAT);
53
54 flag = (status & PS2STAT_STP ? SERIO_FRAME : 0) |
55 (status & PS2STAT_RXP ? 0 : SERIO_PARITY);
56
57 scancode = sa1111_readl(ps2if->base + SA1111_PS2DATA) & 0xff;
58
59 if (hweight8(scancode) & 1)
60 flag ^= SERIO_PARITY;
61
62 serio_interrupt(ps2if->io, scancode, flag, regs);
63
64 status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
65 }
66
67 return IRQ_HANDLED;
68}
69
70/*
71 * Completion of ps2 write
72 */
73static irqreturn_t ps2_txint(int irq, void *dev_id, struct pt_regs *regs)
74{
75 struct ps2if *ps2if = dev_id;
76 unsigned int status;
77
78 spin_lock(&ps2if->lock);
79 status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
80 if (ps2if->head == ps2if->tail) {
81 disable_irq(irq);
82 /* done */
83 } else if (status & PS2STAT_TXE) {
84 sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + SA1111_PS2DATA);
85 ps2if->tail = (ps2if->tail + 1) & (sizeof(ps2if->buf) - 1);
86 }
87 spin_unlock(&ps2if->lock);
88
89 return IRQ_HANDLED;
90}
91
92/*
93 * Write a byte to the PS2 port. We have to wait for the
94 * port to indicate that the transmitter is empty.
95 */
96static int ps2_write(struct serio *io, unsigned char val)
97{
98 struct ps2if *ps2if = io->port_data;
99 unsigned long flags;
100 unsigned int head;
101
102 spin_lock_irqsave(&ps2if->lock, flags);
103
104 /*
105 * If the TX register is empty, we can go straight out.
106 */
107 if (sa1111_readl(ps2if->base + SA1111_PS2STAT) & PS2STAT_TXE) {
108 sa1111_writel(val, ps2if->base + SA1111_PS2DATA);
109 } else {
110 if (ps2if->head == ps2if->tail)
111 enable_irq(ps2if->dev->irq[1]);
112 head = (ps2if->head + 1) & (sizeof(ps2if->buf) - 1);
113 if (head != ps2if->tail) {
114 ps2if->buf[ps2if->head] = val;
115 ps2if->head = head;
116 }
117 }
118
119 spin_unlock_irqrestore(&ps2if->lock, flags);
120 return 0;
121}
122
123static int ps2_open(struct serio *io)
124{
125 struct ps2if *ps2if = io->port_data;
126 int ret;
127
128 sa1111_enable_device(ps2if->dev);
129
130 ret = request_irq(ps2if->dev->irq[0], ps2_rxint, 0,
131 SA1111_DRIVER_NAME(ps2if->dev), ps2if);
132 if (ret) {
133 printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
134 ps2if->dev->irq[0], ret);
135 return ret;
136 }
137
138 ret = request_irq(ps2if->dev->irq[1], ps2_txint, 0,
139 SA1111_DRIVER_NAME(ps2if->dev), ps2if);
140 if (ret) {
141 printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
142 ps2if->dev->irq[1], ret);
143 free_irq(ps2if->dev->irq[0], ps2if);
144 return ret;
145 }
146
147 ps2if->open = 1;
148
149 enable_irq_wake(ps2if->dev->irq[0]);
150
151 sa1111_writel(PS2CR_ENA, ps2if->base + SA1111_PS2CR);
152 return 0;
153}
154
155static void ps2_close(struct serio *io)
156{
157 struct ps2if *ps2if = io->port_data;
158
159 sa1111_writel(0, ps2if->base + SA1111_PS2CR);
160
161 disable_irq_wake(ps2if->dev->irq[0]);
162
163 ps2if->open = 0;
164
165 free_irq(ps2if->dev->irq[1], ps2if);
166 free_irq(ps2if->dev->irq[0], ps2if);
167
168 sa1111_disable_device(ps2if->dev);
169}
170
171/*
172 * Clear the input buffer.
173 */
174static void __init ps2_clear_input(struct ps2if *ps2if)
175{
176 int maxread = 100;
177
178 while (maxread--) {
179 if ((sa1111_readl(ps2if->base + SA1111_PS2DATA) & 0xff) == 0xff)
180 break;
181 }
182}
183
184static inline unsigned int
185ps2_test_one(struct ps2if *ps2if, unsigned int mask)
186{
187 unsigned int val;
188
189 sa1111_writel(PS2CR_ENA | mask, ps2if->base + SA1111_PS2CR);
190
191 udelay(2);
192
193 val = sa1111_readl(ps2if->base + SA1111_PS2STAT);
194 return val & (PS2STAT_KBC | PS2STAT_KBD);
195}
196
197/*
198 * Test the keyboard interface. We basically check to make sure that
199 * we can drive each line to the keyboard independently of each other.
200 */
201static int __init ps2_test(struct ps2if *ps2if)
202{
203 unsigned int stat;
204 int ret = 0;
205
206 stat = ps2_test_one(ps2if, PS2CR_FKC);
207 if (stat != PS2STAT_KBD) {
208 printk("PS/2 interface test failed[1]: %02x\n", stat);
209 ret = -ENODEV;
210 }
211
212 stat = ps2_test_one(ps2if, 0);
213 if (stat != (PS2STAT_KBC | PS2STAT_KBD)) {
214 printk("PS/2 interface test failed[2]: %02x\n", stat);
215 ret = -ENODEV;
216 }
217
218 stat = ps2_test_one(ps2if, PS2CR_FKD);
219 if (stat != PS2STAT_KBC) {
220 printk("PS/2 interface test failed[3]: %02x\n", stat);
221 ret = -ENODEV;
222 }
223
224 sa1111_writel(0, ps2if->base + SA1111_PS2CR);
225
226 return ret;
227}
228
229/*
230 * Add one device to this driver.
231 */
232static int ps2_probe(struct sa1111_dev *dev)
233{
234 struct ps2if *ps2if;
235 struct serio *serio;
236 int ret;
237
238 ps2if = kmalloc(sizeof(struct ps2if), GFP_KERNEL);
239 serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
240 if (!ps2if || !serio) {
241 ret = -ENOMEM;
242 goto free;
243 }
244
245 memset(ps2if, 0, sizeof(struct ps2if));
246 memset(serio, 0, sizeof(struct serio));
247
248 serio->id.type = SERIO_8042;
249 serio->write = ps2_write;
250 serio->open = ps2_open;
251 serio->close = ps2_close;
252 strlcpy(serio->name, dev->dev.bus_id, sizeof(serio->name));
253 strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
254 serio->port_data = ps2if;
255 serio->dev.parent = &dev->dev;
256 ps2if->io = serio;
257 ps2if->dev = dev;
258 sa1111_set_drvdata(dev, ps2if);
259
260 spin_lock_init(&ps2if->lock);
261
262 /*
263 * Request the physical region for this PS2 port.
264 */
265 if (!request_mem_region(dev->res.start,
266 dev->res.end - dev->res.start + 1,
267 SA1111_DRIVER_NAME(dev))) {
268 ret = -EBUSY;
269 goto free;
270 }
271
272 /*
273 * Our parent device has already mapped the region.
274 */
275 ps2if->base = dev->mapbase;
276
277 sa1111_enable_device(ps2if->dev);
278
279 /* Incoming clock is 8MHz */
280 sa1111_writel(0, ps2if->base + SA1111_PS2CLKDIV);
281 sa1111_writel(127, ps2if->base + SA1111_PS2PRECNT);
282
283 /*
284 * Flush any pending input.
285 */
286 ps2_clear_input(ps2if);
287
288 /*
289 * Test the keyboard interface.
290 */
291 ret = ps2_test(ps2if);
292 if (ret)
293 goto out;
294
295 /*
296 * Flush any pending input.
297 */
298 ps2_clear_input(ps2if);
299
300 sa1111_disable_device(ps2if->dev);
301 serio_register_port(ps2if->io);
302 return 0;
303
304 out:
305 sa1111_disable_device(ps2if->dev);
306 release_mem_region(dev->res.start,
307 dev->res.end - dev->res.start + 1);
308 free:
309 sa1111_set_drvdata(dev, NULL);
310 kfree(ps2if);
311 kfree(serio);
312 return ret;
313}
314
315/*
316 * Remove one device from this driver.
317 */
318static int ps2_remove(struct sa1111_dev *dev)
319{
320 struct ps2if *ps2if = sa1111_get_drvdata(dev);
321
322 serio_unregister_port(ps2if->io);
323 release_mem_region(dev->res.start,
324 dev->res.end - dev->res.start + 1);
325 sa1111_set_drvdata(dev, NULL);
326
327 kfree(ps2if);
328
329 return 0;
330}
331
332/*
333 * Our device driver structure
334 */
335static struct sa1111_driver ps2_driver = {
336 .drv = {
337 .name = "sa1111-ps2",
338 },
339 .devid = SA1111_DEVID_PS2,
340 .probe = ps2_probe,
341 .remove = ps2_remove,
342};
343
344static int __init ps2_init(void)
345{
346 return sa1111_driver_register(&ps2_driver);
347}
348
349static void __exit ps2_exit(void)
350{
351 sa1111_driver_unregister(&ps2_driver);
352}
353
354module_init(ps2_init);
355module_exit(ps2_exit);
356
357MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
358MODULE_DESCRIPTION("SA1111 PS2 controller driver");
359MODULE_LICENSE("GPL");
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
new file mode 100644
index 000000000000..3313e2daeab0
--- /dev/null
+++ b/drivers/input/serio/serio.c
@@ -0,0 +1,859 @@
1/*
2 * The Serio abstraction module
3 *
4 * Copyright (c) 1999-2004 Vojtech Pavlik
5 * Copyright (c) 2004 Dmitry Torokhov
6 * Copyright (c) 2003 Daniele Bellucci
7 */
8
9/*
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * Should you need to contact me, the author, you can do so either by
25 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
26 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
27 */
28
29#include <linux/stddef.h>
30#include <linux/module.h>
31#include <linux/serio.h>
32#include <linux/errno.h>
33#include <linux/wait.h>
34#include <linux/completion.h>
35#include <linux/sched.h>
36#include <linux/smp_lock.h>
37#include <linux/slab.h>
38
39MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
40MODULE_DESCRIPTION("Serio abstraction core");
41MODULE_LICENSE("GPL");
42
43EXPORT_SYMBOL(serio_interrupt);
44EXPORT_SYMBOL(__serio_register_port);
45EXPORT_SYMBOL(serio_unregister_port);
46EXPORT_SYMBOL(__serio_unregister_port_delayed);
47EXPORT_SYMBOL(__serio_register_driver);
48EXPORT_SYMBOL(serio_unregister_driver);
49EXPORT_SYMBOL(serio_open);
50EXPORT_SYMBOL(serio_close);
51EXPORT_SYMBOL(serio_rescan);
52EXPORT_SYMBOL(serio_reconnect);
53
54/*
55 * serio_sem protects entire serio subsystem and is taken every time
56 * serio port or driver registrered or unregistered.
57 */
58static DECLARE_MUTEX(serio_sem);
59
60static LIST_HEAD(serio_list);
61
62static struct bus_type serio_bus = {
63 .name = "serio",
64};
65
66static void serio_add_port(struct serio *serio);
67static void serio_destroy_port(struct serio *serio);
68static void serio_reconnect_port(struct serio *serio);
69static void serio_disconnect_port(struct serio *serio);
70
71static int serio_match_port(const struct serio_device_id *ids, struct serio *serio)
72{
73 while (ids->type || ids->proto) {
74 if ((ids->type == SERIO_ANY || ids->type == serio->id.type) &&
75 (ids->proto == SERIO_ANY || ids->proto == serio->id.proto) &&
76 (ids->extra == SERIO_ANY || ids->extra == serio->id.extra) &&
77 (ids->id == SERIO_ANY || ids->id == serio->id.id))
78 return 1;
79 ids++;
80 }
81 return 0;
82}
83
84/*
85 * Basic serio -> driver core mappings
86 */
87
88static void serio_bind_driver(struct serio *serio, struct serio_driver *drv)
89{
90 down_write(&serio_bus.subsys.rwsem);
91
92 if (serio_match_port(drv->id_table, serio)) {
93 serio->dev.driver = &drv->driver;
94 if (drv->connect(serio, drv)) {
95 serio->dev.driver = NULL;
96 goto out;
97 }
98 device_bind_driver(&serio->dev);
99 }
100out:
101 up_write(&serio_bus.subsys.rwsem);
102}
103
104static void serio_release_driver(struct serio *serio)
105{
106 down_write(&serio_bus.subsys.rwsem);
107 device_release_driver(&serio->dev);
108 up_write(&serio_bus.subsys.rwsem);
109}
110
111static void serio_find_driver(struct serio *serio)
112{
113 down_write(&serio_bus.subsys.rwsem);
114 device_attach(&serio->dev);
115 up_write(&serio_bus.subsys.rwsem);
116}
117
118
119/*
120 * Serio event processing.
121 */
122
123enum serio_event_type {
124 SERIO_RESCAN,
125 SERIO_RECONNECT,
126 SERIO_REGISTER_PORT,
127 SERIO_UNREGISTER_PORT,
128 SERIO_REGISTER_DRIVER,
129};
130
131struct serio_event {
132 enum serio_event_type type;
133 void *object;
134 struct module *owner;
135 struct list_head node;
136};
137
138static DEFINE_SPINLOCK(serio_event_lock); /* protects serio_event_list */
139static LIST_HEAD(serio_event_list);
140static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
141static DECLARE_COMPLETION(serio_exited);
142static int serio_pid;
143
144static void serio_queue_event(void *object, struct module *owner,
145 enum serio_event_type event_type)
146{
147 unsigned long flags;
148 struct serio_event *event;
149
150 spin_lock_irqsave(&serio_event_lock, flags);
151
152 /*
153 * Scan event list for the other events for the same serio port,
154 * starting with the most recent one. If event is the same we
155 * do not need add new one. If event is of different type we
156 * need to add this event and should not look further because
157 * we need to preseve sequence of distinct events.
158 */
159 list_for_each_entry_reverse(event, &serio_event_list, node) {
160 if (event->object == object) {
161 if (event->type == event_type)
162 goto out;
163 break;
164 }
165 }
166
167 if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
168 if (!try_module_get(owner)) {
169 printk(KERN_WARNING "serio: Can't get module reference, dropping event %d\n", event_type);
170 goto out;
171 }
172
173 event->type = event_type;
174 event->object = object;
175 event->owner = owner;
176
177 list_add_tail(&event->node, &serio_event_list);
178 wake_up(&serio_wait);
179 } else {
180 printk(KERN_ERR "serio: Not enough memory to queue event %d\n", event_type);
181 }
182out:
183 spin_unlock_irqrestore(&serio_event_lock, flags);
184}
185
186static void serio_free_event(struct serio_event *event)
187{
188 module_put(event->owner);
189 kfree(event);
190}
191
192static void serio_remove_duplicate_events(struct serio_event *event)
193{
194 struct list_head *node, *next;
195 struct serio_event *e;
196 unsigned long flags;
197
198 spin_lock_irqsave(&serio_event_lock, flags);
199
200 list_for_each_safe(node, next, &serio_event_list) {
201 e = list_entry(node, struct serio_event, node);
202 if (event->object == e->object) {
203 /*
204 * If this event is of different type we should not
205 * look further - we only suppress duplicate events
206 * that were sent back-to-back.
207 */
208 if (event->type != e->type)
209 break;
210
211 list_del_init(node);
212 serio_free_event(e);
213 }
214 }
215
216 spin_unlock_irqrestore(&serio_event_lock, flags);
217}
218
219
220static struct serio_event *serio_get_event(void)
221{
222 struct serio_event *event;
223 struct list_head *node;
224 unsigned long flags;
225
226 spin_lock_irqsave(&serio_event_lock, flags);
227
228 if (list_empty(&serio_event_list)) {
229 spin_unlock_irqrestore(&serio_event_lock, flags);
230 return NULL;
231 }
232
233 node = serio_event_list.next;
234 event = list_entry(node, struct serio_event, node);
235 list_del_init(node);
236
237 spin_unlock_irqrestore(&serio_event_lock, flags);
238
239 return event;
240}
241
242static void serio_handle_events(void)
243{
244 struct serio_event *event;
245 struct serio_driver *serio_drv;
246
247 down(&serio_sem);
248
249 while ((event = serio_get_event())) {
250
251 switch (event->type) {
252 case SERIO_REGISTER_PORT:
253 serio_add_port(event->object);
254 break;
255
256 case SERIO_UNREGISTER_PORT:
257 serio_disconnect_port(event->object);
258 serio_destroy_port(event->object);
259 break;
260
261 case SERIO_RECONNECT:
262 serio_reconnect_port(event->object);
263 break;
264
265 case SERIO_RESCAN:
266 serio_disconnect_port(event->object);
267 serio_find_driver(event->object);
268 break;
269
270 case SERIO_REGISTER_DRIVER:
271 serio_drv = event->object;
272 driver_register(&serio_drv->driver);
273 break;
274
275 default:
276 break;
277 }
278
279 serio_remove_duplicate_events(event);
280 serio_free_event(event);
281 }
282
283 up(&serio_sem);
284}
285
286/*
287 * Remove all events that have been submitted for a given serio port.
288 */
289static void serio_remove_pending_events(struct serio *serio)
290{
291 struct list_head *node, *next;
292 struct serio_event *event;
293 unsigned long flags;
294
295 spin_lock_irqsave(&serio_event_lock, flags);
296
297 list_for_each_safe(node, next, &serio_event_list) {
298 event = list_entry(node, struct serio_event, node);
299 if (event->object == serio) {
300 list_del_init(node);
301 serio_free_event(event);
302 }
303 }
304
305 spin_unlock_irqrestore(&serio_event_lock, flags);
306}
307
308/*
309 * Destroy child serio port (if any) that has not been fully registered yet.
310 *
311 * Note that we rely on the fact that port can have only one child and therefore
312 * only one child registration request can be pending. Additionally, children
313 * are registered by driver's connect() handler so there can't be a grandchild
314 * pending registration together with a child.
315 */
316static struct serio *serio_get_pending_child(struct serio *parent)
317{
318 struct serio_event *event;
319 struct serio *serio, *child = NULL;
320 unsigned long flags;
321
322 spin_lock_irqsave(&serio_event_lock, flags);
323
324 list_for_each_entry(event, &serio_event_list, node) {
325 if (event->type == SERIO_REGISTER_PORT) {
326 serio = event->object;
327 if (serio->parent == parent) {
328 child = serio;
329 break;
330 }
331 }
332 }
333
334 spin_unlock_irqrestore(&serio_event_lock, flags);
335 return child;
336}
337
338static int serio_thread(void *nothing)
339{
340 lock_kernel();
341 daemonize("kseriod");
342 allow_signal(SIGTERM);
343
344 do {
345 serio_handle_events();
346 wait_event_interruptible(serio_wait, !list_empty(&serio_event_list));
347 try_to_freeze(PF_FREEZE);
348 } while (!signal_pending(current));
349
350 printk(KERN_DEBUG "serio: kseriod exiting\n");
351
352 unlock_kernel();
353 complete_and_exit(&serio_exited, 0);
354}
355
356
357/*
358 * Serio port operations
359 */
360
361static ssize_t serio_show_description(struct device *dev, char *buf)
362{
363 struct serio *serio = to_serio_port(dev);
364 return sprintf(buf, "%s\n", serio->name);
365}
366
367static ssize_t serio_show_id_type(struct device *dev, char *buf)
368{
369 struct serio *serio = to_serio_port(dev);
370 return sprintf(buf, "%02x\n", serio->id.type);
371}
372
373static ssize_t serio_show_id_proto(struct device *dev, char *buf)
374{
375 struct serio *serio = to_serio_port(dev);
376 return sprintf(buf, "%02x\n", serio->id.proto);
377}
378
379static ssize_t serio_show_id_id(struct device *dev, char *buf)
380{
381 struct serio *serio = to_serio_port(dev);
382 return sprintf(buf, "%02x\n", serio->id.id);
383}
384
385static ssize_t serio_show_id_extra(struct device *dev, char *buf)
386{
387 struct serio *serio = to_serio_port(dev);
388 return sprintf(buf, "%02x\n", serio->id.extra);
389}
390
391static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t count)
392{
393 struct serio *serio = to_serio_port(dev);
394 struct device_driver *drv;
395 int retval;
396
397 retval = down_interruptible(&serio_sem);
398 if (retval)
399 return retval;
400
401 retval = count;
402 if (!strncmp(buf, "none", count)) {
403 serio_disconnect_port(serio);
404 } else if (!strncmp(buf, "reconnect", count)) {
405 serio_reconnect_port(serio);
406 } else if (!strncmp(buf, "rescan", count)) {
407 serio_disconnect_port(serio);
408 serio_find_driver(serio);
409 } else if ((drv = driver_find(buf, &serio_bus)) != NULL) {
410 serio_disconnect_port(serio);
411 serio_bind_driver(serio, to_serio_driver(drv));
412 put_driver(drv);
413 } else {
414 retval = -EINVAL;
415 }
416
417 up(&serio_sem);
418
419 return retval;
420}
421
422static ssize_t serio_show_bind_mode(struct device *dev, char *buf)
423{
424 struct serio *serio = to_serio_port(dev);
425 return sprintf(buf, "%s\n", serio->manual_bind ? "manual" : "auto");
426}
427
428static ssize_t serio_set_bind_mode(struct device *dev, const char *buf, size_t count)
429{
430 struct serio *serio = to_serio_port(dev);
431 int retval;
432
433 retval = count;
434 if (!strncmp(buf, "manual", count)) {
435 serio->manual_bind = 1;
436 } else if (!strncmp(buf, "auto", count)) {
437 serio->manual_bind = 0;
438 } else {
439 retval = -EINVAL;
440 }
441
442 return retval;
443}
444
445static struct device_attribute serio_device_attrs[] = {
446 __ATTR(description, S_IRUGO, serio_show_description, NULL),
447 __ATTR(id_type, S_IRUGO, serio_show_id_type, NULL),
448 __ATTR(id_proto, S_IRUGO, serio_show_id_proto, NULL),
449 __ATTR(id_id, S_IRUGO, serio_show_id_id, NULL),
450 __ATTR(id_extra, S_IRUGO, serio_show_id_extra, NULL),
451 __ATTR(drvctl, S_IWUSR, NULL, serio_rebind_driver),
452 __ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode),
453 __ATTR_NULL
454};
455
456
457static void serio_release_port(struct device *dev)
458{
459 struct serio *serio = to_serio_port(dev);
460
461 kfree(serio);
462 module_put(THIS_MODULE);
463}
464
465/*
466 * Prepare serio port for registration.
467 */
468static void serio_init_port(struct serio *serio)
469{
470 static atomic_t serio_no = ATOMIC_INIT(0);
471
472 __module_get(THIS_MODULE);
473
474 spin_lock_init(&serio->lock);
475 init_MUTEX(&serio->drv_sem);
476 device_initialize(&serio->dev);
477 snprintf(serio->dev.bus_id, sizeof(serio->dev.bus_id),
478 "serio%ld", (long)atomic_inc_return(&serio_no) - 1);
479 serio->dev.bus = &serio_bus;
480 serio->dev.release = serio_release_port;
481 if (serio->parent)
482 serio->dev.parent = &serio->parent->dev;
483}
484
485/*
486 * Complete serio port registration.
487 * Driver core will attempt to find appropriate driver for the port.
488 */
489static void serio_add_port(struct serio *serio)
490{
491 if (serio->parent) {
492 serio_pause_rx(serio->parent);
493 serio->parent->child = serio;
494 serio_continue_rx(serio->parent);
495 }
496
497 list_add_tail(&serio->node, &serio_list);
498 if (serio->start)
499 serio->start(serio);
500 device_add(&serio->dev);
501 serio->registered = 1;
502}
503
504/*
505 * serio_destroy_port() completes deregistration process and removes
506 * port from the system
507 */
508static void serio_destroy_port(struct serio *serio)
509{
510 struct serio *child;
511
512 child = serio_get_pending_child(serio);
513 if (child) {
514 serio_remove_pending_events(child);
515 put_device(&child->dev);
516 }
517
518 if (serio->stop)
519 serio->stop(serio);
520
521 if (serio->parent) {
522 serio_pause_rx(serio->parent);
523 serio->parent->child = NULL;
524 serio_continue_rx(serio->parent);
525 serio->parent = NULL;
526 }
527
528 if (serio->registered) {
529 device_del(&serio->dev);
530 list_del_init(&serio->node);
531 serio->registered = 0;
532 }
533
534 serio_remove_pending_events(serio);
535 put_device(&serio->dev);
536}
537
538/*
539 * Reconnect serio port and all its children (re-initialize attached devices)
540 */
541static void serio_reconnect_port(struct serio *serio)
542{
543 do {
544 if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) {
545 serio_disconnect_port(serio);
546 serio_find_driver(serio);
547 /* Ok, old children are now gone, we are done */
548 break;
549 }
550 serio = serio->child;
551 } while (serio);
552}
553
554/*
555 * serio_disconnect_port() unbinds a port from its driver. As a side effect
556 * all child ports are unbound and destroyed.
557 */
558static void serio_disconnect_port(struct serio *serio)
559{
560 struct serio *s, *parent;
561
562 if (serio->child) {
563 /*
564 * Children ports should be disconnected and destroyed
565 * first, staring with the leaf one, since we don't want
566 * to do recursion
567 */
568 for (s = serio; s->child; s = s->child)
569 /* empty */;
570
571 do {
572 parent = s->parent;
573
574 serio_release_driver(s);
575 serio_destroy_port(s);
576 } while ((s = parent) != serio);
577 }
578
579 /*
580 * Ok, no children left, now disconnect this port
581 */
582 serio_release_driver(serio);
583}
584
585void serio_rescan(struct serio *serio)
586{
587 serio_queue_event(serio, NULL, SERIO_RESCAN);
588}
589
590void serio_reconnect(struct serio *serio)
591{
592 serio_queue_event(serio, NULL, SERIO_RECONNECT);
593}
594
595/*
596 * Submits register request to kseriod for subsequent execution.
597 * Note that port registration is always asynchronous.
598 */
599void __serio_register_port(struct serio *serio, struct module *owner)
600{
601 serio_init_port(serio);
602 serio_queue_event(serio, owner, SERIO_REGISTER_PORT);
603}
604
605/*
606 * Synchronously unregisters serio port.
607 */
608void serio_unregister_port(struct serio *serio)
609{
610 down(&serio_sem);
611 serio_disconnect_port(serio);
612 serio_destroy_port(serio);
613 up(&serio_sem);
614}
615
616/*
617 * Submits register request to kseriod for subsequent execution.
618 * Can be used when it is not obvious whether the serio_sem is
619 * taken or not and when delayed execution is feasible.
620 */
621void __serio_unregister_port_delayed(struct serio *serio, struct module *owner)
622{
623 serio_queue_event(serio, owner, SERIO_UNREGISTER_PORT);
624}
625
626
627/*
628 * Serio driver operations
629 */
630
631static ssize_t serio_driver_show_description(struct device_driver *drv, char *buf)
632{
633 struct serio_driver *driver = to_serio_driver(drv);
634 return sprintf(buf, "%s\n", driver->description ? driver->description : "(none)");
635}
636
637static ssize_t serio_driver_show_bind_mode(struct device_driver *drv, char *buf)
638{
639 struct serio_driver *serio_drv = to_serio_driver(drv);
640 return sprintf(buf, "%s\n", serio_drv->manual_bind ? "manual" : "auto");
641}
642
643static ssize_t serio_driver_set_bind_mode(struct device_driver *drv, const char *buf, size_t count)
644{
645 struct serio_driver *serio_drv = to_serio_driver(drv);
646 int retval;
647
648 retval = count;
649 if (!strncmp(buf, "manual", count)) {
650 serio_drv->manual_bind = 1;
651 } else if (!strncmp(buf, "auto", count)) {
652 serio_drv->manual_bind = 0;
653 } else {
654 retval = -EINVAL;
655 }
656
657 return retval;
658}
659
660
661static struct driver_attribute serio_driver_attrs[] = {
662 __ATTR(description, S_IRUGO, serio_driver_show_description, NULL),
663 __ATTR(bind_mode, S_IWUSR | S_IRUGO,
664 serio_driver_show_bind_mode, serio_driver_set_bind_mode),
665 __ATTR_NULL
666};
667
668static int serio_driver_probe(struct device *dev)
669{
670 struct serio *serio = to_serio_port(dev);
671 struct serio_driver *drv = to_serio_driver(dev->driver);
672
673 return drv->connect(serio, drv);
674}
675
676static int serio_driver_remove(struct device *dev)
677{
678 struct serio *serio = to_serio_port(dev);
679 struct serio_driver *drv = to_serio_driver(dev->driver);
680
681 drv->disconnect(serio);
682 return 0;
683}
684
685void __serio_register_driver(struct serio_driver *drv, struct module *owner)
686{
687 drv->driver.bus = &serio_bus;
688 drv->driver.probe = serio_driver_probe;
689 drv->driver.remove = serio_driver_remove;
690
691 serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER);
692}
693
694void serio_unregister_driver(struct serio_driver *drv)
695{
696 struct serio *serio;
697
698 down(&serio_sem);
699 drv->manual_bind = 1; /* so serio_find_driver ignores it */
700
701start_over:
702 list_for_each_entry(serio, &serio_list, node) {
703 if (serio->drv == drv) {
704 serio_disconnect_port(serio);
705 serio_find_driver(serio);
706 /* we could've deleted some ports, restart */
707 goto start_over;
708 }
709 }
710
711 driver_unregister(&drv->driver);
712 up(&serio_sem);
713}
714
715static void serio_set_drv(struct serio *serio, struct serio_driver *drv)
716{
717 down(&serio->drv_sem);
718 serio_pause_rx(serio);
719 serio->drv = drv;
720 serio_continue_rx(serio);
721 up(&serio->drv_sem);
722}
723
724static int serio_bus_match(struct device *dev, struct device_driver *drv)
725{
726 struct serio *serio = to_serio_port(dev);
727 struct serio_driver *serio_drv = to_serio_driver(drv);
728
729 if (serio->manual_bind || serio_drv->manual_bind)
730 return 0;
731
732 return serio_match_port(serio_drv->id_table, serio);
733}
734
735#ifdef CONFIG_HOTPLUG
736
737#define PUT_ENVP(fmt, val) \
738do { \
739 envp[i++] = buffer; \
740 length += snprintf(buffer, buffer_size - length, fmt, val); \
741 if (buffer_size - length <= 0 || i >= num_envp) \
742 return -ENOMEM; \
743 length++; \
744 buffer += length; \
745} while (0)
746static int serio_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
747{
748 struct serio *serio;
749 int i = 0;
750 int length = 0;
751
752 if (!dev)
753 return -ENODEV;
754
755 serio = to_serio_port(dev);
756
757 PUT_ENVP("SERIO_TYPE=%02x", serio->id.type);
758 PUT_ENVP("SERIO_PROTO=%02x", serio->id.proto);
759 PUT_ENVP("SERIO_ID=%02x", serio->id.id);
760 PUT_ENVP("SERIO_EXTRA=%02x", serio->id.extra);
761
762 envp[i] = NULL;
763
764 return 0;
765}
766#undef PUT_ENVP
767
768#else
769
770static int serio_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
771{
772 return -ENODEV;
773}
774
775#endif /* CONFIG_HOTPLUG */
776
777static int serio_resume(struct device *dev)
778{
779 struct serio *serio = to_serio_port(dev);
780
781 if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) {
782 serio_disconnect_port(serio);
783 /*
784 * Driver re-probing can take a while, so better let kseriod
785 * deal with it.
786 */
787 serio_rescan(serio);
788 }
789
790 return 0;
791}
792
793/* called from serio_driver->connect/disconnect methods under serio_sem */
794int serio_open(struct serio *serio, struct serio_driver *drv)
795{
796 serio_set_drv(serio, drv);
797
798 if (serio->open && serio->open(serio)) {
799 serio_set_drv(serio, NULL);
800 return -1;
801 }
802 return 0;
803}
804
805/* called from serio_driver->connect/disconnect methods under serio_sem */
806void serio_close(struct serio *serio)
807{
808 if (serio->close)
809 serio->close(serio);
810
811 serio_set_drv(serio, NULL);
812}
813
814irqreturn_t serio_interrupt(struct serio *serio,
815 unsigned char data, unsigned int dfl, struct pt_regs *regs)
816{
817 unsigned long flags;
818 irqreturn_t ret = IRQ_NONE;
819
820 spin_lock_irqsave(&serio->lock, flags);
821
822 if (likely(serio->drv)) {
823 ret = serio->drv->interrupt(serio, data, dfl, regs);
824 } else if (!dfl && serio->registered) {
825 serio_rescan(serio);
826 ret = IRQ_HANDLED;
827 }
828
829 spin_unlock_irqrestore(&serio->lock, flags);
830
831 return ret;
832}
833
834static int __init serio_init(void)
835{
836 if (!(serio_pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL))) {
837 printk(KERN_ERR "serio: Failed to start kseriod\n");
838 return -1;
839 }
840
841 serio_bus.dev_attrs = serio_device_attrs;
842 serio_bus.drv_attrs = serio_driver_attrs;
843 serio_bus.match = serio_bus_match;
844 serio_bus.hotplug = serio_hotplug;
845 serio_bus.resume = serio_resume;
846 bus_register(&serio_bus);
847
848 return 0;
849}
850
851static void __exit serio_exit(void)
852{
853 bus_unregister(&serio_bus);
854 kill_proc(serio_pid, SIGTERM, 1);
855 wait_for_completion(&serio_exited);
856}
857
858module_init(serio_init);
859module_exit(serio_exit);
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
new file mode 100644
index 000000000000..d914e7e93db4
--- /dev/null
+++ b/drivers/input/serio/serio_raw.c
@@ -0,0 +1,403 @@
1/*
2 * Raw serio device providing access to a raw byte stream from underlying
3 * serio port. Closely emulates behavior of pre-2.6 /dev/psaux device
4 *
5 * Copyright (c) 2004 Dmitry Torokhov
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 */
11
12#include <linux/slab.h>
13#include <linux/poll.h>
14#include <linux/module.h>
15#include <linux/serio.h>
16#include <linux/init.h>
17#include <linux/major.h>
18#include <linux/device.h>
19#include <linux/devfs_fs_kernel.h>
20#include <linux/miscdevice.h>
21#include <linux/wait.h>
22
23#define DRIVER_DESC "Raw serio driver"
24
25MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
26MODULE_DESCRIPTION(DRIVER_DESC);
27MODULE_LICENSE("GPL");
28
29#define SERIO_RAW_QUEUE_LEN 64
30struct serio_raw {
31 unsigned char queue[SERIO_RAW_QUEUE_LEN];
32 unsigned int tail, head;
33
34 char name[16];
35 unsigned int refcnt;
36 struct serio *serio;
37 struct miscdevice dev;
38 wait_queue_head_t wait;
39 struct list_head list;
40 struct list_head node;
41};
42
43struct serio_raw_list {
44 struct fasync_struct *fasync;
45 struct serio_raw *serio_raw;
46 struct list_head node;
47};
48
49static DECLARE_MUTEX(serio_raw_sem);
50static LIST_HEAD(serio_raw_list);
51static unsigned int serio_raw_no;
52
53/*********************************************************************
54 * Interface with userspace (file operations) *
55 *********************************************************************/
56
57static int serio_raw_fasync(int fd, struct file *file, int on)
58{
59 struct serio_raw_list *list = file->private_data;
60 int retval;
61
62 retval = fasync_helper(fd, file, on, &list->fasync);
63 return retval < 0 ? retval : 0;
64}
65
66static struct serio_raw *serio_raw_locate(int minor)
67{
68 struct serio_raw *serio_raw;
69
70 list_for_each_entry(serio_raw, &serio_raw_list, node) {
71 if (serio_raw->dev.minor == minor)
72 return serio_raw;
73 }
74
75 return NULL;
76}
77
78static int serio_raw_open(struct inode *inode, struct file *file)
79{
80 struct serio_raw *serio_raw;
81 struct serio_raw_list *list;
82 int retval = 0;
83
84 retval = down_interruptible(&serio_raw_sem);
85 if (retval)
86 return retval;
87
88 if (!(serio_raw = serio_raw_locate(iminor(inode)))) {
89 retval = -ENODEV;
90 goto out;
91 }
92
93 if (!serio_raw->serio) {
94 retval = -ENODEV;
95 goto out;
96 }
97
98 if (!(list = kmalloc(sizeof(struct serio_raw_list), GFP_KERNEL))) {
99 retval = -ENOMEM;
100 goto out;
101 }
102
103 memset(list, 0, sizeof(struct serio_raw_list));
104 list->serio_raw = serio_raw;
105 file->private_data = list;
106
107 serio_raw->refcnt++;
108 list_add_tail(&list->node, &serio_raw->list);
109
110out:
111 up(&serio_raw_sem);
112 return retval;
113}
114
115static int serio_raw_cleanup(struct serio_raw *serio_raw)
116{
117 if (--serio_raw->refcnt == 0) {
118 misc_deregister(&serio_raw->dev);
119 list_del_init(&serio_raw->node);
120 kfree(serio_raw);
121
122 return 1;
123 }
124
125 return 0;
126}
127
128static int serio_raw_release(struct inode *inode, struct file *file)
129{
130 struct serio_raw_list *list = file->private_data;
131 struct serio_raw *serio_raw = list->serio_raw;
132
133 down(&serio_raw_sem);
134
135 serio_raw_fasync(-1, file, 0);
136 serio_raw_cleanup(serio_raw);
137
138 up(&serio_raw_sem);
139 return 0;
140}
141
142static int serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
143{
144 unsigned long flags;
145 int empty;
146
147 spin_lock_irqsave(&serio_raw->serio->lock, flags);
148
149 empty = serio_raw->head == serio_raw->tail;
150 if (!empty) {
151 *c = serio_raw->queue[serio_raw->tail];
152 serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN;
153 }
154
155 spin_unlock_irqrestore(&serio_raw->serio->lock, flags);
156
157 return !empty;
158}
159
160static ssize_t serio_raw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
161{
162 struct serio_raw_list *list = file->private_data;
163 struct serio_raw *serio_raw = list->serio_raw;
164 char c;
165 ssize_t retval = 0;
166
167 if (!serio_raw->serio)
168 return -ENODEV;
169
170 if (serio_raw->head == serio_raw->tail && (file->f_flags & O_NONBLOCK))
171 return -EAGAIN;
172
173 retval = wait_event_interruptible(list->serio_raw->wait,
174 serio_raw->head != serio_raw->tail || !serio_raw->serio);
175 if (retval)
176 return retval;
177
178 if (!serio_raw->serio)
179 return -ENODEV;
180
181 while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) {
182 if (put_user(c, buffer++))
183 return -EFAULT;
184 retval++;
185 }
186
187 return retval;
188}
189
190static ssize_t serio_raw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
191{
192 struct serio_raw_list *list = file->private_data;
193 ssize_t written = 0;
194 int retval;
195 unsigned char c;
196
197 retval = down_interruptible(&serio_raw_sem);
198 if (retval)
199 return retval;
200
201 if (!list->serio_raw->serio) {
202 retval = -ENODEV;
203 goto out;
204 }
205
206 if (count > 32)
207 count = 32;
208
209 while (count--) {
210 if (get_user(c, buffer++)) {
211 retval = -EFAULT;
212 goto out;
213 }
214 if (serio_write(list->serio_raw->serio, c)) {
215 retval = -EIO;
216 goto out;
217 }
218 written++;
219 };
220
221out:
222 up(&serio_raw_sem);
223 return written;
224}
225
226static unsigned int serio_raw_poll(struct file *file, poll_table *wait)
227{
228 struct serio_raw_list *list = file->private_data;
229
230 poll_wait(file, &list->serio_raw->wait, wait);
231
232 if (list->serio_raw->head != list->serio_raw->tail)
233 return POLLIN | POLLRDNORM;
234
235 return 0;
236}
237
238static struct file_operations serio_raw_fops = {
239 .owner = THIS_MODULE,
240 .open = serio_raw_open,
241 .release = serio_raw_release,
242 .read = serio_raw_read,
243 .write = serio_raw_write,
244 .poll = serio_raw_poll,
245 .fasync = serio_raw_fasync,
246};
247
248
249/*********************************************************************
250 * Interface with serio port *
251 *********************************************************************/
252
253static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data,
254 unsigned int dfl, struct pt_regs *regs)
255{
256 struct serio_raw *serio_raw = serio_get_drvdata(serio);
257 struct serio_raw_list *list;
258 unsigned int head = serio_raw->head;
259
260 /* we are holding serio->lock here so we are prootected */
261 serio_raw->queue[head] = data;
262 head = (head + 1) % SERIO_RAW_QUEUE_LEN;
263 if (likely(head != serio_raw->tail)) {
264 serio_raw->head = head;
265 list_for_each_entry(list, &serio_raw->list, node)
266 kill_fasync(&list->fasync, SIGIO, POLL_IN);
267 wake_up_interruptible(&serio_raw->wait);
268 }
269
270 return IRQ_HANDLED;
271}
272
273static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
274{
275 struct serio_raw *serio_raw;
276 int err;
277
278 if (!(serio_raw = kmalloc(sizeof(struct serio_raw), GFP_KERNEL))) {
279 printk(KERN_ERR "serio_raw.c: can't allocate memory for a device\n");
280 return -ENOMEM;
281 }
282
283 down(&serio_raw_sem);
284
285 memset(serio_raw, 0, sizeof(struct serio_raw));
286 snprintf(serio_raw->name, sizeof(serio_raw->name), "serio_raw%d", serio_raw_no++);
287 serio_raw->refcnt = 1;
288 serio_raw->serio = serio;
289 INIT_LIST_HEAD(&serio_raw->list);
290 init_waitqueue_head(&serio_raw->wait);
291
292 serio_set_drvdata(serio, serio_raw);
293
294 err = serio_open(serio, drv);
295 if (err)
296 goto out_free;
297
298 list_add_tail(&serio_raw->node, &serio_raw_list);
299
300 serio_raw->dev.minor = PSMOUSE_MINOR;
301 serio_raw->dev.name = serio_raw->name;
302 serio_raw->dev.fops = &serio_raw_fops;
303
304 err = misc_register(&serio_raw->dev);
305 if (err) {
306 serio_raw->dev.minor = MISC_DYNAMIC_MINOR;
307 err = misc_register(&serio_raw->dev);
308 }
309
310 if (err) {
311 printk(KERN_INFO "serio_raw: failed to register raw access device for %s\n",
312 serio->phys);
313 goto out_close;
314 }
315
316 printk(KERN_INFO "serio_raw: raw access enabled on %s (%s, minor %d)\n",
317 serio->phys, serio_raw->name, serio_raw->dev.minor);
318 goto out;
319
320out_close:
321 serio_close(serio);
322 list_del_init(&serio_raw->node);
323out_free:
324 serio_set_drvdata(serio, NULL);
325 kfree(serio_raw);
326out:
327 up(&serio_raw_sem);
328 return err;
329}
330
331static int serio_raw_reconnect(struct serio *serio)
332{
333 struct serio_raw *serio_raw = serio_get_drvdata(serio);
334 struct serio_driver *drv = serio->drv;
335
336 if (!drv || !serio_raw) {
337 printk(KERN_DEBUG "serio_raw: reconnect request, but serio is disconnected, ignoring...\n");
338 return -1;
339 }
340
341 /*
342 * Nothing needs to be done here, we just need this method to
343 * keep the same device.
344 */
345 return 0;
346}
347
348static void serio_raw_disconnect(struct serio *serio)
349{
350 struct serio_raw *serio_raw;
351
352 down(&serio_raw_sem);
353
354 serio_raw = serio_get_drvdata(serio);
355
356 serio_close(serio);
357 serio_set_drvdata(serio, NULL);
358
359 serio_raw->serio = NULL;
360 if (!serio_raw_cleanup(serio_raw))
361 wake_up_interruptible(&serio_raw->wait);
362
363 up(&serio_raw_sem);
364}
365
366static struct serio_device_id serio_raw_serio_ids[] = {
367 {
368 .type = SERIO_8042,
369 .proto = SERIO_ANY,
370 .id = SERIO_ANY,
371 .extra = SERIO_ANY,
372 },
373 { 0 }
374};
375
376MODULE_DEVICE_TABLE(serio, serio_raw_serio_ids);
377
378static struct serio_driver serio_raw_drv = {
379 .driver = {
380 .name = "serio_raw",
381 },
382 .description = DRIVER_DESC,
383 .id_table = serio_raw_serio_ids,
384 .interrupt = serio_raw_interrupt,
385 .connect = serio_raw_connect,
386 .reconnect = serio_raw_reconnect,
387 .disconnect = serio_raw_disconnect,
388 .manual_bind = 1,
389};
390
391static int __init serio_raw_init(void)
392{
393 serio_register_driver(&serio_raw_drv);
394 return 0;
395}
396
397static void __exit serio_raw_exit(void)
398{
399 serio_unregister_driver(&serio_raw_drv);
400}
401
402module_init(serio_raw_init);
403module_exit(serio_raw_exit);
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
new file mode 100644
index 000000000000..22f73683952b
--- /dev/null
+++ b/drivers/input/serio/serport.c
@@ -0,0 +1,226 @@
1/*
2 * Input device TTY line discipline
3 *
4 * Copyright (c) 1999-2002 Vojtech Pavlik
5 *
6 * This is a module that converts a tty line into a much simpler
7 * 'serial io port' abstraction that the input device drivers use.
8 */
9
10/*
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License version 2 as published by
13 * the Free Software Foundation.
14 */
15
16#include <asm/uaccess.h>
17#include <linux/kernel.h>
18#include <linux/slab.h>
19#include <linux/module.h>
20#include <linux/init.h>
21#include <linux/serio.h>
22#include <linux/tty.h>
23
24MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
25MODULE_DESCRIPTION("Input device TTY line discipline");
26MODULE_LICENSE("GPL");
27MODULE_ALIAS_LDISC(N_MOUSE);
28
29#define SERPORT_BUSY 1
30
31struct serport {
32 struct tty_struct *tty;
33 wait_queue_head_t wait;
34 struct serio *serio;
35 unsigned long flags;
36};
37
38/*
39 * Callback functions from the serio code.
40 */
41
42static int serport_serio_write(struct serio *serio, unsigned char data)
43{
44 struct serport *serport = serio->port_data;
45 return -(serport->tty->driver->write(serport->tty, &data, 1) != 1);
46}
47
48static void serport_serio_close(struct serio *serio)
49{
50 struct serport *serport = serio->port_data;
51
52 serport->serio->id.type = 0;
53 wake_up_interruptible(&serport->wait);
54}
55
56/*
57 * serport_ldisc_open() is the routine that is called upon setting our line
58 * discipline on a tty. It prepares the serio struct.
59 */
60
61static int serport_ldisc_open(struct tty_struct *tty)
62{
63 struct serport *serport;
64 struct serio *serio;
65 char name[64];
66
67 if (!capable(CAP_SYS_ADMIN))
68 return -EPERM;
69
70 serport = kmalloc(sizeof(struct serport), GFP_KERNEL);
71 serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
72 if (unlikely(!serport || !serio)) {
73 kfree(serport);
74 kfree(serio);
75 return -ENOMEM;
76 }
77
78 memset(serport, 0, sizeof(struct serport));
79 serport->serio = serio;
80 set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
81 serport->tty = tty;
82 tty->disc_data = serport;
83
84 memset(serio, 0, sizeof(struct serio));
85 strlcpy(serio->name, "Serial port", sizeof(serio->name));
86 snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", tty_name(tty, name));
87 serio->id.type = SERIO_RS232;
88 serio->write = serport_serio_write;
89 serio->close = serport_serio_close;
90 serio->port_data = serport;
91
92 init_waitqueue_head(&serport->wait);
93
94 return 0;
95}
96
97/*
98 * serport_ldisc_close() is the opposite of serport_ldisc_open()
99 */
100
101static void serport_ldisc_close(struct tty_struct *tty)
102{
103 struct serport *serport = (struct serport*) tty->disc_data;
104 kfree(serport);
105}
106
107/*
108 * serport_ldisc_receive() is called by the low level tty driver when characters
109 * are ready for us. We forward the characters, one by one to the 'interrupt'
110 * routine.
111 *
112 * FIXME: We should get pt_regs from the tty layer and forward them to
113 * serio_interrupt here.
114 */
115
116static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
117{
118 struct serport *serport = (struct serport*) tty->disc_data;
119 int i;
120 for (i = 0; i < count; i++)
121 serio_interrupt(serport->serio, cp[i], 0, NULL);
122}
123
124/*
125 * serport_ldisc_room() reports how much room we do have for receiving data.
126 * Although we in fact have infinite room, we need to specify some value
127 * here, and 256 seems to be reasonable.
128 */
129
130static int serport_ldisc_room(struct tty_struct *tty)
131{
132 return 256;
133}
134
135/*
136 * serport_ldisc_read() just waits indefinitely if everything goes well.
137 * However, when the serio driver closes the serio port, it finishes,
138 * returning 0 characters.
139 */
140
141static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, unsigned char __user * buf, size_t nr)
142{
143 struct serport *serport = (struct serport*) tty->disc_data;
144 char name[64];
145
146 if (test_and_set_bit(SERPORT_BUSY, &serport->flags))
147 return -EBUSY;
148
149 serio_register_port(serport->serio);
150 printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name));
151 wait_event_interruptible(serport->wait, !serport->serio->id.type);
152 serio_unregister_port(serport->serio);
153
154 clear_bit(SERPORT_BUSY, &serport->flags);
155
156 return 0;
157}
158
159/*
160 * serport_ldisc_ioctl() allows to set the port protocol, and device ID
161 */
162
163static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg)
164{
165 struct serport *serport = (struct serport*) tty->disc_data;
166 struct serio *serio = serport->serio;
167 unsigned long type;
168
169 if (cmd == SPIOCSTYPE) {
170 if (get_user(type, (unsigned long __user *) arg))
171 return -EFAULT;
172
173 serio->id.proto = type & 0x000000ff;
174 serio->id.id = (type & 0x0000ff00) >> 8;
175 serio->id.extra = (type & 0x00ff0000) >> 16;
176
177 return 0;
178 }
179
180 return -EINVAL;
181}
182
183static void serport_ldisc_write_wakeup(struct tty_struct * tty)
184{
185 struct serport *sp = (struct serport *) tty->disc_data;
186
187 serio_drv_write_wakeup(sp->serio);
188}
189
190/*
191 * The line discipline structure.
192 */
193
194static struct tty_ldisc serport_ldisc = {
195 .owner = THIS_MODULE,
196 .name = "input",
197 .open = serport_ldisc_open,
198 .close = serport_ldisc_close,
199 .read = serport_ldisc_read,
200 .ioctl = serport_ldisc_ioctl,
201 .receive_buf = serport_ldisc_receive,
202 .receive_room = serport_ldisc_room,
203 .write_wakeup = serport_ldisc_write_wakeup
204};
205
206/*
207 * The functions for insering/removing us as a module.
208 */
209
210static int __init serport_init(void)
211{
212 int retval;
213 retval = tty_register_ldisc(N_MOUSE, &serport_ldisc);
214 if (retval)
215 printk(KERN_ERR "serport.c: Error registering line discipline.\n");
216
217 return retval;
218}
219
220static void __exit serport_exit(void)
221{
222 tty_register_ldisc(N_MOUSE, NULL);
223}
224
225module_init(serport_init);
226module_exit(serport_exit);
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
new file mode 100644
index 000000000000..7e991274ea40
--- /dev/null
+++ b/drivers/input/touchscreen/Kconfig
@@ -0,0 +1,98 @@
1#
2# Mouse driver configuration
3#
4menuconfig INPUT_TOUCHSCREEN
5 bool "Touchscreens"
6 help
7 Say Y here, and a list of supported touchscreens will be displayed.
8 This option doesn't affect the kernel.
9
10 If unsure, say Y.
11
12if INPUT_TOUCHSCREEN
13
14config TOUCHSCREEN_BITSY
15 tristate "Compaq iPAQ H3600 (Bitsy) touchscreen"
16 depends on SA1100_BITSY
17 select SERIO
18 help
19 Say Y here if you have the h3600 (Bitsy) touchscreen.
20
21 If unsure, say N.
22
23 To compile this driver as a module, choose M here: the
24 module will be called h3600_ts_input.
25
26config TOUCHSCREEN_CORGI
27 tristate "Corgi touchscreen (for Sharp SL-C7xx)"
28 depends on PXA_SHARPSL
29 default y
30 help
31 Say Y here to enable the driver for the touchscreen on the
32 Sharp SL-C7xx series of PDAs.
33
34 If unsure, say N.
35
36 To compile this driver as a module, choose M here: the
37 module will be called ads7846_ts.
38
39config TOUCHSCREEN_GUNZE
40 tristate "Gunze AHL-51S touchscreen"
41 select SERIO
42 help
43 Say Y here if you have the Gunze AHL-51 touchscreen connected to
44 your system.
45
46 If unsure, say N.
47
48 To compile this driver as a module, choose M here: the
49 module will be called gunze.
50
51config TOUCHSCREEN_ELO
52 tristate "Elo serial touchscreens"
53 select SERIO
54 help
55 Say Y here if you have an Elo serial touchscreen connected to
56 your system.
57
58 If unsure, say N.
59
60 To compile this driver as a module, choose M here: the
61 module will be called gunze.
62
63config TOUCHSCREEN_MTOUCH
64 tristate "MicroTouch serial touchscreens"
65 select SERIO
66 help
67 Say Y here if you have a MicroTouch (3M) serial touchscreen connected to
68 your system.
69
70 If unsure, say N.
71
72 To compile this driver as a module, choose M here: the
73 module will be called mtouch.
74
75config TOUCHSCREEN_MK712
76 tristate "ICS MicroClock MK712 touchscreen"
77 help
78 Say Y here if you have the ICS MicroClock MK712 touchscreen
79 controller chip in your system.
80
81 If unsure, say N.
82
83 To compile this driver as a module, choose M here: the
84 module will be called mk712.
85
86config TOUCHSCREEN_HP600
87 tristate "HP Jornada 680/690 touchscreen"
88 depends on SH_HP600 && SH_ADC
89 help
90 Say Y here if you have a HP Jornada 680 or 690 and want to
91 support the built-in touchscreen.
92
93 If unsure, say N.
94
95 To compile this driver as a module, choose M here: the
96 module will be called hp680_ts_input.
97
98endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
new file mode 100644
index 000000000000..6842869c9a26
--- /dev/null
+++ b/drivers/input/touchscreen/Makefile
@@ -0,0 +1,13 @@
1#
2# Makefile for the mouse drivers.
3#
4
5# Each configuration option enables a list of files.
6
7obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o
8obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o
9obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o
10obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
11obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
12obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o
13obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
new file mode 100644
index 000000000000..3f8b61cfbc37
--- /dev/null
+++ b/drivers/input/touchscreen/corgi_ts.c
@@ -0,0 +1,380 @@
1/*
2 * Touchscreen driver for Sharp Corgi models (SL-C7xx)
3 *
4 * Copyright (c) 2004-2005 Richard Purdie
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 */
11
12
13#include <linux/delay.h>
14#include <linux/device.h>
15#include <linux/init.h>
16#include <linux/input.h>
17#include <linux/interrupt.h>
18#include <linux/module.h>
19#include <linux/slab.h>
20#include <asm/irq.h>
21
22#include <asm/arch/corgi.h>
23#include <asm/arch/hardware.h>
24#include <asm/arch/pxa-regs.h>
25
26
27#define PWR_MODE_ACTIVE 0
28#define PWR_MODE_SUSPEND 1
29
30#define X_AXIS_MAX 3830
31#define X_AXIS_MIN 150
32#define Y_AXIS_MAX 3830
33#define Y_AXIS_MIN 190
34#define PRESSURE_MIN 0
35#define PRESSURE_MAX 15000
36
37struct ts_event {
38 short pressure;
39 short x;
40 short y;
41};
42
43struct corgi_ts {
44 char phys[32];
45 struct input_dev input;
46 struct timer_list timer;
47 struct ts_event tc;
48 int pendown;
49 int power_mode;
50};
51
52#define STATUS_HSYNC (GPLR(CORGI_GPIO_HSYNC) & GPIO_bit(CORGI_GPIO_HSYNC))
53
54#define SyncHS() while((STATUS_HSYNC) == 0); while((STATUS_HSYNC) != 0);
55#define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C0, 0" : "=r"(a))
56#define CCNT_ON() {int pmnc = 1; asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(pmnc));}
57#define CCNT_OFF() {int pmnc = 0; asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(pmnc));}
58
59#define WAIT_HS_400_VGA 7013U // 17.615us
60#define WAIT_HS_400_QVGA 16622U // 41.750us
61
62
63/* ADS7846 Touch Screen Controller bit definitions */
64#define ADSCTRL_PD0 (1u << 0) /* PD0 */
65#define ADSCTRL_PD1 (1u << 1) /* PD1 */
66#define ADSCTRL_DFR (1u << 2) /* SER/DFR */
67#define ADSCTRL_MOD (1u << 3) /* Mode */
68#define ADSCTRL_ADR_SH 4 /* Address setting */
69#define ADSCTRL_STS (1u << 7) /* Start Bit */
70
71/* External Functions */
72extern int w100fb_get_xres(void);
73extern int w100fb_get_blanking(void);
74extern int w100fb_get_fastsysclk(void);
75extern unsigned int get_clk_frequency_khz(int info);
76
77static unsigned long calc_waittime(void)
78{
79 int w100fb_xres = w100fb_get_xres();
80 unsigned int waittime = 0;
81
82 if (w100fb_xres == 480 || w100fb_xres == 640) {
83 waittime = WAIT_HS_400_VGA * get_clk_frequency_khz(0) / 398131U;
84
85 if (w100fb_get_fastsysclk() == 100)
86 waittime = waittime * 75 / 100;
87
88 if (w100fb_xres == 640)
89 waittime *= 3;
90
91 return waittime;
92 }
93
94 return WAIT_HS_400_QVGA * get_clk_frequency_khz(0) / 398131U;
95}
96
97static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int address, unsigned long wait_time)
98{
99 int pos = 0;
100 unsigned long timer1 = 0, timer2;
101 int dosleep;
102
103 dosleep = !w100fb_get_blanking();
104
105 if (dosleep && doSend) {
106 CCNT_ON();
107 /* polling HSync */
108 SyncHS();
109 /* get CCNT */
110 CCNT(timer1);
111 }
112
113 if (doRecive)
114 pos = corgi_ssp_ads7846_get();
115
116 if (doSend) {
117 int cmd = ADSCTRL_PD0 | ADSCTRL_PD1 | (address << ADSCTRL_ADR_SH) | ADSCTRL_STS;
118 /* dummy command */
119 corgi_ssp_ads7846_put(cmd);
120 corgi_ssp_ads7846_get();
121
122 if (dosleep) {
123 /* Wait after HSync */
124 CCNT(timer2);
125 if (timer2-timer1 > wait_time) {
126 /* timeout */
127 SyncHS();
128 /* get OSCR */
129 CCNT(timer1);
130 /* Wait after HSync */
131 CCNT(timer2);
132 }
133 while (timer2 - timer1 < wait_time)
134 CCNT(timer2);
135 }
136 corgi_ssp_ads7846_put(cmd);
137 if (dosleep)
138 CCNT_OFF();
139 }
140 return pos;
141}
142
143static int read_xydata(struct corgi_ts *corgi_ts)
144{
145 unsigned int x, y, z1, z2;
146 unsigned long flags, wait_time;
147
148 /* critical section */
149 local_irq_save(flags);
150 corgi_ssp_ads7846_lock();
151 wait_time=calc_waittime();
152
153 /* Y-axis */
154 sync_receive_data_send_cmd(0, 1, 1u, wait_time);
155
156 /* Y-axis */
157 sync_receive_data_send_cmd(1, 1, 1u, wait_time);
158
159 /* X-axis */
160 y = sync_receive_data_send_cmd(1, 1, 5u, wait_time);
161
162 /* Z1 */
163 x = sync_receive_data_send_cmd(1, 1, 3u, wait_time);
164
165 /* Z2 */
166 z1 = sync_receive_data_send_cmd(1, 1, 4u, wait_time);
167 z2 = sync_receive_data_send_cmd(1, 0, 4u, wait_time);
168
169 /* Power-Down Enable */
170 corgi_ssp_ads7846_put((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
171 corgi_ssp_ads7846_get();
172
173 corgi_ssp_ads7846_unlock();
174 local_irq_restore(flags);
175
176 if (x== 0 || y == 0 || z1 == 0 || (x * (z2 - z1) / z1) >= 15000) {
177 corgi_ts->tc.pressure = 0;
178 return 0;
179 }
180
181 corgi_ts->tc.x = x;
182 corgi_ts->tc.y = y;
183 corgi_ts->tc.pressure = (x * (z2 - z1)) / z1;
184 return 1;
185}
186
187static void new_data(struct corgi_ts *corgi_ts, struct pt_regs *regs)
188{
189 if (corgi_ts->power_mode != PWR_MODE_ACTIVE)
190 return;
191
192 if (!corgi_ts->tc.pressure && corgi_ts->pendown == 0)
193 return;
194
195 if (regs)
196 input_regs(&corgi_ts->input, regs);
197
198 input_report_abs(&corgi_ts->input, ABS_X, corgi_ts->tc.x);
199 input_report_abs(&corgi_ts->input, ABS_Y, corgi_ts->tc.y);
200 input_report_abs(&corgi_ts->input, ABS_PRESSURE, corgi_ts->tc.pressure);
201 input_report_key(&corgi_ts->input, BTN_TOUCH, (corgi_ts->pendown != 0));
202 input_sync(&corgi_ts->input);
203}
204
205static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer, struct pt_regs *regs)
206{
207 if ((GPLR(CORGI_GPIO_TP_INT) & GPIO_bit(CORGI_GPIO_TP_INT)) == 0) {
208 /* Disable Interrupt */
209 set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_NOEDGE);
210 if (read_xydata(corgi_ts)) {
211 corgi_ts->pendown = 1;
212 new_data(corgi_ts, regs);
213 }
214 mod_timer(&corgi_ts->timer, jiffies + HZ / 100);
215 } else {
216 if (corgi_ts->pendown == 1 || corgi_ts->pendown == 2) {
217 mod_timer(&corgi_ts->timer, jiffies + HZ / 100);
218 corgi_ts->pendown++;
219 return;
220 }
221
222 if (corgi_ts->pendown) {
223 corgi_ts->tc.pressure = 0;
224 new_data(corgi_ts, regs);
225 }
226
227 /* Enable Falling Edge */
228 set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
229 corgi_ts->pendown = 0;
230 }
231}
232
233static void corgi_ts_timer(unsigned long data)
234{
235 struct corgi_ts *corgits_data = (struct corgi_ts *) data;
236 ts_interrupt_main(corgits_data, 1, NULL);
237}
238
239static irqreturn_t ts_interrupt(int irq, void *dev_id, struct pt_regs *regs)
240{
241 struct corgi_ts *corgits_data = dev_id;
242 ts_interrupt_main(corgits_data, 0, regs);
243 return IRQ_HANDLED;
244}
245
246#ifdef CONFIG_PM
247static int corgits_suspend(struct device *dev, uint32_t state, uint32_t level)
248{
249 if (level == SUSPEND_POWER_DOWN) {
250 struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
251
252 if (corgi_ts->pendown) {
253 del_timer_sync(&corgi_ts->timer);
254 corgi_ts->tc.pressure = 0;
255 new_data(corgi_ts, NULL);
256 corgi_ts->pendown = 0;
257 }
258 corgi_ts->power_mode = PWR_MODE_SUSPEND;
259
260 corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
261 }
262 return 0;
263}
264
265static int corgits_resume(struct device *dev, uint32_t level)
266{
267 if (level == RESUME_POWER_ON) {
268 struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
269
270 corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
271 /* Enable Falling Edge */
272 set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
273 corgi_ts->power_mode = PWR_MODE_ACTIVE;
274 }
275 return 0;
276}
277#else
278#define corgits_suspend NULL
279#define corgits_resume NULL
280#endif
281
282static int __init corgits_probe(struct device *dev)
283{
284 struct corgi_ts *corgi_ts;
285
286 if (!(corgi_ts = kmalloc(sizeof(struct corgi_ts), GFP_KERNEL)))
287 return -ENOMEM;
288
289 dev_set_drvdata(dev, corgi_ts);
290
291 memset(corgi_ts, 0, sizeof(struct corgi_ts));
292
293 init_input_dev(&corgi_ts->input);
294 corgi_ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
295 corgi_ts->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
296 input_set_abs_params(&corgi_ts->input, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0);
297 input_set_abs_params(&corgi_ts->input, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0);
298 input_set_abs_params(&corgi_ts->input, ABS_PRESSURE, PRESSURE_MIN, PRESSURE_MAX, 0, 0);
299
300 strcpy(corgi_ts->phys, "corgits/input0");
301
302 corgi_ts->input.private = corgi_ts;
303 corgi_ts->input.name = "Corgi Touchscreen";
304 corgi_ts->input.dev = dev;
305 corgi_ts->input.phys = corgi_ts->phys;
306 corgi_ts->input.id.bustype = BUS_HOST;
307 corgi_ts->input.id.vendor = 0x0001;
308 corgi_ts->input.id.product = 0x0002;
309 corgi_ts->input.id.version = 0x0100;
310
311 pxa_gpio_mode(CORGI_GPIO_TP_INT | GPIO_IN);
312 pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN);
313
314 /* Initiaize ADS7846 Difference Reference mode */
315 corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
316 mdelay(5);
317 corgi_ssp_ads7846_putget((3u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
318 mdelay(5);
319 corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
320 mdelay(5);
321 corgi_ssp_ads7846_putget((5u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
322 mdelay(5);
323
324 init_timer(&corgi_ts->timer);
325 corgi_ts->timer.data = (unsigned long) corgi_ts;
326 corgi_ts->timer.function = corgi_ts_timer;
327
328 input_register_device(&corgi_ts->input);
329 corgi_ts->power_mode = PWR_MODE_ACTIVE;
330
331 if (request_irq(CORGI_IRQ_GPIO_TP_INT, ts_interrupt, SA_INTERRUPT, "ts", corgi_ts)) {
332 input_unregister_device(&corgi_ts->input);
333 kfree(corgi_ts);
334 return -EBUSY;
335 }
336
337 /* Enable Falling Edge */
338 set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
339
340 printk(KERN_INFO "input: Corgi Touchscreen Registered\n");
341
342 return 0;
343}
344
345static int corgits_remove(struct device *dev)
346{
347 struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
348
349 free_irq(CORGI_IRQ_GPIO_TP_INT, NULL);
350 del_timer_sync(&corgi_ts->timer);
351 input_unregister_device(&corgi_ts->input);
352 kfree(corgi_ts);
353 return 0;
354}
355
356static struct device_driver corgits_driver = {
357 .name = "corgi-ts",
358 .bus = &platform_bus_type,
359 .probe = corgits_probe,
360 .remove = corgits_remove,
361 .suspend = corgits_suspend,
362 .resume = corgits_resume,
363};
364
365static int __devinit corgits_init(void)
366{
367 return driver_register(&corgits_driver);
368}
369
370static void __exit corgits_exit(void)
371{
372 driver_unregister(&corgits_driver);
373}
374
375module_init(corgits_init);
376module_exit(corgits_exit);
377
378MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
379MODULE_DESCRIPTION("Corgi TouchScreen Driver");
380MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c
new file mode 100644
index 000000000000..546ce599334e
--- /dev/null
+++ b/drivers/input/touchscreen/elo.c
@@ -0,0 +1,315 @@
1/*
2 * Elo serial touchscreen driver
3 *
4 * Copyright (c) 2004 Vojtech Pavlik
5 */
6
7/*
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 */
12
13/*
14 * This driver can handle serial Elo touchscreens using either the Elo standard
15 * 'E271-2210' 10-byte protocol, Elo legacy 'E281A-4002' 6-byte protocol, Elo
16 * legacy 'E271-140' 4-byte protocol and Elo legacy 'E261-280' 3-byte protocol.
17 */
18
19#include <linux/errno.h>
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/slab.h>
23#include <linux/input.h>
24#include <linux/serio.h>
25#include <linux/init.h>
26
27#define DRIVER_DESC "Elo serial touchscreen driver"
28
29MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
30MODULE_DESCRIPTION(DRIVER_DESC);
31MODULE_LICENSE("GPL");
32
33/*
34 * Definitions & global arrays.
35 */
36
37#define ELO_MAX_LENGTH 10
38
39static char *elo_name = "Elo Serial TouchScreen";
40
41/*
42 * Per-touchscreen data.
43 */
44
45struct elo {
46 struct input_dev dev;
47 struct serio *serio;
48 int id;
49 int idx;
50 unsigned char csum;
51 unsigned char data[ELO_MAX_LENGTH];
52 char phys[32];
53};
54
55static void elo_process_data_10(struct elo* elo, unsigned char data, struct pt_regs *regs)
56{
57 struct input_dev *dev = &elo->dev;
58
59 elo->csum += elo->data[elo->idx] = data;
60
61 switch (elo->idx++) {
62
63 case 0:
64 if (data != 'U') {
65 elo->idx = 0;
66 elo->csum = 0;
67 }
68 break;
69
70 case 1:
71 if (data != 'T') {
72 elo->idx = 0;
73 elo->csum = 0;
74 }
75 break;
76
77 case 9:
78 if (elo->csum) {
79 input_regs(dev, regs);
80 input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]);
81 input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]);
82 input_report_abs(dev, ABS_PRESSURE, (elo->data[8] << 8) | elo->data[7]);
83 input_report_key(dev, BTN_TOUCH, elo->data[2] & 3);
84 input_sync(dev);
85 }
86 elo->idx = 0;
87 elo->csum = 0;
88 break;
89 }
90}
91
92static void elo_process_data_6(struct elo* elo, unsigned char data, struct pt_regs *regs)
93{
94 struct input_dev *dev = &elo->dev;
95
96 elo->data[elo->idx] = data;
97
98 switch (elo->idx++) {
99
100 case 0: if ((data & 0xc0) != 0xc0) elo->idx = 0; break;
101 case 1: if ((data & 0xc0) != 0x80) elo->idx = 0; break;
102 case 2: if ((data & 0xc0) != 0x40) elo->idx = 0; break;
103
104 case 3:
105 if (data & 0xc0) {
106 elo->idx = 0;
107 break;
108 }
109
110 input_regs(dev, regs);
111 input_report_abs(dev, ABS_X, ((elo->data[0] & 0x3f) << 6) | (elo->data[1] & 0x3f));
112 input_report_abs(dev, ABS_Y, ((elo->data[2] & 0x3f) << 6) | (elo->data[3] & 0x3f));
113
114 if (elo->id == 2) {
115 input_report_key(dev, BTN_TOUCH, 1);
116 input_sync(dev);
117 elo->idx = 0;
118 }
119
120 break;
121
122 case 4:
123 if (data) {
124 input_sync(dev);
125 elo->idx = 0;
126 }
127 break;
128
129 case 5:
130 if ((data & 0xf0) == 0) {
131 input_report_abs(dev, ABS_PRESSURE, elo->data[5]);
132 input_report_key(dev, BTN_TOUCH, elo->data[5]);
133 }
134 input_sync(dev);
135 elo->idx = 0;
136 break;
137 }
138}
139
140static void elo_process_data_3(struct elo* elo, unsigned char data, struct pt_regs *regs)
141{
142 struct input_dev *dev = &elo->dev;
143
144 elo->data[elo->idx] = data;
145
146 switch (elo->idx++) {
147
148 case 0:
149 if ((data & 0x7f) != 0x01)
150 elo->idx = 0;
151 break;
152 case 2:
153 input_regs(dev, regs);
154 input_report_key(dev, BTN_TOUCH, !(elo->data[1] & 0x80));
155 input_report_abs(dev, ABS_X, elo->data[1]);
156 input_report_abs(dev, ABS_Y, elo->data[2]);
157 input_sync(dev);
158 elo->idx = 0;
159 break;
160 }
161}
162
163static irqreturn_t elo_interrupt(struct serio *serio,
164 unsigned char data, unsigned int flags, struct pt_regs *regs)
165{
166 struct elo* elo = serio_get_drvdata(serio);
167
168 switch(elo->id) {
169 case 0:
170 elo_process_data_10(elo, data, regs);
171 break;
172
173 case 1:
174 case 2:
175 elo_process_data_6(elo, data, regs);
176 break;
177
178 case 3:
179 elo_process_data_3(elo, data, regs);
180 break;
181 }
182
183 return IRQ_HANDLED;
184}
185
186/*
187 * elo_disconnect() is the opposite of elo_connect()
188 */
189
190static void elo_disconnect(struct serio *serio)
191{
192 struct elo* elo = serio_get_drvdata(serio);
193
194 input_unregister_device(&elo->dev);
195 serio_close(serio);
196 serio_set_drvdata(serio, NULL);
197 kfree(elo);
198}
199
200/*
201 * elo_connect() is the routine that is called when someone adds a
202 * new serio device that supports Gunze protocol and registers it as
203 * an input device.
204 */
205
206static int elo_connect(struct serio *serio, struct serio_driver *drv)
207{
208 struct elo *elo;
209 int err;
210
211 if (!(elo = kmalloc(sizeof(struct elo), GFP_KERNEL)))
212 return -ENOMEM;
213
214 memset(elo, 0, sizeof(struct elo));
215
216 init_input_dev(&elo->dev);
217 elo->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
218 elo->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
219
220 elo->id = serio->id.id;
221
222 switch (elo->id) {
223
224 case 0: /* 10-byte protocol */
225 input_set_abs_params(&elo->dev, ABS_X, 96, 4000, 0, 0);
226 input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0);
227 input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 255, 0, 0);
228 break;
229
230 case 1: /* 6-byte protocol */
231 input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 15, 0, 0);
232
233 case 2: /* 4-byte protocol */
234 input_set_abs_params(&elo->dev, ABS_X, 96, 4000, 0, 0);
235 input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0);
236 break;
237
238 case 3: /* 3-byte protocol */
239 input_set_abs_params(&elo->dev, ABS_X, 0, 255, 0, 0);
240 input_set_abs_params(&elo->dev, ABS_Y, 0, 255, 0, 0);
241 break;
242 }
243
244 elo->serio = serio;
245
246 sprintf(elo->phys, "%s/input0", serio->phys);
247
248 elo->dev.private = elo;
249 elo->dev.name = elo_name;
250 elo->dev.phys = elo->phys;
251 elo->dev.id.bustype = BUS_RS232;
252 elo->dev.id.vendor = SERIO_ELO;
253 elo->dev.id.product = elo->id;
254 elo->dev.id.version = 0x0100;
255
256 serio_set_drvdata(serio, elo);
257
258 err = serio_open(serio, drv);
259 if (err) {
260 serio_set_drvdata(serio, NULL);
261 kfree(elo);
262 return err;
263 }
264
265 input_register_device(&elo->dev);
266
267 printk(KERN_INFO "input: %s on %s\n", elo_name, serio->phys);
268
269 return 0;
270}
271
272/*
273 * The serio driver structure.
274 */
275
276static struct serio_device_id elo_serio_ids[] = {
277 {
278 .type = SERIO_RS232,
279 .proto = SERIO_ELO,
280 .id = SERIO_ANY,
281 .extra = SERIO_ANY,
282 },
283 { 0 }
284};
285
286MODULE_DEVICE_TABLE(serio, elo_serio_ids);
287
288static struct serio_driver elo_drv = {
289 .driver = {
290 .name = "elo",
291 },
292 .description = DRIVER_DESC,
293 .id_table = elo_serio_ids,
294 .interrupt = elo_interrupt,
295 .connect = elo_connect,
296 .disconnect = elo_disconnect,
297};
298
299/*
300 * The functions for inserting/removing us as a module.
301 */
302
303static int __init elo_init(void)
304{
305 serio_register_driver(&elo_drv);
306 return 0;
307}
308
309static void __exit elo_exit(void)
310{
311 serio_unregister_driver(&elo_drv);
312}
313
314module_init(elo_init);
315module_exit(elo_exit);
diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c
new file mode 100644
index 000000000000..c9d0a153671c
--- /dev/null
+++ b/drivers/input/touchscreen/gunze.c
@@ -0,0 +1,205 @@
1/*
2 * $Id: gunze.c,v 1.12 2001/09/25 10:12:07 vojtech Exp $
3 *
4 * Copyright (c) 2000-2001 Vojtech Pavlik
5 */
6
7/*
8 * Gunze AHL-51S touchscreen driver for Linux
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/errno.h>
32#include <linux/kernel.h>
33#include <linux/module.h>
34#include <linux/slab.h>
35#include <linux/input.h>
36#include <linux/serio.h>
37#include <linux/init.h>
38
39#define DRIVER_DESC "Gunze AHL-51S touchscreen driver"
40
41MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
42MODULE_DESCRIPTION(DRIVER_DESC);
43MODULE_LICENSE("GPL");
44
45/*
46 * Definitions & global arrays.
47 */
48
49#define GUNZE_MAX_LENGTH 10
50
51static char *gunze_name = "Gunze AHL-51S TouchScreen";
52
53/*
54 * Per-touchscreen data.
55 */
56
57struct gunze {
58 struct input_dev dev;
59 struct serio *serio;
60 int idx;
61 unsigned char data[GUNZE_MAX_LENGTH];
62 char phys[32];
63};
64
65static void gunze_process_packet(struct gunze* gunze, struct pt_regs *regs)
66{
67 struct input_dev *dev = &gunze->dev;
68
69 if (gunze->idx != GUNZE_MAX_LENGTH || gunze->data[5] != ',' ||
70 (gunze->data[0] != 'T' && gunze->data[0] != 'R')) {
71 gunze->data[10] = 0;
72 printk(KERN_WARNING "gunze.c: bad packet: >%s<\n", gunze->data);
73 return;
74 }
75
76 input_regs(dev, regs);
77 input_report_abs(dev, ABS_X, simple_strtoul(gunze->data + 1, NULL, 10));
78 input_report_abs(dev, ABS_Y, 1024 - simple_strtoul(gunze->data + 6, NULL, 10));
79 input_report_key(dev, BTN_TOUCH, gunze->data[0] == 'T');
80 input_sync(dev);
81}
82
83static irqreturn_t gunze_interrupt(struct serio *serio,
84 unsigned char data, unsigned int flags, struct pt_regs *regs)
85{
86 struct gunze* gunze = serio_get_drvdata(serio);
87
88 if (data == '\r') {
89 gunze_process_packet(gunze, regs);
90 gunze->idx = 0;
91 } else {
92 if (gunze->idx < GUNZE_MAX_LENGTH)
93 gunze->data[gunze->idx++] = data;
94 }
95 return IRQ_HANDLED;
96}
97
98/*
99 * gunze_disconnect() is the opposite of gunze_connect()
100 */
101
102static void gunze_disconnect(struct serio *serio)
103{
104 struct gunze* gunze = serio_get_drvdata(serio);
105
106 input_unregister_device(&gunze->dev);
107 serio_close(serio);
108 serio_set_drvdata(serio, NULL);
109 kfree(gunze);
110}
111
112/*
113 * gunze_connect() is the routine that is called when someone adds a
114 * new serio device that supports Gunze protocol and registers it as
115 * an input device.
116 */
117
118static int gunze_connect(struct serio *serio, struct serio_driver *drv)
119{
120 struct gunze *gunze;
121 int err;
122
123 if (!(gunze = kmalloc(sizeof(struct gunze), GFP_KERNEL)))
124 return -ENOMEM;
125
126 memset(gunze, 0, sizeof(struct gunze));
127
128 init_input_dev(&gunze->dev);
129 gunze->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
130 gunze->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
131 input_set_abs_params(&gunze->dev, ABS_X, 24, 1000, 0, 0);
132 input_set_abs_params(&gunze->dev, ABS_Y, 24, 1000, 0, 0);
133
134 gunze->serio = serio;
135
136 sprintf(gunze->phys, "%s/input0", serio->phys);
137
138 gunze->dev.private = gunze;
139 gunze->dev.name = gunze_name;
140 gunze->dev.phys = gunze->phys;
141 gunze->dev.id.bustype = BUS_RS232;
142 gunze->dev.id.vendor = SERIO_GUNZE;
143 gunze->dev.id.product = 0x0051;
144 gunze->dev.id.version = 0x0100;
145
146 serio_set_drvdata(serio, gunze);
147
148 err = serio_open(serio, drv);
149 if (err) {
150 serio_set_drvdata(serio, NULL);
151 kfree(gunze);
152 return err;
153 }
154
155 input_register_device(&gunze->dev);
156
157 printk(KERN_INFO "input: %s on %s\n", gunze_name, serio->phys);
158
159 return 0;
160}
161
162/*
163 * The serio driver structure.
164 */
165
166static struct serio_device_id gunze_serio_ids[] = {
167 {
168 .type = SERIO_RS232,
169 .proto = SERIO_GUNZE,
170 .id = SERIO_ANY,
171 .extra = SERIO_ANY,
172 },
173 { 0 }
174};
175
176MODULE_DEVICE_TABLE(serio, gunze_serio_ids);
177
178static struct serio_driver gunze_drv = {
179 .driver = {
180 .name = "gunze",
181 },
182 .description = DRIVER_DESC,
183 .id_table = gunze_serio_ids,
184 .interrupt = gunze_interrupt,
185 .connect = gunze_connect,
186 .disconnect = gunze_disconnect,
187};
188
189/*
190 * The functions for inserting/removing us as a module.
191 */
192
193static int __init gunze_init(void)
194{
195 serio_register_driver(&gunze_drv);
196 return 0;
197}
198
199static void __exit gunze_exit(void)
200{
201 serio_unregister_driver(&gunze_drv);
202}
203
204module_init(gunze_init);
205module_exit(gunze_exit);
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c
new file mode 100644
index 000000000000..acb9137a0226
--- /dev/null
+++ b/drivers/input/touchscreen/h3600_ts_input.c
@@ -0,0 +1,528 @@
1/*
2 * $Id: h3600_ts_input.c,v 1.4 2002/01/23 06:39:37 jsimmons Exp $
3 *
4 * Copyright (c) 2001 "Crazy" James Simmons jsimmons@transvirtual.com
5 *
6 * Sponsored by Transvirtual Technology.
7 *
8 * Derived from the code in h3600_ts.[ch] by Charles Flynn
9 */
10
11/*
12 * Driver for the h3600 Touch Screen and other Atmel controlled devices.
13 */
14
15/*
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 * Should you need to contact me, the author, you can do so by
31 * e-mail - mail your message to <jsimmons@transvirtual.com>.
32 */
33
34#include <linux/errno.h>
35#include <linux/kernel.h>
36#include <linux/module.h>
37#include <linux/slab.h>
38#include <linux/input.h>
39#include <linux/serio.h>
40#include <linux/init.h>
41#include <linux/delay.h>
42#include <linux/pm.h>
43
44/* SA1100 serial defines */
45#include <asm/arch/hardware.h>
46#include <asm/arch/irqs.h>
47
48#define DRIVER_DESC "H3600 touchscreen driver"
49
50MODULE_AUTHOR("James Simmons <jsimmons@transvirtual.com>");
51MODULE_DESCRIPTION(DRIVER_DESC);
52MODULE_LICENSE("GPL");
53
54/*
55 * Definitions & global arrays.
56 */
57
58/* The start and end of frame characters SOF and EOF */
59#define CHAR_SOF 0x02
60#define CHAR_EOF 0x03
61#define FRAME_OVERHEAD 3 /* CHAR_SOF,CHAR_EOF,LENGTH = 3 */
62
63/*
64 Atmel events and response IDs contained in frame.
65 Programmer has no control over these numbers.
66 TODO there are holes - specifically 1,7,0x0a
67*/
68#define VERSION_ID 0 /* Get Version (request/respose) */
69#define KEYBD_ID 2 /* Keyboard (event) */
70#define TOUCHS_ID 3 /* Touch Screen (event)*/
71#define EEPROM_READ_ID 4 /* (request/response) */
72#define EEPROM_WRITE_ID 5 /* (request/response) */
73#define THERMAL_ID 6 /* (request/response) */
74#define NOTIFY_LED_ID 8 /* (request/response) */
75#define BATTERY_ID 9 /* (request/response) */
76#define SPI_READ_ID 0x0b /* ( request/response) */
77#define SPI_WRITE_ID 0x0c /* ( request/response) */
78#define FLITE_ID 0x0d /* backlight ( request/response) */
79#define STX_ID 0xa1 /* extension pack status (req/resp) */
80
81#define MAX_ID 14
82
83#define H3600_MAX_LENGTH 16
84#define H3600_KEY 0xf
85
86#define H3600_SCANCODE_RECORD 1 /* 1 -> record button */
87#define H3600_SCANCODE_CALENDAR 2 /* 2 -> calendar */
88#define H3600_SCANCODE_CONTACTS 3 /* 3 -> contact */
89#define H3600_SCANCODE_Q 4 /* 4 -> Q button */
90#define H3600_SCANCODE_START 5 /* 5 -> start menu */
91#define H3600_SCANCODE_UP 6 /* 6 -> up */
92#define H3600_SCANCODE_RIGHT 7 /* 7 -> right */
93#define H3600_SCANCODE_LEFT 8 /* 8 -> left */
94#define H3600_SCANCODE_DOWN 9 /* 9 -> down */
95
96static char *h3600_name = "H3600 TouchScreen";
97
98/*
99 * Per-touchscreen data.
100 */
101struct h3600_dev {
102 struct input_dev dev;
103 struct pm_dev *pm_dev;
104 struct serio *serio;
105 struct pm_dev *pm_dev;
106 unsigned char event; /* event ID from packet */
107 unsigned char chksum;
108 unsigned char len;
109 unsigned char idx;
110 unsigned char buf[H3600_MAX_LENGTH];
111 char phys[32];
112};
113
114static irqreturn_t action_button_handler(int irq, void *dev_id, struct pt_regs *regs)
115{
116 int down = (GPLR & GPIO_BITSY_ACTION_BUTTON) ? 0 : 1;
117 struct input_dev *dev = (struct input_dev *) dev_id;
118
119 input_regs(dev, regs);
120 input_report_key(dev, KEY_ENTER, down);
121 input_sync(dev);
122
123 return IRQ_HANDLED;
124}
125
126static irqreturn_t npower_button_handler(int irq, void *dev_id, struct pt_regs *regs)
127{
128 int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1;
129 struct input_dev *dev = (struct input_dev *) dev_id;
130
131 /*
132 * This interrupt is only called when we release the key. So we have
133 * to fake a key press.
134 */
135 input_regs(dev, regs);
136 input_report_key(dev, KEY_SUSPEND, 1);
137 input_report_key(dev, KEY_SUSPEND, down);
138 input_sync(dev);
139
140 return IRQ_HANDLED;
141}
142
143#ifdef CONFIG_PM
144
145static int flite_brightness = 25;
146
147enum flite_pwr {
148 FLITE_PWR_OFF = 0,
149 FLITE_PWR_ON = 1
150};
151
152/*
153 * h3600_flite_power: enables or disables power to frontlight, using last bright */
154unsigned int h3600_flite_power(struct input_dev *dev, enum flite_pwr pwr)
155{
156 unsigned char brightness = (pwr == FLITE_PWR_OFF) ? 0 : flite_brightness;
157 struct h3600_dev *ts = dev->private;
158
159 /* Must be in this order */
160 ts->serio->write(ts->serio, 1);
161 ts->serio->write(ts->serio, pwr);
162 ts->serio->write(ts->serio, brightness);
163 return 0;
164}
165
166static int suspended = 0;
167static int h3600ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req,
168 void *data)
169{
170 struct input_dev *dev = (struct input_dev *) data;
171
172 switch (req) {
173 case PM_SUSPEND: /* enter D1-D3 */
174 suspended = 1;
175 h3600_flite_power(dev, FLITE_PWR_OFF);
176 break;
177 case PM_BLANK:
178 if (!suspended)
179 h3600_flite_power(dev, FLITE_PWR_OFF);
180 break;
181 case PM_RESUME: /* enter D0 */
182 /* same as unblank */
183 case PM_UNBLANK:
184 if (suspended) {
185 //initSerial();
186 suspended = 0;
187 }
188 h3600_flite_power(dev, FLITE_PWR_ON);
189 break;
190 }
191 return 0;
192}
193#endif
194
195/*
196 * This function translates the native event packets to linux input event
197 * packets. Some packets coming from serial are not touchscreen related. In
198 * this case we send them off to be processed elsewhere.
199 */
200static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs)
201{
202 struct input_dev *dev = &ts->dev;
203 static int touched = 0;
204 int key, down = 0;
205
206 input_regs(dev, regs);
207
208 switch (ts->event) {
209 /*
210 Buttons - returned as a single byte
211 7 6 5 4 3 2 1 0
212 S x x x N N N N
213
214 S switch state ( 0=pressed 1=released)
215 x Unused.
216 NNNN switch number 0-15
217
218 Note: This is true for non interrupt generated key events.
219 */
220 case KEYBD_ID:
221 down = (ts->buf[0] & 0x80) ? 0 : 1;
222
223 switch (ts->buf[0] & 0x7f) {
224 case H3600_SCANCODE_RECORD:
225 key = KEY_RECORD;
226 break;
227 case H3600_SCANCODE_CALENDAR:
228 key = KEY_PROG1;
229 break;
230 case H3600_SCANCODE_CONTACTS:
231 key = KEY_PROG2;
232 break;
233 case H3600_SCANCODE_Q:
234 key = KEY_Q;
235 break;
236 case H3600_SCANCODE_START:
237 key = KEY_PROG3;
238 break;
239 case H3600_SCANCODE_UP:
240 key = KEY_UP;
241 break;
242 case H3600_SCANCODE_RIGHT:
243 key = KEY_RIGHT;
244 break;
245 case H3600_SCANCODE_LEFT:
246 key = KEY_LEFT;
247 break;
248 case H3600_SCANCODE_DOWN:
249 key = KEY_DOWN;
250 break;
251 default:
252 key = 0;
253 }
254 if (key)
255 input_report_key(dev, key, down);
256 break;
257 /*
258 * Native touchscreen event data is formatted as shown below:-
259 *
260 * +-------+-------+-------+-------+
261 * | Xmsb | Xlsb | Ymsb | Ylsb |
262 * +-------+-------+-------+-------+
263 * byte 0 1 2 3
264 */
265 case TOUCHS_ID:
266 if (!touched) {
267 input_report_key(dev, BTN_TOUCH, 1);
268 touched = 1;
269 }
270
271 if (ts->len) {
272 unsigned short x, y;
273
274 x = ts->buf[0]; x <<= 8; x += ts->buf[1];
275 y = ts->buf[2]; y <<= 8; y += ts->buf[3];
276
277 input_report_abs(dev, ABS_X, x);
278 input_report_abs(dev, ABS_Y, y);
279 } else {
280 input_report_key(dev, BTN_TOUCH, 0);
281 touched = 0;
282 }
283 break;
284 default:
285 /* Send a non input event elsewhere */
286 break;
287 }
288
289 input_sync(dev);
290}
291
292/*
293 * h3600ts_event() handles events from the input module.
294 */
295static int h3600ts_event(struct input_dev *dev, unsigned int type,
296 unsigned int code, int value)
297{
298 struct h3600_dev *ts = dev->private;
299
300 switch (type) {
301 case EV_LED: {
302 // ts->serio->write(ts->serio, SOME_CMD);
303 return 0;
304 }
305 }
306 return -1;
307}
308
309/*
310 Frame format
311 byte 1 2 3 len + 4
312 +-------+---------------+---------------+--=------------+
313 |SOF |id |len | len bytes | Chksum |
314 +-------+---------------+---------------+--=------------+
315 bit 0 7 8 11 12 15 16
316
317 +-------+---------------+-------+
318 |SOF |id |0 |Chksum | - Note Chksum does not include SOF
319 +-------+---------------+-------+
320 bit 0 7 8 11 12 15 16
321
322*/
323
324static int state;
325
326/* decode States */
327#define STATE_SOF 0 /* start of FRAME */
328#define STATE_ID 1 /* state where we decode the ID & len */
329#define STATE_DATA 2 /* state where we decode data */
330#define STATE_EOF 3 /* state where we decode checksum or EOF */
331
332static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data,
333 unsigned int flags, struct pt_regs *regs)
334{
335 struct h3600_dev *ts = serio_get_drvdata(serio);
336
337 /*
338 * We have a new frame coming in.
339 */
340 switch (state) {
341 case STATE_SOF:
342 if (data == CHAR_SOF)
343 state = STATE_ID;
344 break;
345 case STATE_ID:
346 ts->event = (data & 0xf0) >> 4;
347 ts->len = (data & 0xf);
348 ts->idx = 0;
349 if (ts->event >= MAX_ID) {
350 state = STATE_SOF;
351 break;
352 }
353 ts->chksum = data;
354 state = (ts->len > 0) ? STATE_DATA : STATE_EOF;
355 break;
356 case STATE_DATA:
357 ts->chksum += data;
358 ts->buf[ts->idx]= data;
359 if(++ts->idx == ts->len)
360 state = STATE_EOF;
361 break;
362 case STATE_EOF:
363 state = STATE_SOF;
364 if (data == CHAR_EOF || data == ts->chksum)
365 h3600ts_process_packet(ts, regs);
366 break;
367 default:
368 printk("Error3\n");
369 break;
370 }
371
372 return IRQ_HANDLED;
373}
374
375/*
376 * h3600ts_connect() is the routine that is called when someone adds a
377 * new serio device that supports H3600 protocol and registers it as
378 * an input device.
379 */
380static int h3600ts_connect(struct serio *serio, struct serio_driver *drv)
381{
382 struct h3600_dev *ts;
383 int err;
384
385 if (!(ts = kmalloc(sizeof(struct h3600_dev), GFP_KERNEL)))
386 return -ENOMEM;
387
388 memset(ts, 0, sizeof(struct h3600_dev));
389
390 init_input_dev(&ts->dev);
391
392 /* Device specific stuff */
393 set_GPIO_IRQ_edge(GPIO_BITSY_ACTION_BUTTON, GPIO_BOTH_EDGES);
394 set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE);
395
396 if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler,
397 SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM,
398 "h3600_action", &ts->dev)) {
399 printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n");
400 kfree(ts);
401 return -EBUSY;
402 }
403
404 if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler,
405 SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM,
406 "h3600_suspend", &ts->dev)) {
407 free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev);
408 printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n");
409 kfree(ts);
410 return -EBUSY;
411 }
412
413 /* Now we have things going we setup our input device */
414 ts->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_LED) | BIT(EV_PWR);
415 ts->dev.ledbit[0] = BIT(LED_SLEEP);
416 input_set_abs_params(&ts->dev, ABS_X, 60, 985, 0, 0);
417 input_set_abs_params(&ts->dev, ABS_Y, 35, 1024, 0, 0);
418
419 set_bit(KEY_RECORD, ts->dev.keybit);
420 set_bit(KEY_Q, ts->dev.keybit);
421 set_bit(KEY_PROG1, ts->dev.keybit);
422 set_bit(KEY_PROG2, ts->dev.keybit);
423 set_bit(KEY_PROG3, ts->dev.keybit);
424 set_bit(KEY_UP, ts->dev.keybit);
425 set_bit(KEY_RIGHT, ts->dev.keybit);
426 set_bit(KEY_LEFT, ts->dev.keybit);
427 set_bit(KEY_DOWN, ts->dev.keybit);
428 set_bit(KEY_ENTER, ts->dev.keybit);
429 ts->dev.keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH);
430 ts->dev.keybit[LONG(KEY_SUSPEND)] |= BIT(KEY_SUSPEND);
431
432 ts->serio = serio;
433
434 sprintf(ts->phys, "%s/input0", serio->phys);
435
436 ts->dev.event = h3600ts_event;
437 ts->dev.private = ts;
438 ts->dev.name = h3600_name;
439 ts->dev.phys = ts->phys;
440 ts->dev.id.bustype = BUS_RS232;
441 ts->dev.id.vendor = SERIO_H3600;
442 ts->dev.id.product = 0x0666; /* FIXME !!! We can ask the hardware */
443 ts->dev.id.version = 0x0100;
444
445 serio_set_drvdata(serio, ts);
446
447 err = serio_open(serio, drv);
448 if (err) {
449 free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts);
450 free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts);
451 serio_set_drvdata(serio, NULL);
452 kfree(ts);
453 return err;
454 }
455
456 //h3600_flite_control(1, 25); /* default brightness */
457#ifdef CONFIG_PM
458 ts->pm_dev = pm_register(PM_ILLUMINATION_DEV, PM_SYS_LIGHT,
459 h3600ts_pm_callback);
460 printk("registered pm callback\n");
461#endif
462 input_register_device(&ts->dev);
463
464 printk(KERN_INFO "input: %s on %s\n", h3600_name, serio->phys);
465
466 return 0;
467}
468
469/*
470 * h3600ts_disconnect() is the opposite of h3600ts_connect()
471 */
472
473static void h3600ts_disconnect(struct serio *serio)
474{
475 struct h3600_dev *ts = serio_get_drvdata(serio);
476
477 free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev);
478 free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, &ts->dev);
479 input_unregister_device(&ts->dev);
480 serio_close(serio);
481 serio_set_drvdata(serio, NULL);
482 kfree(ts);
483}
484
485/*
486 * The serio driver structure.
487 */
488
489static struct serio_device_id h3600ts_serio_ids[] = {
490 {
491 .type = SERIO_RS232,
492 .proto = SERIO_H3600,
493 .id = SERIO_ANY,
494 .extra = SERIO_ANY,
495 },
496 { 0 }
497};
498
499MODULE_DEVICE_TABLE(serio, h3600ts_serio_ids);
500
501static struct serio_driver h3600ts_drv = {
502 .driver = {
503 .name = "h3600ts",
504 },
505 .description = DRIVER_DESC,
506 .id_table = h3600ts_serio_ids,
507 .interrupt = h3600ts_interrupt,
508 .connect = h3600ts_connect,
509 .disconnect = h3600ts_disconnect,
510};
511
512/*
513 * The functions for inserting/removing us as a module.
514 */
515
516static int __init h3600ts_init(void)
517{
518 serio_register_driver(&h3600ts_drv);
519 return 0;
520}
521
522static void __exit h3600ts_exit(void)
523{
524 serio_unregister_driver(&h3600ts_drv);
525}
526
527module_init(h3600ts_init);
528module_exit(h3600ts_exit);
diff --git a/drivers/input/touchscreen/hp680_ts_input.c b/drivers/input/touchscreen/hp680_ts_input.c
new file mode 100644
index 000000000000..7e1404441eca
--- /dev/null
+++ b/drivers/input/touchscreen/hp680_ts_input.c
@@ -0,0 +1,135 @@
1#include <linux/input.h>
2#include <linux/module.h>
3#include <linux/init.h>
4
5#include <linux/interrupt.h>
6#include <asm/io.h>
7#include <asm/delay.h>
8#include <asm/adc.h>
9#include <asm/hp6xx/hp6xx.h>
10
11#define MODNAME "hp680_ts_input"
12
13#define HP680_TS_ABS_X_MIN 40
14#define HP680_TS_ABS_X_MAX 950
15#define HP680_TS_ABS_Y_MIN 80
16#define HP680_TS_ABS_Y_MAX 910
17
18#define SCPCR 0xa4000116
19#define PHDR 0xa400012e
20#define SCPDR 0xa4000136
21
22static void do_softint(void *data);
23
24static struct input_dev hp680_ts_dev;
25static DECLARE_WORK(work, do_softint, 0);
26static char *hp680_ts_name = "HP Jornada touchscreen";
27static char *hp680_ts_phys = "input0";
28
29static void do_softint(void *data)
30{
31 int absx = 0, absy = 0;
32 u8 scpdr;
33 int touched = 0;
34
35 if (ctrl_inb(PHDR) & PHDR_TS_PEN_DOWN) {
36 scpdr = ctrl_inb(SCPDR);
37 scpdr |= SCPDR_TS_SCAN_ENABLE;
38 scpdr &= ~SCPDR_TS_SCAN_Y;
39 ctrl_outb(scpdr, SCPDR);
40 udelay(30);
41
42 absy = adc_single(ADC_CHANNEL_TS_Y);
43
44 scpdr = ctrl_inb(SCPDR);
45 scpdr |= SCPDR_TS_SCAN_Y;
46 scpdr &= ~SCPDR_TS_SCAN_X;
47 ctrl_outb(scpdr, SCPDR);
48 udelay(30);
49
50 absx = adc_single(ADC_CHANNEL_TS_X);
51
52 scpdr = ctrl_inb(SCPDR);
53 scpdr |= SCPDR_TS_SCAN_X;
54 scpdr &= ~SCPDR_TS_SCAN_ENABLE;
55 ctrl_outb(scpdr, SCPDR);
56 udelay(100);
57 touched = ctrl_inb(PHDR) & PHDR_TS_PEN_DOWN;
58 }
59
60 if (touched) {
61 input_report_key(&hp680_ts_dev, BTN_TOUCH, 1);
62 input_report_abs(&hp680_ts_dev, ABS_X, absx);
63 input_report_abs(&hp680_ts_dev, ABS_Y, absy);
64 } else {
65 input_report_key(&hp680_ts_dev, BTN_TOUCH, 0);
66 }
67
68 input_sync(&hp680_ts_dev);
69 enable_irq(HP680_TS_IRQ);
70}
71
72static irqreturn_t hp680_ts_interrupt(int irq, void *dev, struct pt_regs *regs)
73{
74 disable_irq_nosync(irq);
75 schedule_delayed_work(&work, HZ / 20);
76
77 return IRQ_HANDLED;
78}
79
80static int __init hp680_ts_init(void)
81{
82 u8 scpdr;
83 u16 scpcr;
84
85 scpdr = ctrl_inb(SCPDR);
86 scpdr |= SCPDR_TS_SCAN_X | SCPDR_TS_SCAN_Y;
87 scpdr &= ~SCPDR_TS_SCAN_ENABLE;
88 ctrl_outb(scpdr, SCPDR);
89
90 scpcr = ctrl_inw(SCPCR);
91 scpcr &= ~SCPCR_TS_MASK;
92 scpcr |= SCPCR_TS_ENABLE;
93 ctrl_outw(scpcr, SCPCR);
94
95 memset(&hp680_ts_dev, 0, sizeof(hp680_ts_dev));
96 init_input_dev(&hp680_ts_dev);
97
98 hp680_ts_dev.evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
99 hp680_ts_dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
100 hp680_ts_dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
101
102 hp680_ts_dev.absmin[ABS_X] = HP680_TS_ABS_X_MIN;
103 hp680_ts_dev.absmin[ABS_Y] = HP680_TS_ABS_Y_MIN;
104 hp680_ts_dev.absmax[ABS_X] = HP680_TS_ABS_X_MAX;
105 hp680_ts_dev.absmax[ABS_Y] = HP680_TS_ABS_Y_MAX;
106
107 hp680_ts_dev.name = hp680_ts_name;
108 hp680_ts_dev.phys = hp680_ts_phys;
109 input_register_device(&hp680_ts_dev);
110
111 if (request_irq
112 (HP680_TS_IRQ, hp680_ts_interrupt, SA_INTERRUPT, MODNAME, 0) < 0) {
113 printk(KERN_ERR "hp680_touchscreen.c : Can't allocate irq %d\n",
114 HP680_TS_IRQ);
115 input_unregister_device(&hp680_ts_dev);
116 return -EBUSY;
117 }
118
119 return 0;
120}
121
122static void __exit hp680_ts_exit(void)
123{
124 free_irq(HP680_TS_IRQ, 0);
125 cancel_delayed_work(&work);
126 flush_scheduled_work();
127 input_unregister_device(&hp680_ts_dev);
128}
129
130module_init(hp680_ts_init);
131module_exit(hp680_ts_exit);
132
133MODULE_AUTHOR("Andriy Skulysh, askulysh@image.kiev.ua");
134MODULE_DESCRIPTION("HP Jornada 680 touchscreen driver");
135MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/mk712.c b/drivers/input/touchscreen/mk712.c
new file mode 100644
index 000000000000..2d14a57a05e5
--- /dev/null
+++ b/drivers/input/touchscreen/mk712.c
@@ -0,0 +1,222 @@
1/*
2 * ICS MK712 touchscreen controller driver
3 *
4 * Copyright (c) 1999-2002 Transmeta Corporation
5 * Copyright (c) 2005 Rick Koch <n1gp@hotmail.com>
6 * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
7 */
8
9/*
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 */
14
15/*
16 * This driver supports the ICS MicroClock MK712 TouchScreen controller,
17 * found in Gateway AOL Connected Touchpad computers.
18 *
19 * Documentation for ICS MK712 can be found at:
20 * http://www.icst.com/pdf/mk712.pdf
21 */
22
23/*
24 * 1999-12-18: original version, Daniel Quinlan
25 * 1999-12-19: added anti-jitter code, report pen-up events, fixed mk712_poll
26 * to use queue_empty, Nathan Laredo
27 * 1999-12-20: improved random point rejection, Nathan Laredo
28 * 2000-01-05: checked in new anti-jitter code, changed mouse protocol, fixed
29 * queue code, added module options, other fixes, Daniel Quinlan
30 * 2002-03-15: Clean up for kernel merge <alan@redhat.com>
31 * Fixed multi open race, fixed memory checks, fixed resource
32 * allocation, fixed close/powerdown bug, switched to new init
33 * 2005-01-18: Ported to 2.6 from 2.4.28, Rick Koch
34 * 2005-02-05: Rewritten for the input layer, Vojtech Pavlik
35 *
36 */
37
38#include <linux/module.h>
39#include <linux/moduleparam.h>
40#include <linux/kernel.h>
41#include <linux/init.h>
42#include <linux/errno.h>
43#include <linux/delay.h>
44#include <linux/ioport.h>
45#include <linux/interrupt.h>
46#include <linux/input.h>
47#include <asm/io.h>
48
49MODULE_AUTHOR("Daniel Quinlan <quinlan@pathname.com>, Vojtech Pavlik <vojtech@suse.cz>");
50MODULE_DESCRIPTION("ICS MicroClock MK712 TouchScreen driver");
51MODULE_LICENSE("GPL");
52
53static unsigned int mk712_io = 0x260; /* Also 0x200, 0x208, 0x300 */
54module_param_named(io, mk712_io, uint, 0);
55MODULE_PARM_DESC(io, "I/O base address of MK712 touchscreen controller");
56
57static unsigned int mk712_irq = 10; /* Also 12, 14, 15 */
58module_param_named(irq, mk712_irq, uint, 0);
59MODULE_PARM_DESC(irq, "IRQ of MK712 touchscreen controller");
60
61/* eight 8-bit registers */
62#define MK712_STATUS 0
63#define MK712_X 2
64#define MK712_Y 4
65#define MK712_CONTROL 6
66#define MK712_RATE 7
67
68/* status */
69#define MK712_STATUS_TOUCH 0x10
70#define MK712_CONVERSION_COMPLETE 0x80
71
72/* control */
73#define MK712_ENABLE_INT 0x01
74#define MK712_INT_ON_CONVERSION_COMPLETE 0x02
75#define MK712_INT_ON_CHANGE_IN_TOUCH_STATUS 0x04
76#define MK712_ENABLE_PERIODIC_CONVERSIONS 0x10
77#define MK712_READ_ONE_POINT 0x20
78#define MK712_POWERUP 0x40
79
80static int mk712_used = 0;
81static struct input_dev mk712_dev;
82static DEFINE_SPINLOCK(mk712_lock);
83
84static irqreturn_t mk712_interrupt(int irq, void *dev_id, struct pt_regs *regs)
85{
86 unsigned char status;
87 static int debounce = 1;
88 static unsigned short last_x;
89 static unsigned short last_y;
90
91 spin_lock(&mk712_lock);
92 input_regs(&mk712_dev, regs);
93
94 status = inb(mk712_io + MK712_STATUS);
95
96 if (~status & MK712_CONVERSION_COMPLETE) {
97 debounce = 1;
98 goto end;
99 }
100
101 if (~status & MK712_STATUS_TOUCH)
102 {
103 debounce = 1;
104 input_report_key(&mk712_dev, BTN_TOUCH, 0);
105 goto end;
106 }
107
108 if (debounce)
109 {
110 debounce = 0;
111 goto end;
112 }
113
114 input_report_key(&mk712_dev, BTN_TOUCH, 1);
115 input_report_abs(&mk712_dev, ABS_X, last_x);
116 input_report_abs(&mk712_dev, ABS_Y, last_y);
117
118end:
119
120 last_x = inw(mk712_io + MK712_X) & 0x0fff;
121 last_y = inw(mk712_io + MK712_Y) & 0x0fff;
122 input_sync(&mk712_dev);
123 spin_unlock(&mk712_lock);
124 return IRQ_HANDLED;
125}
126
127static int mk712_open(struct input_dev *dev)
128{
129 unsigned long flags;
130
131 spin_lock_irqsave(&mk712_lock, flags);
132
133 if (!mk712_used++) {
134
135 outb(0, mk712_io + MK712_CONTROL); /* Reset */
136
137 outb(MK712_ENABLE_INT | MK712_INT_ON_CONVERSION_COMPLETE |
138 MK712_INT_ON_CHANGE_IN_TOUCH_STATUS |
139 MK712_ENABLE_PERIODIC_CONVERSIONS |
140 MK712_POWERUP, mk712_io + MK712_CONTROL);
141
142 outb(10, mk712_io + MK712_RATE); /* 187 points per second */
143 }
144
145 spin_unlock_irqrestore(&mk712_lock, flags);
146
147 return 0;
148}
149
150static void mk712_close(struct input_dev *dev)
151{
152 unsigned long flags;
153
154 spin_lock_irqsave(&mk712_lock, flags);
155
156 if (!--mk712_used)
157 outb(0, mk712_io + MK712_CONTROL);
158
159 spin_unlock_irqrestore(&mk712_lock, flags);
160}
161
162static struct input_dev mk712_dev = {
163 .evbit = { BIT(EV_KEY) | BIT(EV_ABS) },
164 .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
165 .absbit = { BIT(ABS_X) | BIT(ABS_Y) },
166 .open = mk712_open,
167 .close = mk712_close,
168 .name = "ICS MicroClock MK712 TouchScreen",
169 .phys = "isa0260/input0",
170 .absmin = { [ABS_X] = 0, [ABS_Y] = 0 },
171 .absmax = { [ABS_X] = 0xfff, [ABS_Y] = 0xfff },
172 .absfuzz = { [ABS_X] = 88, [ABS_Y] = 88 },
173 .id = {
174 .bustype = BUS_ISA,
175 .vendor = 0x0005,
176 .product = 0x0001,
177 .version = 0x0100,
178 },
179};
180
181int __init mk712_init(void)
182{
183
184 if(!request_region(mk712_io, 8, "mk712"))
185 {
186 printk(KERN_WARNING "mk712: unable to get IO region\n");
187 return -ENODEV;
188 }
189
190 outb(0, mk712_io + MK712_CONTROL);
191
192 if ((inw(mk712_io + MK712_X) & 0xf000) || /* Sanity check */
193 (inw(mk712_io + MK712_Y) & 0xf000) ||
194 (inw(mk712_io + MK712_STATUS) & 0xf333)) {
195 printk(KERN_WARNING "mk712: device not present\n");
196 release_region(mk712_io, 8);
197 return -ENODEV;
198 }
199
200 if(request_irq(mk712_irq, mk712_interrupt, 0, "mk712", &mk712_dev))
201 {
202 printk(KERN_WARNING "mk712: unable to get IRQ\n");
203 release_region(mk712_io, 8);
204 return -EBUSY;
205 }
206
207 input_register_device(&mk712_dev);
208
209 printk(KERN_INFO "input: ICS MicroClock MK712 TouchScreen at %#x irq %d\n", mk712_io, mk712_irq);
210
211 return 0;
212}
213
214static void __exit mk712_exit(void)
215{
216 input_unregister_device(&mk712_dev);
217 free_irq(mk712_irq, &mk712_dev);
218 release_region(mk712_io, 8);
219}
220
221module_init(mk712_init);
222module_exit(mk712_exit);
diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c
new file mode 100644
index 000000000000..aa8ee7842179
--- /dev/null
+++ b/drivers/input/touchscreen/mtouch.c
@@ -0,0 +1,219 @@
1/*
2 * MicroTouch (3M) serial touchscreen driver
3 *
4 * Copyright (c) 2004 Vojtech Pavlik
5 */
6
7/*
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 */
12
13/*
14 * 2005/02/19 Dan Streetman <ddstreet@ieee.org>
15 * Copied elo.c and edited for MicroTouch protocol
16 */
17
18#include <linux/errno.h>
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/slab.h>
22#include <linux/input.h>
23#include <linux/serio.h>
24#include <linux/init.h>
25
26#define DRIVER_DESC "MicroTouch serial touchscreen driver"
27
28MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
29MODULE_DESCRIPTION(DRIVER_DESC);
30MODULE_LICENSE("GPL");
31
32/*
33 * Definitions & global arrays.
34 */
35
36#define MTOUCH_FORMAT_TABLET_STATUS_BIT 0x80
37#define MTOUCH_FORMAT_TABLET_TOUCH_BIT 0x40
38#define MTOUCH_FORMAT_TABLET_LENGTH 5
39#define MTOUCH_RESPONSE_BEGIN_BYTE 0x01
40#define MTOUCH_RESPONSE_END_BYTE 0x0d
41
42/* todo: check specs for max length of all responses */
43#define MTOUCH_MAX_LENGTH 16
44
45#define MTOUCH_MIN_XC 0
46#define MTOUCH_MAX_XC 0x3fff
47#define MTOUCH_MIN_YC 0
48#define MTOUCH_MAX_YC 0x3fff
49
50#define MTOUCH_GET_XC(data) (((data[2])<<7) | data[1])
51#define MTOUCH_GET_YC(data) (((data[4])<<7) | data[3])
52#define MTOUCH_GET_TOUCHED(data) (MTOUCH_FORMAT_TABLET_TOUCH_BIT & data[0])
53
54static char *mtouch_name = "MicroTouch Serial TouchScreen";
55
56/*
57 * Per-touchscreen data.
58 */
59
60struct mtouch {
61 struct input_dev dev;
62 struct serio *serio;
63 int idx;
64 unsigned char data[MTOUCH_MAX_LENGTH];
65 char phys[32];
66};
67
68static void mtouch_process_format_tablet(struct mtouch *mtouch, struct pt_regs *regs)
69{
70 struct input_dev *dev = &mtouch->dev;
71
72 if (MTOUCH_FORMAT_TABLET_LENGTH == ++mtouch->idx) {
73 input_regs(dev, regs);
74 input_report_abs(dev, ABS_X, MTOUCH_GET_XC(mtouch->data));
75 input_report_abs(dev, ABS_Y, MTOUCH_MAX_YC - MTOUCH_GET_YC(mtouch->data));
76 input_report_key(dev, BTN_TOUCH, MTOUCH_GET_TOUCHED(mtouch->data));
77 input_sync(dev);
78
79 mtouch->idx = 0;
80 }
81}
82
83static void mtouch_process_response(struct mtouch *mtouch, struct pt_regs *regs)
84{
85 if (MTOUCH_RESPONSE_END_BYTE == mtouch->data[mtouch->idx++]) {
86 /* FIXME - process response */
87 mtouch->idx = 0;
88 } else if (MTOUCH_MAX_LENGTH == mtouch->idx) {
89 printk(KERN_ERR "mtouch.c: too many response bytes\n");
90 mtouch->idx = 0;
91 }
92}
93
94static irqreturn_t mtouch_interrupt(struct serio *serio,
95 unsigned char data, unsigned int flags, struct pt_regs *regs)
96{
97 struct mtouch* mtouch = serio_get_drvdata(serio);
98
99 mtouch->data[mtouch->idx] = data;
100
101 if (MTOUCH_FORMAT_TABLET_STATUS_BIT & mtouch->data[0])
102 mtouch_process_format_tablet(mtouch, regs);
103 else if (MTOUCH_RESPONSE_BEGIN_BYTE == mtouch->data[0])
104 mtouch_process_response(mtouch, regs);
105 else
106 printk(KERN_DEBUG "mtouch.c: unknown/unsynchronized data from device, byte %x\n",mtouch->data[0]);
107
108 return IRQ_HANDLED;
109}
110
111/*
112 * mtouch_disconnect() is the opposite of mtouch_connect()
113 */
114
115static void mtouch_disconnect(struct serio *serio)
116{
117 struct mtouch* mtouch = serio_get_drvdata(serio);
118
119 input_unregister_device(&mtouch->dev);
120 serio_close(serio);
121 serio_set_drvdata(serio, NULL);
122 kfree(mtouch);
123}
124
125/*
126 * mtouch_connect() is the routine that is called when someone adds a
127 * new serio device that supports MicroTouch (Format Tablet) protocol and registers it as
128 * an input device.
129 */
130
131static int mtouch_connect(struct serio *serio, struct serio_driver *drv)
132{
133 struct mtouch *mtouch;
134 int err;
135
136 if (!(mtouch = kmalloc(sizeof(*mtouch), GFP_KERNEL)))
137 return -ENOMEM;
138
139 memset(mtouch, 0, sizeof(*mtouch));
140
141 init_input_dev(&mtouch->dev);
142 mtouch->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
143 mtouch->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
144
145 input_set_abs_params(&mtouch->dev, ABS_X, MTOUCH_MIN_XC, MTOUCH_MAX_XC, 0, 0);
146 input_set_abs_params(&mtouch->dev, ABS_Y, MTOUCH_MIN_YC, MTOUCH_MAX_YC, 0, 0);
147
148 mtouch->serio = serio;
149
150 sprintf(mtouch->phys, "%s/input0", serio->phys);
151
152 mtouch->dev.private = mtouch;
153 mtouch->dev.name = mtouch_name;
154 mtouch->dev.phys = mtouch->phys;
155 mtouch->dev.id.bustype = BUS_RS232;
156 mtouch->dev.id.vendor = SERIO_MICROTOUCH;
157 mtouch->dev.id.product = 0;
158 mtouch->dev.id.version = 0x0100;
159
160 serio_set_drvdata(serio, mtouch);
161
162 err = serio_open(serio, drv);
163 if (err) {
164 serio_set_drvdata(serio, NULL);
165 kfree(mtouch);
166 return err;
167 }
168
169 input_register_device(&mtouch->dev);
170
171 printk(KERN_INFO "input: %s on %s\n", mtouch->dev.name, serio->phys);
172
173 return 0;
174}
175
176/*
177 * The serio driver structure.
178 */
179
180static struct serio_device_id mtouch_serio_ids[] = {
181 {
182 .type = SERIO_RS232,
183 .proto = SERIO_MICROTOUCH,
184 .id = SERIO_ANY,
185 .extra = SERIO_ANY,
186 },
187 { 0 }
188};
189
190MODULE_DEVICE_TABLE(serio, mtouch_serio_ids);
191
192static struct serio_driver mtouch_drv = {
193 .driver = {
194 .name = "mtouch",
195 },
196 .description = DRIVER_DESC,
197 .id_table = mtouch_serio_ids,
198 .interrupt = mtouch_interrupt,
199 .connect = mtouch_connect,
200 .disconnect = mtouch_disconnect,
201};
202
203/*
204 * The functions for inserting/removing us as a module.
205 */
206
207static int __init mtouch_init(void)
208{
209 serio_register_driver(&mtouch_drv);
210 return 0;
211}
212
213static void __exit mtouch_exit(void)
214{
215 serio_unregister_driver(&mtouch_drv);
216}
217
218module_init(mtouch_init);
219module_exit(mtouch_exit);
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
new file mode 100644
index 000000000000..d0afba85720b
--- /dev/null
+++ b/drivers/input/tsdev.c
@@ -0,0 +1,492 @@
1/*
2 * $Id: tsdev.c,v 1.15 2002/04/10 16:50:19 jsimmons Exp $
3 *
4 * Copyright (c) 2001 "Crazy" james Simmons
5 *
6 * Compaq touchscreen protocol driver. The protocol emulated by this driver
7 * is obsolete; for new programs use the tslib library which can read directly
8 * from evdev and perform dejittering, variance filtering and calibration -
9 * all in user space, not at kernel level. The meaning of this driver is
10 * to allow usage of newer input drivers with old applications that use the
11 * old /dev/h3600_ts and /dev/h3600_tsraw devices.
12 *
13 * 09-Apr-2004: Andrew Zabolotny <zap@homelink.ru>
14 * Fixed to actually work, not just output random numbers.
15 * Added support for both h3600_ts and h3600_tsraw protocol
16 * emulation.
17 */
18
19/*
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 *
34 * Should you need to contact me, the author, you can do so either by
35 * e-mail - mail your message to <jsimmons@infradead.org>.
36 */
37
38#define TSDEV_MINOR_BASE 128
39#define TSDEV_MINORS 32
40/* First 16 devices are h3600_ts compatible; second 16 are h3600_tsraw */
41#define TSDEV_MINOR_MASK 15
42#define TSDEV_BUFFER_SIZE 64
43
44#include <linux/slab.h>
45#include <linux/poll.h>
46#include <linux/module.h>
47#include <linux/moduleparam.h>
48#include <linux/init.h>
49#include <linux/input.h>
50#include <linux/major.h>
51#include <linux/config.h>
52#include <linux/smp_lock.h>
53#include <linux/random.h>
54#include <linux/time.h>
55#include <linux/device.h>
56#include <linux/devfs_fs_kernel.h>
57
58#ifndef CONFIG_INPUT_TSDEV_SCREEN_X
59#define CONFIG_INPUT_TSDEV_SCREEN_X 240
60#endif
61#ifndef CONFIG_INPUT_TSDEV_SCREEN_Y
62#define CONFIG_INPUT_TSDEV_SCREEN_Y 320
63#endif
64
65/* This driver emulates both protocols of the old h3600_ts and h3600_tsraw
66 * devices. The first one must output X/Y data in 'cooked' format, e.g.
67 * filtered, dejittered and calibrated. Second device just outputs raw
68 * data received from the hardware.
69 *
70 * This driver doesn't support filtering and dejittering; it supports only
71 * calibration. Filtering and dejittering must be done in the low-level
72 * driver, if needed, because it may gain additional benefits from knowing
73 * the low-level details, the nature of noise and so on.
74 *
75 * The driver precomputes a calibration matrix given the initial xres and
76 * yres values (quite innacurate for most touchscreens) that will result
77 * in a more or less expected range of output values. The driver supports
78 * the TS_SET_CAL ioctl, which will replace the calibration matrix with a
79 * new one, supposedly generated from the values taken from the raw device.
80 */
81
82MODULE_AUTHOR("James Simmons <jsimmons@transvirtual.com>");
83MODULE_DESCRIPTION("Input driver to touchscreen converter");
84MODULE_LICENSE("GPL");
85
86static int xres = CONFIG_INPUT_TSDEV_SCREEN_X;
87module_param(xres, uint, 0);
88MODULE_PARM_DESC(xres, "Horizontal screen resolution (can be negative for X-mirror)");
89
90static int yres = CONFIG_INPUT_TSDEV_SCREEN_Y;
91module_param(yres, uint, 0);
92MODULE_PARM_DESC(yres, "Vertical screen resolution (can be negative for Y-mirror)");
93
94/* From Compaq's Touch Screen Specification version 0.2 (draft) */
95struct ts_event {
96 short pressure;
97 short x;
98 short y;
99 short millisecs;
100};
101
102struct ts_calibration {
103 int xscale;
104 int xtrans;
105 int yscale;
106 int ytrans;
107 int xyswap;
108};
109
110struct tsdev {
111 int exist;
112 int open;
113 int minor;
114 char name[8];
115 wait_queue_head_t wait;
116 struct list_head list;
117 struct input_handle handle;
118 int x, y, pressure;
119 struct ts_calibration cal;
120};
121
122struct tsdev_list {
123 struct fasync_struct *fasync;
124 struct list_head node;
125 struct tsdev *tsdev;
126 int head, tail;
127 struct ts_event event[TSDEV_BUFFER_SIZE];
128 int raw;
129};
130
131/* The following ioctl codes are defined ONLY for backward compatibility.
132 * Don't use tsdev for new developement; use the tslib library instead.
133 * Touchscreen calibration is a fully userspace task.
134 */
135/* Use 'f' as magic number */
136#define IOC_H3600_TS_MAGIC 'f'
137#define TS_GET_CAL _IOR(IOC_H3600_TS_MAGIC, 10, struct ts_calibration)
138#define TS_SET_CAL _IOW(IOC_H3600_TS_MAGIC, 11, struct ts_calibration)
139
140static struct input_handler tsdev_handler;
141
142static struct tsdev *tsdev_table[TSDEV_MINORS/2];
143
144static int tsdev_fasync(int fd, struct file *file, int on)
145{
146 struct tsdev_list *list = file->private_data;
147 int retval;
148
149 retval = fasync_helper(fd, file, on, &list->fasync);
150 return retval < 0 ? retval : 0;
151}
152
153static int tsdev_open(struct inode *inode, struct file *file)
154{
155 int i = iminor(inode) - TSDEV_MINOR_BASE;
156 struct tsdev_list *list;
157
158 if (i >= TSDEV_MINORS || !tsdev_table[i & TSDEV_MINOR_MASK])
159 return -ENODEV;
160
161 if (!(list = kmalloc(sizeof(struct tsdev_list), GFP_KERNEL)))
162 return -ENOMEM;
163 memset(list, 0, sizeof(struct tsdev_list));
164
165 list->raw = (i >= TSDEV_MINORS/2) ? 1 : 0;
166
167 i &= TSDEV_MINOR_MASK;
168 list->tsdev = tsdev_table[i];
169 list_add_tail(&list->node, &tsdev_table[i]->list);
170 file->private_data = list;
171
172 if (!list->tsdev->open++)
173 if (list->tsdev->exist)
174 input_open_device(&list->tsdev->handle);
175 return 0;
176}
177
178static void tsdev_free(struct tsdev *tsdev)
179{
180 tsdev_table[tsdev->minor] = NULL;
181 kfree(tsdev);
182}
183
184static int tsdev_release(struct inode *inode, struct file *file)
185{
186 struct tsdev_list *list = file->private_data;
187
188 tsdev_fasync(-1, file, 0);
189 list_del(&list->node);
190
191 if (!--list->tsdev->open) {
192 if (list->tsdev->exist)
193 input_close_device(&list->tsdev->handle);
194 else
195 tsdev_free(list->tsdev);
196 }
197 kfree(list);
198 return 0;
199}
200
201static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count,
202 loff_t * ppos)
203{
204 struct tsdev_list *list = file->private_data;
205 int retval = 0;
206
207 if (list->head == list->tail && list->tsdev->exist && (file->f_flags & O_NONBLOCK))
208 return -EAGAIN;
209
210 retval = wait_event_interruptible(list->tsdev->wait,
211 list->head != list->tail || !list->tsdev->exist);
212
213 if (retval)
214 return retval;
215
216 if (!list->tsdev->exist)
217 return -ENODEV;
218
219 while (list->head != list->tail &&
220 retval + sizeof (struct ts_event) <= count) {
221 if (copy_to_user (buffer + retval, list->event + list->tail,
222 sizeof (struct ts_event)))
223 return -EFAULT;
224 list->tail = (list->tail + 1) & (TSDEV_BUFFER_SIZE - 1);
225 retval += sizeof (struct ts_event);
226 }
227
228 return retval;
229}
230
231/* No kernel lock - fine */
232static unsigned int tsdev_poll(struct file *file, poll_table * wait)
233{
234 struct tsdev_list *list = file->private_data;
235 poll_wait(file, &list->tsdev->wait, wait);
236 return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) |
237 (list->tsdev->exist ? 0 : (POLLHUP | POLLERR));
238}
239
240static int tsdev_ioctl(struct inode *inode, struct file *file,
241 unsigned int cmd, unsigned long arg)
242{
243 struct tsdev_list *list = file->private_data;
244 struct tsdev *tsdev = list->tsdev;
245 int retval = 0;
246
247 switch (cmd) {
248 case TS_GET_CAL:
249 if (copy_to_user ((void __user *)arg, &tsdev->cal,
250 sizeof (struct ts_calibration)))
251 retval = -EFAULT;
252 break;
253 case TS_SET_CAL:
254 if (copy_from_user (&tsdev->cal, (void __user *)arg,
255 sizeof (struct ts_calibration)))
256 retval = -EFAULT;
257 break;
258 default:
259 retval = -EINVAL;
260 break;
261 }
262
263 return retval;
264}
265
266static struct file_operations tsdev_fops = {
267 .owner = THIS_MODULE,
268 .open = tsdev_open,
269 .release = tsdev_release,
270 .read = tsdev_read,
271 .poll = tsdev_poll,
272 .fasync = tsdev_fasync,
273 .ioctl = tsdev_ioctl,
274};
275
276static void tsdev_event(struct input_handle *handle, unsigned int type,
277 unsigned int code, int value)
278{
279 struct tsdev *tsdev = handle->private;
280 struct tsdev_list *list;
281 struct timeval time;
282
283 switch (type) {
284 case EV_ABS:
285 switch (code) {
286 case ABS_X:
287 tsdev->x = value;
288 break;
289 case ABS_Y:
290 tsdev->y = value;
291 break;
292 case ABS_PRESSURE:
293 if (value > handle->dev->absmax[ABS_PRESSURE])
294 value = handle->dev->absmax[ABS_PRESSURE];
295 value -= handle->dev->absmin[ABS_PRESSURE];
296 if (value < 0)
297 value = 0;
298 tsdev->pressure = value;
299 break;
300 }
301 break;
302
303 case EV_REL:
304 switch (code) {
305 case REL_X:
306 tsdev->x += value;
307 if (tsdev->x < 0)
308 tsdev->x = 0;
309 else if (tsdev->x > xres)
310 tsdev->x = xres;
311 break;
312 case REL_Y:
313 tsdev->y += value;
314 if (tsdev->y < 0)
315 tsdev->y = 0;
316 else if (tsdev->y > yres)
317 tsdev->y = yres;
318 break;
319 }
320 break;
321
322 case EV_KEY:
323 if (code == BTN_TOUCH || code == BTN_MOUSE) {
324 switch (value) {
325 case 0:
326 tsdev->pressure = 0;
327 break;
328 case 1:
329 if (!tsdev->pressure)
330 tsdev->pressure = 1;
331 break;
332 }
333 }
334 break;
335 }
336
337 if (type != EV_SYN || code != SYN_REPORT)
338 return;
339
340 list_for_each_entry(list, &tsdev->list, node) {
341 int x, y, tmp;
342
343 do_gettimeofday(&time);
344 list->event[list->head].millisecs = time.tv_usec / 100;
345 list->event[list->head].pressure = tsdev->pressure;
346
347 x = tsdev->x;
348 y = tsdev->y;
349
350 /* Calibration */
351 if (!list->raw) {
352 x = ((x * tsdev->cal.xscale) >> 8) + tsdev->cal.xtrans;
353 y = ((y * tsdev->cal.yscale) >> 8) + tsdev->cal.ytrans;
354 if (tsdev->cal.xyswap) {
355 tmp = x; x = y; y = tmp;
356 }
357 }
358
359 list->event[list->head].x = x;
360 list->event[list->head].y = y;
361 list->head = (list->head + 1) & (TSDEV_BUFFER_SIZE - 1);
362 kill_fasync(&list->fasync, SIGIO, POLL_IN);
363 }
364 wake_up_interruptible(&tsdev->wait);
365}
366
367static struct input_handle *tsdev_connect(struct input_handler *handler,
368 struct input_dev *dev,
369 struct input_device_id *id)
370{
371 struct tsdev *tsdev;
372 int minor, delta;
373
374 for (minor = 0; minor < TSDEV_MINORS/2 && tsdev_table[minor];
375 minor++);
376 if (minor >= TSDEV_MINORS/2) {
377 printk(KERN_ERR
378 "tsdev: You have way too many touchscreens\n");
379 return NULL;
380 }
381
382 if (!(tsdev = kmalloc(sizeof(struct tsdev), GFP_KERNEL)))
383 return NULL;
384 memset(tsdev, 0, sizeof(struct tsdev));
385
386 INIT_LIST_HEAD(&tsdev->list);
387 init_waitqueue_head(&tsdev->wait);
388
389 sprintf(tsdev->name, "ts%d", minor);
390
391 tsdev->exist = 1;
392 tsdev->minor = minor;
393 tsdev->handle.dev = dev;
394 tsdev->handle.name = tsdev->name;
395 tsdev->handle.handler = handler;
396 tsdev->handle.private = tsdev;
397
398 /* Precompute the rough calibration matrix */
399 delta = dev->absmax [ABS_X] - dev->absmin [ABS_X] + 1;
400 if (delta == 0)
401 delta = 1;
402 tsdev->cal.xscale = (xres << 8) / delta;
403 tsdev->cal.xtrans = - ((dev->absmin [ABS_X] * tsdev->cal.xscale) >> 8);
404
405 delta = dev->absmax [ABS_Y] - dev->absmin [ABS_Y] + 1;
406 if (delta == 0)
407 delta = 1;
408 tsdev->cal.yscale = (yres << 8) / delta;
409 tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8);
410
411 tsdev_table[minor] = tsdev;
412
413 devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
414 S_IFCHR|S_IRUGO|S_IWUSR, "input/ts%d", minor);
415 devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor + TSDEV_MINORS/2),
416 S_IFCHR|S_IRUGO|S_IWUSR, "input/tsraw%d", minor);
417 class_simple_device_add(input_class,
418 MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
419 dev->dev, "ts%d", minor);
420
421 return &tsdev->handle;
422}
423
424static void tsdev_disconnect(struct input_handle *handle)
425{
426 struct tsdev *tsdev = handle->private;
427 struct tsdev_list *list;
428
429 class_simple_device_remove(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
430 devfs_remove("input/ts%d", tsdev->minor);
431 devfs_remove("input/tsraw%d", tsdev->minor);
432 tsdev->exist = 0;
433
434 if (tsdev->open) {
435 input_close_device(handle);
436 wake_up_interruptible(&tsdev->wait);
437 list_for_each_entry(list, &tsdev->list, node)
438 kill_fasync(&list->fasync, SIGIO, POLL_HUP);
439 } else
440 tsdev_free(tsdev);
441}
442
443static struct input_device_id tsdev_ids[] = {
444 {
445 .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT,
446 .evbit = { BIT(EV_KEY) | BIT(EV_REL) },
447 .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) },
448 .relbit = { BIT(REL_X) | BIT(REL_Y) },
449 },/* A mouse like device, at least one button, two relative axes */
450
451 {
452 .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
453 .evbit = { BIT(EV_KEY) | BIT(EV_ABS) },
454 .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
455 .absbit = { BIT(ABS_X) | BIT(ABS_Y) },
456 },/* A tablet like device, at least touch detection, two absolute axes */
457
458 {
459 .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
460 .evbit = { BIT(EV_ABS) },
461 .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) },
462 },/* A tablet like device with several gradations of pressure */
463
464 {},/* Terminating entry */
465};
466
467MODULE_DEVICE_TABLE(input, tsdev_ids);
468
469static struct input_handler tsdev_handler = {
470 .event = tsdev_event,
471 .connect = tsdev_connect,
472 .disconnect = tsdev_disconnect,
473 .fops = &tsdev_fops,
474 .minor = TSDEV_MINOR_BASE,
475 .name = "tsdev",
476 .id_table = tsdev_ids,
477};
478
479static int __init tsdev_init(void)
480{
481 input_register_handler(&tsdev_handler);
482 printk(KERN_INFO "ts: Compaq touchscreen protocol output\n");
483 return 0;
484}
485
486static void __exit tsdev_exit(void)
487{
488 input_unregister_handler(&tsdev_handler);
489}
490
491module_init(tsdev_init);
492module_exit(tsdev_exit);