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/interrupt.h> 25 #include <linux/jiffies.h> 26 #include <linux/kernel.h> 27 #include <linux/mc146818rtc.h> 28 #include <linux/module.h> 29 #include <linux/preempt.h> 30 #include <linux/string.h> 31 #include <linux/types.h> 32 #include <linux/platform_device.h> 33 #include <linux/leds.h> 34 35 /* How often we poll keys - msecs */ 36 #define POLL_INTERVAL_DEFAULT 500 /* when idle */ 37 #define POLL_INTERVAL_BURST 100 /* when a key was recently pressed */ 38 39 /* BIOS subsystem IDs */ 40 #define WIFI 0x35 41 #define BLUETOOTH 0x34 42 #define MAIL_LED 0x31 43 44 MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>"); 45 MODULE_DESCRIPTION("Wistron laptop button driver"); 46 MODULE_LICENSE("GPL v2"); 47 MODULE_VERSION("0.3"); 48 49 static int force; /* = 0; */ 50 module_param(force, bool, 0); 51 MODULE_PARM_DESC(force, "Load even if computer is not in database"); 52 53 static char *keymap_name; /* = NULL; */ 54 module_param_named(keymap, keymap_name, charp, 0); 55 MODULE_PARM_DESC(keymap, "Keymap name, if it can't be autodetected [generic, 1557/MS2141]"); 56 57 static struct platform_device *wistron_device; 58 59 /* BIOS interface implementation */ 60 61 static void __iomem *bios_entry_point; /* BIOS routine entry point */ 62 static void __iomem *bios_code_map_base; 63 static void __iomem *bios_data_map_base; 64 65 static u8 cmos_address; 66 67 struct regs { 68 u32 eax, ebx, ecx; 69 }; 70 71 static void call_bios(struct regs *regs) 72 { 73 unsigned long flags; 74 75 preempt_disable(); 76 local_irq_save(flags); 77 asm volatile ("pushl %%ebp;" 78 "movl %7, %%ebp;" 79 "call *%6;" 80 "popl %%ebp" 81 : "=a" (regs->eax), "=b" (regs->ebx), "=c" (regs->ecx) 82 : "0" (regs->eax), "1" (regs->ebx), "2" (regs->ecx), 83 "m" (bios_entry_point), "m" (bios_data_map_base) 84 : "edx", "edi", "esi", "memory"); 85 local_irq_restore(flags); 86 preempt_enable(); 87 } 88 89 static ssize_t __init locate_wistron_bios(void __iomem *base) 90 { 91 static unsigned char __initdata signature[] = 92 { 0x42, 0x21, 0x55, 0x30 }; 93 ssize_t offset; 94 95 for (offset = 0; offset < 0x10000; offset += 0x10) { 96 if (check_signature(base + offset, signature, 97 sizeof(signature)) != 0) 98 return offset; 99 } 100 return -1; 101 } 102 103 static int __init map_bios(void) 104 { 105 void __iomem *base; 106 ssize_t offset; 107 u32 entry_point; 108 109 base = ioremap(0xF0000, 0x10000); /* Can't fail */ 110 offset = locate_wistron_bios(base); 111 if (offset < 0) { 112 printk(KERN_ERR "wistron_btns: BIOS entry point not found\n"); 113 iounmap(base); 114 return -ENODEV; 115 } 116 117 entry_point = readl(base + offset + 5); 118 printk(KERN_DEBUG 119 "wistron_btns: BIOS signature found at %p, entry point %08X\n", 120 base + offset, entry_point); 121 122 if (entry_point >= 0xF0000) { 123 bios_code_map_base = base; 124 bios_entry_point = bios_code_map_base + (entry_point & 0xFFFF); 125 } else { 126 iounmap(base); 127 bios_code_map_base = ioremap(entry_point & ~0x3FFF, 0x4000); 128 if (bios_code_map_base == NULL) { 129 printk(KERN_ERR 130 "wistron_btns: Can't map BIOS code at %08X\n", 131 entry_point & ~0x3FFF); 132 goto err; 133 } 134 bios_entry_point = bios_code_map_base + (entry_point & 0x3FFF); 135 } 136 /* The Windows driver maps 0x10000 bytes, we keep only one page... */ 137 bios_data_map_base = ioremap(0x400, 0xc00); 138 if (bios_data_map_base == NULL) { 139 printk(KERN_ERR "wistron_btns: Can't map BIOS data\n"); 140 goto err_code; 141 } 142 return 0; 143 144 err_code: 145 iounmap(bios_code_map_base); 146 err: 147 return -ENOMEM; 148 } 149 150 static inline void unmap_bios(void) 151 { 152 iounmap(bios_code_map_base); 153 iounmap(bios_data_map_base); 154 } 155 156 /* BIOS calls */ 157 158 static u16 bios_pop_queue(void) 159 { 160 struct regs regs; 161 162 memset(®s, 0, sizeof (regs)); 163 regs.eax = 0x9610; 164 regs.ebx = 0x061C; 165 regs.ecx = 0x0000; 166 call_bios(®s); 167 168 return regs.eax; 169 } 170 171 static void __devinit bios_attach(void) 172 { 173 struct regs regs; 174 175 memset(®s, 0, sizeof (regs)); 176 regs.eax = 0x9610; 177 regs.ebx = 0x012E; 178 call_bios(®s); 179 } 180 181 static void bios_detach(void) 182 { 183 struct regs regs; 184 185 memset(®s, 0, sizeof (regs)); 186 regs.eax = 0x9610; 187 regs.ebx = 0x002E; 188 call_bios(®s); 189 } 190 191 static u8 __devinit bios_get_cmos_address(void) 192 { 193 struct regs regs; 194 195 memset(®s, 0, sizeof (regs)); 196 regs.eax = 0x9610; 197 regs.ebx = 0x051C; 198 call_bios(®s); 199 200 return regs.ecx; 201 } 202 203 static u16 __devinit bios_get_default_setting(u8 subsys) 204 { 205 struct regs regs; 206 207 memset(®s, 0, sizeof (regs)); 208 regs.eax = 0x9610; 209 regs.ebx = 0x0200 | subsys; 210 call_bios(®s); 211 212 return regs.eax; 213 } 214 215 static void bios_set_state(u8 subsys, int enable) 216 { 217 struct regs regs; 218 219 memset(®s, 0, sizeof (regs)); 220 regs.eax = 0x9610; 221 regs.ebx = (enable ? 0x0100 : 0x0000) | subsys; 222 call_bios(®s); 223 } 224 225 /* Hardware database */ 226 227 struct key_entry { 228 char type; /* See KE_* below */ 229 u8 code; 230 union { 231 u16 keycode; /* For KE_KEY */ 232 struct { /* For KE_SW */ 233 u8 code; 234 u8 value; 235 } sw; 236 }; 237 }; 238 239 enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH }; 240 241 #define FE_MAIL_LED 0x01 242 #define FE_WIFI_LED 0x02 243 #define FE_UNTESTED 0x80 244 245 static struct key_entry *keymap; /* = NULL; Current key map */ 246 static bool have_wifi; 247 static bool have_bluetooth; 248 static int leds_present; /* bitmask of leds present */ 249 250 static int __init dmi_matched(const struct dmi_system_id *dmi) 251 { 252 const struct key_entry *key; 253 254 keymap = dmi->driver_data; 255 for (key = keymap; key->type != KE_END; key++) { 256 if (key->type == KE_WIFI) 257 have_wifi = true; 258 else if (key->type == KE_BLUETOOTH) 259 have_bluetooth = true; 260 } 261 leds_present = key->code & (FE_MAIL_LED | FE_WIFI_LED); 262 263 return 1; 264 } 265 266 static struct key_entry keymap_empty[] __initdata = { 267 { KE_END, 0 } 268 }; 269 270 static struct key_entry keymap_fs_amilo_pro_v2000[] __initdata = { 271 { KE_KEY, 0x01, {KEY_HELP} }, 272 { KE_KEY, 0x11, {KEY_PROG1} }, 273 { KE_KEY, 0x12, {KEY_PROG2} }, 274 { KE_WIFI, 0x30 }, 275 { KE_KEY, 0x31, {KEY_MAIL} }, 276 { KE_KEY, 0x36, {KEY_WWW} }, 277 { KE_END, 0 } 278 }; 279 280 static struct key_entry keymap_fs_amilo_pro_v3505[] __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, 0 } 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, FE_UNTESTED } 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 struct dmi_system_id dmi_ids[] __initdata = { 648 { 649 .callback = dmi_matched, 650 .ident = "Fujitsu-Siemens Amilo Pro V2000", 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 .callback = dmi_matched, 659 .ident = "Fujitsu-Siemens Amilo Pro Edition V3505", 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 .callback = dmi_matched, 668 .ident = "Fujitsu-Siemens Amilo M7400", 669 .matches = { 670 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 671 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO M "), 672 }, 673 .driver_data = keymap_fs_amilo_pro_v2000 674 }, 675 { 676 .callback = dmi_matched, 677 .ident = "Maxdata Pro 7000 DX", 678 .matches = { 679 DMI_MATCH(DMI_SYS_VENDOR, "MAXDATA"), 680 DMI_MATCH(DMI_PRODUCT_NAME, "Pro 7000"), 681 }, 682 .driver_data = keymap_fs_amilo_pro_v2000 683 }, 684 { 685 .callback = dmi_matched, 686 .ident = "Fujitsu N3510", 687 .matches = { 688 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), 689 DMI_MATCH(DMI_PRODUCT_NAME, "N3510"), 690 }, 691 .driver_data = keymap_fujitsu_n3510 692 }, 693 { 694 .callback = dmi_matched, 695 .ident = "Acer Aspire 1500", 696 .matches = { 697 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 698 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1500"), 699 }, 700 .driver_data = keymap_acer_aspire_1500 701 }, 702 { 703 .callback = dmi_matched, 704 .ident = "Acer Aspire 1600", 705 .matches = { 706 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 707 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1600"), 708 }, 709 .driver_data = keymap_acer_aspire_1600 710 }, 711 { 712 .callback = dmi_matched, 713 .ident = "Acer Aspire 3020", 714 .matches = { 715 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 716 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3020"), 717 }, 718 .driver_data = keymap_acer_aspire_5020 719 }, 720 { 721 .callback = dmi_matched, 722 .ident = "Acer Aspire 5020", 723 .matches = { 724 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 725 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5020"), 726 }, 727 .driver_data = keymap_acer_aspire_5020 728 }, 729 { 730 .callback = dmi_matched, 731 .ident = "Acer TravelMate 2100", 732 .matches = { 733 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 734 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2100"), 735 }, 736 .driver_data = keymap_acer_aspire_5020 737 }, 738 { 739 .callback = dmi_matched, 740 .ident = "Acer TravelMate 2410", 741 .matches = { 742 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 743 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2410"), 744 }, 745 .driver_data = keymap_acer_travelmate_2410 746 }, 747 { 748 .callback = dmi_matched, 749 .ident = "Acer TravelMate C300", 750 .matches = { 751 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 752 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C300"), 753 }, 754 .driver_data = keymap_acer_travelmate_300 755 }, 756 { 757 .callback = dmi_matched, 758 .ident = "Acer TravelMate C100", 759 .matches = { 760 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 761 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C100"), 762 }, 763 .driver_data = keymap_acer_travelmate_300 764 }, 765 { 766 .callback = dmi_matched, 767 .ident = "Acer TravelMate C110", 768 .matches = { 769 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 770 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C110"), 771 }, 772 .driver_data = keymap_acer_travelmate_110 773 }, 774 { 775 .callback = dmi_matched, 776 .ident = "Acer TravelMate 380", 777 .matches = { 778 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 779 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 380"), 780 }, 781 .driver_data = keymap_acer_travelmate_380 782 }, 783 { 784 .callback = dmi_matched, 785 .ident = "Acer TravelMate 370", 786 .matches = { 787 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 788 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 370"), 789 }, 790 .driver_data = keymap_acer_travelmate_380 /* keyboard minus 1 key */ 791 }, 792 { 793 .callback = dmi_matched, 794 .ident = "Acer TravelMate 220", 795 .matches = { 796 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 797 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 220"), 798 }, 799 .driver_data = keymap_acer_travelmate_220 800 }, 801 { 802 .callback = dmi_matched, 803 .ident = "Acer TravelMate 260", 804 .matches = { 805 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 806 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 260"), 807 }, 808 .driver_data = keymap_acer_travelmate_220 809 }, 810 { 811 .callback = dmi_matched, 812 .ident = "Acer TravelMate 230", 813 .matches = { 814 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 815 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 230"), 816 /* acerhk looks for "TravelMate F4..." ?! */ 817 }, 818 .driver_data = keymap_acer_travelmate_230 819 }, 820 { 821 .callback = dmi_matched, 822 .ident = "Acer TravelMate 280", 823 .matches = { 824 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 825 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 280"), 826 }, 827 .driver_data = keymap_acer_travelmate_230 828 }, 829 { 830 .callback = dmi_matched, 831 .ident = "Acer TravelMate 240", 832 .matches = { 833 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 834 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 240"), 835 }, 836 .driver_data = keymap_acer_travelmate_240 837 }, 838 { 839 .callback = dmi_matched, 840 .ident = "Acer TravelMate 250", 841 .matches = { 842 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 843 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 250"), 844 }, 845 .driver_data = keymap_acer_travelmate_240 846 }, 847 { 848 .callback = dmi_matched, 849 .ident = "Acer TravelMate 2424NWXCi", 850 .matches = { 851 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 852 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2420"), 853 }, 854 .driver_data = keymap_acer_travelmate_240 855 }, 856 { 857 .callback = dmi_matched, 858 .ident = "Acer TravelMate 350", 859 .matches = { 860 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 861 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 350"), 862 }, 863 .driver_data = keymap_acer_travelmate_350 864 }, 865 { 866 .callback = dmi_matched, 867 .ident = "Acer TravelMate 360", 868 .matches = { 869 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 870 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), 871 }, 872 .driver_data = keymap_acer_travelmate_360 873 }, 874 { 875 .callback = dmi_matched, 876 .ident = "Acer TravelMate 610", 877 .matches = { 878 DMI_MATCH(DMI_SYS_VENDOR, "ACER"), 879 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 610"), 880 }, 881 .driver_data = keymap_acer_travelmate_610 882 }, 883 { 884 .callback = dmi_matched, 885 .ident = "Acer TravelMate 620", 886 .matches = { 887 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 888 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 620"), 889 }, 890 .driver_data = keymap_acer_travelmate_630 891 }, 892 { 893 .callback = dmi_matched, 894 .ident = "Acer TravelMate 630", 895 .matches = { 896 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 897 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 630"), 898 }, 899 .driver_data = keymap_acer_travelmate_630 900 }, 901 { 902 .callback = dmi_matched, 903 .ident = "AOpen 1559AS", 904 .matches = { 905 DMI_MATCH(DMI_PRODUCT_NAME, "E2U"), 906 DMI_MATCH(DMI_BOARD_NAME, "E2U"), 907 }, 908 .driver_data = keymap_aopen_1559as 909 }, 910 { 911 .callback = dmi_matched, 912 .ident = "Medion MD 9783", 913 .matches = { 914 DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), 915 DMI_MATCH(DMI_PRODUCT_NAME, "MD 9783"), 916 }, 917 .driver_data = keymap_wistron_ms2111 918 }, 919 { 920 .callback = dmi_matched, 921 .ident = "Medion MD 40100", 922 .matches = { 923 DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), 924 DMI_MATCH(DMI_PRODUCT_NAME, "WID2000"), 925 }, 926 .driver_data = keymap_wistron_md40100 927 }, 928 { 929 .callback = dmi_matched, 930 .ident = "Medion MD 2900", 931 .matches = { 932 DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), 933 DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2000"), 934 }, 935 .driver_data = keymap_wistron_md2900 936 }, 937 { 938 .callback = dmi_matched, 939 .ident = "Medion MD 42200", 940 .matches = { 941 DMI_MATCH(DMI_SYS_VENDOR, "Medion"), 942 DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2030"), 943 }, 944 .driver_data = keymap_fs_amilo_pro_v2000 945 }, 946 { 947 .callback = dmi_matched, 948 .ident = "Medion MD 96500", 949 .matches = { 950 DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"), 951 DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2040"), 952 }, 953 .driver_data = keymap_wistron_md96500 954 }, 955 { 956 .callback = dmi_matched, 957 .ident = "Medion MD 95400", 958 .matches = { 959 DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"), 960 DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2050"), 961 }, 962 .driver_data = keymap_wistron_md96500 963 }, 964 { 965 .callback = dmi_matched, 966 .ident = "Fujitsu Siemens Amilo D7820", 967 .matches = { 968 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), /* not sure */ 969 DMI_MATCH(DMI_PRODUCT_NAME, "Amilo D"), 970 }, 971 .driver_data = keymap_fs_amilo_d88x0 972 }, 973 { 974 .callback = dmi_matched, 975 .ident = "Fujitsu Siemens Amilo D88x0", 976 .matches = { 977 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 978 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO D"), 979 }, 980 .driver_data = keymap_fs_amilo_d88x0 981 }, 982 { NULL, } 983 }; 984 985 /* Copy the good keymap, as the original ones are free'd */ 986 static int __init copy_keymap(void) 987 { 988 const struct key_entry *key; 989 struct key_entry *new_keymap; 990 unsigned int length = 1; 991 992 for (key = keymap; key->type != KE_END; key++) 993 length++; 994 995 new_keymap = kmalloc(length * sizeof(struct key_entry), GFP_KERNEL); 996 if (!new_keymap) 997 return -ENOMEM; 998 999 memcpy(new_keymap, keymap, length * sizeof(struct key_entry)); 1000 keymap = new_keymap; 1001 1002 return 0; 1003 } 1004 1005 static int __init select_keymap(void) 1006 { 1007 dmi_check_system(dmi_ids); 1008 if (keymap_name != NULL) { 1009 if (strcmp (keymap_name, "1557/MS2141") == 0) 1010 keymap = keymap_wistron_ms2141; 1011 else if (strcmp (keymap_name, "aopen1557") == 0) 1012 keymap = keymap_aopen_1557; 1013 else if (strcmp (keymap_name, "prestigio") == 0) 1014 keymap = keymap_prestigio; 1015 else if (strcmp (keymap_name, "generic") == 0) 1016 keymap = keymap_wistron_generic; 1017 else { 1018 printk(KERN_ERR "wistron_btns: Keymap unknown\n"); 1019 return -EINVAL; 1020 } 1021 } 1022 if (keymap == NULL) { 1023 if (!force) { 1024 printk(KERN_ERR "wistron_btns: System unknown\n"); 1025 return -ENODEV; 1026 } 1027 keymap = keymap_empty; 1028 } 1029 1030 return copy_keymap(); 1031 } 1032 1033 /* Input layer interface */ 1034 1035 static struct input_polled_dev *wistron_idev; 1036 static unsigned long jiffies_last_press; 1037 static bool wifi_enabled; 1038 static bool bluetooth_enabled; 1039 1040 static void report_key(struct input_dev *dev, unsigned int keycode) 1041 { 1042 input_report_key(dev, keycode, 1); 1043 input_sync(dev); 1044 input_report_key(dev, keycode, 0); 1045 input_sync(dev); 1046 } 1047 1048 static void report_switch(struct input_dev *dev, unsigned int code, int value) 1049 { 1050 input_report_switch(dev, code, value); 1051 input_sync(dev); 1052 } 1053 1054 1055 /* led management */ 1056 static void wistron_mail_led_set(struct led_classdev *led_cdev, 1057 enum led_brightness value) 1058 { 1059 bios_set_state(MAIL_LED, (value != LED_OFF) ? 1 : 0); 1060 } 1061 1062 /* same as setting up wifi card, but for laptops on which the led is managed */ 1063 static void wistron_wifi_led_set(struct led_classdev *led_cdev, 1064 enum led_brightness value) 1065 { 1066 bios_set_state(WIFI, (value != LED_OFF) ? 1 : 0); 1067 } 1068 1069 static struct led_classdev wistron_mail_led = { 1070 .name = "wistron:green:mail", 1071 .brightness_set = wistron_mail_led_set, 1072 }; 1073 1074 static struct led_classdev wistron_wifi_led = { 1075 .name = "wistron:red:wifi", 1076 .brightness_set = wistron_wifi_led_set, 1077 }; 1078 1079 static void __devinit wistron_led_init(struct device *parent) 1080 { 1081 if (leds_present & FE_WIFI_LED) { 1082 u16 wifi = bios_get_default_setting(WIFI); 1083 if (wifi & 1) { 1084 wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF; 1085 if (led_classdev_register(parent, &wistron_wifi_led)) 1086 leds_present &= ~FE_WIFI_LED; 1087 else 1088 bios_set_state(WIFI, wistron_wifi_led.brightness); 1089 1090 } else 1091 leds_present &= ~FE_WIFI_LED; 1092 } 1093 1094 if (leds_present & FE_MAIL_LED) { 1095 /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */ 1096 wistron_mail_led.brightness = LED_OFF; 1097 if (led_classdev_register(parent, &wistron_mail_led)) 1098 leds_present &= ~FE_MAIL_LED; 1099 else 1100 bios_set_state(MAIL_LED, wistron_mail_led.brightness); 1101 } 1102 } 1103 1104 static void __devexit wistron_led_remove(void) 1105 { 1106 if (leds_present & FE_MAIL_LED) 1107 led_classdev_unregister(&wistron_mail_led); 1108 1109 if (leds_present & FE_WIFI_LED) 1110 led_classdev_unregister(&wistron_wifi_led); 1111 } 1112 1113 static inline void wistron_led_suspend(void) 1114 { 1115 if (leds_present & FE_MAIL_LED) 1116 led_classdev_suspend(&wistron_mail_led); 1117 1118 if (leds_present & FE_WIFI_LED) 1119 led_classdev_suspend(&wistron_wifi_led); 1120 } 1121 1122 static inline void wistron_led_resume(void) 1123 { 1124 if (leds_present & FE_MAIL_LED) 1125 led_classdev_resume(&wistron_mail_led); 1126 1127 if (leds_present & FE_WIFI_LED) 1128 led_classdev_resume(&wistron_wifi_led); 1129 } 1130 1131 static struct key_entry *wistron_get_entry_by_scancode(int code) 1132 { 1133 struct key_entry *key; 1134 1135 for (key = keymap; key->type != KE_END; key++) 1136 if (code == key->code) 1137 return key; 1138 1139 return NULL; 1140 } 1141 1142 static struct key_entry *wistron_get_entry_by_keycode(int keycode) 1143 { 1144 struct key_entry *key; 1145 1146 for (key = keymap; key->type != KE_END; key++) 1147 if (key->type == KE_KEY && keycode == key->keycode) 1148 return key; 1149 1150 return NULL; 1151 } 1152 1153 static void handle_key(u8 code) 1154 { 1155 const struct key_entry *key = wistron_get_entry_by_scancode(code); 1156 1157 if (key) { 1158 switch (key->type) { 1159 case KE_KEY: 1160 report_key(wistron_idev->input, key->keycode); 1161 break; 1162 1163 case KE_SW: 1164 report_switch(wistron_idev->input, 1165 key->sw.code, key->sw.value); 1166 break; 1167 1168 case KE_WIFI: 1169 if (have_wifi) { 1170 wifi_enabled = !wifi_enabled; 1171 bios_set_state(WIFI, wifi_enabled); 1172 } 1173 break; 1174 1175 case KE_BLUETOOTH: 1176 if (have_bluetooth) { 1177 bluetooth_enabled = !bluetooth_enabled; 1178 bios_set_state(BLUETOOTH, bluetooth_enabled); 1179 } 1180 break; 1181 1182 default: 1183 BUG(); 1184 } 1185 jiffies_last_press = jiffies; 1186 } else 1187 printk(KERN_NOTICE 1188 "wistron_btns: Unknown key code %02X\n", code); 1189 } 1190 1191 static void poll_bios(bool discard) 1192 { 1193 u8 qlen; 1194 u16 val; 1195 1196 for (;;) { 1197 qlen = CMOS_READ(cmos_address); 1198 if (qlen == 0) 1199 break; 1200 val = bios_pop_queue(); 1201 if (val != 0 && !discard) 1202 handle_key((u8)val); 1203 } 1204 } 1205 1206 static void wistron_flush(struct input_polled_dev *dev) 1207 { 1208 /* Flush stale event queue */ 1209 poll_bios(true); 1210 } 1211 1212 static void wistron_poll(struct input_polled_dev *dev) 1213 { 1214 poll_bios(false); 1215 1216 /* Increase poll frequency if user is currently pressing keys (< 2s ago) */ 1217 if (time_before(jiffies, jiffies_last_press + 2 * HZ)) 1218 dev->poll_interval = POLL_INTERVAL_BURST; 1219 else 1220 dev->poll_interval = POLL_INTERVAL_DEFAULT; 1221 } 1222 1223 static int wistron_getkeycode(struct input_dev *dev, int scancode, int *keycode) 1224 { 1225 const struct key_entry *key = wistron_get_entry_by_scancode(scancode); 1226 1227 if (key && key->type == KE_KEY) { 1228 *keycode = key->keycode; 1229 return 0; 1230 } 1231 1232 return -EINVAL; 1233 } 1234 1235 static int wistron_setkeycode(struct input_dev *dev, int scancode, int keycode) 1236 { 1237 struct key_entry *key; 1238 int old_keycode; 1239 1240 if (keycode < 0 || keycode > KEY_MAX) 1241 return -EINVAL; 1242 1243 key = wistron_get_entry_by_scancode(scancode); 1244 if (key && key->type == KE_KEY) { 1245 old_keycode = key->keycode; 1246 key->keycode = keycode; 1247 set_bit(keycode, dev->keybit); 1248 if (!wistron_get_entry_by_keycode(old_keycode)) 1249 clear_bit(old_keycode, dev->keybit); 1250 return 0; 1251 } 1252 1253 return -EINVAL; 1254 } 1255 1256 static int __devinit setup_input_dev(void) 1257 { 1258 struct key_entry *key; 1259 struct input_dev *input_dev; 1260 int error; 1261 1262 wistron_idev = input_allocate_polled_device(); 1263 if (!wistron_idev) 1264 return -ENOMEM; 1265 1266 wistron_idev->flush = wistron_flush; 1267 wistron_idev->poll = wistron_poll; 1268 wistron_idev->poll_interval = POLL_INTERVAL_DEFAULT; 1269 1270 input_dev = wistron_idev->input; 1271 input_dev->name = "Wistron laptop buttons"; 1272 input_dev->phys = "wistron/input0"; 1273 input_dev->id.bustype = BUS_HOST; 1274 input_dev->dev.parent = &wistron_device->dev; 1275 1276 input_dev->getkeycode = wistron_getkeycode; 1277 input_dev->setkeycode = wistron_setkeycode; 1278 1279 for (key = keymap; key->type != KE_END; key++) { 1280 switch (key->type) { 1281 case KE_KEY: 1282 set_bit(EV_KEY, input_dev->evbit); 1283 set_bit(key->keycode, input_dev->keybit); 1284 break; 1285 1286 case KE_SW: 1287 set_bit(EV_SW, input_dev->evbit); 1288 set_bit(key->sw.code, input_dev->swbit); 1289 break; 1290 1291 /* if wifi or bluetooth are not available, create normal keys */ 1292 case KE_WIFI: 1293 if (!have_wifi) { 1294 key->type = KE_KEY; 1295 key->keycode = KEY_WLAN; 1296 key--; 1297 } 1298 break; 1299 1300 case KE_BLUETOOTH: 1301 if (!have_bluetooth) { 1302 key->type = KE_KEY; 1303 key->keycode = KEY_BLUETOOTH; 1304 key--; 1305 } 1306 break; 1307 1308 default: 1309 break; 1310 } 1311 } 1312 1313 /* reads information flags on KE_END */ 1314 if (key->code & FE_UNTESTED) 1315 printk(KERN_WARNING "Untested laptop multimedia keys, " 1316 "please report success or failure to eric.piel" 1317 "@tremplin-utc.net\n"); 1318 1319 error = input_register_polled_device(wistron_idev); 1320 if (error) { 1321 input_free_polled_device(wistron_idev); 1322 return error; 1323 } 1324 1325 return 0; 1326 } 1327 1328 /* Driver core */ 1329 1330 static int __devinit wistron_probe(struct platform_device *dev) 1331 { 1332 int err; 1333 1334 bios_attach(); 1335 cmos_address = bios_get_cmos_address(); 1336 1337 if (have_wifi) { 1338 u16 wifi = bios_get_default_setting(WIFI); 1339 if (wifi & 1) 1340 wifi_enabled = wifi & 2; 1341 else 1342 have_wifi = 0; 1343 1344 if (have_wifi) 1345 bios_set_state(WIFI, wifi_enabled); 1346 } 1347 1348 if (have_bluetooth) { 1349 u16 bt = bios_get_default_setting(BLUETOOTH); 1350 if (bt & 1) 1351 bluetooth_enabled = bt & 2; 1352 else 1353 have_bluetooth = false; 1354 1355 if (have_bluetooth) 1356 bios_set_state(BLUETOOTH, bluetooth_enabled); 1357 } 1358 1359 wistron_led_init(&dev->dev); 1360 1361 err = setup_input_dev(); 1362 if (err) { 1363 bios_detach(); 1364 return err; 1365 } 1366 1367 return 0; 1368 } 1369 1370 static int __devexit wistron_remove(struct platform_device *dev) 1371 { 1372 wistron_led_remove(); 1373 input_unregister_polled_device(wistron_idev); 1374 input_free_polled_device(wistron_idev); 1375 bios_detach(); 1376 1377 return 0; 1378 } 1379 1380 #ifdef CONFIG_PM 1381 static int wistron_suspend(struct device *dev) 1382 { 1383 if (have_wifi) 1384 bios_set_state(WIFI, 0); 1385 1386 if (have_bluetooth) 1387 bios_set_state(BLUETOOTH, 0); 1388 1389 wistron_led_suspend(); 1390 1391 return 0; 1392 } 1393 1394 static int wistron_resume(struct device *dev) 1395 { 1396 if (have_wifi) 1397 bios_set_state(WIFI, wifi_enabled); 1398 1399 if (have_bluetooth) 1400 bios_set_state(BLUETOOTH, bluetooth_enabled); 1401 1402 wistron_led_resume(); 1403 1404 poll_bios(true); 1405 1406 return 0; 1407 } 1408 1409 static const struct dev_pm_ops wistron_pm_ops = { 1410 .suspend = wistron_suspend, 1411 .resume = wistron_resume, 1412 .poweroff = wistron_suspend, 1413 .restore = wistron_resume, 1414 }; 1415 #endif 1416 1417 static struct platform_driver wistron_driver = { 1418 .driver = { 1419 .name = "wistron-bios", 1420 .owner = THIS_MODULE, 1421 #if CONFIG_PM 1422 .pm = &wistron_pm_ops, 1423 #endif 1424 }, 1425 .probe = wistron_probe, 1426 .remove = __devexit_p(wistron_remove), 1427 }; 1428 1429 static int __init wb_module_init(void) 1430 { 1431 int err; 1432 1433 err = select_keymap(); 1434 if (err) 1435 return err; 1436 1437 err = map_bios(); 1438 if (err) 1439 return err; 1440 1441 err = platform_driver_register(&wistron_driver); 1442 if (err) 1443 goto err_unmap_bios; 1444 1445 wistron_device = platform_device_alloc("wistron-bios", -1); 1446 if (!wistron_device) { 1447 err = -ENOMEM; 1448 goto err_unregister_driver; 1449 } 1450 1451 err = platform_device_add(wistron_device); 1452 if (err) 1453 goto err_free_device; 1454 1455 return 0; 1456 1457 err_free_device: 1458 platform_device_put(wistron_device); 1459 err_unregister_driver: 1460 platform_driver_unregister(&wistron_driver); 1461 err_unmap_bios: 1462 unmap_bios(); 1463 1464 return err; 1465 } 1466 1467 static void __exit wb_module_exit(void) 1468 { 1469 platform_device_unregister(wistron_device); 1470 platform_driver_unregister(&wistron_driver); 1471 unmap_bios(); 1472 kfree(keymap); 1473 } 1474 1475 module_init(wb_module_init); 1476 module_exit(wb_module_exit); 1477