1 /* 2 * Wistron laptop button driver 3 * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz> 4 * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org> 5 * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru> 6 * 7 * You can redistribute and/or modify this program under the terms of the 8 * GNU General Public License version 2 as published by the Free Software 9 * Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 14 * Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License along 17 * with this program; if not, write to the Free Software Foundation, Inc., 18 * 59 Temple Place Suite 330, Boston, MA 02111-1307, USA. 19 */ 20 #include <linux/io.h> 21 #include <linux/dmi.h> 22 #include <linux/init.h> 23 #include <linux/input-polldev.h> 24 #include <linux/input/sparse-keymap.h> 25 #include <linux/interrupt.h> 26 #include <linux/jiffies.h> 27 #include <linux/kernel.h> 28 #include <linux/mc146818rtc.h> 29 #include <linux/module.h> 30 #include <linux/preempt.h> 31 #include <linux/string.h> 32 #include <linux/slab.h> 33 #include <linux/types.h> 34 #include <linux/platform_device.h> 35 #include <linux/leds.h> 36 37 /* How often we poll keys - msecs */ 38 #define POLL_INTERVAL_DEFAULT 500 /* when idle */ 39 #define POLL_INTERVAL_BURST 100 /* when a key was recently pressed */ 40 41 /* BIOS subsystem IDs */ 42 #define WIFI 0x35 43 #define BLUETOOTH 0x34 44 #define MAIL_LED 0x31 45 46 MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>"); 47 MODULE_DESCRIPTION("Wistron laptop button driver"); 48 MODULE_LICENSE("GPL v2"); 49 50 static bool force; /* = 0; */ 51 module_param(force, bool, 0); 52 MODULE_PARM_DESC(force, "Load even if computer is not in database"); 53 54 static char *keymap_name; /* = NULL; */ 55 module_param_named(keymap, keymap_name, charp, 0); 56 MODULE_PARM_DESC(keymap, "Keymap name, if it can't be autodetected [generic, 1557/MS2141]"); 57 58 static struct platform_device *wistron_device; 59 60 /* BIOS interface implementation */ 61 62 static void __iomem *bios_entry_point; /* BIOS routine entry point */ 63 static void __iomem *bios_code_map_base; 64 static void __iomem *bios_data_map_base; 65 66 static u8 cmos_address; 67 68 struct regs { 69 u32 eax, ebx, ecx; 70 }; 71 72 static void call_bios(struct regs *regs) 73 { 74 unsigned long flags; 75 76 preempt_disable(); 77 local_irq_save(flags); 78 asm volatile ("pushl %%ebp;" 79 "movl %7, %%ebp;" 80 "call *%6;" 81 "popl %%ebp" 82 : "=a" (regs->eax), "=b" (regs->ebx), "=c" (regs->ecx) 83 : "0" (regs->eax), "1" (regs->ebx), "2" (regs->ecx), 84 "m" (bios_entry_point), "m" (bios_data_map_base) 85 : "edx", "edi", "esi", "memory"); 86 local_irq_restore(flags); 87 preempt_enable(); 88 } 89 90 static ssize_t __init locate_wistron_bios(void __iomem *base) 91 { 92 static unsigned char __initdata signature[] = 93 { 0x42, 0x21, 0x55, 0x30 }; 94 ssize_t offset; 95 96 for (offset = 0; offset < 0x10000; offset += 0x10) { 97 if (check_signature(base + offset, signature, 98 sizeof(signature)) != 0) 99 return offset; 100 } 101 return -1; 102 } 103 104 static int __init map_bios(void) 105 { 106 void __iomem *base; 107 ssize_t offset; 108 u32 entry_point; 109 110 base = ioremap(0xF0000, 0x10000); /* Can't fail */ 111 offset = locate_wistron_bios(base); 112 if (offset < 0) { 113 printk(KERN_ERR "wistron_btns: BIOS entry point not found\n"); 114 iounmap(base); 115 return -ENODEV; 116 } 117 118 entry_point = readl(base + offset + 5); 119 printk(KERN_DEBUG 120 "wistron_btns: BIOS signature found at %p, entry point %08X\n", 121 base + offset, entry_point); 122 123 if (entry_point >= 0xF0000) { 124 bios_code_map_base = base; 125 bios_entry_point = bios_code_map_base + (entry_point & 0xFFFF); 126 } else { 127 iounmap(base); 128 bios_code_map_base = ioremap(entry_point & ~0x3FFF, 0x4000); 129 if (bios_code_map_base == NULL) { 130 printk(KERN_ERR 131 "wistron_btns: Can't map BIOS code at %08X\n", 132 entry_point & ~0x3FFF); 133 goto err; 134 } 135 bios_entry_point = bios_code_map_base + (entry_point & 0x3FFF); 136 } 137 /* The Windows driver maps 0x10000 bytes, we keep only one page... */ 138 bios_data_map_base = ioremap(0x400, 0xc00); 139 if (bios_data_map_base == NULL) { 140 printk(KERN_ERR "wistron_btns: Can't map BIOS data\n"); 141 goto err_code; 142 } 143 return 0; 144 145 err_code: 146 iounmap(bios_code_map_base); 147 err: 148 return -ENOMEM; 149 } 150 151 static inline void unmap_bios(void) 152 { 153 iounmap(bios_code_map_base); 154 iounmap(bios_data_map_base); 155 } 156 157 /* BIOS calls */ 158 159 static u16 bios_pop_queue(void) 160 { 161 struct regs regs; 162 163 memset(®s, 0, sizeof (regs)); 164 regs.eax = 0x9610; 165 regs.ebx = 0x061C; 166 regs.ecx = 0x0000; 167 call_bios(®s); 168 169 return regs.eax; 170 } 171 172 static void bios_attach(void) 173 { 174 struct regs regs; 175 176 memset(®s, 0, sizeof (regs)); 177 regs.eax = 0x9610; 178 regs.ebx = 0x012E; 179 call_bios(®s); 180 } 181 182 static void bios_detach(void) 183 { 184 struct regs regs; 185 186 memset(®s, 0, sizeof (regs)); 187 regs.eax = 0x9610; 188 regs.ebx = 0x002E; 189 call_bios(®s); 190 } 191 192 static u8 bios_get_cmos_address(void) 193 { 194 struct regs regs; 195 196 memset(®s, 0, sizeof (regs)); 197 regs.eax = 0x9610; 198 regs.ebx = 0x051C; 199 call_bios(®s); 200 201 return regs.ecx; 202 } 203 204 static u16 bios_get_default_setting(u8 subsys) 205 { 206 struct regs regs; 207 208 memset(®s, 0, sizeof (regs)); 209 regs.eax = 0x9610; 210 regs.ebx = 0x0200 | subsys; 211 call_bios(®s); 212 213 return regs.eax; 214 } 215 216 static void bios_set_state(u8 subsys, int enable) 217 { 218 struct regs regs; 219 220 memset(®s, 0, sizeof (regs)); 221 regs.eax = 0x9610; 222 regs.ebx = (enable ? 0x0100 : 0x0000) | subsys; 223 call_bios(®s); 224 } 225 226 /* Hardware database */ 227 228 #define KE_WIFI (KE_LAST + 1) 229 #define KE_BLUETOOTH (KE_LAST + 2) 230 231 #define FE_MAIL_LED 0x01 232 #define FE_WIFI_LED 0x02 233 #define FE_UNTESTED 0x80 234 235 static struct key_entry *keymap; /* = NULL; Current key map */ 236 static bool have_wifi; 237 static bool have_bluetooth; 238 static int leds_present; /* bitmask of leds present */ 239 240 static int __init dmi_matched(const struct dmi_system_id *dmi) 241 { 242 const struct key_entry *key; 243 244 keymap = dmi->driver_data; 245 for (key = keymap; key->type != KE_END; key++) { 246 if (key->type == KE_WIFI) 247 have_wifi = true; 248 else if (key->type == KE_BLUETOOTH) 249 have_bluetooth = true; 250 } 251 leds_present = key->code & (FE_MAIL_LED | FE_WIFI_LED); 252 253 return 1; 254 } 255 256 static struct key_entry keymap_empty[] __initdata = { 257 { KE_END, 0 } 258 }; 259 260 static struct key_entry keymap_fs_amilo_pro_v2000[] __initdata = { 261 { KE_KEY, 0x01, {KEY_HELP} }, 262 { KE_KEY, 0x11, {KEY_PROG1} }, 263 { KE_KEY, 0x12, {KEY_PROG2} }, 264 { KE_WIFI, 0x30 }, 265 { KE_KEY, 0x31, {KEY_MAIL} }, 266 { KE_KEY, 0x36, {KEY_WWW} }, 267 { KE_END, 0 } 268 }; 269 270 static struct key_entry keymap_fs_amilo_pro_v3505[] __initdata = { 271 { KE_KEY, 0x01, {KEY_HELP} }, /* Fn+F1 */ 272 { KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Fn+F4 */ 273 { KE_BLUETOOTH, 0x30 }, /* Fn+F10 */ 274 { KE_KEY, 0x31, {KEY_MAIL} }, /* mail button */ 275 { KE_KEY, 0x36, {KEY_WWW} }, /* www button */ 276 { KE_WIFI, 0x78 }, /* satellite dish button */ 277 { KE_END, 0 } 278 }; 279 280 static struct key_entry keymap_fs_amilo_pro_v8210[] __initdata = { 281 { KE_KEY, 0x01, {KEY_HELP} }, /* Fn+F1 */ 282 { KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Fn+F4 */ 283 { KE_BLUETOOTH, 0x30 }, /* Fn+F10 */ 284 { KE_KEY, 0x31, {KEY_MAIL} }, /* mail button */ 285 { KE_KEY, 0x36, {KEY_WWW} }, /* www button */ 286 { KE_WIFI, 0x78 }, /* satelite dish button */ 287 { KE_END, FE_WIFI_LED } 288 }; 289 290 static struct key_entry keymap_fujitsu_n3510[] __initdata = { 291 { KE_KEY, 0x11, {KEY_PROG1} }, 292 { KE_KEY, 0x12, {KEY_PROG2} }, 293 { KE_KEY, 0x36, {KEY_WWW} }, 294 { KE_KEY, 0x31, {KEY_MAIL} }, 295 { KE_KEY, 0x71, {KEY_STOPCD} }, 296 { KE_KEY, 0x72, {KEY_PLAYPAUSE} }, 297 { KE_KEY, 0x74, {KEY_REWIND} }, 298 { KE_KEY, 0x78, {KEY_FORWARD} }, 299 { KE_END, 0 } 300 }; 301 302 static struct key_entry keymap_wistron_ms2111[] __initdata = { 303 { KE_KEY, 0x11, {KEY_PROG1} }, 304 { KE_KEY, 0x12, {KEY_PROG2} }, 305 { KE_KEY, 0x13, {KEY_PROG3} }, 306 { KE_KEY, 0x31, {KEY_MAIL} }, 307 { KE_KEY, 0x36, {KEY_WWW} }, 308 { KE_END, FE_MAIL_LED } 309 }; 310 311 static struct key_entry keymap_wistron_md40100[] __initdata = { 312 { KE_KEY, 0x01, {KEY_HELP} }, 313 { KE_KEY, 0x02, {KEY_CONFIG} }, 314 { KE_KEY, 0x31, {KEY_MAIL} }, 315 { KE_KEY, 0x36, {KEY_WWW} }, 316 { KE_KEY, 0x37, {KEY_DISPLAYTOGGLE} }, /* Display on/off */ 317 { KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED } 318 }; 319 320 static struct key_entry keymap_wistron_ms2141[] __initdata = { 321 { KE_KEY, 0x11, {KEY_PROG1} }, 322 { KE_KEY, 0x12, {KEY_PROG2} }, 323 { KE_WIFI, 0x30 }, 324 { KE_KEY, 0x22, {KEY_REWIND} }, 325 { KE_KEY, 0x23, {KEY_FORWARD} }, 326 { KE_KEY, 0x24, {KEY_PLAYPAUSE} }, 327 { KE_KEY, 0x25, {KEY_STOPCD} }, 328 { KE_KEY, 0x31, {KEY_MAIL} }, 329 { KE_KEY, 0x36, {KEY_WWW} }, 330 { KE_END, 0 } 331 }; 332 333 static struct key_entry keymap_acer_aspire_1500[] __initdata = { 334 { KE_KEY, 0x01, {KEY_HELP} }, 335 { KE_KEY, 0x03, {KEY_POWER} }, 336 { KE_KEY, 0x11, {KEY_PROG1} }, 337 { KE_KEY, 0x12, {KEY_PROG2} }, 338 { KE_WIFI, 0x30 }, 339 { KE_KEY, 0x31, {KEY_MAIL} }, 340 { KE_KEY, 0x36, {KEY_WWW} }, 341 { KE_KEY, 0x49, {KEY_CONFIG} }, 342 { KE_BLUETOOTH, 0x44 }, 343 { KE_END, FE_UNTESTED } 344 }; 345 346 static struct key_entry keymap_acer_aspire_1600[] __initdata = { 347 { KE_KEY, 0x01, {KEY_HELP} }, 348 { KE_KEY, 0x03, {KEY_POWER} }, 349 { KE_KEY, 0x08, {KEY_MUTE} }, 350 { KE_KEY, 0x11, {KEY_PROG1} }, 351 { KE_KEY, 0x12, {KEY_PROG2} }, 352 { KE_KEY, 0x13, {KEY_PROG3} }, 353 { KE_KEY, 0x31, {KEY_MAIL} }, 354 { KE_KEY, 0x36, {KEY_WWW} }, 355 { KE_KEY, 0x49, {KEY_CONFIG} }, 356 { KE_WIFI, 0x30 }, 357 { KE_BLUETOOTH, 0x44 }, 358 { KE_END, FE_MAIL_LED | FE_UNTESTED } 359 }; 360 361 /* 3020 has been tested */ 362 static struct key_entry keymap_acer_aspire_5020[] __initdata = { 363 { KE_KEY, 0x01, {KEY_HELP} }, 364 { KE_KEY, 0x03, {KEY_POWER} }, 365 { KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */ 366 { KE_KEY, 0x11, {KEY_PROG1} }, 367 { KE_KEY, 0x12, {KEY_PROG2} }, 368 { KE_KEY, 0x31, {KEY_MAIL} }, 369 { KE_KEY, 0x36, {KEY_WWW} }, 370 { KE_KEY, 0x6a, {KEY_CONFIG} }, 371 { KE_WIFI, 0x30 }, 372 { KE_BLUETOOTH, 0x44 }, 373 { KE_END, FE_MAIL_LED | FE_UNTESTED } 374 }; 375 376 static struct key_entry keymap_acer_travelmate_2410[] __initdata = { 377 { KE_KEY, 0x01, {KEY_HELP} }, 378 { KE_KEY, 0x6d, {KEY_POWER} }, 379 { KE_KEY, 0x11, {KEY_PROG1} }, 380 { KE_KEY, 0x12, {KEY_PROG2} }, 381 { KE_KEY, 0x31, {KEY_MAIL} }, 382 { KE_KEY, 0x36, {KEY_WWW} }, 383 { KE_KEY, 0x6a, {KEY_CONFIG} }, 384 { KE_WIFI, 0x30 }, 385 { KE_BLUETOOTH, 0x44 }, 386 { KE_END, FE_MAIL_LED | FE_UNTESTED } 387 }; 388 389 static struct key_entry keymap_acer_travelmate_110[] __initdata = { 390 { KE_KEY, 0x01, {KEY_HELP} }, 391 { KE_KEY, 0x02, {KEY_CONFIG} }, 392 { KE_KEY, 0x03, {KEY_POWER} }, 393 { KE_KEY, 0x08, {KEY_MUTE} }, 394 { KE_KEY, 0x11, {KEY_PROG1} }, 395 { KE_KEY, 0x12, {KEY_PROG2} }, 396 { KE_KEY, 0x20, {KEY_VOLUMEUP} }, 397 { KE_KEY, 0x21, {KEY_VOLUMEDOWN} }, 398 { KE_KEY, 0x31, {KEY_MAIL} }, 399 { KE_KEY, 0x36, {KEY_WWW} }, 400 { KE_SW, 0x4a, {.sw = {SW_LID, 1}} }, /* lid close */ 401 { KE_SW, 0x4b, {.sw = {SW_LID, 0}} }, /* lid open */ 402 { KE_WIFI, 0x30 }, 403 { KE_END, FE_MAIL_LED | FE_UNTESTED } 404 }; 405 406 static struct key_entry keymap_acer_travelmate_300[] __initdata = { 407 { KE_KEY, 0x01, {KEY_HELP} }, 408 { KE_KEY, 0x02, {KEY_CONFIG} }, 409 { KE_KEY, 0x03, {KEY_POWER} }, 410 { KE_KEY, 0x08, {KEY_MUTE} }, 411 { KE_KEY, 0x11, {KEY_PROG1} }, 412 { KE_KEY, 0x12, {KEY_PROG2} }, 413 { KE_KEY, 0x20, {KEY_VOLUMEUP} }, 414 { KE_KEY, 0x21, {KEY_VOLUMEDOWN} }, 415 { KE_KEY, 0x31, {KEY_MAIL} }, 416 { KE_KEY, 0x36, {KEY_WWW} }, 417 { KE_WIFI, 0x30 }, 418 { KE_BLUETOOTH, 0x44 }, 419 { KE_END, FE_MAIL_LED | FE_UNTESTED } 420 }; 421 422 static struct key_entry keymap_acer_travelmate_380[] __initdata = { 423 { KE_KEY, 0x01, {KEY_HELP} }, 424 { KE_KEY, 0x02, {KEY_CONFIG} }, 425 { KE_KEY, 0x03, {KEY_POWER} }, /* not 370 */ 426 { KE_KEY, 0x11, {KEY_PROG1} }, 427 { KE_KEY, 0x12, {KEY_PROG2} }, 428 { KE_KEY, 0x13, {KEY_PROG3} }, 429 { KE_KEY, 0x31, {KEY_MAIL} }, 430 { KE_KEY, 0x36, {KEY_WWW} }, 431 { KE_WIFI, 0x30 }, 432 { KE_END, FE_MAIL_LED | FE_UNTESTED } 433 }; 434 435 /* unusual map */ 436 static struct key_entry keymap_acer_travelmate_220[] __initdata = { 437 { KE_KEY, 0x01, {KEY_HELP} }, 438 { KE_KEY, 0x02, {KEY_CONFIG} }, 439 { KE_KEY, 0x11, {KEY_MAIL} }, 440 { KE_KEY, 0x12, {KEY_WWW} }, 441 { KE_KEY, 0x13, {KEY_PROG2} }, 442 { KE_KEY, 0x31, {KEY_PROG1} }, 443 { KE_END, FE_WIFI_LED | FE_UNTESTED } 444 }; 445 446 static struct key_entry keymap_acer_travelmate_230[] __initdata = { 447 { KE_KEY, 0x01, {KEY_HELP} }, 448 { KE_KEY, 0x02, {KEY_CONFIG} }, 449 { KE_KEY, 0x11, {KEY_PROG1} }, 450 { KE_KEY, 0x12, {KEY_PROG2} }, 451 { KE_KEY, 0x31, {KEY_MAIL} }, 452 { KE_KEY, 0x36, {KEY_WWW} }, 453 { KE_END, FE_WIFI_LED | FE_UNTESTED } 454 }; 455 456 static struct key_entry keymap_acer_travelmate_240[] __initdata = { 457 { KE_KEY, 0x01, {KEY_HELP} }, 458 { KE_KEY, 0x02, {KEY_CONFIG} }, 459 { KE_KEY, 0x03, {KEY_POWER} }, 460 { KE_KEY, 0x08, {KEY_MUTE} }, 461 { KE_KEY, 0x31, {KEY_MAIL} }, 462 { KE_KEY, 0x36, {KEY_WWW} }, 463 { KE_KEY, 0x11, {KEY_PROG1} }, 464 { KE_KEY, 0x12, {KEY_PROG2} }, 465 { KE_BLUETOOTH, 0x44 }, 466 { KE_WIFI, 0x30 }, 467 { KE_END, FE_UNTESTED } 468 }; 469 470 static struct key_entry keymap_acer_travelmate_350[] __initdata = { 471 { KE_KEY, 0x01, {KEY_HELP} }, 472 { KE_KEY, 0x02, {KEY_CONFIG} }, 473 { KE_KEY, 0x11, {KEY_PROG1} }, 474 { KE_KEY, 0x12, {KEY_PROG2} }, 475 { KE_KEY, 0x13, {KEY_MAIL} }, 476 { KE_KEY, 0x14, {KEY_PROG3} }, 477 { KE_KEY, 0x15, {KEY_WWW} }, 478 { KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED } 479 }; 480 481 static struct key_entry keymap_acer_travelmate_360[] __initdata = { 482 { KE_KEY, 0x01, {KEY_HELP} }, 483 { KE_KEY, 0x02, {KEY_CONFIG} }, 484 { KE_KEY, 0x11, {KEY_PROG1} }, 485 { KE_KEY, 0x12, {KEY_PROG2} }, 486 { KE_KEY, 0x13, {KEY_MAIL} }, 487 { KE_KEY, 0x14, {KEY_PROG3} }, 488 { KE_KEY, 0x15, {KEY_WWW} }, 489 { KE_KEY, 0x40, {KEY_WLAN} }, 490 { KE_END, FE_WIFI_LED | FE_UNTESTED } /* no mail led */ 491 }; 492 493 /* Wifi subsystem only activates the led. Therefore we need to pass 494 * wifi event as a normal key, then userspace can really change the wifi state. 495 * TODO we need to export led state to userspace (wifi and mail) */ 496 static struct key_entry keymap_acer_travelmate_610[] __initdata = { 497 { KE_KEY, 0x01, {KEY_HELP} }, 498 { KE_KEY, 0x02, {KEY_CONFIG} }, 499 { KE_KEY, 0x11, {KEY_PROG1} }, 500 { KE_KEY, 0x12, {KEY_PROG2} }, 501 { KE_KEY, 0x13, {KEY_PROG3} }, 502 { KE_KEY, 0x14, {KEY_MAIL} }, 503 { KE_KEY, 0x15, {KEY_WWW} }, 504 { KE_KEY, 0x40, {KEY_WLAN} }, 505 { KE_END, FE_MAIL_LED | FE_WIFI_LED } 506 }; 507 508 static struct key_entry keymap_acer_travelmate_630[] __initdata = { 509 { KE_KEY, 0x01, {KEY_HELP} }, 510 { KE_KEY, 0x02, {KEY_CONFIG} }, 511 { KE_KEY, 0x03, {KEY_POWER} }, 512 { KE_KEY, 0x08, {KEY_MUTE} }, /* not 620 */ 513 { KE_KEY, 0x11, {KEY_PROG1} }, 514 { KE_KEY, 0x12, {KEY_PROG2} }, 515 { KE_KEY, 0x13, {KEY_PROG3} }, 516 { KE_KEY, 0x20, {KEY_VOLUMEUP} }, 517 { KE_KEY, 0x21, {KEY_VOLUMEDOWN} }, 518 { KE_KEY, 0x31, {KEY_MAIL} }, 519 { KE_KEY, 0x36, {KEY_WWW} }, 520 { KE_WIFI, 0x30 }, 521 { KE_END, FE_MAIL_LED | FE_UNTESTED } 522 }; 523 524 static struct key_entry keymap_aopen_1559as[] __initdata = { 525 { KE_KEY, 0x01, {KEY_HELP} }, 526 { KE_KEY, 0x06, {KEY_PROG3} }, 527 { KE_KEY, 0x11, {KEY_PROG1} }, 528 { KE_KEY, 0x12, {KEY_PROG2} }, 529 { KE_WIFI, 0x30 }, 530 { KE_KEY, 0x31, {KEY_MAIL} }, 531 { KE_KEY, 0x36, {KEY_WWW} }, 532 { KE_END, 0 }, 533 }; 534 535 static struct key_entry keymap_fs_amilo_d88x0[] __initdata = { 536 { KE_KEY, 0x01, {KEY_HELP} }, 537 { KE_KEY, 0x08, {KEY_MUTE} }, 538 { KE_KEY, 0x31, {KEY_MAIL} }, 539 { KE_KEY, 0x36, {KEY_WWW} }, 540 { KE_KEY, 0x11, {KEY_PROG1} }, 541 { KE_KEY, 0x12, {KEY_PROG2} }, 542 { KE_KEY, 0x13, {KEY_PROG3} }, 543 { KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED } 544 }; 545 546 static struct key_entry keymap_wistron_md2900[] __initdata = { 547 { KE_KEY, 0x01, {KEY_HELP} }, 548 { KE_KEY, 0x02, {KEY_CONFIG} }, 549 { KE_KEY, 0x11, {KEY_PROG1} }, 550 { KE_KEY, 0x12, {KEY_PROG2} }, 551 { KE_KEY, 0x31, {KEY_MAIL} }, 552 { KE_KEY, 0x36, {KEY_WWW} }, 553 { KE_WIFI, 0x30 }, 554 { KE_END, FE_MAIL_LED | FE_UNTESTED } 555 }; 556 557 static struct key_entry keymap_wistron_md96500[] __initdata = { 558 { KE_KEY, 0x01, {KEY_HELP} }, 559 { KE_KEY, 0x02, {KEY_CONFIG} }, 560 { KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */ 561 { KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Display on/off */ 562 { KE_KEY, 0x08, {KEY_MUTE} }, 563 { KE_KEY, 0x11, {KEY_PROG1} }, 564 { KE_KEY, 0x12, {KEY_PROG2} }, 565 { KE_KEY, 0x20, {KEY_VOLUMEUP} }, 566 { KE_KEY, 0x21, {KEY_VOLUMEDOWN} }, 567 { KE_KEY, 0x22, {KEY_REWIND} }, 568 { KE_KEY, 0x23, {KEY_FORWARD} }, 569 { KE_KEY, 0x24, {KEY_PLAYPAUSE} }, 570 { KE_KEY, 0x25, {KEY_STOPCD} }, 571 { KE_KEY, 0x31, {KEY_MAIL} }, 572 { KE_KEY, 0x36, {KEY_WWW} }, 573 { KE_WIFI, 0x30 }, 574 { KE_BLUETOOTH, 0x44 }, 575 { KE_END, 0 } 576 }; 577 578 static struct key_entry keymap_wistron_generic[] __initdata = { 579 { KE_KEY, 0x01, {KEY_HELP} }, 580 { KE_KEY, 0x02, {KEY_CONFIG} }, 581 { KE_KEY, 0x03, {KEY_POWER} }, 582 { KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */ 583 { KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Display on/off */ 584 { KE_KEY, 0x08, {KEY_MUTE} }, 585 { KE_KEY, 0x11, {KEY_PROG1} }, 586 { KE_KEY, 0x12, {KEY_PROG2} }, 587 { KE_KEY, 0x13, {KEY_PROG3} }, 588 { KE_KEY, 0x14, {KEY_MAIL} }, 589 { KE_KEY, 0x15, {KEY_WWW} }, 590 { KE_KEY, 0x20, {KEY_VOLUMEUP} }, 591 { KE_KEY, 0x21, {KEY_VOLUMEDOWN} }, 592 { KE_KEY, 0x22, {KEY_REWIND} }, 593 { KE_KEY, 0x23, {KEY_FORWARD} }, 594 { KE_KEY, 0x24, {KEY_PLAYPAUSE} }, 595 { KE_KEY, 0x25, {KEY_STOPCD} }, 596 { KE_KEY, 0x31, {KEY_MAIL} }, 597 { KE_KEY, 0x36, {KEY_WWW} }, 598 { KE_KEY, 0x37, {KEY_DISPLAYTOGGLE} }, /* Display on/off */ 599 { KE_KEY, 0x40, {KEY_WLAN} }, 600 { KE_KEY, 0x49, {KEY_CONFIG} }, 601 { KE_SW, 0x4a, {.sw = {SW_LID, 1}} }, /* lid close */ 602 { KE_SW, 0x4b, {.sw = {SW_LID, 0}} }, /* lid open */ 603 { KE_KEY, 0x6a, {KEY_CONFIG} }, 604 { KE_KEY, 0x6d, {KEY_POWER} }, 605 { KE_KEY, 0x71, {KEY_STOPCD} }, 606 { KE_KEY, 0x72, {KEY_PLAYPAUSE} }, 607 { KE_KEY, 0x74, {KEY_REWIND} }, 608 { KE_KEY, 0x78, {KEY_FORWARD} }, 609 { KE_WIFI, 0x30 }, 610 { KE_BLUETOOTH, 0x44 }, 611 { KE_END, 0 } 612 }; 613 614 static struct key_entry keymap_aopen_1557[] __initdata = { 615 { KE_KEY, 0x01, {KEY_HELP} }, 616 { KE_KEY, 0x11, {KEY_PROG1} }, 617 { KE_KEY, 0x12, {KEY_PROG2} }, 618 { KE_WIFI, 0x30 }, 619 { KE_KEY, 0x22, {KEY_REWIND} }, 620 { KE_KEY, 0x23, {KEY_FORWARD} }, 621 { KE_KEY, 0x24, {KEY_PLAYPAUSE} }, 622 { KE_KEY, 0x25, {KEY_STOPCD} }, 623 { KE_KEY, 0x31, {KEY_MAIL} }, 624 { KE_KEY, 0x36, {KEY_WWW} }, 625 { KE_END, 0 } 626 }; 627 628 static struct key_entry keymap_prestigio[] __initdata = { 629 { KE_KEY, 0x11, {KEY_PROG1} }, 630 { KE_KEY, 0x12, {KEY_PROG2} }, 631 { KE_WIFI, 0x30 }, 632 { KE_KEY, 0x22, {KEY_REWIND} }, 633 { KE_KEY, 0x23, {KEY_FORWARD} }, 634 { KE_KEY, 0x24, {KEY_PLAYPAUSE} }, 635 { KE_KEY, 0x25, {KEY_STOPCD} }, 636 { KE_KEY, 0x31, {KEY_MAIL} }, 637 { KE_KEY, 0x36, {KEY_WWW} }, 638 { KE_END, 0 } 639 }; 640 641 642 /* 643 * If your machine is not here (which is currently rather likely), please send 644 * a list of buttons and their key codes (reported when loading this module 645 * with force=1) and the output of dmidecode to $MODULE_AUTHOR. 646 */ 647 static const struct dmi_system_id dmi_ids[] __initconst = { 648 { 649 /* Fujitsu-Siemens Amilo Pro V2000 */ 650 .callback = dmi_matched, 651 .matches = { 652 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 653 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro V2000"), 654 }, 655 .driver_data = keymap_fs_amilo_pro_v2000 656 }, 657 { 658 /* Fujitsu-Siemens Amilo Pro Edition V3505 */ 659 .callback = dmi_matched, 660 .matches = { 661 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 662 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Edition V3505"), 663 }, 664 .driver_data = keymap_fs_amilo_pro_v3505 665 }, 666 { 667 /* Fujitsu-Siemens Amilo Pro Edition V8210 */ 668 .callback = dmi_matched, 669 .matches = { 670 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 671 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Series V8210"), 672 }, 673 .driver_data = keymap_fs_amilo_pro_v8210 674 }, 675 { 676 /* Fujitsu-Siemens Amilo M7400 */ 677 .callback = dmi_matched, 678 .matches = { 679 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 680 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO M "), 681 }, 682 .driver_data = keymap_fs_amilo_pro_v2000 683 }, 684 { 685 /* Maxdata Pro 7000 DX */ 686 .callback = dmi_matched, 687 .matches = { 688 DMI_MATCH(DMI_SYS_VENDOR, "MAXDATA"), 689 DMI_MATCH(DMI_PRODUCT_NAME, "Pro 7000"), 690 }, 691 .driver_data = keymap_fs_amilo_pro_v2000 692 }, 693 { 694 /* Fujitsu N3510 */ 695 .callback = dmi_matched, 696 .matches = { 697 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), 698 DMI_MATCH(DMI_PRODUCT_NAME, "N3510"), 699 }, 700 .driver_data = keymap_fujitsu_n3510 701 }, 702 { 703 /* Acer Aspire 1500 */ 704 .callback = dmi_matched, 705 .matches = { 706 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 707 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1500"), 708 }, 709 .driver_data = keymap_acer_aspire_1500 710 }, 711 { 712 /* Acer Aspire 1600 */ 713 .callback = dmi_matched, 714 .matches = { 715 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 716 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1600"), 717 }, 718 .driver_data = keymap_acer_aspire_1600 719 }, 720 { 721 /* Acer Aspire 3020 */ 722 .callback = dmi_matched, 723 .matches = { 724 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 725 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3020"), 726 }, 727 .driver_data = keymap_acer_aspire_5020 728 }, 729 { 730 /* Acer Aspire 5020 */ 731 .callback = dmi_matched, 732 .matches = { 733 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 734 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5020"), 735 }, 736 .driver_data = keymap_acer_aspire_5020 737 }, 738 { 739 /* Acer TravelMate 2100 */ 740 .callback = dmi_matched, 741 .matches = { 742 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 743 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2100"), 744 }, 745 .driver_data = keymap_acer_aspire_5020 746 }, 747 { 748 /* Acer TravelMate 2410 */ 749 .callback = dmi_matched, 750 .matches = { 751 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 752 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2410"), 753 }, 754 .driver_data = keymap_acer_travelmate_2410 755 }, 756 { 757 /* Acer TravelMate C300 */ 758 .callback = dmi_matched, 759 .matches = { 760 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 761 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C300"), 762 }, 763 .driver_data = keymap_acer_travelmate_300 764 }, 765 { 766 /* Acer TravelMate C100 */ 767 .callback = dmi_matched, 768 .matches = { 769 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 770 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C100"), 771 }, 772 .driver_data = keymap_acer_travelmate_300 773 }, 774 { 775 /* Acer TravelMate C110 */ 776 .callback = dmi_matched, 777 .matches = { 778 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 779 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C110"), 780 }, 781 .driver_data = keymap_acer_travelmate_110 782 }, 783 { 784 /* Acer TravelMate 380 */ 785 .callback = dmi_matched, 786 .matches = { 787 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 788 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 380"), 789 }, 790 .driver_data = keymap_acer_travelmate_380 791 }, 792 { 793 /* Acer TravelMate 370 */ 794 .callback = dmi_matched, 795 .matches = { 796 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 797 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 370"), 798 }, 799 .driver_data = keymap_acer_travelmate_380 /* keyboard minus 1 key */ 800 }, 801 { 802 /* Acer TravelMate 220 */ 803 .callback = dmi_matched, 804 .matches = { 805 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 806 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 220"), 807 }, 808 .driver_data = keymap_acer_travelmate_220 809 }, 810 { 811 /* Acer TravelMate 260 */ 812 .callback = dmi_matched, 813 .matches = { 814 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 815 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 260"), 816 }, 817 .driver_data = keymap_acer_travelmate_220 818 }, 819 { 820 /* Acer TravelMate 230 */ 821 .callback = dmi_matched, 822 .matches = { 823 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 824 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 230"), 825 /* acerhk looks for "TravelMate F4..." ?! */ 826 }, 827 .driver_data = keymap_acer_travelmate_230 828 }, 829 { 830 /* Acer TravelMate 280 */ 831 .callback = dmi_matched, 832 .matches = { 833 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 834 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 280"), 835 }, 836 .driver_data = keymap_acer_travelmate_230 837 }, 838 { 839 /* Acer TravelMate 240 */ 840 .callback = dmi_matched, 841 .matches = { 842 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 843 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 240"), 844 }, 845 .driver_data = keymap_acer_travelmate_240 846 }, 847 { 848 /* Acer TravelMate 250 */ 849 .callback = dmi_matched, 850 .matches = { 851 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 852 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 250"), 853 }, 854 .driver_data = keymap_acer_travelmate_240 855 }, 856 { 857 /* Acer TravelMate 2424NWXCi */ 858 .callback = dmi_matched, 859 .matches = { 860 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 861 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2420"), 862 }, 863 .driver_data = keymap_acer_travelmate_240 864 }, 865 { 866 /* Acer TravelMate 350 */ 867 .callback = dmi_matched, 868 .matches = { 869 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 870 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 350"), 871 }, 872 .driver_data = keymap_acer_travelmate_350 873 }, 874 { 875 /* Acer TravelMate 360 */ 876 .callback = dmi_matched, 877 .matches = { 878 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 879 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), 880 }, 881 .driver_data = keymap_acer_travelmate_360 882 }, 883 { 884 /* Acer TravelMate 610 */ 885 .callback = dmi_matched, 886 .matches = { 887 DMI_MATCH(DMI_SYS_VENDOR, "ACER"), 888 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 610"), 889 }, 890 .driver_data = keymap_acer_travelmate_610 891 }, 892 { 893 /* Acer TravelMate 620 */ 894 .callback = dmi_matched, 895 .matches = { 896 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 897 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 620"), 898 }, 899 .driver_data = keymap_acer_travelmate_630 900 }, 901 { 902 /* Acer TravelMate 630 */ 903 .callback = dmi_matched, 904 .matches = { 905 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 906 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 630"), 907 }, 908 .driver_data = keymap_acer_travelmate_630 909 }, 910 { 911 /* AOpen 1559AS */ 912 .callback = dmi_matched, 913 .matches = { 914 DMI_MATCH(DMI_PRODUCT_NAME, "E2U"), 915 DMI_MATCH(DMI_BOARD_NAME, "E2U"), 916 }, 917 .driver_data = keymap_aopen_1559as 918 }, 919 { 920 /* Medion MD 9783 */ 921 .callback = dmi_matched, 922 .matches = { 923 DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), 924 DMI_MATCH(DMI_PRODUCT_NAME, "MD 9783"), 925 }, 926 .driver_data = keymap_wistron_ms2111 927 }, 928 { 929 /* Medion MD 40100 */ 930 .callback = dmi_matched, 931 .matches = { 932 DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), 933 DMI_MATCH(DMI_PRODUCT_NAME, "WID2000"), 934 }, 935 .driver_data = keymap_wistron_md40100 936 }, 937 { 938 /* Medion MD 2900 */ 939 .callback = dmi_matched, 940 .matches = { 941 DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), 942 DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2000"), 943 }, 944 .driver_data = keymap_wistron_md2900 945 }, 946 { 947 /* Medion MD 42200 */ 948 .callback = dmi_matched, 949 .matches = { 950 DMI_MATCH(DMI_SYS_VENDOR, "Medion"), 951 DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2030"), 952 }, 953 .driver_data = keymap_fs_amilo_pro_v2000 954 }, 955 { 956 /* Medion MD 96500 */ 957 .callback = dmi_matched, 958 .matches = { 959 DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"), 960 DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2040"), 961 }, 962 .driver_data = keymap_wistron_md96500 963 }, 964 { 965 /* Medion MD 95400 */ 966 .callback = dmi_matched, 967 .matches = { 968 DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"), 969 DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2050"), 970 }, 971 .driver_data = keymap_wistron_md96500 972 }, 973 { 974 /* Fujitsu Siemens Amilo D7820 */ 975 .callback = dmi_matched, 976 .matches = { 977 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), /* not sure */ 978 DMI_MATCH(DMI_PRODUCT_NAME, "Amilo D"), 979 }, 980 .driver_data = keymap_fs_amilo_d88x0 981 }, 982 { 983 /* Fujitsu Siemens Amilo D88x0 */ 984 .callback = dmi_matched, 985 .matches = { 986 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 987 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO D"), 988 }, 989 .driver_data = keymap_fs_amilo_d88x0 990 }, 991 { NULL, } 992 }; 993 MODULE_DEVICE_TABLE(dmi, dmi_ids); 994 995 /* Copy the good keymap, as the original ones are free'd */ 996 static int __init copy_keymap(void) 997 { 998 const struct key_entry *key; 999 struct key_entry *new_keymap; 1000 unsigned int length = 1; 1001 1002 for (key = keymap; key->type != KE_END; key++) 1003 length++; 1004 1005 new_keymap = kmemdup(keymap, length * sizeof(struct key_entry), 1006 GFP_KERNEL); 1007 if (!new_keymap) 1008 return -ENOMEM; 1009 1010 keymap = new_keymap; 1011 1012 return 0; 1013 } 1014 1015 static int __init select_keymap(void) 1016 { 1017 dmi_check_system(dmi_ids); 1018 if (keymap_name != NULL) { 1019 if (strcmp (keymap_name, "1557/MS2141") == 0) 1020 keymap = keymap_wistron_ms2141; 1021 else if (strcmp (keymap_name, "aopen1557") == 0) 1022 keymap = keymap_aopen_1557; 1023 else if (strcmp (keymap_name, "prestigio") == 0) 1024 keymap = keymap_prestigio; 1025 else if (strcmp (keymap_name, "generic") == 0) 1026 keymap = keymap_wistron_generic; 1027 else { 1028 printk(KERN_ERR "wistron_btns: Keymap unknown\n"); 1029 return -EINVAL; 1030 } 1031 } 1032 if (keymap == NULL) { 1033 if (!force) { 1034 printk(KERN_ERR "wistron_btns: System unknown\n"); 1035 return -ENODEV; 1036 } 1037 keymap = keymap_empty; 1038 } 1039 1040 return copy_keymap(); 1041 } 1042 1043 /* Input layer interface */ 1044 1045 static struct input_polled_dev *wistron_idev; 1046 static unsigned long jiffies_last_press; 1047 static bool wifi_enabled; 1048 static bool bluetooth_enabled; 1049 1050 /* led management */ 1051 static void wistron_mail_led_set(struct led_classdev *led_cdev, 1052 enum led_brightness value) 1053 { 1054 bios_set_state(MAIL_LED, (value != LED_OFF) ? 1 : 0); 1055 } 1056 1057 /* same as setting up wifi card, but for laptops on which the led is managed */ 1058 static void wistron_wifi_led_set(struct led_classdev *led_cdev, 1059 enum led_brightness value) 1060 { 1061 bios_set_state(WIFI, (value != LED_OFF) ? 1 : 0); 1062 } 1063 1064 static struct led_classdev wistron_mail_led = { 1065 .name = "wistron:green:mail", 1066 .brightness_set = wistron_mail_led_set, 1067 }; 1068 1069 static struct led_classdev wistron_wifi_led = { 1070 .name = "wistron:red:wifi", 1071 .brightness_set = wistron_wifi_led_set, 1072 }; 1073 1074 static void wistron_led_init(struct device *parent) 1075 { 1076 if (leds_present & FE_WIFI_LED) { 1077 u16 wifi = bios_get_default_setting(WIFI); 1078 if (wifi & 1) { 1079 wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF; 1080 if (led_classdev_register(parent, &wistron_wifi_led)) 1081 leds_present &= ~FE_WIFI_LED; 1082 else 1083 bios_set_state(WIFI, wistron_wifi_led.brightness); 1084 1085 } else 1086 leds_present &= ~FE_WIFI_LED; 1087 } 1088 1089 if (leds_present & FE_MAIL_LED) { 1090 /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */ 1091 wistron_mail_led.brightness = LED_OFF; 1092 if (led_classdev_register(parent, &wistron_mail_led)) 1093 leds_present &= ~FE_MAIL_LED; 1094 else 1095 bios_set_state(MAIL_LED, wistron_mail_led.brightness); 1096 } 1097 } 1098 1099 static void wistron_led_remove(void) 1100 { 1101 if (leds_present & FE_MAIL_LED) 1102 led_classdev_unregister(&wistron_mail_led); 1103 1104 if (leds_present & FE_WIFI_LED) 1105 led_classdev_unregister(&wistron_wifi_led); 1106 } 1107 1108 static inline void wistron_led_suspend(void) 1109 { 1110 if (leds_present & FE_MAIL_LED) 1111 led_classdev_suspend(&wistron_mail_led); 1112 1113 if (leds_present & FE_WIFI_LED) 1114 led_classdev_suspend(&wistron_wifi_led); 1115 } 1116 1117 static inline void wistron_led_resume(void) 1118 { 1119 if (leds_present & FE_MAIL_LED) 1120 led_classdev_resume(&wistron_mail_led); 1121 1122 if (leds_present & FE_WIFI_LED) 1123 led_classdev_resume(&wistron_wifi_led); 1124 } 1125 1126 static void handle_key(u8 code) 1127 { 1128 const struct key_entry *key = 1129 sparse_keymap_entry_from_scancode(wistron_idev->input, code); 1130 1131 if (key) { 1132 switch (key->type) { 1133 case KE_WIFI: 1134 if (have_wifi) { 1135 wifi_enabled = !wifi_enabled; 1136 bios_set_state(WIFI, wifi_enabled); 1137 } 1138 break; 1139 1140 case KE_BLUETOOTH: 1141 if (have_bluetooth) { 1142 bluetooth_enabled = !bluetooth_enabled; 1143 bios_set_state(BLUETOOTH, bluetooth_enabled); 1144 } 1145 break; 1146 1147 default: 1148 sparse_keymap_report_entry(wistron_idev->input, 1149 key, 1, true); 1150 break; 1151 } 1152 jiffies_last_press = jiffies; 1153 } else 1154 printk(KERN_NOTICE 1155 "wistron_btns: Unknown key code %02X\n", code); 1156 } 1157 1158 static void poll_bios(bool discard) 1159 { 1160 u8 qlen; 1161 u16 val; 1162 1163 for (;;) { 1164 qlen = CMOS_READ(cmos_address); 1165 if (qlen == 0) 1166 break; 1167 val = bios_pop_queue(); 1168 if (val != 0 && !discard) 1169 handle_key((u8)val); 1170 } 1171 } 1172 1173 static void wistron_flush(struct input_polled_dev *dev) 1174 { 1175 /* Flush stale event queue */ 1176 poll_bios(true); 1177 } 1178 1179 static void wistron_poll(struct input_polled_dev *dev) 1180 { 1181 poll_bios(false); 1182 1183 /* Increase poll frequency if user is currently pressing keys (< 2s ago) */ 1184 if (time_before(jiffies, jiffies_last_press + 2 * HZ)) 1185 dev->poll_interval = POLL_INTERVAL_BURST; 1186 else 1187 dev->poll_interval = POLL_INTERVAL_DEFAULT; 1188 } 1189 1190 static int wistron_setup_keymap(struct input_dev *dev, 1191 struct key_entry *entry) 1192 { 1193 switch (entry->type) { 1194 1195 /* if wifi or bluetooth are not available, create normal keys */ 1196 case KE_WIFI: 1197 if (!have_wifi) { 1198 entry->type = KE_KEY; 1199 entry->keycode = KEY_WLAN; 1200 } 1201 break; 1202 1203 case KE_BLUETOOTH: 1204 if (!have_bluetooth) { 1205 entry->type = KE_KEY; 1206 entry->keycode = KEY_BLUETOOTH; 1207 } 1208 break; 1209 1210 case KE_END: 1211 if (entry->code & FE_UNTESTED) 1212 printk(KERN_WARNING "Untested laptop multimedia keys, " 1213 "please report success or failure to " 1214 "eric.piel@tremplin-utc.net\n"); 1215 break; 1216 } 1217 1218 return 0; 1219 } 1220 1221 static int setup_input_dev(void) 1222 { 1223 struct input_dev *input_dev; 1224 int error; 1225 1226 wistron_idev = input_allocate_polled_device(); 1227 if (!wistron_idev) 1228 return -ENOMEM; 1229 1230 wistron_idev->open = wistron_flush; 1231 wistron_idev->poll = wistron_poll; 1232 wistron_idev->poll_interval = POLL_INTERVAL_DEFAULT; 1233 1234 input_dev = wistron_idev->input; 1235 input_dev->name = "Wistron laptop buttons"; 1236 input_dev->phys = "wistron/input0"; 1237 input_dev->id.bustype = BUS_HOST; 1238 input_dev->dev.parent = &wistron_device->dev; 1239 1240 error = sparse_keymap_setup(input_dev, keymap, wistron_setup_keymap); 1241 if (error) 1242 goto err_free_dev; 1243 1244 error = input_register_polled_device(wistron_idev); 1245 if (error) 1246 goto err_free_dev; 1247 1248 return 0; 1249 1250 err_free_dev: 1251 input_free_polled_device(wistron_idev); 1252 return error; 1253 } 1254 1255 /* Driver core */ 1256 1257 static int wistron_probe(struct platform_device *dev) 1258 { 1259 int err; 1260 1261 bios_attach(); 1262 cmos_address = bios_get_cmos_address(); 1263 1264 if (have_wifi) { 1265 u16 wifi = bios_get_default_setting(WIFI); 1266 if (wifi & 1) 1267 wifi_enabled = wifi & 2; 1268 else 1269 have_wifi = 0; 1270 1271 if (have_wifi) 1272 bios_set_state(WIFI, wifi_enabled); 1273 } 1274 1275 if (have_bluetooth) { 1276 u16 bt = bios_get_default_setting(BLUETOOTH); 1277 if (bt & 1) 1278 bluetooth_enabled = bt & 2; 1279 else 1280 have_bluetooth = false; 1281 1282 if (have_bluetooth) 1283 bios_set_state(BLUETOOTH, bluetooth_enabled); 1284 } 1285 1286 wistron_led_init(&dev->dev); 1287 1288 err = setup_input_dev(); 1289 if (err) { 1290 bios_detach(); 1291 return err; 1292 } 1293 1294 return 0; 1295 } 1296 1297 static int wistron_remove(struct platform_device *dev) 1298 { 1299 wistron_led_remove(); 1300 input_unregister_polled_device(wistron_idev); 1301 input_free_polled_device(wistron_idev); 1302 bios_detach(); 1303 1304 return 0; 1305 } 1306 1307 #ifdef CONFIG_PM 1308 static int wistron_suspend(struct device *dev) 1309 { 1310 if (have_wifi) 1311 bios_set_state(WIFI, 0); 1312 1313 if (have_bluetooth) 1314 bios_set_state(BLUETOOTH, 0); 1315 1316 wistron_led_suspend(); 1317 1318 return 0; 1319 } 1320 1321 static int wistron_resume(struct device *dev) 1322 { 1323 if (have_wifi) 1324 bios_set_state(WIFI, wifi_enabled); 1325 1326 if (have_bluetooth) 1327 bios_set_state(BLUETOOTH, bluetooth_enabled); 1328 1329 wistron_led_resume(); 1330 1331 poll_bios(true); 1332 1333 return 0; 1334 } 1335 1336 static const struct dev_pm_ops wistron_pm_ops = { 1337 .suspend = wistron_suspend, 1338 .resume = wistron_resume, 1339 .poweroff = wistron_suspend, 1340 .restore = wistron_resume, 1341 }; 1342 #endif 1343 1344 static struct platform_driver wistron_driver = { 1345 .driver = { 1346 .name = "wistron-bios", 1347 #ifdef CONFIG_PM 1348 .pm = &wistron_pm_ops, 1349 #endif 1350 }, 1351 .probe = wistron_probe, 1352 .remove = wistron_remove, 1353 }; 1354 1355 static int __init wb_module_init(void) 1356 { 1357 int err; 1358 1359 err = select_keymap(); 1360 if (err) 1361 return err; 1362 1363 err = map_bios(); 1364 if (err) 1365 goto err_free_keymap; 1366 1367 err = platform_driver_register(&wistron_driver); 1368 if (err) 1369 goto err_unmap_bios; 1370 1371 wistron_device = platform_device_alloc("wistron-bios", -1); 1372 if (!wistron_device) { 1373 err = -ENOMEM; 1374 goto err_unregister_driver; 1375 } 1376 1377 err = platform_device_add(wistron_device); 1378 if (err) 1379 goto err_free_device; 1380 1381 return 0; 1382 1383 err_free_device: 1384 platform_device_put(wistron_device); 1385 err_unregister_driver: 1386 platform_driver_unregister(&wistron_driver); 1387 err_unmap_bios: 1388 unmap_bios(); 1389 err_free_keymap: 1390 kfree(keymap); 1391 1392 return err; 1393 } 1394 1395 static void __exit wb_module_exit(void) 1396 { 1397 platform_device_unregister(wistron_device); 1398 platform_driver_unregister(&wistron_driver); 1399 unmap_bios(); 1400 kfree(keymap); 1401 } 1402 1403 module_init(wb_module_init); 1404 module_exit(wb_module_exit); 1405