diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-09-03 20:22:04 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-09-03 23:30:36 -0400 |
commit | 1ba36e11b227e32f818aea5b4d84f5cbff71e7db (patch) | |
tree | da3a05fc84ece5c911ea3a586b30f9cef2dec0ef /drivers/input/keyboard/atkbd.c | |
parent | 903b9124eae00edf8a9d6491dab60fcda777aabd (diff) |
Input: atkbd - allow setting force-release bitmap via sysfs
There are more and more laptop requiring use of force_release quirk
for their multimedia and other specialized keys. Adding their DMI data
to the kernel is not sustainable; instead we will rely on help from
userspace (HAL) to do that for us.
This patch creates a new 'force_release' sysfs attribute (that belongs
to serio device to which keyboard is attached) which can be used to set
up force_release keymap. For example, Dell laptop owners might do:
echo 133-139,143,147 > /sys/devices/platform/i8042/serio0/force_release
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/keyboard/atkbd.c')
-rw-r--r-- | drivers/input/keyboard/atkbd.c | 43 |
1 files changed, 37 insertions, 6 deletions
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 95fe0452dae4..80835080fee9 100644 --- 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 | |||
68 | * are loadable via a userland utility. | 68 | * are loadable via a userland utility. |
69 | */ | 69 | */ |
70 | 70 | ||
71 | static const unsigned short atkbd_set2_keycode[512] = { | 71 | #define ATKBD_KEYMAP_SIZE 512 |
72 | |||
73 | static const unsigned short atkbd_set2_keycode[ATKBD_KEYMAP_SIZE] = { | ||
72 | 74 | ||
73 | #ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES | 75 | #ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES |
74 | 76 | ||
@@ -99,7 +101,7 @@ static const unsigned short atkbd_set2_keycode[512] = { | |||
99 | #endif | 101 | #endif |
100 | }; | 102 | }; |
101 | 103 | ||
102 | static const unsigned short atkbd_set3_keycode[512] = { | 104 | static const unsigned short atkbd_set3_keycode[ATKBD_KEYMAP_SIZE] = { |
103 | 105 | ||
104 | 0, 0, 0, 0, 0, 0, 0, 59, 1,138,128,129,130, 15, 41, 60, | 106 | 0, 0, 0, 0, 0, 0, 0, 59, 1,138,128,129,130, 15, 41, 60, |
105 | 131, 29, 42, 86, 58, 16, 2, 61,133, 56, 44, 31, 30, 17, 3, 62, | 107 | 131, 29, 42, 86, 58, 16, 2, 61,133, 56, 44, 31, 30, 17, 3, 62, |
@@ -200,8 +202,8 @@ struct atkbd { | |||
200 | char phys[32]; | 202 | char phys[32]; |
201 | 203 | ||
202 | unsigned short id; | 204 | unsigned short id; |
203 | unsigned short keycode[512]; | 205 | unsigned short keycode[ATKBD_KEYMAP_SIZE]; |
204 | DECLARE_BITMAP(force_release_mask, 512); | 206 | DECLARE_BITMAP(force_release_mask, ATKBD_KEYMAP_SIZE); |
205 | unsigned char set; | 207 | unsigned char set; |
206 | unsigned char translated; | 208 | unsigned char translated; |
207 | unsigned char extra; | 209 | unsigned char extra; |
@@ -253,6 +255,7 @@ static struct device_attribute atkbd_attr_##_name = \ | |||
253 | __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name); | 255 | __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name); |
254 | 256 | ||
255 | ATKBD_DEFINE_ATTR(extra); | 257 | ATKBD_DEFINE_ATTR(extra); |
258 | ATKBD_DEFINE_ATTR(force_release); | ||
256 | ATKBD_DEFINE_ATTR(scroll); | 259 | ATKBD_DEFINE_ATTR(scroll); |
257 | ATKBD_DEFINE_ATTR(set); | 260 | ATKBD_DEFINE_ATTR(set); |
258 | ATKBD_DEFINE_ATTR(softrepeat); | 261 | ATKBD_DEFINE_ATTR(softrepeat); |
@@ -272,6 +275,7 @@ ATKBD_DEFINE_RO_ATTR(err_count); | |||
272 | 275 | ||
273 | static struct attribute *atkbd_attributes[] = { | 276 | static struct attribute *atkbd_attributes[] = { |
274 | &atkbd_attr_extra.attr, | 277 | &atkbd_attr_extra.attr, |
278 | &atkbd_attr_force_release.attr, | ||
275 | &atkbd_attr_scroll.attr, | 279 | &atkbd_attr_scroll.attr, |
276 | &atkbd_attr_set.attr, | 280 | &atkbd_attr_set.attr, |
277 | &atkbd_attr_softrepeat.attr, | 281 | &atkbd_attr_softrepeat.attr, |
@@ -926,7 +930,7 @@ static void atkbd_set_keycode_table(struct atkbd *atkbd) | |||
926 | int i, j; | 930 | int i, j; |
927 | 931 | ||
928 | memset(atkbd->keycode, 0, sizeof(atkbd->keycode)); | 932 | memset(atkbd->keycode, 0, sizeof(atkbd->keycode)); |
929 | bitmap_zero(atkbd->force_release_mask, 512); | 933 | bitmap_zero(atkbd->force_release_mask, ATKBD_KEYMAP_SIZE); |
930 | 934 | ||
931 | if (atkbd->translated) { | 935 | if (atkbd->translated) { |
932 | for (i = 0; i < 128; i++) { | 936 | for (i = 0; i < 128; i++) { |
@@ -1033,7 +1037,7 @@ static void atkbd_set_device_attrs(struct atkbd *atkbd) | |||
1033 | input_dev->keycodesize = sizeof(unsigned short); | 1037 | input_dev->keycodesize = sizeof(unsigned short); |
1034 | input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode); | 1038 | input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode); |
1035 | 1039 | ||
1036 | for (i = 0; i < 512; i++) | 1040 | for (i = 0; i < ATKBD_KEYMAP_SIZE; i++) |
1037 | if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL) | 1041 | if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL) |
1038 | __set_bit(atkbd->keycode[i], input_dev->keybit); | 1042 | __set_bit(atkbd->keycode[i], input_dev->keybit); |
1039 | } | 1043 | } |
@@ -1301,6 +1305,33 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun | |||
1301 | return count; | 1305 | return count; |
1302 | } | 1306 | } |
1303 | 1307 | ||
1308 | static ssize_t atkbd_show_force_release(struct atkbd *atkbd, char *buf) | ||
1309 | { | ||
1310 | size_t len = bitmap_scnlistprintf(buf, PAGE_SIZE - 2, | ||
1311 | atkbd->force_release_mask, ATKBD_KEYMAP_SIZE); | ||
1312 | |||
1313 | buf[len++] = '\n'; | ||
1314 | buf[len] = '\0'; | ||
1315 | |||
1316 | return len; | ||
1317 | } | ||
1318 | |||
1319 | static ssize_t atkbd_set_force_release(struct atkbd *atkbd, | ||
1320 | const char *buf, size_t count) | ||
1321 | { | ||
1322 | /* 64 bytes on stack should be acceptable */ | ||
1323 | DECLARE_BITMAP(new_mask, ATKBD_KEYMAP_SIZE); | ||
1324 | int err; | ||
1325 | |||
1326 | err = bitmap_parselist(buf, new_mask, ATKBD_KEYMAP_SIZE); | ||
1327 | if (err) | ||
1328 | return err; | ||
1329 | |||
1330 | memcpy(atkbd->force_release_mask, new_mask, sizeof(atkbd->force_release_mask)); | ||
1331 | return count; | ||
1332 | } | ||
1333 | |||
1334 | |||
1304 | static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf) | 1335 | static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf) |
1305 | { | 1336 | { |
1306 | return sprintf(buf, "%d\n", atkbd->scroll ? 1 : 0); | 1337 | return sprintf(buf, "%d\n", atkbd->scroll ? 1 : 0); |