From 541e316aed6f7d6efeb427a88645c2a8f61418d6 Mon Sep 17 00:00:00 2001 From: Stephen Evanchik Date: Mon, 8 Aug 2005 01:26:18 -0500 Subject: Input: psmouse - add support for IBM TrackPoint devices. Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/Makefile | 2 +- drivers/input/mouse/psmouse-base.c | 15 +- drivers/input/mouse/psmouse.h | 1 + drivers/input/mouse/trackpoint.c | 297 +++++++++++++++++++++++++++++++++++++ drivers/input/mouse/trackpoint.h | 147 ++++++++++++++++++ 5 files changed, 460 insertions(+), 2 deletions(-) create mode 100644 drivers/input/mouse/trackpoint.c create mode 100644 drivers/input/mouse/trackpoint.h (limited to 'drivers/input') 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 obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o -psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o +psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o trackpoint.o diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 2bb2fe78bdca..b3508276785f 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -25,6 +25,7 @@ #include "logips2pp.h" #include "alps.h" #include "lifebook.h" +#include "trackpoint.h" #define DRIVER_DESC "PS/2 mouse driver" @@ -519,6 +520,12 @@ static int psmouse_extensions(struct psmouse *psmouse, if (max_proto >= PSMOUSE_IMPS && intellimouse_detect(psmouse, set_properties) == 0) return PSMOUSE_IMPS; +/* + * Try to initialize the IBM TrackPoint + */ + if (max_proto > PSMOUSE_IMEX && trackpoint_detect(psmouse, set_properties) == 0) + return PSMOUSE_TRACKPOINT; + /* * Okay, all failed, we have a standard mouse here. The number of the buttons * is still a question, though. We assume 3. @@ -599,6 +606,12 @@ static struct psmouse_protocol psmouse_protocols[] = { .alias = "lifebook", .init = lifebook_init, }, + { + .type = PSMOUSE_TRACKPOINT, + .name = "TPPS/2", + .alias = "trackpoint", + .detect = trackpoint_detect, + }, { .type = PSMOUSE_AUTO, .name = "auto", @@ -1234,7 +1247,7 @@ static int psmouse_set_maxproto(const char *val, struct kernel_param *kp) *((unsigned int *)kp->arg) = proto->type; - return 0; \ + return 0; } static 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..e312a6b41681 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h @@ -78,6 +78,7 @@ enum psmouse_type { PSMOUSE_SYNAPTICS, PSMOUSE_ALPS, PSMOUSE_LIFEBOOK, + PSMOUSE_TRACKPOINT, PSMOUSE_AUTO /* This one should always be last */ }; diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c new file mode 100644 index 000000000000..aee3b24a9102 --- /dev/null +++ b/drivers/input/mouse/trackpoint.c @@ -0,0 +1,297 @@ +/* + * Stephen Evanchik + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * Trademarks are the property of their respective owners. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "psmouse.h" +#include "trackpoint.h" + +PSMOUSE_DEFINE_ATTR(sensitivity); +PSMOUSE_DEFINE_ATTR(speed); +PSMOUSE_DEFINE_ATTR(inertia); +PSMOUSE_DEFINE_ATTR(reach); +PSMOUSE_DEFINE_ATTR(draghys); +PSMOUSE_DEFINE_ATTR(mindrag); +PSMOUSE_DEFINE_ATTR(thresh); +PSMOUSE_DEFINE_ATTR(upthresh); +PSMOUSE_DEFINE_ATTR(ztime); +PSMOUSE_DEFINE_ATTR(jenks); +PSMOUSE_DEFINE_ATTR(press_to_select); +PSMOUSE_DEFINE_ATTR(skipback); +PSMOUSE_DEFINE_ATTR(ext_dev); + +#define MAKE_ATTR_READ(_item) \ + static ssize_t psmouse_attr_show_##_item(struct psmouse *psmouse, char *buf) \ + { \ + struct trackpoint_data *tp = psmouse->private; \ + return sprintf(buf, "%lu\n", (unsigned long)tp->_item); \ + } + +#define MAKE_ATTR_WRITE(_item, command) \ + static ssize_t psmouse_attr_set_##_item(struct psmouse *psmouse, const char *buf, size_t count) \ + { \ + char *rest; \ + unsigned long value; \ + struct trackpoint_data *tp = psmouse->private; \ + value = simple_strtoul(buf, &rest, 10); \ + if (*rest) \ + return -EINVAL; \ + tp->_item = value; \ + trackpoint_write(&psmouse->ps2dev, command, tp->_item); \ + return count; \ + } + +#define MAKE_ATTR_TOGGLE(_item, command, mask) \ + static ssize_t psmouse_attr_set_##_item(struct psmouse *psmouse, const char *buf, size_t count) \ + { \ + unsigned char toggle; \ + struct trackpoint_data *tp = psmouse->private; \ + toggle = (buf[0] == '1') ? 1 : 0; \ + if (toggle != tp->_item) { \ + tp->_item = toggle; \ + trackpoint_toggle_bit(&psmouse->ps2dev, command, mask); \ + } \ + return count; \ + } + +/* + * Device IO: read, write and toggle bit + */ +static int trackpoint_read(struct ps2dev *ps2dev, unsigned char loc, unsigned char *results) +{ + if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) || + ps2_command(ps2dev, results, MAKE_PS2_CMD(0, 1, loc))) { + return -1; + } + + return 0; +} + +static int trackpoint_write(struct ps2dev *ps2dev, unsigned char loc, unsigned char val) +{ + if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) || + ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_WRITE_MEM)) || + ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, loc)) || + ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, val))) { + return -1; + } + + return 0; +} + +static int trackpoint_toggle_bit(struct ps2dev *ps2dev, unsigned char loc, unsigned char mask) +{ + /* Bad things will happen if the loc param isn't in this range */ + if (loc < 0x20 || loc >= 0x2F) + return -1; + + if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) || + ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_TOGGLE)) || + ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, loc)) || + ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, mask))) { + return -1; + } + + return 0; +} + +MAKE_ATTR_WRITE(sensitivity, TP_SENS); +MAKE_ATTR_READ(sensitivity); + +MAKE_ATTR_WRITE(speed, TP_SPEED); +MAKE_ATTR_READ(speed); + +MAKE_ATTR_WRITE(inertia, TP_INERTIA); +MAKE_ATTR_READ(inertia); + +MAKE_ATTR_WRITE(reach, TP_REACH); +MAKE_ATTR_READ(reach); + +MAKE_ATTR_WRITE(draghys, TP_DRAGHYS); +MAKE_ATTR_READ(draghys); + +MAKE_ATTR_WRITE(mindrag, TP_MINDRAG); +MAKE_ATTR_READ(mindrag); + +MAKE_ATTR_WRITE(thresh, TP_THRESH); +MAKE_ATTR_READ(thresh); + +MAKE_ATTR_WRITE(upthresh, TP_UP_THRESH); +MAKE_ATTR_READ(upthresh); + +MAKE_ATTR_WRITE(ztime, TP_Z_TIME); +MAKE_ATTR_READ(ztime); + +MAKE_ATTR_WRITE(jenks, TP_JENKS_CURV); +MAKE_ATTR_READ(jenks); + +MAKE_ATTR_TOGGLE(press_to_select, TP_TOGGLE_PTSON, TP_MASK_PTSON); +MAKE_ATTR_READ(press_to_select); + +MAKE_ATTR_TOGGLE(skipback, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK); +MAKE_ATTR_READ(skipback); + +MAKE_ATTR_TOGGLE(ext_dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV); +MAKE_ATTR_READ(ext_dev); + +static struct attribute *trackpoint_attrs[] = { + &psmouse_attr_sensitivity.attr, + &psmouse_attr_speed.attr, + &psmouse_attr_inertia.attr, + &psmouse_attr_reach.attr, + &psmouse_attr_draghys.attr, + &psmouse_attr_mindrag.attr, + &psmouse_attr_thresh.attr, + &psmouse_attr_upthresh.attr, + &psmouse_attr_ztime.attr, + &psmouse_attr_jenks.attr, + &psmouse_attr_press_to_select.attr, + &psmouse_attr_skipback.attr, + &psmouse_attr_ext_dev.attr, + NULL +}; + +static struct attribute_group trackpoint_attr_group = { + .attrs = trackpoint_attrs, +}; + +static void trackpoint_disconnect(struct psmouse *psmouse) +{ + sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, &trackpoint_attr_group); + + kfree(psmouse->private); + psmouse->private = NULL; +} + +static int trackpoint_sync(struct psmouse *psmouse) +{ + unsigned char toggle; + struct trackpoint_data *tp = psmouse->private; + + if (!tp) + return -1; + + /* Disable features that may make device unusable with this driver */ + trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, &toggle); + if (toggle & TP_MASK_TWOHAND) + trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, TP_MASK_TWOHAND); + + trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_SOURCE_TAG, &toggle); + if (toggle & TP_MASK_SOURCE_TAG) + trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_SOURCE_TAG, TP_MASK_SOURCE_TAG); + + trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_MB, &toggle); + if (toggle & TP_MASK_MB) + trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_MB, TP_MASK_MB); + + /* Push the config to the device */ + trackpoint_write(&psmouse->ps2dev, TP_SENS, tp->sensitivity); + trackpoint_write(&psmouse->ps2dev, TP_INERTIA, tp->inertia); + trackpoint_write(&psmouse->ps2dev, TP_SPEED, tp->speed); + + trackpoint_write(&psmouse->ps2dev, TP_REACH, tp->reach); + trackpoint_write(&psmouse->ps2dev, TP_DRAGHYS, tp->draghys); + trackpoint_write(&psmouse->ps2dev, TP_MINDRAG, tp->mindrag); + + trackpoint_write(&psmouse->ps2dev, TP_THRESH, tp->thresh); + trackpoint_write(&psmouse->ps2dev, TP_UP_THRESH, tp->upthresh); + + trackpoint_write(&psmouse->ps2dev, TP_Z_TIME, tp->ztime); + trackpoint_write(&psmouse->ps2dev, TP_JENKS_CURV, tp->jenks); + + trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_PTSON, &toggle); + if (((toggle & TP_MASK_PTSON) == TP_MASK_PTSON) != tp->press_to_select) + trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_PTSON, TP_MASK_PTSON); + + trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_SKIPBACK, &toggle); + if (((toggle & TP_MASK_SKIPBACK) == TP_MASK_SKIPBACK) != tp->skipback) + trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK); + + trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_EXT_DEV, &toggle); + if (((toggle & TP_MASK_EXT_DEV) == TP_MASK_EXT_DEV) != tp->ext_dev) + trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV); + + return 0; +} + +static void trackpoint_defaults(struct trackpoint_data *tp) +{ + tp->press_to_select = TP_DEF_PTSON; + tp->sensitivity = TP_DEF_SENS; + tp->speed = TP_DEF_SPEED; + tp->reach = TP_DEF_REACH; + + tp->draghys = TP_DEF_DRAGHYS; + tp->mindrag = TP_DEF_MINDRAG; + + tp->thresh = TP_DEF_THRESH; + tp->upthresh = TP_DEF_UP_THRESH; + + tp->ztime = TP_DEF_Z_TIME; + tp->jenks = TP_DEF_JENKS_CURV; + + tp->inertia = TP_DEF_INERTIA; + tp->skipback = TP_DEF_SKIPBACK; + tp->ext_dev = TP_DEF_EXT_DEV; +} + +int trackpoint_detect(struct psmouse *psmouse, int set_properties) +{ + struct trackpoint_data *priv; + struct ps2dev *ps2dev = &psmouse->ps2dev; + unsigned char firmware_id; + unsigned char button_info; + unsigned char param[2]; + + param[0] = param[1] = 0; + + if (ps2_command(ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID))) + return -1; + + if (param[0] != TP_MAGIC_IDENT) + return -1; + + if (!set_properties) + return 0; + + firmware_id = param[1]; + + if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) { + printk(KERN_WARNING "trackpoint.c: failed to get extended button data\n"); + button_info = 0; + } + + psmouse->private = priv = kcalloc(1, sizeof(struct trackpoint_data), GFP_KERNEL); + if (!priv) + return -1; + + psmouse->vendor = "IBM"; + psmouse->name = "TrackPoint"; + + psmouse->reconnect = trackpoint_sync; + psmouse->disconnect = trackpoint_disconnect; + + trackpoint_defaults(priv); + trackpoint_sync(psmouse); + + sysfs_create_group(&ps2dev->serio->dev.kobj, &trackpoint_attr_group); + + printk(KERN_INFO "IBM TrackPoint firmware: 0x%02x, buttons: %d/%d\n", + firmware_id, (button_info & 0xf0) >> 4, button_info & 0x0f); + + return 0; +} + 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 @@ +/* + * IBM TrackPoint PS/2 mouse driver + * + * Stephen Evanchik + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#ifndef _TRACKPOINT_H +#define _TRACKPOINT_H + +/* + * These constants are from the TrackPoint System + * Engineering documentation Version 4 from IBM Watson + * research: + * http://wwwcssrv.almaden.ibm.com/trackpoint/download.html + */ + +#define TP_COMMAND 0xE2 /* Commands start with this */ + +#define TP_READ_ID 0xE1 /* Sent for device identification */ +#define TP_MAGIC_IDENT 0x01 /* Sent after a TP_READ_ID followed */ + /* by the firmware ID */ + + +/* + * Commands + */ +#define TP_RECALIB 0x51 /* Recalibrate */ +#define TP_POWER_DOWN 0x44 /* Can only be undone through HW reset */ +#define TP_EXT_DEV 0x21 /* Determines if external device is connected (RO) */ +#define TP_EXT_BTN 0x4B /* Read extended button status */ +#define TP_POR 0x7F /* Execute Power on Reset */ +#define TP_POR_RESULTS 0x25 /* Read Power on Self test results */ +#define TP_DISABLE_EXT 0x40 /* Disable external pointing device */ +#define TP_ENABLE_EXT 0x41 /* Enable external pointing device */ + +/* + * Mode manipulation + */ +#define TP_SET_SOFT_TRANS 0x4E /* Set mode */ +#define TP_CANCEL_SOFT_TRANS 0xB9 /* Cancel mode */ +#define TP_SET_HARD_TRANS 0x45 /* Mode can only be set */ + + +/* + * Register oriented commands/properties + */ +#define TP_WRITE_MEM 0x81 +#define TP_READ_MEM 0x80 /* Not used in this implementation */ + +/* +* RAM Locations for properties + */ +#define TP_SENS 0x4A /* Sensitivity */ +#define TP_MB 0x4C /* Read Middle Button Status (RO) */ +#define TP_INERTIA 0x4D /* Negative Inertia */ +#define TP_SPEED 0x60 /* Speed of TP Cursor */ +#define TP_REACH 0x57 /* Backup for Z-axis press */ +#define TP_DRAGHYS 0x58 /* Drag Hysteresis */ + /* (how hard it is to drag */ + /* with Z-axis pressed) */ + +#define TP_MINDRAG 0x59 /* Minimum amount of force needed */ + /* to trigger dragging */ + +#define TP_THRESH 0x5C /* Minimum value for a Z-axis press */ +#define TP_UP_THRESH 0x5A /* Used to generate a 'click' on Z-axis */ +#define TP_Z_TIME 0x5E /* How sharp of a press */ +#define TP_JENKS_CURV 0x5D /* Minimum curvature for double click */ + +/* + * Toggling Flag bits + */ +#define TP_TOGGLE 0x47 /* Toggle command */ + +#define TP_TOGGLE_MB 0x23 /* Disable/Enable Middle Button */ +#define TP_MASK_MB 0x01 +#define TP_TOGGLE_EXT_DEV 0x23 /* Toggle external device */ +#define TP_MASK_EXT_DEV 0x02 +#define TP_TOGGLE_DRIFT 0x23 /* Drift Correction */ +#define TP_MASK_DRIFT 0x80 +#define TP_TOGGLE_BURST 0x28 /* Burst Mode */ +#define TP_MASK_BURST 0x80 +#define TP_TOGGLE_PTSON 0x2C /* Press to Select */ +#define TP_MASK_PTSON 0x01 +#define TP_TOGGLE_HARD_TRANS 0x2C /* Alternate method to set Hard Transparency */ +#define TP_MASK_HARD_TRANS 0x80 +#define TP_TOGGLE_TWOHAND 0x2D /* Two handed */ +#define TP_MASK_TWOHAND 0x01 +#define TP_TOGGLE_STICKY_TWO 0x2D /* Sticky two handed */ +#define TP_MASK_STICKY_TWO 0x04 +#define TP_TOGGLE_SKIPBACK 0x2D /* Suppress movement after drag release */ +#define TP_MASK_SKIPBACK 0x08 +#define TP_TOGGLE_SOURCE_TAG 0x20 /* Bit 3 of the first packet will be set to + to the origin of the packet (external or TP) */ +#define TP_MASK_SOURCE_TAG 0x80 +#define TP_TOGGLE_EXT_TAG 0x22 /* Bit 3 of the first packet coming from the + external device will be forced to 1 */ +#define TP_MASK_EXT_TAG 0x04 + + +/* Power on Self Test Results */ +#define TP_POR_SUCCESS 0x3B + +/* + * Default power on values + */ +#define TP_DEF_SENS 0x80 +#define TP_DEF_INERTIA 0x06 +#define TP_DEF_SPEED 0x61 +#define TP_DEF_REACH 0x0A + +#define TP_DEF_DRAGHYS 0xFF +#define TP_DEF_MINDRAG 0x14 + +#define TP_DEF_THRESH 0x08 +#define TP_DEF_UP_THRESH 0xFF +#define TP_DEF_Z_TIME 0x26 +#define TP_DEF_JENKS_CURV 0x87 + +/* Toggles */ +#define TP_DEF_MB 0x00 +#define TP_DEF_PTSON 0x00 +#define TP_DEF_SKIPBACK 0x00 +#define TP_DEF_EXT_DEV 0x01 + +#define MAKE_PS2_CMD(params, results, cmd) ((params<<12) | (results<<8) | (cmd)) + +struct trackpoint_data +{ + unsigned char sensitivity, speed, inertia, reach; + unsigned char draghys, mindrag; + unsigned char thresh, upthresh; + unsigned char ztime, jenks; + + unsigned char press_to_select; + unsigned char skipback; + + unsigned char ext_dev; +}; + +extern int trackpoint_detect(struct psmouse *psmouse, int set_properties); + +#endif /* _TRACKPOINT_H */ -- cgit v1.2.3 From cfe9e88866fe892f4f71bf132c64ec8bd5256e5e Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 4 Sep 2005 01:40:20 -0500 Subject: Input: rework psmouse attributes to reduce module size Rearrange attribute code to use generic show and set handlers instead of replicating them for every attribute; switch to using attribute_group instead of creating all attributes manually. All this saves about 4K. Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/logips2pp.c | 12 ++- drivers/input/mouse/psmouse-base.c | 117 +++++++++++++----------- drivers/input/mouse/psmouse.h | 51 +++++++---- drivers/input/mouse/trackpoint.c | 183 +++++++++++++++++++------------------ 4 files changed, 200 insertions(+), 163 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index 48d2b20d2642..e65c2798a491 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 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); } -static ssize_t psmouse_attr_show_smartscroll(struct psmouse *psmouse, char *buf) +static ssize_t ps2pp_attr_show_smartscroll(struct psmouse *psmouse, void *data, char *buf) { return sprintf(buf, "%d\n", psmouse->smartscroll ? 1 : 0); } -static ssize_t psmouse_attr_set_smartscroll(struct psmouse *psmouse, const char *buf, size_t count) +static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data, const char *buf, size_t count) { unsigned long value; char *rest; @@ -169,7 +169,8 @@ static ssize_t psmouse_attr_set_smartscroll(struct psmouse *psmouse, const char return count; } -PSMOUSE_DEFINE_ATTR(smartscroll); +PSMOUSE_DEFINE_ATTR(smartscroll, S_IWUSR | S_IRUGO, NULL, + ps2pp_attr_show_smartscroll, ps2pp_attr_set_smartscroll); /* * 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 static void ps2pp_disconnect(struct psmouse *psmouse) { - device_remove_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll); + device_remove_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll.dattr); } static struct ps2pp_info *get_model_info(unsigned char model) @@ -379,7 +380,8 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties) psmouse->set_resolution = ps2pp_set_resolution; psmouse->disconnect = ps2pp_disconnect; - device_create_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll); + device_create_file(&psmouse->ps2dev.serio->dev, + &psmouse_attr_smartscroll.dattr); } } diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index b3508276785f..0830c6e13ef6 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -58,10 +58,30 @@ static unsigned int psmouse_resetafter; module_param_named(resetafter, psmouse_resetafter, uint, 0644); MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); -PSMOUSE_DEFINE_ATTR(protocol); -PSMOUSE_DEFINE_ATTR(rate); -PSMOUSE_DEFINE_ATTR(resolution); -PSMOUSE_DEFINE_ATTR(resetafter); +PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO, + NULL, + psmouse_attr_show_protocol, psmouse_attr_set_protocol); +PSMOUSE_DEFINE_ATTR(rate, S_IWUSR | S_IRUGO, + (void *) offsetof(struct psmouse, rate), + psmouse_show_int_attr, psmouse_attr_set_rate); +PSMOUSE_DEFINE_ATTR(resolution, S_IWUSR | S_IRUGO, + (void *) offsetof(struct psmouse, resolution), + psmouse_show_int_attr, psmouse_attr_set_resolution); +PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO, + (void *) offsetof(struct psmouse, resetafter), + psmouse_show_int_attr, psmouse_set_int_attr); + +static struct attribute *psmouse_attributes[] = { + &psmouse_attr_protocol.dattr.attr, + &psmouse_attr_rate.dattr.attr, + &psmouse_attr_resolution.dattr.attr, + &psmouse_attr_resetafter.dattr.attr, + NULL +}; + +static struct attribute_group psmouse_attribute_group = { + .attrs = psmouse_attributes, +}; __obsolete_setup("psmouse_noext"); __obsolete_setup("psmouse_resolution="); @@ -800,10 +820,7 @@ static void psmouse_disconnect(struct serio *serio) psmouse = serio_get_drvdata(serio); - device_remove_file(&serio->dev, &psmouse_attr_protocol); - device_remove_file(&serio->dev, &psmouse_attr_rate); - device_remove_file(&serio->dev, &psmouse_attr_resolution); - device_remove_file(&serio->dev, &psmouse_attr_resetafter); + sysfs_remove_group(&serio->dev.kobj, &psmouse_attribute_group); down(&psmouse_sem); @@ -940,10 +957,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) if (parent && parent->pt_activate) parent->pt_activate(parent); - device_create_file(&serio->dev, &psmouse_attr_protocol); - device_create_file(&serio->dev, &psmouse_attr_rate); - device_create_file(&serio->dev, &psmouse_attr_resolution); - device_create_file(&serio->dev, &psmouse_attr_resetafter); + sysfs_create_group(&serio->dev.kobj, &psmouse_attribute_group); psmouse_activate(psmouse); @@ -1040,10 +1054,12 @@ static struct serio_driver psmouse_drv = { .cleanup = psmouse_cleanup, }; -ssize_t psmouse_attr_show_helper(struct device *dev, char *buf, - ssize_t (*handler)(struct psmouse *, char *)) +ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *devattr, + char *buf) { struct serio *serio = to_serio_port(dev); + struct psmouse_attribute *attr = to_psmouse_attr(devattr); + struct psmouse *psmouse; int retval; retval = serio_pin_driver(serio); @@ -1055,19 +1071,21 @@ ssize_t psmouse_attr_show_helper(struct device *dev, char *buf, goto out; } - retval = handler(serio_get_drvdata(serio), buf); + psmouse = serio_get_drvdata(serio); + + retval = attr->show(psmouse, attr->data, buf); out: serio_unpin_driver(serio); return retval; } -ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t count, - ssize_t (*handler)(struct psmouse *, const char *, size_t)) +ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) { struct serio *serio = to_serio_port(dev); - struct psmouse *psmouse = serio_get_drvdata(serio); - struct psmouse *parent = NULL; + struct psmouse_attribute *attr = to_psmouse_attr(devattr); + struct psmouse *psmouse, *parent = NULL; int retval; retval = serio_pin_driver(serio); @@ -1083,6 +1101,8 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun if (retval) goto out_unpin; + psmouse = serio_get_drvdata(serio); + if (psmouse->state == PSMOUSE_IGNORE) { retval = -ENODEV; goto out_up; @@ -1095,7 +1115,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun psmouse_deactivate(psmouse); - retval = handler(psmouse, buf, count); + retval = attr->set(psmouse, attr->data, buf, count); if (retval != -ENODEV) psmouse_activate(psmouse); @@ -1110,12 +1130,34 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun return retval; } -static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, char *buf) +static ssize_t psmouse_show_int_attr(struct psmouse *psmouse, void *offset, char *buf) +{ + unsigned long *field = (unsigned long *)((char *)psmouse + (size_t)offset); + + return sprintf(buf, "%lu\n", *field); +} + +static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const char *buf, size_t count) +{ + unsigned long *field = (unsigned long *)((char *)psmouse + (size_t)offset); + unsigned long value; + char *rest; + + value = simple_strtoul(buf, &rest, 10); + if (*rest) + return -EINVAL; + + *field = value; + + return count; +} + +static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, void *data, char *buf) { return sprintf(buf, "%s\n", psmouse_protocol_by_type(psmouse->type)->name); } -static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *buf, size_t count) +static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, const char *buf, size_t count) { struct serio *serio = psmouse->ps2dev.serio; struct psmouse *parent = NULL; @@ -1179,12 +1221,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *bu return count; } -static ssize_t psmouse_attr_show_rate(struct psmouse *psmouse, char *buf) -{ - return sprintf(buf, "%d\n", psmouse->rate); -} - -static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, const char *buf, size_t count) +static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const char *buf, size_t count) { unsigned long value; char *rest; @@ -1197,12 +1234,7 @@ static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, const char *buf, s return count; } -static ssize_t psmouse_attr_show_resolution(struct psmouse *psmouse, char *buf) -{ - return sprintf(buf, "%d\n", psmouse->resolution); -} - -static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, const char *buf, size_t count) +static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, const char *buf, size_t count) { unsigned long value; char *rest; @@ -1215,23 +1247,6 @@ static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, const char * return count; } -static ssize_t psmouse_attr_show_resetafter(struct psmouse *psmouse, char *buf) -{ - return sprintf(buf, "%d\n", psmouse->resetafter); -} - -static ssize_t psmouse_attr_set_resetafter(struct psmouse *psmouse, const char *buf, size_t count) -{ - unsigned long value; - char *rest; - - value = simple_strtoul(buf, &rest, 10); - if (*rest) - return -EINVAL; - - psmouse->resetafter = value; - return count; -} static int psmouse_set_maxproto(const char *val, struct kernel_param *kp) { diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index e312a6b41681..45d2bd774f00 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h @@ -86,24 +86,37 @@ int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command); int psmouse_reset(struct psmouse *psmouse); void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution); -ssize_t psmouse_attr_show_helper(struct device *dev, char *buf, - ssize_t (*handler)(struct psmouse *, char *)); -ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t count, - ssize_t (*handler)(struct psmouse *, const char *, size_t)); - -#define PSMOUSE_DEFINE_ATTR(_name) \ -static ssize_t psmouse_attr_show_##_name(struct psmouse *, char *); \ -static ssize_t psmouse_attr_set_##_name(struct psmouse *, const char *, size_t);\ -static ssize_t psmouse_do_show_##_name(struct device *d, struct device_attribute *attr, char *b) \ -{ \ - return psmouse_attr_show_helper(d, b, psmouse_attr_show_##_name); \ -} \ -static ssize_t psmouse_do_set_##_name(struct device *d, struct device_attribute *attr, const char *b, size_t s)\ -{ \ - return psmouse_attr_set_helper(d, b, s, psmouse_attr_set_##_name); \ -} \ -static struct device_attribute psmouse_attr_##_name = \ - __ATTR(_name, S_IWUSR | S_IRUGO, \ - psmouse_do_show_##_name, psmouse_do_set_##_name); + +struct psmouse_attribute { + struct device_attribute dattr; + void *data; + ssize_t (*show)(struct psmouse *psmouse, void *data, char *buf); + ssize_t (*set)(struct psmouse *psmouse, void *data, + const char *buf, size_t count); +}; +#define to_psmouse_attr(a) container_of((a), struct psmouse_attribute, dattr) + +ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *attr, + char *buf); +ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count); + +#define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \ +static ssize_t _show(struct psmouse *, void *data, char *); \ +static ssize_t _set(struct psmouse *, void *data, const char *, size_t); \ +static struct psmouse_attribute psmouse_attr_##_name = { \ + .dattr = { \ + .attr = { \ + .name = __stringify(_name), \ + .mode = _mode, \ + .owner = THIS_MODULE, \ + }, \ + .show = psmouse_attr_show_helper, \ + .store = psmouse_attr_set_helper, \ + }, \ + .data = _data, \ + .show = _show, \ + .set = _set, \ +} #endif /* _PSMOUSE_H */ diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index aee3b24a9102..b4898d8a68e2 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c @@ -19,54 +19,6 @@ #include "psmouse.h" #include "trackpoint.h" -PSMOUSE_DEFINE_ATTR(sensitivity); -PSMOUSE_DEFINE_ATTR(speed); -PSMOUSE_DEFINE_ATTR(inertia); -PSMOUSE_DEFINE_ATTR(reach); -PSMOUSE_DEFINE_ATTR(draghys); -PSMOUSE_DEFINE_ATTR(mindrag); -PSMOUSE_DEFINE_ATTR(thresh); -PSMOUSE_DEFINE_ATTR(upthresh); -PSMOUSE_DEFINE_ATTR(ztime); -PSMOUSE_DEFINE_ATTR(jenks); -PSMOUSE_DEFINE_ATTR(press_to_select); -PSMOUSE_DEFINE_ATTR(skipback); -PSMOUSE_DEFINE_ATTR(ext_dev); - -#define MAKE_ATTR_READ(_item) \ - static ssize_t psmouse_attr_show_##_item(struct psmouse *psmouse, char *buf) \ - { \ - struct trackpoint_data *tp = psmouse->private; \ - return sprintf(buf, "%lu\n", (unsigned long)tp->_item); \ - } - -#define MAKE_ATTR_WRITE(_item, command) \ - static ssize_t psmouse_attr_set_##_item(struct psmouse *psmouse, const char *buf, size_t count) \ - { \ - char *rest; \ - unsigned long value; \ - struct trackpoint_data *tp = psmouse->private; \ - value = simple_strtoul(buf, &rest, 10); \ - if (*rest) \ - return -EINVAL; \ - tp->_item = value; \ - trackpoint_write(&psmouse->ps2dev, command, tp->_item); \ - return count; \ - } - -#define MAKE_ATTR_TOGGLE(_item, command, mask) \ - static ssize_t psmouse_attr_set_##_item(struct psmouse *psmouse, const char *buf, size_t count) \ - { \ - unsigned char toggle; \ - struct trackpoint_data *tp = psmouse->private; \ - toggle = (buf[0] == '1') ? 1 : 0; \ - if (toggle != tp->_item) { \ - tp->_item = toggle; \ - trackpoint_toggle_bit(&psmouse->ps2dev, command, mask); \ - } \ - return count; \ - } - /* * Device IO: read, write and toggle bit */ @@ -108,59 +60,114 @@ static int trackpoint_toggle_bit(struct ps2dev *ps2dev, unsigned char loc, unsig return 0; } -MAKE_ATTR_WRITE(sensitivity, TP_SENS); -MAKE_ATTR_READ(sensitivity); - -MAKE_ATTR_WRITE(speed, TP_SPEED); -MAKE_ATTR_READ(speed); -MAKE_ATTR_WRITE(inertia, TP_INERTIA); -MAKE_ATTR_READ(inertia); +/* + * Trackpoint-specific attributes + */ +struct trackpoint_attr_data { + size_t field_offset; + unsigned char command; + unsigned char mask; +}; -MAKE_ATTR_WRITE(reach, TP_REACH); -MAKE_ATTR_READ(reach); +static ssize_t trackpoint_show_int_attr(struct psmouse *psmouse, void *data, char *buf) +{ + struct trackpoint_data *tp = psmouse->private; + struct trackpoint_attr_data *attr = data; + unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset); -MAKE_ATTR_WRITE(draghys, TP_DRAGHYS); -MAKE_ATTR_READ(draghys); + return sprintf(buf, "%u\n", *field); +} -MAKE_ATTR_WRITE(mindrag, TP_MINDRAG); -MAKE_ATTR_READ(mindrag); +static ssize_t trackpoint_set_int_attr(struct psmouse *psmouse, void *data, + const char *buf, size_t count) +{ + struct trackpoint_data *tp = psmouse->private; + struct trackpoint_attr_data *attr = data; + unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset); + unsigned long value; + char *rest; -MAKE_ATTR_WRITE(thresh, TP_THRESH); -MAKE_ATTR_READ(thresh); + value = simple_strtoul(buf, &rest, 10); + if (*rest || value > 255) + return -EINVAL; -MAKE_ATTR_WRITE(upthresh, TP_UP_THRESH); -MAKE_ATTR_READ(upthresh); + *field = value; + trackpoint_write(&psmouse->ps2dev, attr->command, value); -MAKE_ATTR_WRITE(ztime, TP_Z_TIME); -MAKE_ATTR_READ(ztime); + return count; +} -MAKE_ATTR_WRITE(jenks, TP_JENKS_CURV); -MAKE_ATTR_READ(jenks); +#define TRACKPOINT_INT_ATTR(_name, _command) \ + static struct trackpoint_attr_data trackpoint_attr_##_name = { \ + .field_offset = offsetof(struct trackpoint_data, _name), \ + .command = _command, \ + }; \ + PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO, \ + &trackpoint_attr_##_name, \ + trackpoint_show_int_attr, trackpoint_set_int_attr) + +static ssize_t trackpoint_set_bit_attr(struct psmouse *psmouse, void *data, + const char *buf, size_t count) +{ + struct trackpoint_data *tp = psmouse->private; + struct trackpoint_attr_data *attr = data; + unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset); + unsigned long value; + char *rest; + + value = simple_strtoul(buf, &rest, 10); + if (*rest || value > 1) + return -EINVAL; + + if (*field != value) { + *field = value; + trackpoint_toggle_bit(&psmouse->ps2dev, attr->command, attr->mask); + } -MAKE_ATTR_TOGGLE(press_to_select, TP_TOGGLE_PTSON, TP_MASK_PTSON); -MAKE_ATTR_READ(press_to_select); + return count; +} -MAKE_ATTR_TOGGLE(skipback, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK); -MAKE_ATTR_READ(skipback); -MAKE_ATTR_TOGGLE(ext_dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV); -MAKE_ATTR_READ(ext_dev); +#define TRACKPOINT_BIT_ATTR(_name, _command, _mask) \ + static struct trackpoint_attr_data trackpoint_attr_##_name = { \ + .field_offset = offsetof(struct trackpoint_data, _name), \ + .command = _command, \ + .mask = _mask, \ + }; \ + PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO, \ + &trackpoint_attr_##_name, \ + trackpoint_show_int_attr, trackpoint_set_bit_attr) + +TRACKPOINT_INT_ATTR(sensitivity, TP_SENS); +TRACKPOINT_INT_ATTR(speed, TP_SPEED); +TRACKPOINT_INT_ATTR(inertia, TP_INERTIA); +TRACKPOINT_INT_ATTR(reach, TP_REACH); +TRACKPOINT_INT_ATTR(draghys, TP_DRAGHYS); +TRACKPOINT_INT_ATTR(mindrag, TP_MINDRAG); +TRACKPOINT_INT_ATTR(thresh, TP_THRESH); +TRACKPOINT_INT_ATTR(upthresh, TP_UP_THRESH); +TRACKPOINT_INT_ATTR(ztime, TP_Z_TIME); +TRACKPOINT_INT_ATTR(jenks, TP_JENKS_CURV); + +TRACKPOINT_BIT_ATTR(press_to_select, TP_TOGGLE_PTSON, TP_MASK_PTSON); +TRACKPOINT_BIT_ATTR(skipback, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK); +TRACKPOINT_BIT_ATTR(ext_dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV); static struct attribute *trackpoint_attrs[] = { - &psmouse_attr_sensitivity.attr, - &psmouse_attr_speed.attr, - &psmouse_attr_inertia.attr, - &psmouse_attr_reach.attr, - &psmouse_attr_draghys.attr, - &psmouse_attr_mindrag.attr, - &psmouse_attr_thresh.attr, - &psmouse_attr_upthresh.attr, - &psmouse_attr_ztime.attr, - &psmouse_attr_jenks.attr, - &psmouse_attr_press_to_select.attr, - &psmouse_attr_skipback.attr, - &psmouse_attr_ext_dev.attr, + &psmouse_attr_sensitivity.dattr.attr, + &psmouse_attr_speed.dattr.attr, + &psmouse_attr_inertia.dattr.attr, + &psmouse_attr_reach.dattr.attr, + &psmouse_attr_draghys.dattr.attr, + &psmouse_attr_mindrag.dattr.attr, + &psmouse_attr_thresh.dattr.attr, + &psmouse_attr_upthresh.dattr.attr, + &psmouse_attr_ztime.dattr.attr, + &psmouse_attr_jenks.dattr.attr, + &psmouse_attr_press_to_select.dattr.attr, + &psmouse_attr_skipback.dattr.attr, + &psmouse_attr_ext_dev.dattr.attr, NULL }; -- cgit v1.2.3 From e6c047b98bbd09473c586744c681e877ebf954ff Mon Sep 17 00:00:00 2001 From: Vojtech Pavlik Date: Sun, 4 Sep 2005 01:40:43 -0500 Subject: Input: ALPS - fix wheel decoding Signed-off-by: Vojtech Pavlik Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/alps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') 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) input_report_key(dev, BTN_TOOL_FINGER, z > 0); if (priv->i->flags & ALPS_WHEEL) - input_report_rel(dev, REL_WHEEL, ((packet[0] >> 4) & 0x07) | ((packet[2] >> 2) & 0x08)); + input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07)); if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { input_report_key(dev, BTN_FORWARD, forward); -- cgit v1.2.3 From d2b5ffca73594e4046f405e3ef2438ce41f76fb2 Mon Sep 17 00:00:00 2001 From: Vojtech Pavlik Date: Sun, 4 Sep 2005 01:40:55 -0500 Subject: Input: psmouse - add new Logitech wheel mouse model Signed-off-by: Vojtech Pavlik Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/logips2pp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/input') diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index e65c2798a491..7df96525222e 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c @@ -223,6 +223,7 @@ static struct ps2pp_info *get_model_info(unsigned char model) { 80, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL }, { 81, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, { 83, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, + { 86, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, { 88, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, { 96, 0, 0 }, { 97, PS2PP_KIND_TP3, PS2PP_WHEEL | PS2PP_HWHEEL }, -- cgit v1.2.3 From 4cee99564db7f65a6f88e4b752da52768cde3802 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Sun, 4 Sep 2005 01:41:14 -0500 Subject: Input: fix checking whether new keycode fits size-wise When dev->keycodesize == sizeof(int) the old code produces incorrect result. Signed-off-by: Ian Campbell Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 20e3a165989f..3a8314bb7902 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -320,7 +320,7 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL; if (get_user(v, ip + 1)) return -EFAULT; if (v < 0 || v > KEY_MAX) return -EINVAL; - if (v >> (dev->keycodesize * 8)) return -EINVAL; + if (dev->keycodesize < sizeof(v) && (v >> (dev->keycodesize * 8))) return -EINVAL; u = SET_INPUT_KEYCODE(dev, t, v); clear_bit(u, dev->keybit); set_bit(v, dev->keybit); -- cgit v1.2.3 From 0854e52d86080c1043bc8988daef2ebda4775f64 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 4 Sep 2005 01:41:27 -0500 Subject: Input: i8042 - clean up initialization code; abort if we can't create all ports. Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042.c | 178 +++++++++++++++++++++++++------------------- 1 file changed, 100 insertions(+), 78 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 708a1d3beab9..f0d9c5f9cc36 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -338,10 +338,10 @@ static int i8042_open(struct serio *serio) return 0; -activate_fail: + activate_fail: free_irq(port->irq, i8042_request_irq_cookie); -irq_fail: + irq_fail: serio_unregister_port_delayed(serio); return -1; @@ -485,7 +485,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs) serio_interrupt(port->serio, data, dfl, regs); ret = 1; -out: + out: return IRQ_RETVAL(ret); } @@ -552,7 +552,7 @@ static int i8042_enable_mux_ports(void) * Enable all muxed ports. */ - for (i = 0; i < 4; i++) { + for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { i8042_command(¶m, I8042_CMD_MUX_PFX + i); i8042_command(¶m, I8042_CMD_AUX_ENABLE); } @@ -682,7 +682,7 @@ static int __init i8042_port_register(struct i8042_port *port) kfree(port->serio); port->serio = NULL; i8042_ctr |= port->disable; - return -1; + return -EIO; } printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n", @@ -977,80 +977,83 @@ static struct device_driver i8042_driver = { .shutdown = i8042_shutdown, }; -static void __init i8042_create_kbd_port(void) +static int __init i8042_create_kbd_port(void) { struct serio *serio; struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; - serio = kmalloc(sizeof(struct serio), GFP_KERNEL); - if (serio) { - memset(serio, 0, sizeof(struct serio)); - serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL; - serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; - serio->open = i8042_open; - serio->close = i8042_close; - serio->start = i8042_start; - serio->stop = i8042_stop; - serio->port_data = port; - serio->dev.parent = &i8042_platform_device->dev; - strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name)); - strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys)); - - port->serio = serio; - i8042_port_register(port); - } + serio = kcalloc(1, sizeof(struct serio), GFP_KERNEL); + if (!serio) + return -ENOMEM; + + serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL; + serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; + serio->open = i8042_open; + serio->close = i8042_close; + serio->start = i8042_start; + serio->stop = i8042_stop; + serio->port_data = port; + serio->dev.parent = &i8042_platform_device->dev; + strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name)); + strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys)); + + port->serio = serio; + + return i8042_port_register(port); } -static void __init i8042_create_aux_port(void) +static int __init i8042_create_aux_port(void) { struct serio *serio; struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO]; - serio = kmalloc(sizeof(struct serio), GFP_KERNEL); - if (serio) { - memset(serio, 0, sizeof(struct serio)); - serio->id.type = SERIO_8042; - serio->write = i8042_aux_write; - serio->open = i8042_open; - serio->close = i8042_close; - serio->start = i8042_start; - serio->stop = i8042_stop; - serio->port_data = port; - serio->dev.parent = &i8042_platform_device->dev; - strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name)); - strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); - - port->serio = serio; - i8042_port_register(port); - } + serio = kcalloc(1, sizeof(struct serio), GFP_KERNEL); + if (!serio) + return -ENOMEM; + + serio->id.type = SERIO_8042; + serio->write = i8042_aux_write; + serio->open = i8042_open; + serio->close = i8042_close; + serio->start = i8042_start; + serio->stop = i8042_stop; + serio->port_data = port; + serio->dev.parent = &i8042_platform_device->dev; + strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name)); + strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); + + port->serio = serio; + + return i8042_port_register(port); } -static void __init i8042_create_mux_port(int index) +static int __init i8042_create_mux_port(int index) { struct serio *serio; struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index]; - serio = kmalloc(sizeof(struct serio), GFP_KERNEL); - if (serio) { - memset(serio, 0, sizeof(struct serio)); - serio->id.type = SERIO_8042; - serio->write = i8042_aux_write; - serio->open = i8042_open; - serio->close = i8042_close; - serio->start = i8042_start; - serio->stop = i8042_stop; - serio->port_data = port; - serio->dev.parent = &i8042_platform_device->dev; - snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index); - snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1); - - *port = i8042_ports[I8042_AUX_PORT_NO]; - port->exists = 0; - snprintf(port->name, sizeof(port->name), "AUX%d", index); - port->mux = index; - port->serio = serio; - i8042_port_register(port); - } + serio = kcalloc(1, sizeof(struct serio), GFP_KERNEL); + if (!serio) + return -ENOMEM; + + serio->id.type = SERIO_8042; + serio->write = i8042_aux_write; + serio->open = i8042_open; + serio->close = i8042_close; + serio->start = i8042_start; + serio->stop = i8042_stop; + serio->port_data = port; + serio->dev.parent = &i8042_platform_device->dev; + snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index); + snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1); + + *port = i8042_ports[I8042_AUX_PORT_NO]; + port->exists = 0; + snprintf(port->name, sizeof(port->name), "AUX%d", index); + port->mux = index; + port->serio = serio; + + return i8042_port_register(port); } static int __init i8042_init(void) @@ -1070,36 +1073,55 @@ static int __init i8042_init(void) i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ; if (i8042_controller_init()) { - i8042_platform_exit(); - return -ENODEV; + err = -ENODEV; + goto err_platform_exit; } err = driver_register(&i8042_driver); - if (err) { - i8042_platform_exit(); - return err; - } + if (err) + goto err_controller_cleanup; i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0); if (IS_ERR(i8042_platform_device)) { - driver_unregister(&i8042_driver); - i8042_platform_exit(); - return PTR_ERR(i8042_platform_device); + err = PTR_ERR(i8042_platform_device); + goto err_unregister_driver; } if (!i8042_noaux && !i8042_check_aux()) { - if (!i8042_nomux && !i8042_check_mux()) - for (i = 0; i < I8042_NUM_MUX_PORTS; i++) - i8042_create_mux_port(i); - else - i8042_create_aux_port(); + if (!i8042_nomux && !i8042_check_mux()) { + for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { + err = i8042_create_mux_port(i); + if (err) + goto err_unregister_ports; + } + } else { + err = i8042_create_aux_port(); + if (err) + goto err_unregister_ports; + } } - i8042_create_kbd_port(); + err = i8042_create_kbd_port(); + if (err) + goto err_unregister_ports; mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); return 0; + + err_unregister_ports: + for (i = 0; i < I8042_NUM_PORTS; i++) + if (i8042_ports[i].serio) + serio_unregister_port(i8042_ports[i].serio); + platform_device_unregister(i8042_platform_device); + err_unregister_driver: + driver_unregister(&i8042_driver); + err_controller_cleanup: + i8042_controller_cleanup(); + err_platform_exit: + i8042_platform_exit(); + + return err; } static void __exit i8042_exit(void) -- cgit v1.2.3 From 8d5987a6e17fa36776a0c9964db0f24c3d070862 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 4 Sep 2005 01:41:38 -0500 Subject: Input: make i8042_platform_init return 'real' error code Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-io.h | 6 +++--- drivers/input/serio/i8042-ip22io.h | 2 +- drivers/input/serio/i8042-jazzio.h | 2 +- drivers/input/serio/i8042-sparcio.h | 12 ++++++------ drivers/input/serio/i8042-x86ia64io.h | 22 ++++++++++++---------- drivers/input/serio/i8042.c | 5 +++-- 6 files changed, 26 insertions(+), 23 deletions(-) (limited to 'drivers/input') 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) */ #if !defined(__sh__) && !defined(__alpha__) && !defined(__mips__) && !defined(CONFIG_PPC64) if (!request_region(I8042_DATA_REG, 16, "i8042")) - return -1; + return -EBUSY; #endif i8042_reset = 1; #if defined(CONFIG_PPC64) if (check_legacy_ioport(I8042_DATA_REG)) - return -1; + return -EBUSY; if (!request_region(I8042_DATA_REG, 16, "i8042")) - return -1; + return -EBUSY; #endif return 0; } 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) #if 0 /* XXX sgi_kh is a virtual address */ if (!request_mem_region(sgi_kh, sizeof(struct hpc_keyb), "i8042")) - return 1; + return -EBUSY; #endif 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) #if 0 /* XXX JAZZ_KEYBOARD_ADDRESS is a virtual address */ if (!request_mem_region(JAZZ_KEYBOARD_ADDRESS, 2, "i8042")) - return 1; + return -EBUSY; #endif 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) #define OBP_PS2MS_NAME1 "kdmouse" #define OBP_PS2MS_NAME2 "mouse" -static int i8042_platform_init(void) +static int __init i8042_platform_init(void) { #ifndef CONFIG_PCI - return -1; + return -ENODEV; #else char prop[128]; int len; @@ -59,14 +59,14 @@ static int i8042_platform_init(void) len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop)); if (len < 0) { printk("i8042: Cannot get name property of root OBP node.\n"); - return -1; + return -ENODEV; } if (strncmp(prop, "SUNW,JavaStation-1", len) == 0) { /* Hardcoded values for MrCoffee. */ i8042_kbd_irq = i8042_aux_irq = 13 | 0x20; kbd_iobase = ioremap(0x71300060, 8); if (!kbd_iobase) - return -1; + return -ENODEV; } else { struct linux_ebus *ebus; struct linux_ebus_device *edev; @@ -78,7 +78,7 @@ static int i8042_platform_init(void) goto edev_found; } } - return -1; + return -ENODEV; edev_found: for_each_edevchild(edev, child) { @@ -96,7 +96,7 @@ static int i8042_platform_init(void) i8042_aux_irq == -1) { printk("i8042: Error, 8042 device lacks both kbd and " "mouse nodes.\n"); - return -1; + return -ENODEV; } } diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 03877c84e6ff..02bc23142ce0 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -256,7 +256,7 @@ static void i8042_pnp_exit(void) } } -static int i8042_pnp_init(void) +static int __init i8042_pnp_init(void) { int result_kbd, result_aux; @@ -322,25 +322,29 @@ static int i8042_pnp_init(void) return 0; } +#else +static inline int i8042_pnp_init(void) { return 0; } +static inline void i8042_pnp_exit(void) { } #endif -static inline int i8042_platform_init(void) +static int __init i8042_platform_init(void) { + int retval; + /* * On ix86 platforms touching the i8042 data register region can do really * bad things. Because of this the region is always reserved on ix86 boxes. * * if (!request_region(I8042_DATA_REG, 16, "i8042")) - * return -1; + * return -EBUSY; */ i8042_kbd_irq = I8042_MAP_IRQ(1); i8042_aux_irq = I8042_MAP_IRQ(12); -#ifdef CONFIG_PNP - if (i8042_pnp_init()) - return -1; -#endif + retval = i8042_pnp_init(); + if (retval) + return retval; #if defined(__ia64__) i8042_reset = 1; @@ -354,14 +358,12 @@ static inline int i8042_platform_init(void) i8042_nomux = 1; #endif - return 0; + return retval; } static inline void i8042_platform_exit(void) { -#ifdef CONFIG_PNP i8042_pnp_exit(); -#endif } #endif /* _I8042_X86IA64IO_H */ diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index f0d9c5f9cc36..2a76d08c4d3e 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -1066,8 +1066,9 @@ static int __init i8042_init(void) init_timer(&i8042_timer); i8042_timer.function = i8042_timer_func; - if (i8042_platform_init()) - return -EBUSY; + err = i8042_platform_init(); + if (err) + return err; i8042_ports[I8042_AUX_PORT_NO].irq = I8042_AUX_IRQ; i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ; -- cgit v1.2.3 From c3d31e7f9a94800ba895a081e143e79954f6c62f Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 4 Sep 2005 01:41:51 -0500 Subject: Input: i8042 - fix IRQ printing when either KBD or AUX port is absent from ACPI/PNP tables. Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-x86ia64io.h | 39 ++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 14 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 02bc23142ce0..84a73bc6afdc 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -258,7 +258,8 @@ static void i8042_pnp_exit(void) static int __init i8042_pnp_init(void) { - int result_kbd, result_aux; + int result_kbd = 0, result_aux = 0; + char kbd_irq_str[4] = { 0 }, aux_irq_str[4] = { 0 }; if (i8042_nopnp) { printk(KERN_INFO "i8042: PNP detection disabled\n"); @@ -267,6 +268,7 @@ static int __init i8042_pnp_init(void) if ((result_kbd = pnp_register_driver(&i8042_pnp_kbd_driver)) >= 0) i8042_pnp_kbd_registered = 1; + if ((result_aux = pnp_register_driver(&i8042_pnp_aux_driver)) >= 0) i8042_pnp_aux_registered = 1; @@ -280,6 +282,25 @@ static int __init i8042_pnp_init(void) #endif } + if (result_kbd > 0) + snprintf(kbd_irq_str, sizeof(kbd_irq_str), + "%d", i8042_pnp_kbd_irq); + if (result_aux > 0) + snprintf(aux_irq_str, sizeof(aux_irq_str), + "%d", i8042_pnp_aux_irq); + + printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %s%s%s\n", + i8042_pnp_kbd_name, (result_kbd > 0 && result_aux > 0) ? "," : "", + i8042_pnp_aux_name, + i8042_pnp_data_reg, i8042_pnp_command_reg, + kbd_irq_str, (result_kbd > 0 && result_aux > 0) ? "," : "", + aux_irq_str); + +#if defined(__ia64__) + if (result_aux <= 0) + i8042_noaux = 1; +#endif + if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) && i8042_pnp_data_reg != i8042_data_reg) || !i8042_pnp_data_reg) { printk(KERN_WARNING "PNP: PS/2 controller has invalid data port %#x; using default %#x\n", @@ -295,30 +316,20 @@ static int __init i8042_pnp_init(void) } if (!i8042_pnp_kbd_irq) { - printk(KERN_WARNING "PNP: PS/2 controller doesn't have KBD irq; using default %#x\n", i8042_kbd_irq); + printk(KERN_WARNING "PNP: PS/2 controller doesn't have KBD irq; using default %d\n", i8042_kbd_irq); i8042_pnp_kbd_irq = i8042_kbd_irq; } - if (!i8042_pnp_aux_irq) { - printk(KERN_WARNING "PNP: PS/2 controller doesn't have AUX irq; using default %#x\n", i8042_aux_irq); + if (!i8042_noaux && !i8042_pnp_aux_irq) { + printk(KERN_WARNING "PNP: PS/2 controller doesn't have AUX irq; using default %d\n", i8042_aux_irq); i8042_pnp_aux_irq = i8042_aux_irq; } -#if defined(__ia64__) - if (result_aux <= 0) - i8042_noaux = 1; -#endif - i8042_data_reg = i8042_pnp_data_reg; i8042_command_reg = i8042_pnp_command_reg; i8042_kbd_irq = i8042_pnp_kbd_irq; i8042_aux_irq = i8042_pnp_aux_irq; - printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %d%s%d\n", - i8042_pnp_kbd_name, (result_kbd > 0 && result_aux > 0) ? "," : "", i8042_pnp_aux_name, - i8042_data_reg, i8042_command_reg, i8042_kbd_irq, - (result_aux > 0) ? "," : "", i8042_aux_irq); - return 0; } -- cgit v1.2.3 From 945ef0d428bc33c639e49d27fb8cc765adec3fdf Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 4 Sep 2005 01:42:00 -0500 Subject: Input: i8042 - add i8042.nokbd module option to allow supressing creation of keyboard port. Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-x86ia64io.h | 4 +++- drivers/input/serio/i8042.c | 22 ++++++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 84a73bc6afdc..d5ea3cf09469 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -297,6 +297,8 @@ static int __init i8042_pnp_init(void) aux_irq_str); #if defined(__ia64__) + if (result_kbd <= 0) + i8042_nokbd = 1; if (result_aux <= 0) i8042_noaux = 1; #endif @@ -315,7 +317,7 @@ static int __init i8042_pnp_init(void) i8042_pnp_command_reg = i8042_command_reg; } - if (!i8042_pnp_kbd_irq) { + if (!i8042_nokbd && !i8042_pnp_kbd_irq) { printk(KERN_WARNING "PNP: PS/2 controller doesn't have KBD irq; using default %d\n", i8042_kbd_irq); i8042_pnp_kbd_irq = i8042_kbd_irq; } diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 2a76d08c4d3e..19ef35db342e 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -27,6 +27,10 @@ MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver"); MODULE_LICENSE("GPL"); +static unsigned int i8042_nokbd; +module_param_named(nokbd, i8042_nokbd, bool, 0); +MODULE_PARM_DESC(nokbd, "Do not probe or use KBD port."); + static unsigned int i8042_noaux; module_param_named(noaux, i8042_noaux, bool, 0); MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port."); @@ -1058,7 +1062,7 @@ static int __init i8042_create_mux_port(int index) static int __init i8042_init(void) { - int i; + int i, have_ports = 0; int err; dbg_init(); @@ -1100,11 +1104,20 @@ static int __init i8042_init(void) if (err) goto err_unregister_ports; } + have_ports = 1; } - err = i8042_create_kbd_port(); - if (err) - goto err_unregister_ports; + if (!i8042_nokbd) { + err = i8042_create_kbd_port(); + if (err) + goto err_unregister_ports; + have_ports = 1; + } + + if (!have_ports) { + err = -ENODEV; + goto err_unregister_device; + } mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); @@ -1114,6 +1127,7 @@ static int __init i8042_init(void) for (i = 0; i < I8042_NUM_PORTS; i++) if (i8042_ports[i].serio) serio_unregister_port(i8042_ports[i].serio); + err_unregister_device: platform_device_unregister(i8042_platform_device); err_unregister_driver: driver_unregister(&i8042_driver); -- cgit v1.2.3 From 7545c24c6a6ab62922266197a72119212280ea2a Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 4 Sep 2005 01:42:10 -0500 Subject: Input: i8042 - add Lifebook E4010 to MUX blacklist Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-x86ia64io.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index d5ea3cf09469..273bb3b08cfa 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -137,6 +137,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T3010"), }, }, + { + .ident = "Fujitsu-Siemens Lifebook E4010", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E4010"), + }, + }, { .ident = "Toshiba P10", .matches = { -- cgit v1.2.3 From 903b126bffb77dc313b7c2971880df408bf41a9e Mon Sep 17 00:00:00 2001 From: Vojtech Pavlik Date: Mon, 5 Sep 2005 00:11:41 -0500 Subject: Input: atkbd - handle keyboards generating scancode 0x7f Extend bat_xl handling to do err_xl handling, so that keyboards using 0x7f scancode for regular keys can work. Signed-off-by: Vojtech Pavlik Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/atkbd.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/input') 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 { unsigned char resend; unsigned char release; unsigned char bat_xl; + unsigned char err_xl; unsigned int last; unsigned long time; }; @@ -296,15 +297,18 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, if (atkbd->emul || !(code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1 || code == ATKBD_RET_HANGUEL || code == ATKBD_RET_HANJA || - code == ATKBD_RET_ERR || + (code == ATKBD_RET_ERR && !atkbd->err_xl) || (code == ATKBD_RET_BAT && !atkbd->bat_xl))) { atkbd->release = code >> 7; code &= 0x7f; } - if (!atkbd->emul && - (code & 0x7f) == (ATKBD_RET_BAT & 0x7f)) + if (!atkbd->emul) { + if ((code & 0x7f) == (ATKBD_RET_BAT & 0x7f)) atkbd->bat_xl = !atkbd->release; + if ((code & 0x7f) == (ATKBD_RET_ERR & 0x7f)) + atkbd->err_xl = !atkbd->release; + } } switch (code) { -- cgit v1.2.3 From fb76b099f86624d3c629cfab071aa2296f65b7bb Mon Sep 17 00:00:00 2001 From: Vojtech Pavlik Date: Mon, 5 Sep 2005 00:12:39 -0500 Subject: Input: iforce - use wait_event_interruptible_timeout The timeout while() loops in iforce-packets.c lack a set_current_state(TASK_INTERRUPTIBLE); call. The right solution is to replace them with wait_event_interruptible_timeout(). Reported-by: Nishanth Aravamudan Signed-off-by: Vojtech Pavlik Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-packets.c | 32 ++++++-------------------- drivers/input/joystick/iforce/iforce-usb.c | 1 + 2 files changed, 8 insertions(+), 25 deletions(-) (limited to 'drivers/input') 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, int iforce_get_id_packet(struct iforce *iforce, char *packet) { - DECLARE_WAITQUEUE(wait, current); - int timeout = HZ; /* 1 second */ - switch (iforce->bus) { case IFORCE_USB: @@ -260,22 +257,13 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet) iforce->cr.bRequest = packet[0]; iforce->ctrl->dev = iforce->usbdev; - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&iforce->wait, &wait); - - if (usb_submit_urb(iforce->ctrl, GFP_ATOMIC)) { - set_current_state(TASK_RUNNING); - remove_wait_queue(&iforce->wait, &wait); + if (usb_submit_urb(iforce->ctrl, GFP_ATOMIC)) return -1; - } - while (timeout && iforce->ctrl->status == -EINPROGRESS) - timeout = schedule_timeout(timeout); + wait_event_interruptible_timeout(iforce->wait, + iforce->ctrl->status != -EINPROGRESS, HZ); - set_current_state(TASK_RUNNING); - remove_wait_queue(&iforce->wait, &wait); - - if (!timeout) { + if (iforce->ctrl->status != -EINPROGRESS) { usb_unlink_urb(iforce->ctrl); return -1; } @@ -290,16 +278,10 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet) iforce->expect_packet = FF_CMD_QUERY; iforce_send_packet(iforce, FF_CMD_QUERY, packet); - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&iforce->wait, &wait); - - while (timeout && iforce->expect_packet) - timeout = schedule_timeout(timeout); - - set_current_state(TASK_RUNNING); - remove_wait_queue(&iforce->wait, &wait); + wait_event_interruptible_timeout(iforce->wait, + !iforce->expect_packet, HZ); - if (!timeout) { + if (iforce->expect_packet) { iforce->expect_packet = 0; return -1; } 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) goto exit; } + wake_up(&iforce->wait); iforce_process_packet(iforce, (iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1, regs); -- cgit v1.2.3 From 8d9a9ae3b2941d94bb0023a3aca2ec2bfa83d0c2 Mon Sep 17 00:00:00 2001 From: Vojtech Pavlik Date: Mon, 5 Sep 2005 00:12:47 -0500 Subject: Input: sunkbd - extend mapping to handle Type-6 Sun keyboards Map an unmarked key at 'Esc' position to KEY_MACRO Signed-off-by: Vojtech Pavlik Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/sunkbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') 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); MODULE_LICENSE("GPL"); static unsigned char sunkbd_keycode[128] = { - 0,128,114,129,115, 59, 60, 68, 61, 87, 62, 88, 63,100, 64, 0, + 0,128,114,129,115, 59, 60, 68, 61, 87, 62, 88, 63,100, 64,112, 65, 66, 67, 56,103,119, 99, 70,105,130,131,108,106, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 41, 14,110,113, 98, 55, 116,132, 83,133,102, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -- cgit v1.2.3 From 01703597ead8194b46932ba2bcda897e872e91e0 Mon Sep 17 00:00:00 2001 From: "viro@ZenIV.linux.org.uk" Date: Fri, 9 Sep 2005 20:29:12 +0100 Subject: [PATCH] trivial __user annotations (evdev) Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/input/evdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 19c14c4beb44..60b696e9336b 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -509,7 +509,7 @@ do { \ int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \ if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \ for (i = 0; i < len / sizeof(compat_long_t); i++) \ - if (copy_to_user((compat_long_t*) p + i, \ + if (copy_to_user((compat_long_t __user *) p + i, \ (compat_long_t*) (bit) + i + 1 - ((i % 2) << 1), \ sizeof(compat_long_t))) \ return -EFAULT; \ -- cgit v1.2.3 From d39969deee4b541be4ee5789a2e4c14511c886e2 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 10 Sep 2005 12:04:42 -0500 Subject: Input: i8042 - use kzalloc instead of kcalloc Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 19ef35db342e..40d451ce07ff 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -986,7 +986,7 @@ static int __init i8042_create_kbd_port(void) struct serio *serio; struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; - serio = kcalloc(1, sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(struct serio), GFP_KERNEL); if (!serio) return -ENOMEM; @@ -1011,7 +1011,7 @@ static int __init i8042_create_aux_port(void) struct serio *serio; struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO]; - serio = kcalloc(1, sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(struct serio), GFP_KERNEL); if (!serio) return -ENOMEM; @@ -1036,7 +1036,7 @@ static int __init i8042_create_mux_port(int index) struct serio *serio; struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index]; - serio = kcalloc(1, sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(struct serio), GFP_KERNEL); if (!serio) return -ENOMEM; -- cgit v1.2.3