|
@@ -1,6 +1,7 @@
|
|
|
/*
|
|
|
* Wistron laptop button driver
|
|
|
* Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
|
|
|
+ * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
|
|
|
*
|
|
|
* You can redistribute and/or modify this program under the terms of the
|
|
|
* GNU General Public License version 2 as published by the Free Software
|
|
@@ -40,6 +41,10 @@
|
|
|
#error "POLL_FREQUENCY too high"
|
|
|
#endif
|
|
|
|
|
|
+/* BIOS subsystem IDs */
|
|
|
+#define WIFI 0x35
|
|
|
+#define BLUETOOTH 0x34
|
|
|
+
|
|
|
MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>");
|
|
|
MODULE_DESCRIPTION("Wistron laptop button driver");
|
|
|
MODULE_LICENSE("GPL v2");
|
|
@@ -197,29 +202,29 @@ static u8 __init bios_get_cmos_address(void)
|
|
|
return regs.ecx;
|
|
|
}
|
|
|
|
|
|
-static u16 __init bios_wifi_get_default_setting(void)
|
|
|
+static u16 __init bios_get_default_setting(u8 subsys)
|
|
|
{
|
|
|
struct regs regs;
|
|
|
|
|
|
memset(®s, 0, sizeof (regs));
|
|
|
regs.eax = 0x9610;
|
|
|
- regs.ebx = 0x0235;
|
|
|
+ regs.ebx = 0x0200 | subsys;
|
|
|
call_bios(®s);
|
|
|
|
|
|
return regs.eax;
|
|
|
}
|
|
|
|
|
|
-static void bios_wifi_set_state(int enable)
|
|
|
+static void bios_set_state(u8 subsys, int enable)
|
|
|
{
|
|
|
struct regs regs;
|
|
|
|
|
|
memset(®s, 0, sizeof (regs));
|
|
|
regs.eax = 0x9610;
|
|
|
- regs.ebx = enable ? 0x0135 : 0x0035;
|
|
|
+ regs.ebx = (enable ? 0x0100 : 0x0000) | subsys;
|
|
|
call_bios(®s);
|
|
|
}
|
|
|
|
|
|
- /* Hardware database */
|
|
|
+/* Hardware database */
|
|
|
|
|
|
struct key_entry {
|
|
|
char type; /* See KE_* below */
|
|
@@ -227,10 +232,11 @@ struct key_entry {
|
|
|
unsigned keycode; /* For KE_KEY */
|
|
|
};
|
|
|
|
|
|
-enum { KE_END, KE_KEY, KE_WIFI };
|
|
|
+enum { KE_END, KE_KEY, KE_WIFI, KE_BLUETOOTH };
|
|
|
|
|
|
static const struct key_entry *keymap; /* = NULL; Current key map */
|
|
|
static int have_wifi;
|
|
|
+static int have_bluetooth;
|
|
|
|
|
|
static int __init dmi_matched(struct dmi_system_id *dmi)
|
|
|
{
|
|
@@ -241,6 +247,9 @@ static int __init dmi_matched(struct dmi_system_id *dmi)
|
|
|
if (key->type == KE_WIFI) {
|
|
|
have_wifi = 1;
|
|
|
break;
|
|
|
+ } else if (key->type == KE_BLUETOOTH) {
|
|
|
+ have_bluetooth = 1;
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
return 1;
|
|
@@ -273,6 +282,16 @@ static struct key_entry keymap_wistron_ms2141[] = {
|
|
|
{ KE_END, 0 }
|
|
|
};
|
|
|
|
|
|
+static struct key_entry keymap_acer_aspire_1500[] = {
|
|
|
+ { KE_KEY, 0x11, KEY_PROG1 },
|
|
|
+ { KE_KEY, 0x12, KEY_PROG2 },
|
|
|
+ { KE_WIFI, 0x30, 0 },
|
|
|
+ { KE_KEY, 0x31, KEY_MAIL },
|
|
|
+ { KE_KEY, 0x36, KEY_WWW },
|
|
|
+ { KE_BLUETOOTH, 0x44, 0 },
|
|
|
+ { KE_END, 0 }
|
|
|
+};
|
|
|
+
|
|
|
/*
|
|
|
* If your machine is not here (which is currently rather likely), please send
|
|
|
* a list of buttons and their key codes (reported when loading this module
|
|
@@ -288,6 +307,15 @@ static struct dmi_system_id dmi_ids[] = {
|
|
|
},
|
|
|
.driver_data = keymap_fs_amilo_pro_v2000
|
|
|
},
|
|
|
+ {
|
|
|
+ .callback = dmi_matched,
|
|
|
+ .ident = "Acer Aspire 1500",
|
|
|
+ .matches = {
|
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1500"),
|
|
|
+ },
|
|
|
+ .driver_data = keymap_acer_aspire_1500
|
|
|
+ },
|
|
|
{ 0, }
|
|
|
};
|
|
|
|
|
@@ -344,6 +372,7 @@ static void report_key(unsigned keycode)
|
|
|
/* Driver core */
|
|
|
|
|
|
static int wifi_enabled;
|
|
|
+static int bluetooth_enabled;
|
|
|
|
|
|
static void poll_bios(unsigned long);
|
|
|
|
|
@@ -363,7 +392,14 @@ static void handle_key(u8 code)
|
|
|
case KE_WIFI:
|
|
|
if (have_wifi) {
|
|
|
wifi_enabled = !wifi_enabled;
|
|
|
- bios_wifi_set_state(wifi_enabled);
|
|
|
+ bios_set_state(WIFI, wifi_enabled);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case KE_BLUETOOTH:
|
|
|
+ if (have_bluetooth) {
|
|
|
+ bluetooth_enabled = !bluetooth_enabled;
|
|
|
+ bios_set_state(BLUETOOTH, bluetooth_enabled);
|
|
|
}
|
|
|
break;
|
|
|
|
|
@@ -407,21 +443,24 @@ static int __init wb_module_init(void)
|
|
|
bios_attach();
|
|
|
cmos_address = bios_get_cmos_address();
|
|
|
if (have_wifi) {
|
|
|
- switch (bios_wifi_get_default_setting()) {
|
|
|
- case 0x01:
|
|
|
- wifi_enabled = 0;
|
|
|
- break;
|
|
|
-
|
|
|
- case 0x03:
|
|
|
- wifi_enabled = 1;
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
+ u16 wifi = bios_get_default_setting(WIFI);
|
|
|
+ if (wifi & 1)
|
|
|
+ wifi_enabled = (wifi & 2) ? 1 : 0;
|
|
|
+ else
|
|
|
have_wifi = 0;
|
|
|
- break;
|
|
|
- }
|
|
|
+
|
|
|
if (have_wifi)
|
|
|
- bios_wifi_set_state(wifi_enabled);
|
|
|
+ bios_set_state(WIFI, wifi_enabled);
|
|
|
+ }
|
|
|
+ if (have_bluetooth) {
|
|
|
+ u16 bt = bios_get_default_setting(BLUETOOTH);
|
|
|
+ if (bt & 1)
|
|
|
+ bluetooth_enabled = (bt & 2) ? 1 : 0;
|
|
|
+ else
|
|
|
+ have_bluetooth = 0;
|
|
|
+
|
|
|
+ if (have_bluetooth)
|
|
|
+ bios_set_state(BLUETOOTH, bluetooth_enabled);
|
|
|
}
|
|
|
|
|
|
setup_input_dev();
|