Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+37 -6
+37 -6
drivers/input/keyboard/atkbd.c
··· 68 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 75 #ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES 74 76 ··· 101 99 #endif 102 100 }; 103 101 104 - static const unsigned short atkbd_set3_keycode[512] = { 102 + static const unsigned short atkbd_set3_keycode[ATKBD_KEYMAP_SIZE] = { 105 103 106 104 0, 0, 0, 0, 0, 0, 0, 59, 1,138,128,129,130, 15, 41, 60, 107 105 131, 29, 42, 86, 58, 16, 2, 61,133, 56, 44, 31, 30, 17, 3, 62, ··· 202 200 char phys[32]; 203 201 204 202 unsigned short id; 205 - unsigned short keycode[512]; 206 - DECLARE_BITMAP(force_release_mask, 512); 203 + unsigned short keycode[ATKBD_KEYMAP_SIZE]; 204 + DECLARE_BITMAP(force_release_mask, ATKBD_KEYMAP_SIZE); 207 205 unsigned char set; 208 206 unsigned char translated; 209 207 unsigned char extra; ··· 255 253 __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name); 256 254 257 255 ATKBD_DEFINE_ATTR(extra); 256 + ATKBD_DEFINE_ATTR(force_release); 258 257 ATKBD_DEFINE_ATTR(scroll); 259 258 ATKBD_DEFINE_ATTR(set); 260 259 ATKBD_DEFINE_ATTR(softrepeat); ··· 275 272 276 273 static struct attribute *atkbd_attributes[] = { 277 274 &atkbd_attr_extra.attr, 275 + &atkbd_attr_force_release.attr, 278 276 &atkbd_attr_scroll.attr, 279 277 &atkbd_attr_set.attr, 280 278 &atkbd_attr_softrepeat.attr, ··· 930 926 int i, j; 931 927 932 928 memset(atkbd->keycode, 0, sizeof(atkbd->keycode)); 933 - bitmap_zero(atkbd->force_release_mask, 512); 929 + bitmap_zero(atkbd->force_release_mask, ATKBD_KEYMAP_SIZE); 934 930 935 931 if (atkbd->translated) { 936 932 for (i = 0; i < 128; i++) { ··· 1037 1033 input_dev->keycodesize = sizeof(unsigned short); 1038 1034 input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode); 1039 1035 1040 - for (i = 0; i < 512; i++) 1036 + for (i = 0; i < ATKBD_KEYMAP_SIZE; i++) 1041 1037 if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL) 1042 1038 __set_bit(atkbd->keycode[i], input_dev->keybit); 1043 1039 } ··· 1304 1300 } 1305 1301 return count; 1306 1302 } 1303 + 1304 + static ssize_t atkbd_show_force_release(struct atkbd *atkbd, char *buf) 1305 + { 1306 + size_t len = bitmap_scnlistprintf(buf, PAGE_SIZE - 2, 1307 + atkbd->force_release_mask, ATKBD_KEYMAP_SIZE); 1308 + 1309 + buf[len++] = '\n'; 1310 + buf[len] = '\0'; 1311 + 1312 + return len; 1313 + } 1314 + 1315 + static ssize_t atkbd_set_force_release(struct atkbd *atkbd, 1316 + const char *buf, size_t count) 1317 + { 1318 + /* 64 bytes on stack should be acceptable */ 1319 + DECLARE_BITMAP(new_mask, ATKBD_KEYMAP_SIZE); 1320 + int err; 1321 + 1322 + err = bitmap_parselist(buf, new_mask, ATKBD_KEYMAP_SIZE); 1323 + if (err) 1324 + return err; 1325 + 1326 + memcpy(atkbd->force_release_mask, new_mask, sizeof(atkbd->force_release_mask)); 1327 + return count; 1328 + } 1329 + 1307 1330 1308 1331 static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf) 1309 1332 {