linux/drivers/input/misc/wistron_btns.c
<<
>>
Prefs
   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
  44MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>");
  45MODULE_DESCRIPTION("Wistron laptop button driver");
  46MODULE_LICENSE("GPL v2");
  47MODULE_VERSION("0.3");
  48
  49static int force; /* = 0; */
  50module_param(force, bool, 0);
  51MODULE_PARM_DESC(force, "Load even if computer is not in database");
  52
  53static char *keymap_name; /* = NULL; */
  54module_param_named(keymap, keymap_name, charp, 0);
  55MODULE_PARM_DESC(keymap, "Keymap name, if it can't be autodetected [generic, 1557/MS2141]");
  56
  57static struct platform_device *wistron_device;
  58
  59 /* BIOS interface implementation */
  60
  61static void __iomem *bios_entry_point; /* BIOS routine entry point */
  62static void __iomem *bios_code_map_base;
  63static void __iomem *bios_data_map_base;
  64
  65static u8 cmos_address;
  66
  67struct regs {
  68        u32 eax, ebx, ecx;
  69};
  70
  71static 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
  89static 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
 103static 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
 144err_code:
 145        iounmap(bios_code_map_base);
 146err:
 147        return -ENOMEM;
 148}
 149
 150static inline void unmap_bios(void)
 151{
 152        iounmap(bios_code_map_base);
 153        iounmap(bios_data_map_base);
 154}
 155
 156 /* BIOS calls */
 157
 158static u16 bios_pop_queue(void)
 159{
 160        struct regs regs;
 161
 162        memset(&regs, 0, sizeof (regs));
 163        regs.eax = 0x9610;
 164        regs.ebx = 0x061C;
 165        regs.ecx = 0x0000;
 166        call_bios(&regs);
 167
 168        return regs.eax;
 169}
 170
 171static void __devinit bios_attach(void)
 172{
 173        struct regs regs;
 174
 175        memset(&regs, 0, sizeof (regs));
 176        regs.eax = 0x9610;
 177        regs.ebx = 0x012E;
 178        call_bios(&regs);
 179}
 180
 181static void bios_detach(void)
 182{
 183        struct regs regs;
 184
 185        memset(&regs, 0, sizeof (regs));
 186        regs.eax = 0x9610;
 187        regs.ebx = 0x002E;
 188        call_bios(&regs);
 189}
 190
 191static u8 __devinit bios_get_cmos_address(void)
 192{
 193        struct regs regs;
 194
 195        memset(&regs, 0, sizeof (regs));
 196        regs.eax = 0x9610;
 197        regs.ebx = 0x051C;
 198        call_bios(&regs);
 199
 200        return regs.ecx;
 201}
 202
 203static u16 __devinit bios_get_default_setting(u8 subsys)
 204{
 205        struct regs regs;
 206
 207        memset(&regs, 0, sizeof (regs));
 208        regs.eax = 0x9610;
 209        regs.ebx = 0x0200 | subsys;
 210        call_bios(&regs);
 211
 212        return regs.eax;
 213}
 214
 215static void bios_set_state(u8 subsys, int enable)
 216{
 217        struct regs regs;
 218
 219        memset(&regs, 0, sizeof (regs));
 220        regs.eax = 0x9610;
 221        regs.ebx = (enable ? 0x0100 : 0x0000) | subsys;
 222        call_bios(&regs);
 223}
 224
 225/* Hardware database */
 226
 227struct 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
 239enum { 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
 245static struct key_entry *keymap; /* = NULL; Current key map */
 246static int have_wifi;
 247static int have_bluetooth;
 248static int have_leds;
 249
 250static 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 = 1;
 258                else if (key->type == KE_BLUETOOTH)
 259                        have_bluetooth = 1;
 260        }
 261        have_leds = key->code & (FE_MAIL_LED | FE_WIFI_LED);
 262
 263        return 1;
 264}
 265
 266static struct key_entry keymap_empty[] __initdata = {
 267        { KE_END, 0 }
 268};
 269
 270static 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
 280static 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
 290static 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
 302static 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
 311static 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
 320static 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
 333static 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
 346static 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 */
 362static 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
 376static 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
 389static 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
 406static 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
 422static 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 */
 436static 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
 446static 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
 456static 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
 470static 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
 481static 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) */
 496static 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
 508static 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
 524static 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
 535static 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
 546static 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
 557static 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
 578static 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/*
 615 * If your machine is not here (which is currently rather likely), please send
 616 * a list of buttons and their key codes (reported when loading this module
 617 * with force=1) and the output of dmidecode to $MODULE_AUTHOR.
 618 */
 619static struct dmi_system_id dmi_ids[] __initdata = {
 620        {
 621                .callback = dmi_matched,
 622                .ident = "Fujitsu-Siemens Amilo Pro V2000",
 623                .matches = {
 624                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
 625                        DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro V2000"),
 626                },
 627                .driver_data = keymap_fs_amilo_pro_v2000
 628        },
 629        {
 630                .callback = dmi_matched,
 631                .ident = "Fujitsu-Siemens Amilo Pro Edition V3505",
 632                .matches = {
 633                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
 634                        DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Edition V3505"),
 635                },
 636                .driver_data = keymap_fs_amilo_pro_v3505
 637        },
 638        {
 639                .callback = dmi_matched,
 640                .ident = "Fujitsu-Siemens Amilo M7400",
 641                .matches = {
 642                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
 643                        DMI_MATCH(DMI_PRODUCT_NAME, "AMILO M        "),
 644                },
 645                .driver_data = keymap_fs_amilo_pro_v2000
 646        },
 647        {
 648                .callback = dmi_matched,
 649                .ident = "Maxdata Pro 7000 DX",
 650                .matches = {
 651                        DMI_MATCH(DMI_SYS_VENDOR, "MAXDATA"),
 652                        DMI_MATCH(DMI_PRODUCT_NAME, "Pro 7000"),
 653                },
 654                .driver_data = keymap_fs_amilo_pro_v2000
 655        },
 656        {
 657                .callback = dmi_matched,
 658                .ident = "Fujitsu N3510",
 659                .matches = {
 660                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
 661                        DMI_MATCH(DMI_PRODUCT_NAME, "N3510"),
 662                },
 663                .driver_data = keymap_fujitsu_n3510
 664        },
 665        {
 666                .callback = dmi_matched,
 667                .ident = "Acer Aspire 1500",
 668                .matches = {
 669                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 670                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1500"),
 671                },
 672                .driver_data = keymap_acer_aspire_1500
 673        },
 674        {
 675                .callback = dmi_matched,
 676                .ident = "Acer Aspire 1600",
 677                .matches = {
 678                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 679                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1600"),
 680                },
 681                .driver_data = keymap_acer_aspire_1600
 682        },
 683        {
 684                .callback = dmi_matched,
 685                .ident = "Acer Aspire 3020",
 686                .matches = {
 687                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 688                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3020"),
 689                },
 690                .driver_data = keymap_acer_aspire_5020
 691        },
 692        {
 693                .callback = dmi_matched,
 694                .ident = "Acer Aspire 5020",
 695                .matches = {
 696                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 697                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5020"),
 698                },
 699                .driver_data = keymap_acer_aspire_5020
 700        },
 701        {
 702                .callback = dmi_matched,
 703                .ident = "Acer TravelMate 2100",
 704                .matches = {
 705                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 706                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2100"),
 707                },
 708                .driver_data = keymap_acer_aspire_5020
 709        },
 710        {
 711                .callback = dmi_matched,
 712                .ident = "Acer TravelMate 2410",
 713                .matches = {
 714                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 715                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2410"),
 716                },
 717                .driver_data = keymap_acer_travelmate_2410
 718        },
 719        {
 720                .callback = dmi_matched,
 721                .ident = "Acer TravelMate C300",
 722                .matches = {
 723                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 724                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C300"),
 725                },
 726                .driver_data = keymap_acer_travelmate_300
 727        },
 728        {
 729                .callback = dmi_matched,
 730                .ident = "Acer TravelMate C100",
 731                .matches = {
 732                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 733                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C100"),
 734                },
 735                .driver_data = keymap_acer_travelmate_300
 736        },
 737        {
 738                .callback = dmi_matched,
 739                .ident = "Acer TravelMate C110",
 740                .matches = {
 741                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 742                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C110"),
 743                },
 744                .driver_data = keymap_acer_travelmate_110
 745        },
 746        {
 747                .callback = dmi_matched,
 748                .ident = "Acer TravelMate 380",
 749                .matches = {
 750                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 751                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 380"),
 752                },
 753                .driver_data = keymap_acer_travelmate_380
 754        },
 755        {
 756                .callback = dmi_matched,
 757                .ident = "Acer TravelMate 370",
 758                .matches = {
 759                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 760                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 370"),
 761                },
 762                .driver_data = keymap_acer_travelmate_380 /* keyboard minus 1 key */
 763        },
 764        {
 765                .callback = dmi_matched,
 766                .ident = "Acer TravelMate 220",
 767                .matches = {
 768                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 769                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 220"),
 770                },
 771                .driver_data = keymap_acer_travelmate_220
 772        },
 773        {
 774                .callback = dmi_matched,
 775                .ident = "Acer TravelMate 260",
 776                .matches = {
 777                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 778                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 260"),
 779                },
 780                .driver_data = keymap_acer_travelmate_220
 781        },
 782        {
 783                .callback = dmi_matched,
 784                .ident = "Acer TravelMate 230",
 785                .matches = {
 786                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 787                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 230"),
 788                        /* acerhk looks for "TravelMate F4..." ?! */
 789                },
 790                .driver_data = keymap_acer_travelmate_230
 791        },
 792        {
 793                .callback = dmi_matched,
 794                .ident = "Acer TravelMate 280",
 795                .matches = {
 796                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 797                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 280"),
 798                },
 799                .driver_data = keymap_acer_travelmate_230
 800        },
 801        {
 802                .callback = dmi_matched,
 803                .ident = "Acer TravelMate 240",
 804                .matches = {
 805                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 806                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 240"),
 807                },
 808                .driver_data = keymap_acer_travelmate_240
 809        },
 810        {
 811                .callback = dmi_matched,
 812                .ident = "Acer TravelMate 250",
 813                .matches = {
 814                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 815                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 250"),
 816                },
 817                .driver_data = keymap_acer_travelmate_240
 818        },
 819        {
 820                .callback = dmi_matched,
 821                .ident = "Acer TravelMate 2424NWXCi",
 822                .matches = {
 823                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 824                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2420"),
 825                },
 826                .driver_data = keymap_acer_travelmate_240
 827        },
 828        {
 829                .callback = dmi_matched,
 830                .ident = "Acer TravelMate 350",
 831                .matches = {
 832                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 833                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 350"),
 834                },
 835                .driver_data = keymap_acer_travelmate_350
 836        },
 837        {
 838                .callback = dmi_matched,
 839                .ident = "Acer TravelMate 360",
 840                .matches = {
 841                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 842                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
 843                },
 844                .driver_data = keymap_acer_travelmate_360
 845        },
 846        {
 847                .callback = dmi_matched,
 848                .ident = "Acer TravelMate 610",
 849                .matches = {
 850                        DMI_MATCH(DMI_SYS_VENDOR, "ACER"),
 851                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 610"),
 852                },
 853                .driver_data = keymap_acer_travelmate_610
 854        },
 855        {
 856                .callback = dmi_matched,
 857                .ident = "Acer TravelMate 620",
 858                .matches = {
 859                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 860                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 620"),
 861                },
 862                .driver_data = keymap_acer_travelmate_630
 863        },
 864        {
 865                .callback = dmi_matched,
 866                .ident = "Acer TravelMate 630",
 867                .matches = {
 868                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 869                        DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 630"),
 870                },
 871                .driver_data = keymap_acer_travelmate_630
 872        },
 873        {
 874                .callback = dmi_matched,
 875                .ident = "AOpen 1559AS",
 876                .matches = {
 877                        DMI_MATCH(DMI_PRODUCT_NAME, "E2U"),
 878                        DMI_MATCH(DMI_BOARD_NAME, "E2U"),
 879                },
 880                .driver_data = keymap_aopen_1559as
 881        },
 882        {
 883                .callback = dmi_matched,
 884                .ident = "Medion MD 9783",
 885                .matches = {
 886                        DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
 887                        DMI_MATCH(DMI_PRODUCT_NAME, "MD 9783"),
 888                },
 889                .driver_data = keymap_wistron_ms2111
 890        },
 891        {
 892                .callback = dmi_matched,
 893                .ident = "Medion MD 40100",
 894                .matches = {
 895                        DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
 896                        DMI_MATCH(DMI_PRODUCT_NAME, "WID2000"),
 897                },
 898                .driver_data = keymap_wistron_md40100
 899        },
 900        {
 901                .callback = dmi_matched,
 902                .ident = "Medion MD 2900",
 903                .matches = {
 904                        DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
 905                        DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2000"),
 906                },
 907                .driver_data = keymap_wistron_md2900
 908        },
 909        {
 910                .callback = dmi_matched,
 911                .ident = "Medion MD 96500",
 912                .matches = {
 913                        DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"),
 914                        DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2040"),
 915                },
 916                .driver_data = keymap_wistron_md96500
 917        },
 918        {
 919                .callback = dmi_matched,
 920                .ident = "Medion MD 95400",
 921                .matches = {
 922                        DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"),
 923                        DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2050"),
 924                },
 925                .driver_data = keymap_wistron_md96500
 926        },
 927        {
 928                .callback = dmi_matched,
 929                .ident = "Fujitsu Siemens Amilo D7820",
 930                .matches = {
 931                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), /* not sure */
 932                        DMI_MATCH(DMI_PRODUCT_NAME, "Amilo D"),
 933                },
 934                .driver_data = keymap_fs_amilo_d88x0
 935        },
 936        {
 937                .callback = dmi_matched,
 938                .ident = "Fujitsu Siemens Amilo D88x0",
 939                .matches = {
 940                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
 941                        DMI_MATCH(DMI_PRODUCT_NAME, "AMILO D"),
 942                },
 943                .driver_data = keymap_fs_amilo_d88x0
 944        },
 945        { NULL, }
 946};
 947
 948/* Copy the good keymap, as the original ones are free'd */
 949static int __init copy_keymap(void)
 950{
 951        const struct key_entry *key;
 952        struct key_entry *new_keymap;
 953        unsigned int length = 1;
 954
 955        for (key = keymap; key->type != KE_END; key++)
 956                length++;
 957
 958        new_keymap = kmalloc(length * sizeof(struct key_entry), GFP_KERNEL);
 959        if (!new_keymap)
 960                return -ENOMEM;
 961
 962        memcpy(new_keymap, keymap, length * sizeof(struct key_entry));
 963        keymap = new_keymap;
 964
 965        return 0;
 966}
 967
 968static int __init select_keymap(void)
 969{
 970        dmi_check_system(dmi_ids);
 971        if (keymap_name != NULL) {
 972                if (strcmp (keymap_name, "1557/MS2141") == 0)
 973                        keymap = keymap_wistron_ms2141;
 974                else if (strcmp (keymap_name, "generic") == 0)
 975                        keymap = keymap_wistron_generic;
 976                else {
 977                        printk(KERN_ERR "wistron_btns: Keymap unknown\n");
 978                        return -EINVAL;
 979                }
 980        }
 981        if (keymap == NULL) {
 982                if (!force) {
 983                        printk(KERN_ERR "wistron_btns: System unknown\n");
 984                        return -ENODEV;
 985                }
 986                keymap = keymap_empty;
 987        }
 988
 989        return copy_keymap();
 990}
 991
 992 /* Input layer interface */
 993
 994static struct input_polled_dev *wistron_idev;
 995static unsigned long jiffies_last_press;
 996static int wifi_enabled;
 997static int bluetooth_enabled;
 998
 999static void report_key(struct input_dev *dev, unsigned int keycode)
1000{
1001        input_report_key(dev, keycode, 1);
1002        input_sync(dev);
1003        input_report_key(dev, keycode, 0);
1004        input_sync(dev);
1005}
1006
1007static void report_switch(struct input_dev *dev, unsigned int code, int value)
1008{
1009        input_report_switch(dev, code, value);
1010        input_sync(dev);
1011}
1012
1013
1014 /* led management */
1015static void wistron_mail_led_set(struct led_classdev *led_cdev,
1016                                enum led_brightness value)
1017{
1018        bios_set_state(MAIL_LED, (value != LED_OFF) ? 1 : 0);
1019}
1020
1021/* same as setting up wifi card, but for laptops on which the led is managed */
1022static void wistron_wifi_led_set(struct led_classdev *led_cdev,
1023                                enum led_brightness value)
1024{
1025        bios_set_state(WIFI, (value != LED_OFF) ? 1 : 0);
1026}
1027
1028static struct led_classdev wistron_mail_led = {
1029        .name                   = "wistron:green:mail",
1030        .brightness_set         = wistron_mail_led_set,
1031};
1032
1033static struct led_classdev wistron_wifi_led = {
1034        .name                   = "wistron:red:wifi",
1035        .brightness_set         = wistron_wifi_led_set,
1036};
1037
1038static void __devinit wistron_led_init(struct device *parent)
1039{
1040        if (have_leds & FE_WIFI_LED) {
1041                u16 wifi = bios_get_default_setting(WIFI);
1042                if (wifi & 1) {
1043                        wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF;
1044                        if (led_classdev_register(parent, &wistron_wifi_led))
1045                                have_leds &= ~FE_WIFI_LED;
1046                        else
1047                                bios_set_state(WIFI, wistron_wifi_led.brightness);
1048
1049                } else
1050                        have_leds &= ~FE_WIFI_LED;
1051        }
1052
1053        if (have_leds & FE_MAIL_LED) {
1054                /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */
1055                wistron_mail_led.brightness = LED_OFF;
1056                if (led_classdev_register(parent, &wistron_mail_led))
1057                        have_leds &= ~FE_MAIL_LED;
1058                else
1059                        bios_set_state(MAIL_LED, wistron_mail_led.brightness);
1060        }
1061}
1062
1063static void __devexit wistron_led_remove(void)
1064{
1065        if (have_leds & FE_MAIL_LED)
1066                led_classdev_unregister(&wistron_mail_led);
1067
1068        if (have_leds & FE_WIFI_LED)
1069                led_classdev_unregister(&wistron_wifi_led);
1070}
1071
1072static inline void wistron_led_suspend(void)
1073{
1074        if (have_leds & FE_MAIL_LED)
1075                led_classdev_suspend(&wistron_mail_led);
1076
1077        if (have_leds & FE_WIFI_LED)
1078                led_classdev_suspend(&wistron_wifi_led);
1079}
1080
1081static inline void wistron_led_resume(void)
1082{
1083        if (have_leds & FE_MAIL_LED)
1084                led_classdev_resume(&wistron_mail_led);
1085
1086        if (have_leds & FE_WIFI_LED)
1087                led_classdev_resume(&wistron_wifi_led);
1088}
1089
1090static struct key_entry *wistron_get_entry_by_scancode(int code)
1091{
1092        struct key_entry *key;
1093
1094        for (key = keymap; key->type != KE_END; key++)
1095                if (code == key->code)
1096                        return key;
1097
1098        return NULL;
1099}
1100
1101static struct key_entry *wistron_get_entry_by_keycode(int keycode)
1102{
1103        struct key_entry *key;
1104
1105        for (key = keymap; key->type != KE_END; key++)
1106                if (key->type == KE_KEY && keycode == key->keycode)
1107                        return key;
1108
1109        return NULL;
1110}
1111
1112static void handle_key(u8 code)
1113{
1114        const struct key_entry *key = wistron_get_entry_by_scancode(code);
1115
1116        if (key) {
1117                switch (key->type) {
1118                case KE_KEY:
1119                        report_key(wistron_idev->input, key->keycode);
1120                        break;
1121
1122                case KE_SW:
1123                        report_switch(wistron_idev->input,
1124                                      key->sw.code, key->sw.value);
1125                        break;
1126
1127                case KE_WIFI:
1128                        if (have_wifi) {
1129                                wifi_enabled = !wifi_enabled;
1130                                bios_set_state(WIFI, wifi_enabled);
1131                        }
1132                        break;
1133
1134                case KE_BLUETOOTH:
1135                        if (have_bluetooth) {
1136                                bluetooth_enabled = !bluetooth_enabled;
1137                                bios_set_state(BLUETOOTH, bluetooth_enabled);
1138                        }
1139                        break;
1140
1141                default:
1142                        BUG();
1143                }
1144                jiffies_last_press = jiffies;
1145        } else
1146                printk(KERN_NOTICE
1147                        "wistron_btns: Unknown key code %02X\n", code);
1148}
1149
1150static void poll_bios(bool discard)
1151{
1152        u8 qlen;
1153        u16 val;
1154
1155        for (;;) {
1156                qlen = CMOS_READ(cmos_address);
1157                if (qlen == 0)
1158                        break;
1159                val = bios_pop_queue();
1160                if (val != 0 && !discard)
1161                        handle_key((u8)val);
1162        }
1163}
1164
1165static void wistron_flush(struct input_polled_dev *dev)
1166{
1167        /* Flush stale event queue */
1168        poll_bios(true);
1169}
1170
1171static void wistron_poll(struct input_polled_dev *dev)
1172{
1173        poll_bios(false);
1174
1175        /* Increase poll frequency if user is currently pressing keys (< 2s ago) */
1176        if (time_before(jiffies, jiffies_last_press + 2 * HZ))
1177                dev->poll_interval = POLL_INTERVAL_BURST;
1178        else
1179                dev->poll_interval = POLL_INTERVAL_DEFAULT;
1180}
1181
1182static int wistron_getkeycode(struct input_dev *dev, int scancode, int *keycode)
1183{
1184        const struct key_entry *key = wistron_get_entry_by_scancode(scancode);
1185
1186        if (key && key->type == KE_KEY) {
1187                *keycode = key->keycode;
1188                return 0;
1189        }
1190
1191        return -EINVAL;
1192}
1193
1194static int wistron_setkeycode(struct input_dev *dev, int scancode, int keycode)
1195{
1196        struct key_entry *key;
1197        int old_keycode;
1198
1199        if (keycode < 0 || keycode > KEY_MAX)
1200                return -EINVAL;
1201
1202        key = wistron_get_entry_by_scancode(scancode);
1203        if (key && key->type == KE_KEY) {
1204                old_keycode = key->keycode;
1205                key->keycode = keycode;
1206                set_bit(keycode, dev->keybit);
1207                if (!wistron_get_entry_by_keycode(old_keycode))
1208                        clear_bit(old_keycode, dev->keybit);
1209                return 0;
1210        }
1211
1212        return -EINVAL;
1213}
1214
1215static int __devinit setup_input_dev(void)
1216{
1217        struct key_entry *key;
1218        struct input_dev *input_dev;
1219        int error;
1220
1221        wistron_idev = input_allocate_polled_device();
1222        if (!wistron_idev)
1223                return -ENOMEM;
1224
1225        wistron_idev->flush = wistron_flush;
1226        wistron_idev->poll = wistron_poll;
1227        wistron_idev->poll_interval = POLL_INTERVAL_DEFAULT;
1228
1229        input_dev = wistron_idev->input;
1230        input_dev->name = "Wistron laptop buttons";
1231        input_dev->phys = "wistron/input0";
1232        input_dev->id.bustype = BUS_HOST;
1233        input_dev->dev.parent = &wistron_device->dev;
1234
1235        input_dev->getkeycode = wistron_getkeycode;
1236        input_dev->setkeycode = wistron_setkeycode;
1237
1238        for (key = keymap; key->type != KE_END; key++) {
1239                switch (key->type) {
1240                        case KE_KEY:
1241                                set_bit(EV_KEY, input_dev->evbit);
1242                                set_bit(key->keycode, input_dev->keybit);
1243                                break;
1244
1245                        case KE_SW:
1246                                set_bit(EV_SW, input_dev->evbit);
1247                                set_bit(key->sw.code, input_dev->swbit);
1248                                break;
1249
1250                        /* if wifi or bluetooth are not available, create normal keys */
1251                        case KE_WIFI:
1252                                if (!have_wifi) {
1253                                        key->type = KE_KEY;
1254                                        key->keycode = KEY_WLAN;
1255                                        key--;
1256                                }
1257                                break;
1258
1259                        case KE_BLUETOOTH:
1260                                if (!have_bluetooth) {
1261                                        key->type = KE_KEY;
1262                                        key->keycode = KEY_BLUETOOTH;
1263                                        key--;
1264                                }
1265                                break;
1266
1267                        default:
1268                                break;
1269                }
1270        }
1271
1272        /* reads information flags on KE_END */
1273        if (key->code & FE_UNTESTED)
1274                printk(KERN_WARNING "Untested laptop multimedia keys, "
1275                        "please report success or failure to eric.piel"
1276                        "@tremplin-utc.net\n");
1277
1278        error = input_register_polled_device(wistron_idev);
1279        if (error) {
1280                input_free_polled_device(wistron_idev);
1281                return error;
1282        }
1283
1284        return 0;
1285}
1286
1287/* Driver core */
1288
1289static int __devinit wistron_probe(struct platform_device *dev)
1290{
1291        int err;
1292
1293        bios_attach();
1294        cmos_address = bios_get_cmos_address();
1295
1296        if (have_wifi) {
1297                u16 wifi = bios_get_default_setting(WIFI);
1298                if (wifi & 1)
1299                        wifi_enabled = (wifi & 2) ? 1 : 0;
1300                else
1301                        have_wifi = 0;
1302
1303                if (have_wifi)
1304                        bios_set_state(WIFI, wifi_enabled);
1305        }
1306
1307        if (have_bluetooth) {
1308                u16 bt = bios_get_default_setting(BLUETOOTH);
1309                if (bt & 1)
1310                        bluetooth_enabled = (bt & 2) ? 1 : 0;
1311                else
1312                        have_bluetooth = 0;
1313
1314                if (have_bluetooth)
1315                        bios_set_state(BLUETOOTH, bluetooth_enabled);
1316        }
1317
1318        wistron_led_init(&dev->dev);
1319        err = setup_input_dev();
1320        if (err) {
1321                bios_detach();
1322                return err;
1323        }
1324
1325        return 0;
1326}
1327
1328static int __devexit wistron_remove(struct platform_device *dev)
1329{
1330        wistron_led_remove();
1331        input_unregister_polled_device(wistron_idev);
1332        input_free_polled_device(wistron_idev);
1333        bios_detach();
1334
1335        return 0;
1336}
1337
1338#ifdef CONFIG_PM
1339static int wistron_suspend(struct platform_device *dev, pm_message_t state)
1340{
1341        if (have_wifi)
1342                bios_set_state(WIFI, 0);
1343
1344        if (have_bluetooth)
1345                bios_set_state(BLUETOOTH, 0);
1346
1347        wistron_led_suspend();
1348        return 0;
1349}
1350
1351static int wistron_resume(struct platform_device *dev)
1352{
1353        if (have_wifi)
1354                bios_set_state(WIFI, wifi_enabled);
1355
1356        if (have_bluetooth)
1357                bios_set_state(BLUETOOTH, bluetooth_enabled);
1358
1359        wistron_led_resume();
1360        poll_bios(true);
1361
1362        return 0;
1363}
1364#else
1365#define wistron_suspend         NULL
1366#define wistron_resume          NULL
1367#endif
1368
1369static struct platform_driver wistron_driver = {
1370        .driver         = {
1371                .name   = "wistron-bios",
1372                .owner  = THIS_MODULE,
1373        },
1374        .probe          = wistron_probe,
1375        .remove         = __devexit_p(wistron_remove),
1376        .suspend        = wistron_suspend,
1377        .resume         = wistron_resume,
1378};
1379
1380static int __init wb_module_init(void)
1381{
1382        int err;
1383
1384        err = select_keymap();
1385        if (err)
1386                return err;
1387
1388        err = map_bios();
1389        if (err)
1390                return err;
1391
1392        err = platform_driver_register(&wistron_driver);
1393        if (err)
1394                goto err_unmap_bios;
1395
1396        wistron_device = platform_device_alloc("wistron-bios", -1);
1397        if (!wistron_device) {
1398                err = -ENOMEM;
1399                goto err_unregister_driver;
1400        }
1401
1402        err = platform_device_add(wistron_device);
1403        if (err)
1404                goto err_free_device;
1405
1406        return 0;
1407
1408 err_free_device:
1409        platform_device_put(wistron_device);
1410 err_unregister_driver:
1411        platform_driver_unregister(&wistron_driver);
1412 err_unmap_bios:
1413        unmap_bios();
1414
1415        return err;
1416}
1417
1418static void __exit wb_module_exit(void)
1419{
1420        platform_device_unregister(wistron_device);
1421        platform_driver_unregister(&wistron_driver);
1422        unmap_bios();
1423        kfree(keymap);
1424}
1425
1426module_init(wb_module_init);
1427module_exit(wb_module_exit);
1428