aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/evdev.c2
-rw-r--r--drivers/input/joystick/iforce/iforce-packets.c32
-rw-r--r--drivers/input/joystick/iforce/iforce-usb.c1
-rw-r--r--drivers/input/keyboard/atkbd.c10
-rw-r--r--drivers/input/keyboard/sunkbd.c2
-rw-r--r--drivers/input/mouse/Makefile2
-rw-r--r--drivers/input/mouse/alps.c2
-rw-r--r--drivers/input/mouse/logips2pp.c13
-rw-r--r--drivers/input/mouse/psmouse-base.c132
-rw-r--r--drivers/input/mouse/psmouse.h52
-rw-r--r--drivers/input/mouse/trackpoint.c304
-rw-r--r--drivers/input/mouse/trackpoint.h147
-rw-r--r--drivers/input/serio/i8042-io.h6
-rw-r--r--drivers/input/serio/i8042-ip22io.h2
-rw-r--r--drivers/input/serio/i8042-jazzio.h2
-rw-r--r--drivers/input/serio/i8042-sparcio.h12
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h72
-rw-r--r--drivers/input/serio/i8042.c199
18 files changed, 767 insertions, 225 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 60b696e9336b..3738d173f9a6 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -322,7 +322,7 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
322 if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL; 322 if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL;
323 if (get_user(v, ip + 1)) return -EFAULT; 323 if (get_user(v, ip + 1)) return -EFAULT;
324 if (v < 0 || v > KEY_MAX) return -EINVAL; 324 if (v < 0 || v > KEY_MAX) return -EINVAL;
325 if (v >> (dev->keycodesize * 8)) return -EINVAL; 325 if (dev->keycodesize < sizeof(v) && (v >> (dev->keycodesize * 8))) return -EINVAL;
326 u = SET_INPUT_KEYCODE(dev, t, v); 326 u = SET_INPUT_KEYCODE(dev, t, v);
327 clear_bit(u, dev->keybit); 327 clear_bit(u, dev->keybit);
328 set_bit(v, dev->keybit); 328 set_bit(v, dev->keybit);
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
index 58728ebaaf80..e5a31e55d3e2 100644
--- a/drivers/input/joystick/iforce/iforce-packets.c
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -249,9 +249,6 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data,
249 249
250int iforce_get_id_packet(struct iforce *iforce, char *packet) 250int iforce_get_id_packet(struct iforce *iforce, char *packet)
251{ 251{
252 DECLARE_WAITQUEUE(wait, current);
253 int timeout = HZ; /* 1 second */
254
255 switch (iforce->bus) { 252 switch (iforce->bus) {
256 253
257 case IFORCE_USB: 254 case IFORCE_USB:
@@ -260,22 +257,13 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet)
260 iforce->cr.bRequest = packet[0]; 257 iforce->cr.bRequest = packet[0];
261 iforce->ctrl->dev = iforce->usbdev; 258 iforce->ctrl->dev = iforce->usbdev;
262 259
263 set_current_state(TASK_INTERRUPTIBLE); 260 if (usb_submit_urb(iforce->ctrl, GFP_ATOMIC))
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; 261 return -1;
270 }
271 262
272 while (timeout && iforce->ctrl->status == -EINPROGRESS) 263 wait_event_interruptible_timeout(iforce->wait,
273 timeout = schedule_timeout(timeout); 264 iforce->ctrl->status != -EINPROGRESS, HZ);
274 265
275 set_current_state(TASK_RUNNING); 266 if (iforce->ctrl->status != -EINPROGRESS) {
276 remove_wait_queue(&iforce->wait, &wait);
277
278 if (!timeout) {
279 usb_unlink_urb(iforce->ctrl); 267 usb_unlink_urb(iforce->ctrl);
280 return -1; 268 return -1;
281 } 269 }
@@ -290,16 +278,10 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet)
290 iforce->expect_packet = FF_CMD_QUERY; 278 iforce->expect_packet = FF_CMD_QUERY;
291 iforce_send_packet(iforce, FF_CMD_QUERY, packet); 279 iforce_send_packet(iforce, FF_CMD_QUERY, packet);
292 280
293 set_current_state(TASK_INTERRUPTIBLE); 281 wait_event_interruptible_timeout(iforce->wait,
294 add_wait_queue(&iforce->wait, &wait); 282 !iforce->expect_packet, HZ);
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 283
302 if (!timeout) { 284 if (iforce->expect_packet) {
303 iforce->expect_packet = 0; 285 iforce->expect_packet = 0;
304 return -1; 286 return -1;
305 } 287 }
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index 6369a24684fe..58600f91eff5 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -95,6 +95,7 @@ static void iforce_usb_irq(struct urb *urb, struct pt_regs *regs)
95 goto exit; 95 goto exit;
96 } 96 }
97 97
98 wake_up(&iforce->wait);
98 iforce_process_packet(iforce, 99 iforce_process_packet(iforce,
99 (iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1, regs); 100 (iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1, regs);
100 101
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 4d4985b59abf..1ad8c2ee7dbf 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -208,6 +208,7 @@ struct atkbd {
208 unsigned char resend; 208 unsigned char resend;
209 unsigned char release; 209 unsigned char release;
210 unsigned char bat_xl; 210 unsigned char bat_xl;
211 unsigned char err_xl;
211 unsigned int last; 212 unsigned int last;
212 unsigned long time; 213 unsigned long time;
213}; 214};
@@ -296,15 +297,18 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
296 if (atkbd->emul || 297 if (atkbd->emul ||
297 !(code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1 || 298 !(code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1 ||
298 code == ATKBD_RET_HANGUEL || code == ATKBD_RET_HANJA || 299 code == ATKBD_RET_HANGUEL || code == ATKBD_RET_HANJA ||
299 code == ATKBD_RET_ERR || 300 (code == ATKBD_RET_ERR && !atkbd->err_xl) ||
300 (code == ATKBD_RET_BAT && !atkbd->bat_xl))) { 301 (code == ATKBD_RET_BAT && !atkbd->bat_xl))) {
301 atkbd->release = code >> 7; 302 atkbd->release = code >> 7;
302 code &= 0x7f; 303 code &= 0x7f;
303 } 304 }
304 305
305 if (!atkbd->emul && 306 if (!atkbd->emul) {
306 (code & 0x7f) == (ATKBD_RET_BAT & 0x7f)) 307 if ((code & 0x7f) == (ATKBD_RET_BAT & 0x7f))
307 atkbd->bat_xl = !atkbd->release; 308 atkbd->bat_xl = !atkbd->release;
309 if ((code & 0x7f) == (ATKBD_RET_ERR & 0x7f))
310 atkbd->err_xl = !atkbd->release;
311 }
308 } 312 }
309 313
310 switch (code) { 314 switch (code) {
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index 596964ceb96d..4bae5d89348d 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -44,7 +44,7 @@ MODULE_DESCRIPTION(DRIVER_DESC);
44MODULE_LICENSE("GPL"); 44MODULE_LICENSE("GPL");
45 45
46static unsigned char sunkbd_keycode[128] = { 46static unsigned char sunkbd_keycode[128] = {
47 0,128,114,129,115, 59, 60, 68, 61, 87, 62, 88, 63,100, 64, 0, 47 0,128,114,129,115, 59, 60, 68, 61, 87, 62, 88, 63,100, 64,112,
48 65, 66, 67, 56,103,119, 99, 70,105,130,131,108,106, 1, 2, 3, 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, 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, 50 116,132, 83,133,102, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index c4909b49337d..82b330bbf068 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -15,4 +15,4 @@ obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
15obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o 15obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o
16obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o 16obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o
17 17
18psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o 18psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o trackpoint.o
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 0d68e5e0182a..b20783f9748a 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -170,7 +170,7 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
170 input_report_key(dev, BTN_TOOL_FINGER, z > 0); 170 input_report_key(dev, BTN_TOOL_FINGER, z > 0);
171 171
172 if (priv->i->flags & ALPS_WHEEL) 172 if (priv->i->flags & ALPS_WHEEL)
173 input_report_rel(dev, REL_WHEEL, ((packet[0] >> 4) & 0x07) | ((packet[2] >> 2) & 0x08)); 173 input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07));
174 174
175 if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { 175 if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
176 input_report_key(dev, BTN_FORWARD, forward); 176 input_report_key(dev, BTN_FORWARD, forward);
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 48d2b20d2642..7df96525222e 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -150,12 +150,12 @@ static void ps2pp_set_smartscroll(struct psmouse *psmouse, unsigned int smartscr
150 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); 150 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
151} 151}
152 152
153static ssize_t psmouse_attr_show_smartscroll(struct psmouse *psmouse, char *buf) 153static ssize_t ps2pp_attr_show_smartscroll(struct psmouse *psmouse, void *data, char *buf)
154{ 154{
155 return sprintf(buf, "%d\n", psmouse->smartscroll ? 1 : 0); 155 return sprintf(buf, "%d\n", psmouse->smartscroll ? 1 : 0);
156} 156}
157 157
158static ssize_t psmouse_attr_set_smartscroll(struct psmouse *psmouse, const char *buf, size_t count) 158static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data, const char *buf, size_t count)
159{ 159{
160 unsigned long value; 160 unsigned long value;
161 char *rest; 161 char *rest;
@@ -169,7 +169,8 @@ static ssize_t psmouse_attr_set_smartscroll(struct psmouse *psmouse, const char
169 return count; 169 return count;
170} 170}
171 171
172PSMOUSE_DEFINE_ATTR(smartscroll); 172PSMOUSE_DEFINE_ATTR(smartscroll, S_IWUSR | S_IRUGO, NULL,
173 ps2pp_attr_show_smartscroll, ps2pp_attr_set_smartscroll);
173 174
174/* 175/*
175 * Support 800 dpi resolution _only_ if the user wants it (there are good 176 * Support 800 dpi resolution _only_ if the user wants it (there are good
@@ -194,7 +195,7 @@ static void ps2pp_set_resolution(struct psmouse *psmouse, unsigned int resolutio
194 195
195static void ps2pp_disconnect(struct psmouse *psmouse) 196static void ps2pp_disconnect(struct psmouse *psmouse)
196{ 197{
197 device_remove_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll); 198 device_remove_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll.dattr);
198} 199}
199 200
200static struct ps2pp_info *get_model_info(unsigned char model) 201static struct ps2pp_info *get_model_info(unsigned char model)
@@ -222,6 +223,7 @@ static struct ps2pp_info *get_model_info(unsigned char model)
222 { 80, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL }, 223 { 80, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL },
223 { 81, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, 224 { 81, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
224 { 83, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, 225 { 83, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
226 { 86, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
225 { 88, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, 227 { 88, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
226 { 96, 0, 0 }, 228 { 96, 0, 0 },
227 { 97, PS2PP_KIND_TP3, PS2PP_WHEEL | PS2PP_HWHEEL }, 229 { 97, PS2PP_KIND_TP3, PS2PP_WHEEL | PS2PP_HWHEEL },
@@ -379,7 +381,8 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties)
379 psmouse->set_resolution = ps2pp_set_resolution; 381 psmouse->set_resolution = ps2pp_set_resolution;
380 psmouse->disconnect = ps2pp_disconnect; 382 psmouse->disconnect = ps2pp_disconnect;
381 383
382 device_create_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll); 384 device_create_file(&psmouse->ps2dev.serio->dev,
385 &psmouse_attr_smartscroll.dattr);
383 } 386 }
384 } 387 }
385 388
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 12bdd3eff923..af24313ff5bb 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -25,6 +25,7 @@
25#include "logips2pp.h" 25#include "logips2pp.h"
26#include "alps.h" 26#include "alps.h"
27#include "lifebook.h" 27#include "lifebook.h"
28#include "trackpoint.h"
28 29
29#define DRIVER_DESC "PS/2 mouse driver" 30#define DRIVER_DESC "PS/2 mouse driver"
30 31
@@ -57,10 +58,30 @@ static unsigned int psmouse_resetafter;
57module_param_named(resetafter, psmouse_resetafter, uint, 0644); 58module_param_named(resetafter, psmouse_resetafter, uint, 0644);
58MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); 59MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");
59 60
60PSMOUSE_DEFINE_ATTR(protocol); 61PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO,
61PSMOUSE_DEFINE_ATTR(rate); 62 NULL,
62PSMOUSE_DEFINE_ATTR(resolution); 63 psmouse_attr_show_protocol, psmouse_attr_set_protocol);
63PSMOUSE_DEFINE_ATTR(resetafter); 64PSMOUSE_DEFINE_ATTR(rate, S_IWUSR | S_IRUGO,
65 (void *) offsetof(struct psmouse, rate),
66 psmouse_show_int_attr, psmouse_attr_set_rate);
67PSMOUSE_DEFINE_ATTR(resolution, S_IWUSR | S_IRUGO,
68 (void *) offsetof(struct psmouse, resolution),
69 psmouse_show_int_attr, psmouse_attr_set_resolution);
70PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO,
71 (void *) offsetof(struct psmouse, resetafter),
72 psmouse_show_int_attr, psmouse_set_int_attr);
73
74static struct attribute *psmouse_attributes[] = {
75 &psmouse_attr_protocol.dattr.attr,
76 &psmouse_attr_rate.dattr.attr,
77 &psmouse_attr_resolution.dattr.attr,
78 &psmouse_attr_resetafter.dattr.attr,
79 NULL
80};
81
82static struct attribute_group psmouse_attribute_group = {
83 .attrs = psmouse_attributes,
84};
64 85
65__obsolete_setup("psmouse_noext"); 86__obsolete_setup("psmouse_noext");
66__obsolete_setup("psmouse_resolution="); 87__obsolete_setup("psmouse_resolution=");
@@ -520,6 +541,12 @@ static int psmouse_extensions(struct psmouse *psmouse,
520 return PSMOUSE_IMPS; 541 return PSMOUSE_IMPS;
521 542
522/* 543/*
544 * Try to initialize the IBM TrackPoint
545 */
546 if (max_proto > PSMOUSE_IMEX && trackpoint_detect(psmouse, set_properties) == 0)
547 return PSMOUSE_TRACKPOINT;
548
549/*
523 * Okay, all failed, we have a standard mouse here. The number of the buttons 550 * Okay, all failed, we have a standard mouse here. The number of the buttons
524 * is still a question, though. We assume 3. 551 * is still a question, though. We assume 3.
525 */ 552 */
@@ -600,6 +627,12 @@ static struct psmouse_protocol psmouse_protocols[] = {
600 .init = lifebook_init, 627 .init = lifebook_init,
601 }, 628 },
602 { 629 {
630 .type = PSMOUSE_TRACKPOINT,
631 .name = "TPPS/2",
632 .alias = "trackpoint",
633 .detect = trackpoint_detect,
634 },
635 {
603 .type = PSMOUSE_AUTO, 636 .type = PSMOUSE_AUTO,
604 .name = "auto", 637 .name = "auto",
605 .alias = "any", 638 .alias = "any",
@@ -787,10 +820,7 @@ static void psmouse_disconnect(struct serio *serio)
787 820
788 psmouse = serio_get_drvdata(serio); 821 psmouse = serio_get_drvdata(serio);
789 822
790 device_remove_file(&serio->dev, &psmouse_attr_protocol); 823 sysfs_remove_group(&serio->dev.kobj, &psmouse_attribute_group);
791 device_remove_file(&serio->dev, &psmouse_attr_rate);
792 device_remove_file(&serio->dev, &psmouse_attr_resolution);
793 device_remove_file(&serio->dev, &psmouse_attr_resetafter);
794 824
795 down(&psmouse_sem); 825 down(&psmouse_sem);
796 826
@@ -927,10 +957,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
927 if (parent && parent->pt_activate) 957 if (parent && parent->pt_activate)
928 parent->pt_activate(parent); 958 parent->pt_activate(parent);
929 959
930 device_create_file(&serio->dev, &psmouse_attr_protocol); 960 sysfs_create_group(&serio->dev.kobj, &psmouse_attribute_group);
931 device_create_file(&serio->dev, &psmouse_attr_rate);
932 device_create_file(&serio->dev, &psmouse_attr_resolution);
933 device_create_file(&serio->dev, &psmouse_attr_resetafter);
934 961
935 psmouse_activate(psmouse); 962 psmouse_activate(psmouse);
936 963
@@ -1027,10 +1054,12 @@ static struct serio_driver psmouse_drv = {
1027 .cleanup = psmouse_cleanup, 1054 .cleanup = psmouse_cleanup,
1028}; 1055};
1029 1056
1030ssize_t psmouse_attr_show_helper(struct device *dev, char *buf, 1057ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *devattr,
1031 ssize_t (*handler)(struct psmouse *, char *)) 1058 char *buf)
1032{ 1059{
1033 struct serio *serio = to_serio_port(dev); 1060 struct serio *serio = to_serio_port(dev);
1061 struct psmouse_attribute *attr = to_psmouse_attr(devattr);
1062 struct psmouse *psmouse;
1034 int retval; 1063 int retval;
1035 1064
1036 retval = serio_pin_driver(serio); 1065 retval = serio_pin_driver(serio);
@@ -1042,19 +1071,21 @@ ssize_t psmouse_attr_show_helper(struct device *dev, char *buf,
1042 goto out; 1071 goto out;
1043 } 1072 }
1044 1073
1045 retval = handler(serio_get_drvdata(serio), buf); 1074 psmouse = serio_get_drvdata(serio);
1075
1076 retval = attr->show(psmouse, attr->data, buf);
1046 1077
1047out: 1078out:
1048 serio_unpin_driver(serio); 1079 serio_unpin_driver(serio);
1049 return retval; 1080 return retval;
1050} 1081}
1051 1082
1052ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t count, 1083ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *devattr,
1053 ssize_t (*handler)(struct psmouse *, const char *, size_t)) 1084 const char *buf, size_t count)
1054{ 1085{
1055 struct serio *serio = to_serio_port(dev); 1086 struct serio *serio = to_serio_port(dev);
1056 struct psmouse *psmouse = serio_get_drvdata(serio); 1087 struct psmouse_attribute *attr = to_psmouse_attr(devattr);
1057 struct psmouse *parent = NULL; 1088 struct psmouse *psmouse, *parent = NULL;
1058 int retval; 1089 int retval;
1059 1090
1060 retval = serio_pin_driver(serio); 1091 retval = serio_pin_driver(serio);
@@ -1070,6 +1101,8 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun
1070 if (retval) 1101 if (retval)
1071 goto out_unpin; 1102 goto out_unpin;
1072 1103
1104 psmouse = serio_get_drvdata(serio);
1105
1073 if (psmouse->state == PSMOUSE_IGNORE) { 1106 if (psmouse->state == PSMOUSE_IGNORE) {
1074 retval = -ENODEV; 1107 retval = -ENODEV;
1075 goto out_up; 1108 goto out_up;
@@ -1082,7 +1115,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun
1082 1115
1083 psmouse_deactivate(psmouse); 1116 psmouse_deactivate(psmouse);
1084 1117
1085 retval = handler(psmouse, buf, count); 1118 retval = attr->set(psmouse, attr->data, buf, count);
1086 1119
1087 if (retval != -ENODEV) 1120 if (retval != -ENODEV)
1088 psmouse_activate(psmouse); 1121 psmouse_activate(psmouse);
@@ -1097,12 +1130,34 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun
1097 return retval; 1130 return retval;
1098} 1131}
1099 1132
1100static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, char *buf) 1133static ssize_t psmouse_show_int_attr(struct psmouse *psmouse, void *offset, char *buf)
1134{
1135 unsigned long *field = (unsigned long *)((char *)psmouse + (size_t)offset);
1136
1137 return sprintf(buf, "%lu\n", *field);
1138}
1139
1140static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const char *buf, size_t count)
1141{
1142 unsigned long *field = (unsigned long *)((char *)psmouse + (size_t)offset);
1143 unsigned long value;
1144 char *rest;
1145
1146 value = simple_strtoul(buf, &rest, 10);
1147 if (*rest)
1148 return -EINVAL;
1149
1150 *field = value;
1151
1152 return count;
1153}
1154
1155static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, void *data, char *buf)
1101{ 1156{
1102 return sprintf(buf, "%s\n", psmouse_protocol_by_type(psmouse->type)->name); 1157 return sprintf(buf, "%s\n", psmouse_protocol_by_type(psmouse->type)->name);
1103} 1158}
1104 1159
1105static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *buf, size_t count) 1160static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, const char *buf, size_t count)
1106{ 1161{
1107 struct serio *serio = psmouse->ps2dev.serio; 1162 struct serio *serio = psmouse->ps2dev.serio;
1108 struct psmouse *parent = NULL; 1163 struct psmouse *parent = NULL;
@@ -1166,12 +1221,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *bu
1166 return count; 1221 return count;
1167} 1222}
1168 1223
1169static ssize_t psmouse_attr_show_rate(struct psmouse *psmouse, char *buf) 1224static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const char *buf, size_t count)
1170{
1171 return sprintf(buf, "%d\n", psmouse->rate);
1172}
1173
1174static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, const char *buf, size_t count)
1175{ 1225{
1176 unsigned long value; 1226 unsigned long value;
1177 char *rest; 1227 char *rest;
@@ -1184,12 +1234,7 @@ static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, const char *buf, s
1184 return count; 1234 return count;
1185} 1235}
1186 1236
1187static ssize_t psmouse_attr_show_resolution(struct psmouse *psmouse, char *buf) 1237static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, const char *buf, size_t count)
1188{
1189 return sprintf(buf, "%d\n", psmouse->resolution);
1190}
1191
1192static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, const char *buf, size_t count)
1193{ 1238{
1194 unsigned long value; 1239 unsigned long value;
1195 char *rest; 1240 char *rest;
@@ -1202,23 +1247,6 @@ static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, const char *
1202 return count; 1247 return count;
1203} 1248}
1204 1249
1205static ssize_t psmouse_attr_show_resetafter(struct psmouse *psmouse, char *buf)
1206{
1207 return sprintf(buf, "%d\n", psmouse->resetafter);
1208}
1209
1210static ssize_t psmouse_attr_set_resetafter(struct psmouse *psmouse, const char *buf, size_t count)
1211{
1212 unsigned long value;
1213 char *rest;
1214
1215 value = simple_strtoul(buf, &rest, 10);
1216 if (*rest)
1217 return -EINVAL;
1218
1219 psmouse->resetafter = value;
1220 return count;
1221}
1222 1250
1223static int psmouse_set_maxproto(const char *val, struct kernel_param *kp) 1251static int psmouse_set_maxproto(const char *val, struct kernel_param *kp)
1224{ 1252{
@@ -1234,7 +1262,7 @@ static int psmouse_set_maxproto(const char *val, struct kernel_param *kp)
1234 1262
1235 *((unsigned int *)kp->arg) = proto->type; 1263 *((unsigned int *)kp->arg) = proto->type;
1236 1264
1237 return 0; \ 1265 return 0;
1238} 1266}
1239 1267
1240static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp) 1268static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp)
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 86691cf43433..45d2bd774f00 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -78,6 +78,7 @@ enum psmouse_type {
78 PSMOUSE_SYNAPTICS, 78 PSMOUSE_SYNAPTICS,
79 PSMOUSE_ALPS, 79 PSMOUSE_ALPS,
80 PSMOUSE_LIFEBOOK, 80 PSMOUSE_LIFEBOOK,
81 PSMOUSE_TRACKPOINT,
81 PSMOUSE_AUTO /* This one should always be last */ 82 PSMOUSE_AUTO /* This one should always be last */
82}; 83};
83 84
@@ -85,24 +86,37 @@ int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command);
85int psmouse_reset(struct psmouse *psmouse); 86int psmouse_reset(struct psmouse *psmouse);
86void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution); 87void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution);
87 88
88ssize_t psmouse_attr_show_helper(struct device *dev, char *buf, 89
89 ssize_t (*handler)(struct psmouse *, char *)); 90struct psmouse_attribute {
90ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t count, 91 struct device_attribute dattr;
91 ssize_t (*handler)(struct psmouse *, const char *, size_t)); 92 void *data;
92 93 ssize_t (*show)(struct psmouse *psmouse, void *data, char *buf);
93#define PSMOUSE_DEFINE_ATTR(_name) \ 94 ssize_t (*set)(struct psmouse *psmouse, void *data,
94static ssize_t psmouse_attr_show_##_name(struct psmouse *, char *); \ 95 const char *buf, size_t count);
95static ssize_t psmouse_attr_set_##_name(struct psmouse *, const char *, size_t);\ 96};
96static ssize_t psmouse_do_show_##_name(struct device *d, struct device_attribute *attr, char *b) \ 97#define to_psmouse_attr(a) container_of((a), struct psmouse_attribute, dattr)
97{ \ 98
98 return psmouse_attr_show_helper(d, b, psmouse_attr_show_##_name); \ 99ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *attr,
99} \ 100 char *buf);
100static ssize_t psmouse_do_set_##_name(struct device *d, struct device_attribute *attr, const char *b, size_t s)\ 101ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *attr,
101{ \ 102 const char *buf, size_t count);
102 return psmouse_attr_set_helper(d, b, s, psmouse_attr_set_##_name); \ 103
103} \ 104#define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \
104static struct device_attribute psmouse_attr_##_name = \ 105static ssize_t _show(struct psmouse *, void *data, char *); \
105 __ATTR(_name, S_IWUSR | S_IRUGO, \ 106static ssize_t _set(struct psmouse *, void *data, const char *, size_t); \
106 psmouse_do_show_##_name, psmouse_do_set_##_name); 107static struct psmouse_attribute psmouse_attr_##_name = { \
108 .dattr = { \
109 .attr = { \
110 .name = __stringify(_name), \
111 .mode = _mode, \
112 .owner = THIS_MODULE, \
113 }, \
114 .show = psmouse_attr_show_helper, \
115 .store = psmouse_attr_set_helper, \
116 }, \
117 .data = _data, \
118 .show = _show, \
119 .set = _set, \
120}
107 121
108#endif /* _PSMOUSE_H */ 122#endif /* _PSMOUSE_H */
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
new file mode 100644
index 000000000000..b4898d8a68e2
--- /dev/null
+++ b/drivers/input/mouse/trackpoint.c
@@ -0,0 +1,304 @@
1/*
2 * Stephen Evanchik <evanchsa@gmail.com>
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 * Trademarks are the property of their respective owners.
9 */
10
11#include <linux/delay.h>
12#include <linux/serio.h>
13#include <linux/module.h>
14#include <linux/moduleparam.h>
15#include <linux/input.h>
16#include <linux/libps2.h>
17#include <linux/proc_fs.h>
18#include <asm/uaccess.h>
19#include "psmouse.h"
20#include "trackpoint.h"
21
22/*
23 * Device IO: read, write and toggle bit
24 */
25static int trackpoint_read(struct ps2dev *ps2dev, unsigned char loc, unsigned char *results)
26{
27 if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) ||
28 ps2_command(ps2dev, results, MAKE_PS2_CMD(0, 1, loc))) {
29 return -1;
30 }
31
32 return 0;
33}
34
35static int trackpoint_write(struct ps2dev *ps2dev, unsigned char loc, unsigned char val)
36{
37 if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) ||
38 ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_WRITE_MEM)) ||
39 ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, loc)) ||
40 ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, val))) {
41 return -1;
42 }
43
44 return 0;
45}
46
47static int trackpoint_toggle_bit(struct ps2dev *ps2dev, unsigned char loc, unsigned char mask)
48{
49 /* Bad things will happen if the loc param isn't in this range */
50 if (loc < 0x20 || loc >= 0x2F)
51 return -1;
52
53 if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) ||
54 ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_TOGGLE)) ||
55 ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, loc)) ||
56 ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, mask))) {
57 return -1;
58 }
59
60 return 0;
61}
62
63
64/*
65 * Trackpoint-specific attributes
66 */
67struct trackpoint_attr_data {
68 size_t field_offset;
69 unsigned char command;
70 unsigned char mask;
71};
72
73static ssize_t trackpoint_show_int_attr(struct psmouse *psmouse, void *data, char *buf)
74{
75 struct trackpoint_data *tp = psmouse->private;
76 struct trackpoint_attr_data *attr = data;
77 unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
78
79 return sprintf(buf, "%u\n", *field);
80}
81
82static ssize_t trackpoint_set_int_attr(struct psmouse *psmouse, void *data,
83 const char *buf, size_t count)
84{
85 struct trackpoint_data *tp = psmouse->private;
86 struct trackpoint_attr_data *attr = data;
87 unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
88 unsigned long value;
89 char *rest;
90
91 value = simple_strtoul(buf, &rest, 10);
92 if (*rest || value > 255)
93 return -EINVAL;
94
95 *field = value;
96 trackpoint_write(&psmouse->ps2dev, attr->command, value);
97
98 return count;
99}
100
101#define TRACKPOINT_INT_ATTR(_name, _command) \
102 static struct trackpoint_attr_data trackpoint_attr_##_name = { \
103 .field_offset = offsetof(struct trackpoint_data, _name), \
104 .command = _command, \
105 }; \
106 PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO, \
107 &trackpoint_attr_##_name, \
108 trackpoint_show_int_attr, trackpoint_set_int_attr)
109
110static ssize_t trackpoint_set_bit_attr(struct psmouse *psmouse, void *data,
111 const char *buf, size_t count)
112{
113 struct trackpoint_data *tp = psmouse->private;
114 struct trackpoint_attr_data *attr = data;
115 unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
116 unsigned long value;
117 char *rest;
118
119 value = simple_strtoul(buf, &rest, 10);
120 if (*rest || value > 1)
121 return -EINVAL;
122
123 if (*field != value) {
124 *field = value;
125 trackpoint_toggle_bit(&psmouse->ps2dev, attr->command, attr->mask);
126 }
127
128 return count;
129}
130
131
132#define TRACKPOINT_BIT_ATTR(_name, _command, _mask) \
133 static struct trackpoint_attr_data trackpoint_attr_##_name = { \
134 .field_offset = offsetof(struct trackpoint_data, _name), \
135 .command = _command, \
136 .mask = _mask, \
137 }; \
138 PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO, \
139 &trackpoint_attr_##_name, \
140 trackpoint_show_int_attr, trackpoint_set_bit_attr)
141
142TRACKPOINT_INT_ATTR(sensitivity, TP_SENS);
143TRACKPOINT_INT_ATTR(speed, TP_SPEED);
144TRACKPOINT_INT_ATTR(inertia, TP_INERTIA);
145TRACKPOINT_INT_ATTR(reach, TP_REACH);
146TRACKPOINT_INT_ATTR(draghys, TP_DRAGHYS);
147TRACKPOINT_INT_ATTR(mindrag, TP_MINDRAG);
148TRACKPOINT_INT_ATTR(thresh, TP_THRESH);
149TRACKPOINT_INT_ATTR(upthresh, TP_UP_THRESH);
150TRACKPOINT_INT_ATTR(ztime, TP_Z_TIME);
151TRACKPOINT_INT_ATTR(jenks, TP_JENKS_CURV);
152
153TRACKPOINT_BIT_ATTR(press_to_select, TP_TOGGLE_PTSON, TP_MASK_PTSON);
154TRACKPOINT_BIT_ATTR(skipback, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK);
155TRACKPOINT_BIT_ATTR(ext_dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV);
156
157static struct attribute *trackpoint_attrs[] = {
158 &psmouse_attr_sensitivity.dattr.attr,
159 &psmouse_attr_speed.dattr.attr,
160 &psmouse_attr_inertia.dattr.attr,
161 &psmouse_attr_reach.dattr.attr,
162 &psmouse_attr_draghys.dattr.attr,
163 &psmouse_attr_mindrag.dattr.attr,
164 &psmouse_attr_thresh.dattr.attr,
165 &psmouse_attr_upthresh.dattr.attr,
166 &psmouse_attr_ztime.dattr.attr,
167 &psmouse_attr_jenks.dattr.attr,
168 &psmouse_attr_press_to_select.dattr.attr,
169 &psmouse_attr_skipback.dattr.attr,
170 &psmouse_attr_ext_dev.dattr.attr,
171 NULL
172};
173
174static struct attribute_group trackpoint_attr_group = {
175 .attrs = trackpoint_attrs,
176};
177
178static void trackpoint_disconnect(struct psmouse *psmouse)
179{
180 sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, &trackpoint_attr_group);
181
182 kfree(psmouse->private);
183 psmouse->private = NULL;
184}
185
186static int trackpoint_sync(struct psmouse *psmouse)
187{
188 unsigned char toggle;
189 struct trackpoint_data *tp = psmouse->private;
190
191 if (!tp)
192 return -1;
193
194 /* Disable features that may make device unusable with this driver */
195 trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, &toggle);
196 if (toggle & TP_MASK_TWOHAND)
197 trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, TP_MASK_TWOHAND);
198
199 trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_SOURCE_TAG, &toggle);
200 if (toggle & TP_MASK_SOURCE_TAG)
201 trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_SOURCE_TAG, TP_MASK_SOURCE_TAG);
202
203 trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_MB, &toggle);
204 if (toggle & TP_MASK_MB)
205 trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_MB, TP_MASK_MB);
206
207 /* Push the config to the device */
208 trackpoint_write(&psmouse->ps2dev, TP_SENS, tp->sensitivity);
209 trackpoint_write(&psmouse->ps2dev, TP_INERTIA, tp->inertia);
210 trackpoint_write(&psmouse->ps2dev, TP_SPEED, tp->speed);
211
212 trackpoint_write(&psmouse->ps2dev, TP_REACH, tp->reach);
213 trackpoint_write(&psmouse->ps2dev, TP_DRAGHYS, tp->draghys);
214 trackpoint_write(&psmouse->ps2dev, TP_MINDRAG, tp->mindrag);
215
216 trackpoint_write(&psmouse->ps2dev, TP_THRESH, tp->thresh);
217 trackpoint_write(&psmouse->ps2dev, TP_UP_THRESH, tp->upthresh);
218
219 trackpoint_write(&psmouse->ps2dev, TP_Z_TIME, tp->ztime);
220 trackpoint_write(&psmouse->ps2dev, TP_JENKS_CURV, tp->jenks);
221
222 trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_PTSON, &toggle);
223 if (((toggle & TP_MASK_PTSON) == TP_MASK_PTSON) != tp->press_to_select)
224 trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_PTSON, TP_MASK_PTSON);
225
226 trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_SKIPBACK, &toggle);
227 if (((toggle & TP_MASK_SKIPBACK) == TP_MASK_SKIPBACK) != tp->skipback)
228 trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK);
229
230 trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_EXT_DEV, &toggle);
231 if (((toggle & TP_MASK_EXT_DEV) == TP_MASK_EXT_DEV) != tp->ext_dev)
232 trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV);
233
234 return 0;
235}
236
237static void trackpoint_defaults(struct trackpoint_data *tp)
238{
239 tp->press_to_select = TP_DEF_PTSON;
240 tp->sensitivity = TP_DEF_SENS;
241 tp->speed = TP_DEF_SPEED;
242 tp->reach = TP_DEF_REACH;
243
244 tp->draghys = TP_DEF_DRAGHYS;
245 tp->mindrag = TP_DEF_MINDRAG;
246
247 tp->thresh = TP_DEF_THRESH;
248 tp->upthresh = TP_DEF_UP_THRESH;
249
250 tp->ztime = TP_DEF_Z_TIME;
251 tp->jenks = TP_DEF_JENKS_CURV;
252
253 tp->inertia = TP_DEF_INERTIA;
254 tp->skipback = TP_DEF_SKIPBACK;
255 tp->ext_dev = TP_DEF_EXT_DEV;
256}
257
258int trackpoint_detect(struct psmouse *psmouse, int set_properties)
259{
260 struct trackpoint_data *priv;
261 struct ps2dev *ps2dev = &psmouse->ps2dev;
262 unsigned char firmware_id;
263 unsigned char button_info;
264 unsigned char param[2];
265
266 param[0] = param[1] = 0;
267
268 if (ps2_command(ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID)))
269 return -1;
270
271 if (param[0] != TP_MAGIC_IDENT)
272 return -1;
273
274 if (!set_properties)
275 return 0;
276
277 firmware_id = param[1];
278
279 if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) {
280 printk(KERN_WARNING "trackpoint.c: failed to get extended button data\n");
281 button_info = 0;
282 }
283
284 psmouse->private = priv = kcalloc(1, sizeof(struct trackpoint_data), GFP_KERNEL);
285 if (!priv)
286 return -1;
287
288 psmouse->vendor = "IBM";
289 psmouse->name = "TrackPoint";
290
291 psmouse->reconnect = trackpoint_sync;
292 psmouse->disconnect = trackpoint_disconnect;
293
294 trackpoint_defaults(priv);
295 trackpoint_sync(psmouse);
296
297 sysfs_create_group(&ps2dev->serio->dev.kobj, &trackpoint_attr_group);
298
299 printk(KERN_INFO "IBM TrackPoint firmware: 0x%02x, buttons: %d/%d\n",
300 firmware_id, (button_info & 0xf0) >> 4, button_info & 0x0f);
301
302 return 0;
303}
304
diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h
new file mode 100644
index 000000000000..9857d8b6ad66
--- /dev/null
+++ b/drivers/input/mouse/trackpoint.h
@@ -0,0 +1,147 @@
1/*
2 * IBM TrackPoint PS/2 mouse driver
3 *
4 * Stephen Evanchik <evanchsa@gmail.com>
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 _TRACKPOINT_H
12#define _TRACKPOINT_H
13
14/*
15 * These constants are from the TrackPoint System
16 * Engineering documentation Version 4 from IBM Watson
17 * research:
18 * http://wwwcssrv.almaden.ibm.com/trackpoint/download.html
19 */
20
21#define TP_COMMAND 0xE2 /* Commands start with this */
22
23#define TP_READ_ID 0xE1 /* Sent for device identification */
24#define TP_MAGIC_IDENT 0x01 /* Sent after a TP_READ_ID followed */
25 /* by the firmware ID */
26
27
28/*
29 * Commands
30 */
31#define TP_RECALIB 0x51 /* Recalibrate */
32#define TP_POWER_DOWN 0x44 /* Can only be undone through HW reset */
33#define TP_EXT_DEV 0x21 /* Determines if external device is connected (RO) */
34#define TP_EXT_BTN 0x4B /* Read extended button status */
35#define TP_POR 0x7F /* Execute Power on Reset */
36#define TP_POR_RESULTS 0x25 /* Read Power on Self test results */
37#define TP_DISABLE_EXT 0x40 /* Disable external pointing device */
38#define TP_ENABLE_EXT 0x41 /* Enable external pointing device */
39
40/*
41 * Mode manipulation
42 */
43#define TP_SET_SOFT_TRANS 0x4E /* Set mode */
44#define TP_CANCEL_SOFT_TRANS 0xB9 /* Cancel mode */
45#define TP_SET_HARD_TRANS 0x45 /* Mode can only be set */
46
47
48/*
49 * Register oriented commands/properties
50 */
51#define TP_WRITE_MEM 0x81
52#define TP_READ_MEM 0x80 /* Not used in this implementation */
53
54/*
55* RAM Locations for properties
56 */
57#define TP_SENS 0x4A /* Sensitivity */
58#define TP_MB 0x4C /* Read Middle Button Status (RO) */
59#define TP_INERTIA 0x4D /* Negative Inertia */
60#define TP_SPEED 0x60 /* Speed of TP Cursor */
61#define TP_REACH 0x57 /* Backup for Z-axis press */
62#define TP_DRAGHYS 0x58 /* Drag Hysteresis */
63 /* (how hard it is to drag */
64 /* with Z-axis pressed) */
65
66#define TP_MINDRAG 0x59 /* Minimum amount of force needed */
67 /* to trigger dragging */
68
69#define TP_THRESH 0x5C /* Minimum value for a Z-axis press */
70#define TP_UP_THRESH 0x5A /* Used to generate a 'click' on Z-axis */
71#define TP_Z_TIME 0x5E /* How sharp of a press */
72#define TP_JENKS_CURV 0x5D /* Minimum curvature for double click */
73
74/*
75 * Toggling Flag bits
76 */
77#define TP_TOGGLE 0x47 /* Toggle command */
78
79#define TP_TOGGLE_MB 0x23 /* Disable/Enable Middle Button */
80#define TP_MASK_MB 0x01
81#define TP_TOGGLE_EXT_DEV 0x23 /* Toggle external device */
82#define TP_MASK_EXT_DEV 0x02
83#define TP_TOGGLE_DRIFT 0x23 /* Drift Correction */
84#define TP_MASK_DRIFT 0x80
85#define TP_TOGGLE_BURST 0x28 /* Burst Mode */
86#define TP_MASK_BURST 0x80
87#define TP_TOGGLE_PTSON 0x2C /* Press to Select */
88#define TP_MASK_PTSON 0x01
89#define TP_TOGGLE_HARD_TRANS 0x2C /* Alternate method to set Hard Transparency */
90#define TP_MASK_HARD_TRANS 0x80
91#define TP_TOGGLE_TWOHAND 0x2D /* Two handed */
92#define TP_MASK_TWOHAND 0x01
93#define TP_TOGGLE_STICKY_TWO 0x2D /* Sticky two handed */
94#define TP_MASK_STICKY_TWO 0x04
95#define TP_TOGGLE_SKIPBACK 0x2D /* Suppress movement after drag release */
96#define TP_MASK_SKIPBACK 0x08
97#define TP_TOGGLE_SOURCE_TAG 0x20 /* Bit 3 of the first packet will be set to
98 to the origin of the packet (external or TP) */
99#define TP_MASK_SOURCE_TAG 0x80
100#define TP_TOGGLE_EXT_TAG 0x22 /* Bit 3 of the first packet coming from the
101 external device will be forced to 1 */
102#define TP_MASK_EXT_TAG 0x04
103
104
105/* Power on Self Test Results */
106#define TP_POR_SUCCESS 0x3B
107
108/*
109 * Default power on values
110 */
111#define TP_DEF_SENS 0x80
112#define TP_DEF_INERTIA 0x06
113#define TP_DEF_SPEED 0x61
114#define TP_DEF_REACH 0x0A
115
116#define TP_DEF_DRAGHYS 0xFF
117#define TP_DEF_MINDRAG 0x14
118
119#define TP_DEF_THRESH 0x08
120#define TP_DEF_UP_THRESH 0xFF
121#define TP_DEF_Z_TIME 0x26
122#define TP_DEF_JENKS_CURV 0x87
123
124/* Toggles */
125#define TP_DEF_MB 0x00
126#define TP_DEF_PTSON 0x00
127#define TP_DEF_SKIPBACK 0x00
128#define TP_DEF_EXT_DEV 0x01
129
130#define MAKE_PS2_CMD(params, results, cmd) ((params<<12) | (results<<8) | (cmd))
131
132struct trackpoint_data
133{
134 unsigned char sensitivity, speed, inertia, reach;
135 unsigned char draghys, mindrag;
136 unsigned char thresh, upthresh;
137 unsigned char ztime, jenks;
138
139 unsigned char press_to_select;
140 unsigned char skipback;
141
142 unsigned char ext_dev;
143};
144
145extern int trackpoint_detect(struct psmouse *psmouse, int set_properties);
146
147#endif /* _TRACKPOINT_H */
diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h
index c9e633d21d90..9a9221644250 100644
--- a/drivers/input/serio/i8042-io.h
+++ b/drivers/input/serio/i8042-io.h
@@ -69,16 +69,16 @@ static inline int i8042_platform_init(void)
69 */ 69 */
70#if !defined(__sh__) && !defined(__alpha__) && !defined(__mips__) && !defined(CONFIG_PPC64) 70#if !defined(__sh__) && !defined(__alpha__) && !defined(__mips__) && !defined(CONFIG_PPC64)
71 if (!request_region(I8042_DATA_REG, 16, "i8042")) 71 if (!request_region(I8042_DATA_REG, 16, "i8042"))
72 return -1; 72 return -EBUSY;
73#endif 73#endif
74 74
75 i8042_reset = 1; 75 i8042_reset = 1;
76 76
77#if defined(CONFIG_PPC64) 77#if defined(CONFIG_PPC64)
78 if (check_legacy_ioport(I8042_DATA_REG)) 78 if (check_legacy_ioport(I8042_DATA_REG))
79 return -1; 79 return -EBUSY;
80 if (!request_region(I8042_DATA_REG, 16, "i8042")) 80 if (!request_region(I8042_DATA_REG, 16, "i8042"))
81 return -1; 81 return -EBUSY;
82#endif 82#endif
83 return 0; 83 return 0;
84} 84}
diff --git a/drivers/input/serio/i8042-ip22io.h b/drivers/input/serio/i8042-ip22io.h
index 863b9c95fbb8..ee1ad27d6ed0 100644
--- a/drivers/input/serio/i8042-ip22io.h
+++ b/drivers/input/serio/i8042-ip22io.h
@@ -58,7 +58,7 @@ static inline int i8042_platform_init(void)
58#if 0 58#if 0
59 /* XXX sgi_kh is a virtual address */ 59 /* XXX sgi_kh is a virtual address */
60 if (!request_mem_region(sgi_kh, sizeof(struct hpc_keyb), "i8042")) 60 if (!request_mem_region(sgi_kh, sizeof(struct hpc_keyb), "i8042"))
61 return 1; 61 return -EBUSY;
62#endif 62#endif
63 63
64 i8042_reset = 1; 64 i8042_reset = 1;
diff --git a/drivers/input/serio/i8042-jazzio.h b/drivers/input/serio/i8042-jazzio.h
index 5c20ab131488..13fd7108eb28 100644
--- a/drivers/input/serio/i8042-jazzio.h
+++ b/drivers/input/serio/i8042-jazzio.h
@@ -53,7 +53,7 @@ static inline int i8042_platform_init(void)
53#if 0 53#if 0
54 /* XXX JAZZ_KEYBOARD_ADDRESS is a virtual address */ 54 /* XXX JAZZ_KEYBOARD_ADDRESS is a virtual address */
55 if (!request_mem_region(JAZZ_KEYBOARD_ADDRESS, 2, "i8042")) 55 if (!request_mem_region(JAZZ_KEYBOARD_ADDRESS, 2, "i8042"))
56 return 1; 56 return -EBUSY;
57#endif 57#endif
58 58
59 return 0; 59 return 0;
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h
index da2a19812485..ed9446f6d7e3 100644
--- a/drivers/input/serio/i8042-sparcio.h
+++ b/drivers/input/serio/i8042-sparcio.h
@@ -48,10 +48,10 @@ static inline void i8042_write_command(int val)
48#define OBP_PS2MS_NAME1 "kdmouse" 48#define OBP_PS2MS_NAME1 "kdmouse"
49#define OBP_PS2MS_NAME2 "mouse" 49#define OBP_PS2MS_NAME2 "mouse"
50 50
51static int i8042_platform_init(void) 51static int __init i8042_platform_init(void)
52{ 52{
53#ifndef CONFIG_PCI 53#ifndef CONFIG_PCI
54 return -1; 54 return -ENODEV;
55#else 55#else
56 char prop[128]; 56 char prop[128];
57 int len; 57 int len;
@@ -59,14 +59,14 @@ static int i8042_platform_init(void)
59 len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop)); 59 len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop));
60 if (len < 0) { 60 if (len < 0) {
61 printk("i8042: Cannot get name property of root OBP node.\n"); 61 printk("i8042: Cannot get name property of root OBP node.\n");
62 return -1; 62 return -ENODEV;
63 } 63 }
64 if (strncmp(prop, "SUNW,JavaStation-1", len) == 0) { 64 if (strncmp(prop, "SUNW,JavaStation-1", len) == 0) {
65 /* Hardcoded values for MrCoffee. */ 65 /* Hardcoded values for MrCoffee. */
66 i8042_kbd_irq = i8042_aux_irq = 13 | 0x20; 66 i8042_kbd_irq = i8042_aux_irq = 13 | 0x20;
67 kbd_iobase = ioremap(0x71300060, 8); 67 kbd_iobase = ioremap(0x71300060, 8);
68 if (!kbd_iobase) 68 if (!kbd_iobase)
69 return -1; 69 return -ENODEV;
70 } else { 70 } else {
71 struct linux_ebus *ebus; 71 struct linux_ebus *ebus;
72 struct linux_ebus_device *edev; 72 struct linux_ebus_device *edev;
@@ -78,7 +78,7 @@ static int i8042_platform_init(void)
78 goto edev_found; 78 goto edev_found;
79 } 79 }
80 } 80 }
81 return -1; 81 return -ENODEV;
82 82
83 edev_found: 83 edev_found:
84 for_each_edevchild(edev, child) { 84 for_each_edevchild(edev, child) {
@@ -96,7 +96,7 @@ static int i8042_platform_init(void)
96 i8042_aux_irq == -1) { 96 i8042_aux_irq == -1) {
97 printk("i8042: Error, 8042 device lacks both kbd and " 97 printk("i8042: Error, 8042 device lacks both kbd and "
98 "mouse nodes.\n"); 98 "mouse nodes.\n");
99 return -1; 99 return -ENODEV;
100 } 100 }
101 } 101 }
102 102
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 03877c84e6ff..273bb3b08cfa 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -138,6 +138,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
138 }, 138 },
139 }, 139 },
140 { 140 {
141 .ident = "Fujitsu-Siemens Lifebook E4010",
142 .matches = {
143 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
144 DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E4010"),
145 },
146 },
147 {
141 .ident = "Toshiba P10", 148 .ident = "Toshiba P10",
142 .matches = { 149 .matches = {
143 DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 150 DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
@@ -256,9 +263,10 @@ static void i8042_pnp_exit(void)
256 } 263 }
257} 264}
258 265
259static int i8042_pnp_init(void) 266static int __init i8042_pnp_init(void)
260{ 267{
261 int result_kbd, result_aux; 268 int result_kbd = 0, result_aux = 0;
269 char kbd_irq_str[4] = { 0 }, aux_irq_str[4] = { 0 };
262 270
263 if (i8042_nopnp) { 271 if (i8042_nopnp) {
264 printk(KERN_INFO "i8042: PNP detection disabled\n"); 272 printk(KERN_INFO "i8042: PNP detection disabled\n");
@@ -267,6 +275,7 @@ static int i8042_pnp_init(void)
267 275
268 if ((result_kbd = pnp_register_driver(&i8042_pnp_kbd_driver)) >= 0) 276 if ((result_kbd = pnp_register_driver(&i8042_pnp_kbd_driver)) >= 0)
269 i8042_pnp_kbd_registered = 1; 277 i8042_pnp_kbd_registered = 1;
278
270 if ((result_aux = pnp_register_driver(&i8042_pnp_aux_driver)) >= 0) 279 if ((result_aux = pnp_register_driver(&i8042_pnp_aux_driver)) >= 0)
271 i8042_pnp_aux_registered = 1; 280 i8042_pnp_aux_registered = 1;
272 281
@@ -280,6 +289,27 @@ static int i8042_pnp_init(void)
280#endif 289#endif
281 } 290 }
282 291
292 if (result_kbd > 0)
293 snprintf(kbd_irq_str, sizeof(kbd_irq_str),
294 "%d", i8042_pnp_kbd_irq);
295 if (result_aux > 0)
296 snprintf(aux_irq_str, sizeof(aux_irq_str),
297 "%d", i8042_pnp_aux_irq);
298
299 printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %s%s%s\n",
300 i8042_pnp_kbd_name, (result_kbd > 0 && result_aux > 0) ? "," : "",
301 i8042_pnp_aux_name,
302 i8042_pnp_data_reg, i8042_pnp_command_reg,
303 kbd_irq_str, (result_kbd > 0 && result_aux > 0) ? "," : "",
304 aux_irq_str);
305
306#if defined(__ia64__)
307 if (result_kbd <= 0)
308 i8042_nokbd = 1;
309 if (result_aux <= 0)
310 i8042_noaux = 1;
311#endif
312
283 if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) && 313 if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) &&
284 i8042_pnp_data_reg != i8042_data_reg) || !i8042_pnp_data_reg) { 314 i8042_pnp_data_reg != i8042_data_reg) || !i8042_pnp_data_reg) {
285 printk(KERN_WARNING "PNP: PS/2 controller has invalid data port %#x; using default %#x\n", 315 printk(KERN_WARNING "PNP: PS/2 controller has invalid data port %#x; using default %#x\n",
@@ -294,53 +324,47 @@ static int i8042_pnp_init(void)
294 i8042_pnp_command_reg = i8042_command_reg; 324 i8042_pnp_command_reg = i8042_command_reg;
295 } 325 }
296 326
297 if (!i8042_pnp_kbd_irq) { 327 if (!i8042_nokbd && !i8042_pnp_kbd_irq) {
298 printk(KERN_WARNING "PNP: PS/2 controller doesn't have KBD irq; using default %#x\n", i8042_kbd_irq); 328 printk(KERN_WARNING "PNP: PS/2 controller doesn't have KBD irq; using default %d\n", i8042_kbd_irq);
299 i8042_pnp_kbd_irq = i8042_kbd_irq; 329 i8042_pnp_kbd_irq = i8042_kbd_irq;
300 } 330 }
301 331
302 if (!i8042_pnp_aux_irq) { 332 if (!i8042_noaux && !i8042_pnp_aux_irq) {
303 printk(KERN_WARNING "PNP: PS/2 controller doesn't have AUX irq; using default %#x\n", i8042_aux_irq); 333 printk(KERN_WARNING "PNP: PS/2 controller doesn't have AUX irq; using default %d\n", i8042_aux_irq);
304 i8042_pnp_aux_irq = i8042_aux_irq; 334 i8042_pnp_aux_irq = i8042_aux_irq;
305 } 335 }
306 336
307#if defined(__ia64__)
308 if (result_aux <= 0)
309 i8042_noaux = 1;
310#endif
311
312 i8042_data_reg = i8042_pnp_data_reg; 337 i8042_data_reg = i8042_pnp_data_reg;
313 i8042_command_reg = i8042_pnp_command_reg; 338 i8042_command_reg = i8042_pnp_command_reg;
314 i8042_kbd_irq = i8042_pnp_kbd_irq; 339 i8042_kbd_irq = i8042_pnp_kbd_irq;
315 i8042_aux_irq = i8042_pnp_aux_irq; 340 i8042_aux_irq = i8042_pnp_aux_irq;
316 341
317 printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %d%s%d\n",
318 i8042_pnp_kbd_name, (result_kbd > 0 && result_aux > 0) ? "," : "", i8042_pnp_aux_name,
319 i8042_data_reg, i8042_command_reg, i8042_kbd_irq,
320 (result_aux > 0) ? "," : "", i8042_aux_irq);
321
322 return 0; 342 return 0;
323} 343}
324 344
345#else
346static inline int i8042_pnp_init(void) { return 0; }
347static inline void i8042_pnp_exit(void) { }
325#endif 348#endif
326 349
327static inline int i8042_platform_init(void) 350static int __init i8042_platform_init(void)
328{ 351{
352 int retval;
353
329/* 354/*
330 * On ix86 platforms touching the i8042 data register region can do really 355 * On ix86 platforms touching the i8042 data register region can do really
331 * bad things. Because of this the region is always reserved on ix86 boxes. 356 * bad things. Because of this the region is always reserved on ix86 boxes.
332 * 357 *
333 * if (!request_region(I8042_DATA_REG, 16, "i8042")) 358 * if (!request_region(I8042_DATA_REG, 16, "i8042"))
334 * return -1; 359 * return -EBUSY;
335 */ 360 */
336 361
337 i8042_kbd_irq = I8042_MAP_IRQ(1); 362 i8042_kbd_irq = I8042_MAP_IRQ(1);
338 i8042_aux_irq = I8042_MAP_IRQ(12); 363 i8042_aux_irq = I8042_MAP_IRQ(12);
339 364
340#ifdef CONFIG_PNP 365 retval = i8042_pnp_init();
341 if (i8042_pnp_init()) 366 if (retval)
342 return -1; 367 return retval;
343#endif
344 368
345#if defined(__ia64__) 369#if defined(__ia64__)
346 i8042_reset = 1; 370 i8042_reset = 1;
@@ -354,14 +378,12 @@ static inline int i8042_platform_init(void)
354 i8042_nomux = 1; 378 i8042_nomux = 1;
355#endif 379#endif
356 380
357 return 0; 381 return retval;
358} 382}
359 383
360static inline void i8042_platform_exit(void) 384static inline void i8042_platform_exit(void)
361{ 385{
362#ifdef CONFIG_PNP
363 i8042_pnp_exit(); 386 i8042_pnp_exit();
364#endif
365} 387}
366 388
367#endif /* _I8042_X86IA64IO_H */ 389#endif /* _I8042_X86IA64IO_H */
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 708a1d3beab9..40d451ce07ff 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -27,6 +27,10 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
27MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver"); 27MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver");
28MODULE_LICENSE("GPL"); 28MODULE_LICENSE("GPL");
29 29
30static unsigned int i8042_nokbd;
31module_param_named(nokbd, i8042_nokbd, bool, 0);
32MODULE_PARM_DESC(nokbd, "Do not probe or use KBD port.");
33
30static unsigned int i8042_noaux; 34static unsigned int i8042_noaux;
31module_param_named(noaux, i8042_noaux, bool, 0); 35module_param_named(noaux, i8042_noaux, bool, 0);
32MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port."); 36MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port.");
@@ -338,10 +342,10 @@ static int i8042_open(struct serio *serio)
338 342
339 return 0; 343 return 0;
340 344
341activate_fail: 345 activate_fail:
342 free_irq(port->irq, i8042_request_irq_cookie); 346 free_irq(port->irq, i8042_request_irq_cookie);
343 347
344irq_fail: 348 irq_fail:
345 serio_unregister_port_delayed(serio); 349 serio_unregister_port_delayed(serio);
346 350
347 return -1; 351 return -1;
@@ -485,7 +489,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
485 serio_interrupt(port->serio, data, dfl, regs); 489 serio_interrupt(port->serio, data, dfl, regs);
486 490
487 ret = 1; 491 ret = 1;
488out: 492 out:
489 return IRQ_RETVAL(ret); 493 return IRQ_RETVAL(ret);
490} 494}
491 495
@@ -552,7 +556,7 @@ static int i8042_enable_mux_ports(void)
552 * Enable all muxed ports. 556 * Enable all muxed ports.
553 */ 557 */
554 558
555 for (i = 0; i < 4; i++) { 559 for (i = 0; i < I8042_NUM_MUX_PORTS; i++) {
556 i8042_command(&param, I8042_CMD_MUX_PFX + i); 560 i8042_command(&param, I8042_CMD_MUX_PFX + i);
557 i8042_command(&param, I8042_CMD_AUX_ENABLE); 561 i8042_command(&param, I8042_CMD_AUX_ENABLE);
558 } 562 }
@@ -682,7 +686,7 @@ static int __init i8042_port_register(struct i8042_port *port)
682 kfree(port->serio); 686 kfree(port->serio);
683 port->serio = NULL; 687 port->serio = NULL;
684 i8042_ctr |= port->disable; 688 i8042_ctr |= port->disable;
685 return -1; 689 return -EIO;
686 } 690 }
687 691
688 printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n", 692 printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n",
@@ -977,85 +981,88 @@ static struct device_driver i8042_driver = {
977 .shutdown = i8042_shutdown, 981 .shutdown = i8042_shutdown,
978}; 982};
979 983
980static void __init i8042_create_kbd_port(void) 984static int __init i8042_create_kbd_port(void)
981{ 985{
982 struct serio *serio; 986 struct serio *serio;
983 struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; 987 struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO];
984 988
985 serio = kmalloc(sizeof(struct serio), GFP_KERNEL); 989 serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
986 if (serio) { 990 if (!serio)
987 memset(serio, 0, sizeof(struct serio)); 991 return -ENOMEM;
988 serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL; 992
989 serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; 993 serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL;
990 serio->open = i8042_open; 994 serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write;
991 serio->close = i8042_close; 995 serio->open = i8042_open;
992 serio->start = i8042_start; 996 serio->close = i8042_close;
993 serio->stop = i8042_stop; 997 serio->start = i8042_start;
994 serio->port_data = port; 998 serio->stop = i8042_stop;
995 serio->dev.parent = &i8042_platform_device->dev; 999 serio->port_data = port;
996 strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name)); 1000 serio->dev.parent = &i8042_platform_device->dev;
997 strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys)); 1001 strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name));
998 1002 strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys));
999 port->serio = serio; 1003
1000 i8042_port_register(port); 1004 port->serio = serio;
1001 } 1005
1006 return i8042_port_register(port);
1002} 1007}
1003 1008
1004static void __init i8042_create_aux_port(void) 1009static int __init i8042_create_aux_port(void)
1005{ 1010{
1006 struct serio *serio; 1011 struct serio *serio;
1007 struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO]; 1012 struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO];
1008 1013
1009 serio = kmalloc(sizeof(struct serio), GFP_KERNEL); 1014 serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
1010 if (serio) { 1015 if (!serio)
1011 memset(serio, 0, sizeof(struct serio)); 1016 return -ENOMEM;
1012 serio->id.type = SERIO_8042; 1017
1013 serio->write = i8042_aux_write; 1018 serio->id.type = SERIO_8042;
1014 serio->open = i8042_open; 1019 serio->write = i8042_aux_write;
1015 serio->close = i8042_close; 1020 serio->open = i8042_open;
1016 serio->start = i8042_start; 1021 serio->close = i8042_close;
1017 serio->stop = i8042_stop; 1022 serio->start = i8042_start;
1018 serio->port_data = port; 1023 serio->stop = i8042_stop;
1019 serio->dev.parent = &i8042_platform_device->dev; 1024 serio->port_data = port;
1020 strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name)); 1025 serio->dev.parent = &i8042_platform_device->dev;
1021 strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); 1026 strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name));
1022 1027 strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys));
1023 port->serio = serio; 1028
1024 i8042_port_register(port); 1029 port->serio = serio;
1025 } 1030
1031 return i8042_port_register(port);
1026} 1032}
1027 1033
1028static void __init i8042_create_mux_port(int index) 1034static int __init i8042_create_mux_port(int index)
1029{ 1035{
1030 struct serio *serio; 1036 struct serio *serio;
1031 struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index]; 1037 struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index];
1032 1038
1033 serio = kmalloc(sizeof(struct serio), GFP_KERNEL); 1039 serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
1034 if (serio) { 1040 if (!serio)
1035 memset(serio, 0, sizeof(struct serio)); 1041 return -ENOMEM;
1036 serio->id.type = SERIO_8042; 1042
1037 serio->write = i8042_aux_write; 1043 serio->id.type = SERIO_8042;
1038 serio->open = i8042_open; 1044 serio->write = i8042_aux_write;
1039 serio->close = i8042_close; 1045 serio->open = i8042_open;
1040 serio->start = i8042_start; 1046 serio->close = i8042_close;
1041 serio->stop = i8042_stop; 1047 serio->start = i8042_start;
1042 serio->port_data = port; 1048 serio->stop = i8042_stop;
1043 serio->dev.parent = &i8042_platform_device->dev; 1049 serio->port_data = port;
1044 snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index); 1050 serio->dev.parent = &i8042_platform_device->dev;
1045 snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1); 1051 snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index);
1046 1052 snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1);
1047 *port = i8042_ports[I8042_AUX_PORT_NO]; 1053
1048 port->exists = 0; 1054 *port = i8042_ports[I8042_AUX_PORT_NO];
1049 snprintf(port->name, sizeof(port->name), "AUX%d", index); 1055 port->exists = 0;
1050 port->mux = index; 1056 snprintf(port->name, sizeof(port->name), "AUX%d", index);
1051 port->serio = serio; 1057 port->mux = index;
1052 i8042_port_register(port); 1058 port->serio = serio;
1053 } 1059
1060 return i8042_port_register(port);
1054} 1061}
1055 1062
1056static int __init i8042_init(void) 1063static int __init i8042_init(void)
1057{ 1064{
1058 int i; 1065 int i, have_ports = 0;
1059 int err; 1066 int err;
1060 1067
1061 dbg_init(); 1068 dbg_init();
@@ -1063,43 +1070,73 @@ static int __init i8042_init(void)
1063 init_timer(&i8042_timer); 1070 init_timer(&i8042_timer);
1064 i8042_timer.function = i8042_timer_func; 1071 i8042_timer.function = i8042_timer_func;
1065 1072
1066 if (i8042_platform_init()) 1073 err = i8042_platform_init();
1067 return -EBUSY; 1074 if (err)
1075 return err;
1068 1076
1069 i8042_ports[I8042_AUX_PORT_NO].irq = I8042_AUX_IRQ; 1077 i8042_ports[I8042_AUX_PORT_NO].irq = I8042_AUX_IRQ;
1070 i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ; 1078 i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ;
1071 1079
1072 if (i8042_controller_init()) { 1080 if (i8042_controller_init()) {
1073 i8042_platform_exit(); 1081 err = -ENODEV;
1074 return -ENODEV; 1082 goto err_platform_exit;
1075 } 1083 }
1076 1084
1077 err = driver_register(&i8042_driver); 1085 err = driver_register(&i8042_driver);
1078 if (err) { 1086 if (err)
1079 i8042_platform_exit(); 1087 goto err_controller_cleanup;
1080 return err;
1081 }
1082 1088
1083 i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0); 1089 i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0);
1084 if (IS_ERR(i8042_platform_device)) { 1090 if (IS_ERR(i8042_platform_device)) {
1085 driver_unregister(&i8042_driver); 1091 err = PTR_ERR(i8042_platform_device);
1086 i8042_platform_exit(); 1092 goto err_unregister_driver;
1087 return PTR_ERR(i8042_platform_device);
1088 } 1093 }
1089 1094
1090 if (!i8042_noaux && !i8042_check_aux()) { 1095 if (!i8042_noaux && !i8042_check_aux()) {
1091 if (!i8042_nomux && !i8042_check_mux()) 1096 if (!i8042_nomux && !i8042_check_mux()) {
1092 for (i = 0; i < I8042_NUM_MUX_PORTS; i++) 1097 for (i = 0; i < I8042_NUM_MUX_PORTS; i++) {
1093 i8042_create_mux_port(i); 1098 err = i8042_create_mux_port(i);
1094 else 1099 if (err)
1095 i8042_create_aux_port(); 1100 goto err_unregister_ports;
1101 }
1102 } else {
1103 err = i8042_create_aux_port();
1104 if (err)
1105 goto err_unregister_ports;
1106 }
1107 have_ports = 1;
1096 } 1108 }
1097 1109
1098 i8042_create_kbd_port(); 1110 if (!i8042_nokbd) {
1111 err = i8042_create_kbd_port();
1112 if (err)
1113 goto err_unregister_ports;
1114 have_ports = 1;
1115 }
1116
1117 if (!have_ports) {
1118 err = -ENODEV;
1119 goto err_unregister_device;
1120 }
1099 1121
1100 mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); 1122 mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
1101 1123
1102 return 0; 1124 return 0;
1125
1126 err_unregister_ports:
1127 for (i = 0; i < I8042_NUM_PORTS; i++)
1128 if (i8042_ports[i].serio)
1129 serio_unregister_port(i8042_ports[i].serio);
1130 err_unregister_device:
1131 platform_device_unregister(i8042_platform_device);
1132 err_unregister_driver:
1133 driver_unregister(&i8042_driver);
1134 err_controller_cleanup:
1135 i8042_controller_cleanup();
1136 err_platform_exit:
1137 i8042_platform_exit();
1138
1139 return err;
1103} 1140}
1104 1141
1105static void __exit i8042_exit(void) 1142static void __exit i8042_exit(void)