projects
/
cascardo
/
linux.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Merge commit 'v2.6.32-rc5' into for-linus
[cascardo/linux.git]
/
drivers
/
input
/
keyboard
/
atkbd.c
diff --git
a/drivers/input/keyboard/atkbd.c
b/drivers/input/keyboard/atkbd.c
index
6c6a09b
..
4452eab
100644
(file)
--- a/
drivers/input/keyboard/atkbd.c
+++ b/
drivers/input/keyboard/atkbd.c
@@
-68,7
+68,9
@@
MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and
* are loadable via a userland utility.
*/
* are loadable via a userland utility.
*/
-static const unsigned short atkbd_set2_keycode[512] = {
+#define ATKBD_KEYMAP_SIZE 512
+
+static const unsigned short atkbd_set2_keycode[ATKBD_KEYMAP_SIZE] = {
#ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES
#ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES
@@
-99,7
+101,7
@@
static const unsigned short atkbd_set2_keycode[512] = {
#endif
};
#endif
};
-static const unsigned short atkbd_set3_keycode[
512
] = {
+static const unsigned short atkbd_set3_keycode[
ATKBD_KEYMAP_SIZE
] = {
0, 0, 0, 0, 0, 0, 0, 59, 1,138,128,129,130, 15, 41, 60,
131, 29, 42, 86, 58, 16, 2, 61,133, 56, 44, 31, 30, 17, 3, 62,
0, 0, 0, 0, 0, 0, 0, 59, 1,138,128,129,130, 15, 41, 60,
131, 29, 42, 86, 58, 16, 2, 61,133, 56, 44, 31, 30, 17, 3, 62,
@@
-200,8
+202,8
@@
struct atkbd {
char phys[32];
unsigned short id;
char phys[32];
unsigned short id;
- unsigned short keycode[
512
];
- DECLARE_BITMAP(force_release_mask,
512
);
+ unsigned short keycode[
ATKBD_KEYMAP_SIZE
];
+ DECLARE_BITMAP(force_release_mask,
ATKBD_KEYMAP_SIZE
);
unsigned char set;
unsigned char translated;
unsigned char extra;
unsigned char set;
unsigned char translated;
unsigned char extra;
@@
-227,10
+229,11
@@
struct atkbd {
};
/*
};
/*
- * System-specific ke
t
ymap fixup routine
+ * System-specific keymap fixup routine
*/
static void (*atkbd_platform_fixup)(struct atkbd *, const void *data);
static void *atkbd_platform_fixup_data;
*/
static void (*atkbd_platform_fixup)(struct atkbd *, const void *data);
static void *atkbd_platform_fixup_data;
+static unsigned int (*atkbd_platform_scancode_fixup)(struct atkbd *, unsigned int);
static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
ssize_t (*handler)(struct atkbd *, char *));
static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
ssize_t (*handler)(struct atkbd *, char *));
@@
-253,6
+256,7
@@
static struct device_attribute atkbd_attr_##_name = \
__ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name);
ATKBD_DEFINE_ATTR(extra);
__ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name);
ATKBD_DEFINE_ATTR(extra);
+ATKBD_DEFINE_ATTR(force_release);
ATKBD_DEFINE_ATTR(scroll);
ATKBD_DEFINE_ATTR(set);
ATKBD_DEFINE_ATTR(softrepeat);
ATKBD_DEFINE_ATTR(scroll);
ATKBD_DEFINE_ATTR(set);
ATKBD_DEFINE_ATTR(softrepeat);
@@
-272,6
+276,7
@@
ATKBD_DEFINE_RO_ATTR(err_count);
static struct attribute *atkbd_attributes[] = {
&atkbd_attr_extra.attr,
static struct attribute *atkbd_attributes[] = {
&atkbd_attr_extra.attr,
+ &atkbd_attr_force_release.attr,
&atkbd_attr_scroll.attr,
&atkbd_attr_set.attr,
&atkbd_attr_softrepeat.attr,
&atkbd_attr_scroll.attr,
&atkbd_attr_set.attr,
&atkbd_attr_softrepeat.attr,
@@
-389,6
+394,9
@@
static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
input_event(dev, EV_MSC, MSC_RAW, code);
input_event(dev, EV_MSC, MSC_RAW, code);
+ if (atkbd_platform_scancode_fixup)
+ code = atkbd_platform_scancode_fixup(atkbd, code);
+
if (atkbd->translated) {
if (atkbd->emul || atkbd_need_xlate(atkbd->xl_bit, code)) {
if (atkbd->translated) {
if (atkbd->emul || atkbd_need_xlate(atkbd->xl_bit, code)) {
@@
-570,11
+578,22
@@
static void atkbd_event_work(struct work_struct *work)
mutex_lock(&atkbd->event_mutex);
mutex_lock(&atkbd->event_mutex);
- if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask))
- atkbd_set_leds(atkbd);
+ if (!atkbd->enabled) {
+ /*
+ * Serio ports are resumed asynchronously so while driver core
+ * thinks that device is already fully operational in reality
+ * it may not be ready yet. In this case we need to keep
+ * rescheduling till reconnect completes.
+ */
+ schedule_delayed_work(&atkbd->event_work,
+ msecs_to_jiffies(100));
+ } else {
+ if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask))
+ atkbd_set_leds(atkbd);
- if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask))
- atkbd_set_repeat_rate(atkbd);
+ if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask))
+ atkbd_set_repeat_rate(atkbd);
+ }
mutex_unlock(&atkbd->event_mutex);
}
mutex_unlock(&atkbd->event_mutex);
}
@@
-766,13
+785,13
@@
static int atkbd_select_set(struct atkbd *atkbd, int target_set, int allow_extra
return 3;
}
return 3;
}
-static int atkbd_
activ
ate(struct atkbd *atkbd)
+static int atkbd_
reset_st
ate(struct atkbd *atkbd)
{
{
- struct ps2dev *ps2dev = &atkbd->ps2dev;
+
struct ps2dev *ps2dev = &atkbd->ps2dev;
unsigned char param[1];
/*
unsigned char param[1];
/*
- * Set the LEDs to a
defined state
.
+ * Set the LEDs to a
predefined state (all off)
.
*/
param[0] = 0;
*/
param[0] = 0;
@@
-787,6
+806,13
@@
static int atkbd_activate(struct atkbd *atkbd)
if (ps2_command(ps2dev, param, ATKBD_CMD_SETREP))
return -1;
if (ps2_command(ps2dev, param, ATKBD_CMD_SETREP))
return -1;
+ return 0;
+}
+
+static int atkbd_activate(struct atkbd *atkbd)
+{
+ struct ps2dev *ps2dev = &atkbd->ps2dev;
+
/*
* Enable the keyboard to receive keystrokes.
*/
/*
* Enable the keyboard to receive keystrokes.
*/
@@
-864,29
+890,6
@@
static unsigned int atkbd_hp_forced_release_keys[] = {
0x94, -1U
};
0x94, -1U
};
-/*
- * Inventec system with broken key release on volume keys
- */
-static unsigned int atkbd_inventec_forced_release_keys[] = {
- 0xae, 0xb0, -1U
-};
-
-/*
- * Perform fixup for HP Pavilion ZV6100 laptop that doesn't generate release
- * for its volume buttons
- */
-static unsigned int atkbd_hp_zv6100_forced_release_keys[] = {
- 0xae, 0xb0, -1U
-};
-
-/*
- * Perform fixup for HP (Compaq) Presario R4000 R4100 R4200 that don't generate
- * release for their volume buttons
- */
-static unsigned int atkbd_hp_r4000_forced_release_keys[] = {
- 0xae, 0xb0, -1U
-};
-
/*
* Samsung NC10,NC20 with Fn+F? key release not working
*/
/*
* Samsung NC10,NC20 with Fn+F? key release not working
*/
@@
-894,14
+897,6
@@
static unsigned int atkbd_samsung_forced_release_keys[] = {
0x82, 0x83, 0x84, 0x86, 0x88, 0x89, 0xb3, 0xf7, 0xf9, -1U
};
0x82, 0x83, 0x84, 0x86, 0x88, 0x89, 0xb3, 0xf7, 0xf9, -1U
};
-/*
- * The volume up and volume down special keys on a Fujitsu Amilo PA 1510 laptop
- * do not generate release events so we have to do it ourselves.
- */
-static unsigned int atkbd_amilo_pa1510_forced_release_keys[] = {
- 0xb0, 0xae, -1U
-};
-
/*
* Amilo Pi 3525 key release for Fn+Volume keys not working
*/
/*
* Amilo Pi 3525 key release for Fn+Volume keys not working
*/
@@
-923,6
+918,30
@@
static unsigned int atkdb_soltech_ta12_forced_release_keys[] = {
0xa0, 0xae, 0xb0, -1U
};
0xa0, 0xae, 0xb0, -1U
};
+/*
+ * Many notebooks don't send key release event for volume up/down
+ * keys, with key list below common among them
+ */
+static unsigned int atkbd_volume_forced_release_keys[] = {
+ 0xae, 0xb0, -1U
+};
+
+/*
+ * OQO 01+ multimedia keys (64--66) generate e0 6x upon release whereas
+ * they should be generating e4-e6 (0x80 | code).
+ */
+static unsigned int atkbd_oqo_01plus_scancode_fixup(struct atkbd *atkbd,
+ unsigned int code)
+{
+ if (atkbd->translated && atkbd->emul == 1 &&
+ (code == 0x64 || code == 0x65 || code == 0x66)) {
+ atkbd->emul = 0;
+ code |= 0x80;
+ }
+
+ return code;
+}
+
/*
* atkbd_set_keycode_table() initializes keyboard's keycode table
* according to the selected scancode set
/*
* atkbd_set_keycode_table() initializes keyboard's keycode table
* according to the selected scancode set
@@
-934,7
+953,7
@@
static void atkbd_set_keycode_table(struct atkbd *atkbd)
int i, j;
memset(atkbd->keycode, 0, sizeof(atkbd->keycode));
int i, j;
memset(atkbd->keycode, 0, sizeof(atkbd->keycode));
- bitmap_zero(atkbd->force_release_mask,
512
);
+ bitmap_zero(atkbd->force_release_mask,
ATKBD_KEYMAP_SIZE
);
if (atkbd->translated) {
for (i = 0; i < 128; i++) {
if (atkbd->translated) {
for (i = 0; i < 128; i++) {
@@
-1041,7
+1060,7
@@
static void atkbd_set_device_attrs(struct atkbd *atkbd)
input_dev->keycodesize = sizeof(unsigned short);
input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
input_dev->keycodesize = sizeof(unsigned short);
input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
- for (i = 0; i <
512
; i++)
+ for (i = 0; i <
ATKBD_KEYMAP_SIZE
; i++)
if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL)
__set_bit(atkbd->keycode[i], input_dev->keybit);
}
if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL)
__set_bit(atkbd->keycode[i], input_dev->keybit);
}
@@
-1100,6
+1119,7
@@
static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
}
atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra);
}
atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra);
+ atkbd_reset_state(atkbd);
atkbd_activate(atkbd);
} else {
atkbd_activate(atkbd);
} else {
@@
-1154,14
+1174,6
@@
static int atkbd_reconnect(struct serio *serio)
return -1;
atkbd_activate(atkbd);
return -1;
atkbd_activate(atkbd);
-
-/*
- * Restore repeat rate and LEDs (that were reset by atkbd_activate)
- * to pre-resume state
- */
- if (!atkbd->softrepeat)
- atkbd_set_repeat_rate(atkbd);
- atkbd_set_leds(atkbd);
}
atkbd_enable(atkbd);
}
atkbd_enable(atkbd);
@@
-1288,6
+1300,7
@@
static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun
atkbd->dev = new_dev;
atkbd->set = atkbd_select_set(atkbd, atkbd->set, value);
atkbd->dev = new_dev;
atkbd->set = atkbd_select_set(atkbd, atkbd->set, value);
+ atkbd_reset_state(atkbd);
atkbd_activate(atkbd);
atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd);
atkbd_activate(atkbd);
atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd);
@@
-1309,6
+1322,33
@@
static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun
return count;
}
return count;
}
+static ssize_t atkbd_show_force_release(struct atkbd *atkbd, char *buf)
+{
+ size_t len = bitmap_scnlistprintf(buf, PAGE_SIZE - 2,
+ atkbd->force_release_mask, ATKBD_KEYMAP_SIZE);
+
+ buf[len++] = '\n';
+ buf[len] = '\0';
+
+ return len;
+}
+
+static ssize_t atkbd_set_force_release(struct atkbd *atkbd,
+ const char *buf, size_t count)
+{
+ /* 64 bytes on stack should be acceptable */
+ DECLARE_BITMAP(new_mask, ATKBD_KEYMAP_SIZE);
+ int err;
+
+ err = bitmap_parselist(buf, new_mask, ATKBD_KEYMAP_SIZE);
+ if (err)
+ return err;
+
+ memcpy(atkbd->force_release_mask, new_mask, sizeof(atkbd->force_release_mask));
+ return count;
+}
+
+
static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf)
{
return sprintf(buf, "%d\n", atkbd->scroll ? 1 : 0);
static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf)
{
return sprintf(buf, "%d\n", atkbd->scroll ? 1 : 0);
@@
-1507,6
+1547,13
@@
static int __init atkbd_setup_forced_release(const struct dmi_system_id *id)
return 0;
}
return 0;
}
+static int __init atkbd_setup_scancode_fixup(const struct dmi_system_id *id)
+{
+ atkbd_platform_scancode_fixup = id->driver_data;
+
+ return 0;
+}
+
static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
{
.ident = "Dell Laptop",
static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
{
.ident = "Dell Laptop",
@@
-1542,7
+1589,7
@@
static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ZV6100"),
},
.callback = atkbd_setup_forced_release,
DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ZV6100"),
},
.callback = atkbd_setup_forced_release,
- .driver_data = atkbd_
hp_zv6100
_forced_release_keys,
+ .driver_data = atkbd_
volume
_forced_release_keys,
},
{
.ident = "HP Presario R4000",
},
{
.ident = "HP Presario R4000",
@@
-1551,7
+1598,7
@@
static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4000"),
},
.callback = atkbd_setup_forced_release,
DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4000"),
},
.callback = atkbd_setup_forced_release,
- .driver_data = atkbd_
hp_r4000
_forced_release_keys,
+ .driver_data = atkbd_
volume
_forced_release_keys,
},
{
.ident = "HP Presario R4100",
},
{
.ident = "HP Presario R4100",
@@
-1560,7
+1607,7
@@
static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4100"),
},
.callback = atkbd_setup_forced_release,
DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4100"),
},
.callback = atkbd_setup_forced_release,
- .driver_data = atkbd_
hp_r4000
_forced_release_keys,
+ .driver_data = atkbd_
volume
_forced_release_keys,
},
{
.ident = "HP Presario R4200",
},
{
.ident = "HP Presario R4200",
@@
-1569,7
+1616,7
@@
static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4200"),
},
.callback = atkbd_setup_forced_release,
DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4200"),
},
.callback = atkbd_setup_forced_release,
- .driver_data = atkbd_
hp_r4000
_forced_release_keys,
+ .driver_data = atkbd_
volume
_forced_release_keys,
},
{
.ident = "Inventec Symphony",
},
{
.ident = "Inventec Symphony",
@@
-1578,7
+1625,7
@@
static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "SYMPHONY 6.0/7.0"),
},
.callback = atkbd_setup_forced_release,
DMI_MATCH(DMI_PRODUCT_NAME, "SYMPHONY 6.0/7.0"),
},
.callback = atkbd_setup_forced_release,
- .driver_data = atkbd_
inventec
_forced_release_keys,
+ .driver_data = atkbd_
volume
_forced_release_keys,
},
{
.ident = "Samsung NC10",
},
{
.ident = "Samsung NC10",
@@
-1614,7
+1661,7
@@
static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 1510"),
},
.callback = atkbd_setup_forced_release,
DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 1510"),
},
.callback = atkbd_setup_forced_release,
- .driver_data = atkbd_
amilo_pa1510
_forced_release_keys,
+ .driver_data = atkbd_
volume
_forced_release_keys,
},
{
.ident = "Fujitsu Amilo Pi 3525",
},
{
.ident = "Fujitsu Amilo Pi 3525",
@@
-1643,6
+1690,15
@@
static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.callback = atkbd_setup_forced_release,
.driver_data = atkdb_soltech_ta12_forced_release_keys,
},
.callback = atkbd_setup_forced_release,
.driver_data = atkdb_soltech_ta12_forced_release_keys,
},
+ {
+ .ident = "OQO Model 01+",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "OQO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"),
+ },
+ .callback = atkbd_setup_scancode_fixup,
+ .driver_data = atkbd_oqo_01plus_scancode_fixup,
+ },
{ }
};
{ }
};