Release 4.11 drivers/input/misc/wistron_btns.c
/*
* Wistron laptop button driver
* Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
* Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
* Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
*
* 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
* Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/io.h>
#include <linux/dmi.h>
#include <linux/init.h>
#include <linux/input-polldev.h>
#include <linux/input/sparse-keymap.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/mc146818rtc.h>
#include <linux/module.h>
#include <linux/preempt.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
/* How often we poll keys - msecs */
#define POLL_INTERVAL_DEFAULT 500
/* when idle */
#define POLL_INTERVAL_BURST 100
/* when a key was recently pressed */
/* BIOS subsystem IDs */
#define WIFI 0x35
#define BLUETOOTH 0x34
#define MAIL_LED 0x31
MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>");
MODULE_DESCRIPTION("Wistron laptop button driver");
MODULE_LICENSE("GPL v2");
static bool force;
/* = 0; */
module_param(force, bool, 0);
MODULE_PARM_DESC(force, "Load even if computer is not in database");
static char *keymap_name;
/* = NULL; */
module_param_named(keymap, keymap_name, charp, 0);
MODULE_PARM_DESC(keymap, "Keymap name, if it can't be autodetected [generic, 1557/MS2141]");
static struct platform_device *wistron_device;
/* BIOS interface implementation */
static void __iomem *bios_entry_point;
/* BIOS routine entry point */
static void __iomem *bios_code_map_base;
static void __iomem *bios_data_map_base;
static u8 cmos_address;
struct regs {
u32 eax, ebx, ecx;
};
static void call_bios(struct regs *regs)
{
unsigned long flags;
preempt_disable();
local_irq_save(flags);
asm volatile ("pushl %%ebp;"
"movl %7, %%ebp;"
"call *%6;"
"popl %%ebp"
: "=a" (regs->eax), "=b" (regs->ebx), "=c" (regs->ecx)
: "0" (regs->eax), "1" (regs->ebx), "2" (regs->ecx),
"m" (bios_entry_point), "m" (bios_data_map_base)
: "edx", "edi", "esi", "memory");
local_irq_restore(flags);
preempt_enable();
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 34 | 100.00% | 1 | 100.00% |
Total | 34 | 100.00% | 1 | 100.00% |
static ssize_t __init locate_wistron_bios(void __iomem *base)
{
static unsigned char __initdata signature[] =
{ 0x42, 0x21, 0x55, 0x30 };
ssize_t offset;
for (offset = 0; offset < 0x10000; offset += 0x10) {
if (check_signature(base + offset, signature,
sizeof(signature)) != 0)
return offset;
}
return -1;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 71 | 97.26% | 1 | 50.00% |
Miloslav Trmač | 2 | 2.74% | 1 | 50.00% |
Total | 73 | 100.00% | 2 | 100.00% |
static int __init map_bios(void)
{
void __iomem *base;
ssize_t offset;
u32 entry_point;
base = ioremap(0xF0000, 0x10000); /* Can't fail */
offset = locate_wistron_bios(base);
if (offset < 0) {
printk(KERN_ERR "wistron_btns: BIOS entry point not found\n");
iounmap(base);
return -ENODEV;
}
entry_point = readl(base + offset + 5);
printk(KERN_DEBUG
"wistron_btns: BIOS signature found at %p, entry point %08X\n",
base + offset, entry_point);
if (entry_point >= 0xF0000) {
bios_code_map_base = base;
bios_entry_point = bios_code_map_base + (entry_point & 0xFFFF);
} else {
iounmap(base);
bios_code_map_base = ioremap(entry_point & ~0x3FFF, 0x4000);
if (bios_code_map_base == NULL) {
printk(KERN_ERR
"wistron_btns: Can't map BIOS code at %08X\n",
entry_point & ~0x3FFF);
goto err;
}
bios_entry_point = bios_code_map_base + (entry_point & 0x3FFF);
}
/* The Windows driver maps 0x10000 bytes, we keep only one page... */
bios_data_map_base = ioremap(0x400, 0xc00);
if (bios_data_map_base == NULL) {
printk(KERN_ERR "wistron_btns: Can't map BIOS data\n");
goto err_code;
}
return 0;
err_code:
iounmap(bios_code_map_base);
err:
return -ENOMEM;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 199 | 99.50% | 1 | 50.00% |
Miloslav Trmač | 1 | 0.50% | 1 | 50.00% |
Total | 200 | 100.00% | 2 | 100.00% |
static inline void unmap_bios(void)
{
iounmap(bios_code_map_base);
iounmap(bios_data_map_base);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 19 | 100.00% | 2 | 100.00% |
Total | 19 | 100.00% | 2 | 100.00% |
/* BIOS calls */
static u16 bios_pop_queue(void)
{
struct regs regs;
memset(®s, 0, sizeof (regs));
regs.eax = 0x9610;
regs.ebx = 0x061C;
regs.ecx = 0x0000;
call_bios(®s);
return regs.eax;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 54 | 100.00% | 1 | 100.00% |
Total | 54 | 100.00% | 1 | 100.00% |
static void bios_attach(void)
{
struct regs regs;
memset(®s, 0, sizeof (regs));
regs.eax = 0x9610;
regs.ebx = 0x012E;
call_bios(®s);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 43 | 100.00% | 1 | 100.00% |
Total | 43 | 100.00% | 1 | 100.00% |
static void bios_detach(void)
{
struct regs regs;
memset(®s, 0, sizeof (regs));
regs.eax = 0x9610;
regs.ebx = 0x002E;
call_bios(®s);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 43 | 100.00% | 1 | 100.00% |
Total | 43 | 100.00% | 1 | 100.00% |
static u8 bios_get_cmos_address(void)
{
struct regs regs;
memset(®s, 0, sizeof (regs));
regs.eax = 0x9610;
regs.ebx = 0x051C;
call_bios(®s);
return regs.ecx;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 48 | 100.00% | 1 | 100.00% |
Total | 48 | 100.00% | 1 | 100.00% |
static u16 bios_get_default_setting(u8 subsys)
{
struct regs regs;
memset(®s, 0, sizeof (regs));
regs.eax = 0x9610;
regs.ebx = 0x0200 | subsys;
call_bios(®s);
return regs.eax;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 45 | 88.24% | 1 | 50.00% |
Bernhard Rosenkraenzer | 6 | 11.76% | 1 | 50.00% |
Total | 51 | 100.00% | 2 | 100.00% |
static void bios_set_state(u8 subsys, int enable)
{
struct regs regs;
memset(®s, 0, sizeof (regs));
regs.eax = 0x9610;
regs.ebx = (enable ? 0x0100 : 0x0000) | subsys;
call_bios(®s);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 45 | 81.82% | 1 | 50.00% |
Bernhard Rosenkraenzer | 10 | 18.18% | 1 | 50.00% |
Total | 55 | 100.00% | 2 | 100.00% |
/* Hardware database */
#define KE_WIFI (KE_LAST + 1)
#define KE_BLUETOOTH (KE_LAST + 2)
#define FE_MAIL_LED 0x01
#define FE_WIFI_LED 0x02
#define FE_UNTESTED 0x80
static struct key_entry *keymap;
/* = NULL; Current key map */
static bool have_wifi;
static bool have_bluetooth;
static int leds_present;
/* bitmask of leds present */
static int __init dmi_matched(const struct dmi_system_id *dmi)
{
const struct key_entry *key;
keymap = dmi->driver_data;
for (key = keymap; key->type != KE_END; key++) {
if (key->type == KE_WIFI)
have_wifi = true;
else if (key->type == KE_BLUETOOTH)
have_bluetooth = true;
}
leds_present = key->code & (FE_MAIL_LED | FE_WIFI_LED);
return 1;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 58 | 70.73% | 2 | 40.00% |
Bernhard Rosenkraenzer | 12 | 14.63% | 1 | 20.00% |
Éric Piel | 11 | 13.41% | 1 | 20.00% |
Jeff Garzik | 1 | 1.22% | 1 | 20.00% |
Total | 82 | 100.00% | 5 | 100.00% |
static struct key_entry keymap_empty[] __initdata = {
{ KE_END, 0 }
};
static struct key_entry keymap_fs_amilo_pro_v2000[] __initdata = {
{ KE_KEY, 0x01, {KEY_HELP} },
{ KE_KEY, 0x11, {KEY_PROG1} },
{ KE_KEY, 0x12, {KEY_PROG2} },
{ KE_WIFI, 0x30 },
{ KE_KEY, 0x31, {KEY_MAIL} },
{ KE_KEY, 0x36, {KEY_WWW} },
{ KE_END, 0 }
};
static struct key_entry keymap_fs_amilo_pro_v3505[] __initdata = {
{ KE_KEY, 0x01, {KEY_HELP} }, /* Fn+F1 */
{ KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Fn+F4 */
{ KE_BLUETOOTH, 0x30 }, /* Fn+F10 */
{ KE_KEY, 0x31, {KEY_MAIL} }, /* mail button */
{ KE_KEY, 0x36, {KEY_WWW} }, /* www button */
{ KE_WIFI, 0x78 }, /* satellite dish button */
{ KE_END, 0 }
};
static struct key_entry keymap_fs_amilo_pro_v8210[] __initdata = {
{ KE_KEY, 0x01, {KEY_HELP} }, /* Fn+F1 */
{ KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Fn+F4 */
{ KE_BLUETOOTH, 0x30 }, /* Fn+F10 */
{ KE_KEY, 0x31, {KEY_MAIL} }, /* mail button */
{ KE_KEY, 0x36, {KEY_WWW} }, /* www button */
{ KE_WIFI, 0x78 }, /* satelite dish button */
{ KE_END, FE_WIFI_LED }
};
static struct key_entry keymap_fujitsu_n3510[] __initdata = {
{ KE_KEY, 0x11, {KEY_PROG1} },
{ KE_KEY, 0x12, {KEY_PROG2} },
{ KE_KEY, 0x36, {KEY_WWW} },
{ KE_KEY, 0x31, {KEY_MAIL} },
{ KE_KEY, 0x71, {KEY_STOPCD} },
{ KE_KEY, 0x72, {KEY_PLAYPAUSE} },
{ KE_KEY, 0x74, {KEY_REWIND} },
{ KE_KEY, 0x78, {KEY_FORWARD} },
{ KE_END, 0 }
};
static struct key_entry keymap_wistron_ms2111[] __initdata = {
{ KE_KEY, 0x11, {KEY_PROG1} },
{ KE_KEY, 0x12, {KEY_PROG2} },
{ KE_KEY, 0x13, {KEY_PROG3} },
{ KE_KEY, 0x31, {KEY_MAIL} },
{ KE_KEY, 0x36, {KEY_WWW} },
{ KE_END, FE_MAIL_LED }
};
static struct key_entry keymap_wistron_md40100[] __initdata = {
{ KE_KEY, 0x01, {KEY_HELP} },
{ KE_KEY, 0x02, {KEY_CONFIG} },
{ KE_KEY, 0x31, {KEY_MAIL} },
{ KE_KEY, 0x36, {KEY_WWW} },
{ KE_KEY, 0x37, {KEY_DISPLAYTOGGLE} }, /* Display on/off */
{ KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED }
};
static struct key_entry keymap_wistron_ms2141[] __initdata = {
{ KE_KEY, 0x11, {KEY_PROG1} },
{ KE_KEY, 0x12, {KEY_PROG2} },
{ KE_WIFI, 0x30 },
{ KE_KEY, 0x22, {KEY_REWIND} },
{ KE_KEY, 0x23, {KEY_FORWARD} },
{ KE_KEY, 0x24, {KEY_PLAYPAUSE} },
{ KE_KEY, 0x25, {KEY_STOPCD} },
{ KE_KEY, 0x31, {KEY_MAIL} },
{ KE_KEY, 0x36, {KEY_WWW} },
{ KE_END, 0 }
};
static struct key_entry keymap_acer_aspire_1500[] __initdata = {
{ KE_KEY, 0x01, {KEY_HELP} },
{ KE_KEY, 0x03, {KEY_POWER} },
{ KE_KEY, 0x11, {KEY_PROG1} },
{ KE_KEY, 0x12, {KEY_PROG2} },
{ KE_WIFI, 0x30 },
{ KE_KEY, 0x31, {KEY_MAIL} },
{ KE_KEY, 0x36, {KEY_WWW} },
{ KE_KEY, 0x49, {KEY_CONFIG} },
{ KE_BLUETOOTH, 0x44 },
{ KE_END, FE_UNTESTED }
};
static struct key_entry keymap_acer_aspire_1600[] __initdata = {
{ KE_KEY, 0x01, {KEY_HELP} },
{ KE_KEY, 0x03, {KEY_POWER} },
{ KE_KEY, 0x08, {KEY_MUTE} },
{ KE_KEY, 0x11, {KEY_PROG1} },
{ KE_KEY, 0x12, {KEY_PROG2} },
{ KE_KEY, 0x13, {KEY_PROG3} },
{ KE_KEY, 0x31, {KEY_MAIL} },
{ KE_KEY, 0x36, {KEY_WWW} },
{ KE_KEY, 0x49, {KEY_CONFIG} },
{ KE_WIFI, 0x30 },
{ KE_BLUETOOTH, 0x44 },
{ KE_END, FE_MAIL_LED | FE_UNTESTED }
};
/* 3020 has been tested */
static struct key_entry keymap_acer_aspire_5020[] __initdata = {
{ KE_KEY, 0x01, {KEY_HELP} },
{ KE_KEY, 0x03, {KEY_POWER} },
{ KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */
{ KE_KEY, 0x11, {KEY_PROG1} },
{ KE_KEY, 0x12, {KEY_PROG2} },
{ KE_KEY, 0x31, {KEY_MAIL} },
{ KE_KEY, 0x36, {KEY_WWW} },
{ KE_KEY, 0x6a, {KEY_CONFIG} },
{ KE_WIFI, 0x30 },
{ KE_BLUETOOTH, 0x44 },
{ KE_END, FE_MAIL_LED | FE_UNTESTED }
};
static struct key_entry keymap_acer_travelmate_2410[] __initdata = {
{ KE_KEY, 0x01, {KEY_HELP} },
{ KE_KEY, 0x6d, {KEY_POWER} },
{ KE_KEY, 0x11, {KEY_PROG1} },
{ KE_KEY, 0x12, {KEY_PROG2} },
{ KE_KEY, 0x31, {KEY_MAIL} },
{ KE_KEY, 0x36, {KEY_WWW} },
{ KE_KEY, 0x6a, {KEY_CONFIG} },
{ KE_WIFI, 0x30 },
{ KE_BLUETOOTH, 0x44 },
{ KE_END, FE_MAIL_LED | FE_UNTESTED }
};
static struct key_entry keymap_acer_travelmate_110[] __initdata = {
{ KE_KEY, 0x01, {KEY_HELP} },
{ KE_KEY, 0x02, {KEY_CONFIG} },
{ KE_KEY, 0x03, {KEY_POWER} },
{ KE_KEY, 0x08, {KEY_MUTE} },
{ KE_KEY, 0x11, {KEY_PROG1} },
{ KE_KEY, 0x12, {KEY_PROG2} },
{ KE_KEY, 0x20, {KEY_VOLUMEUP} },
{ KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
{ KE_KEY, 0x31, {KEY_MAIL} },
{ KE_KEY, 0x36, {KEY_WWW} },
{ KE_SW, 0x4a, {.sw = {SW_LID, 1}} }, /* lid close */
{ KE_SW, 0x4b, {.sw = {SW_LID, 0}} }, /* lid open */
{ KE_WIFI, 0x30 },
{ KE_END, FE_MAIL_LED | FE_UNTESTED }
};
static struct key_entry keymap_acer_travelmate_300[] __initdata = {
{ KE_KEY, 0x01, {KEY_HELP} },
{ KE_KEY, 0x02, {KEY_CONFIG} },
{ KE_KEY, 0x03, {KEY_POWER} },
{ KE_KEY, 0x08, {KEY_MUTE} },
{ KE_KEY, 0x11, {KEY_PROG1} },
{ KE_KEY, 0x12, {KEY_PROG2} },
{ KE_KEY, 0x20, {KEY_VOLUMEUP} },
{ KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
{ KE_KEY, 0x31, {KEY_MAIL} },
{ KE_KEY, 0x36, {KEY_WWW} },
{ KE_WIFI, 0x30 },
{ KE_BLUETOOTH, 0x44 },
{ KE_END, FE_MAIL_LED | FE_UNTESTED }
};
static struct key_entry keymap_acer_travelmate_380[] __initdata = {
{ KE_KEY, 0x01, {KEY_HELP} },
{ KE_KEY, 0x02, {KEY_CONFIG} },
{ KE_KEY, 0x03, {KEY_POWER} }, /* not 370 */
{ KE_KEY, 0x11, {KEY_PROG1} },
{ KE_KEY, 0x12, {KEY_PROG2} },
{ KE_KEY, 0x13, {KEY_PROG3} },
{ KE_KEY, 0x31, {KEY_MAIL} },
{ KE_KEY, 0x36, {KEY_WWW} },
{ KE_WIFI, 0x30 },
{ KE_END, FE_MAIL_LED | FE_UNTESTED }
};
/* unusual map */
static struct key_entry keymap_acer_travelmate_220[] __initdata = {
{ KE_KEY, 0x01, {KEY_HELP} },
{ KE_KEY, 0x02, {KEY_CONFIG} },
{ KE_KEY, 0x11, {KEY_MAIL} },
{ KE_KEY, 0x12, {KEY_WWW} },
{ KE_KEY, 0x13, {KEY_PROG2} },
{ KE_KEY, 0x31, {KEY_PROG1} },
{ KE_END, FE_WIFI_LED | FE_UNTESTED }
};
static struct key_entry keymap_acer_travelmate_230[] __initdata = {
{ KE_KEY, 0x01, {KEY_HELP} },
{ KE_KEY, 0x02, {KEY_CONFIG} },
{ KE_KEY, 0x11, {KEY_PROG1} },
{ KE_KEY, 0x12, {KEY_PROG2} },
{ KE_KEY, 0x31, {KEY_MAIL} },
{ KE_KEY, 0x36, {KEY_WWW} },
{ KE_END, FE_WIFI_LED | FE_UNTESTED }
};
static struct key_entry keymap_acer_travelmate_240[] __initdata = {
{ KE_KEY, 0x01, {KEY_HELP} },
{ KE_KEY, 0x02, {KEY_CONFIG} },
{ KE_KEY, 0x03, {KEY_POWER} },
{ KE_KEY, 0x08, {KEY_MUTE} },
{ KE_KEY, 0x31, {KEY_MAIL} },
{ KE_KEY, 0x36, {KEY_WWW} },
{ KE_KEY, 0x11, {KEY_PROG1} },
{ KE_KEY, 0x12, {KEY_PROG2} },
{ KE_BLUETOOTH, 0x44 },
{ KE_WIFI, 0x30 },
{ KE_END, FE_UNTESTED }
};
static struct key_entry keymap_acer_travelmate_350[] __initdata = {
{ KE_KEY, 0x01, {KEY_HELP} },
{ KE_KEY, 0x02, {KEY_CONFIG} },
{ KE_KEY, 0x11, {KEY_PROG1} },
{ KE_KEY, 0x12, {KEY_PROG2} },
{ KE_KEY, 0x13, {KEY_MAIL} },
{ KE_KEY, 0x14, {KEY_PROG3} },
{ KE_KEY, 0x15, {KEY_WWW} },
{ KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED }
};
static struct key_entry keymap_acer_travelmate_360[] __initdata = {
{ KE_KEY, 0x01, {KEY_HELP} },
{ KE_KEY, 0x02, {KEY_CONFIG} },
{ KE_KEY, 0x11, {KEY_PROG1} },
{ KE_KEY, 0x12, {KEY_PROG2} },
{ KE_KEY, 0x13, {KEY_MAIL} },
{ KE_KEY, 0x14, {KEY_PROG3} },
{ KE_KEY, 0x15, {KEY_WWW} },
{ KE_KEY, 0x40, {KEY_WLAN} },
{ KE_END, FE_WIFI_LED | FE_UNTESTED } /* no mail led */
};
/* Wifi subsystem only activates the led. Therefore we need to pass
* wifi event as a normal key, then userspace can really change the wifi state.
* TODO we need to export led state to userspace (wifi and mail) */
static struct key_entry keymap_acer_travelmate_610[] __initdata = {
{ KE_KEY, 0x01, {KEY_HELP} },
{ KE_KEY, 0x02, {KEY_CONFIG} },
{ KE_KEY, 0x11, {KEY_PROG1} },
{ KE_KEY, 0x12, {KEY_PROG2} },
{ KE_KEY, 0x13, {KEY_PROG3} },
{ KE_KEY, 0x14, {KEY_MAIL} },
{ KE_KEY, 0x15, {KEY_WWW} },
{ KE_KEY, 0x40, {KEY_WLAN} },
{ KE_END, FE_MAIL_LED | FE_WIFI_LED }
};
static struct key_entry keymap_acer_travelmate_630[] __initdata = {
{ KE_KEY, 0x01, {KEY_HELP} },
{ KE_KEY, 0x02, {KEY_CONFIG} },
{ KE_KEY, 0x03, {KEY_POWER} },
{ KE_KEY, 0x08, {KEY_MUTE} }, /* not 620 */
{ KE_KEY, 0x11, {KEY_PROG1} },
{ KE_KEY, 0x12, {KEY_PROG2} },
{ KE_KEY, 0x13, {KEY_PROG3} },
{ KE_KEY, 0x20, {KEY_VOLUMEUP} },
{ KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
{ KE_KEY, 0x31, {KEY_MAIL} },
{ KE_KEY, 0x36, {KEY_WWW} },
{ KE_WIFI, 0x30 },
{ KE_END, FE_MAIL_LED | FE_UNTESTED }
};
static struct key_entry keymap_aopen_1559as[] __initdata = {
{ KE_KEY, 0x01, {KEY_HELP} },
{ KE_KEY, 0x06, {KEY_PROG3} },
{ KE_KEY, 0x11, {KEY_PROG1} },
{ KE_KEY, 0x12, {KEY_PROG2} },
{ KE_WIFI, 0x30 },
{ KE_KEY, 0x31, {KEY_MAIL} },
{ KE_KEY, 0x36, {KEY_WWW} },
{ KE_END, 0 },
};
static struct key_entry keymap_fs_amilo_d88x0[] __initdata = {
{ KE_KEY, 0x01, {KEY_HELP} },
{ KE_KEY, 0x08, {KEY_MUTE} },
{ KE_KEY, 0x31, {