diff options
Diffstat (limited to 'drivers/input/misc/wistron_btns.c')
| -rw-r--r-- | drivers/input/misc/wistron_btns.c | 420 |
1 files changed, 223 insertions, 197 deletions
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 72176f3d49c..7b7add5061a 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c @@ -21,6 +21,7 @@ #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> @@ -28,6 +29,7 @@ #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> @@ -44,9 +46,8 @@ MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>"); MODULE_DESCRIPTION("Wistron laptop button driver"); MODULE_LICENSE("GPL v2"); -MODULE_VERSION("0.3"); -static int force; /* = 0; */ +static bool force; /* = 0; */ module_param(force, bool, 0); MODULE_PARM_DESC(force, "Load even if computer is not in database"); @@ -168,7 +169,7 @@ static u16 bios_pop_queue(void) return regs.eax; } -static void __devinit bios_attach(void) +static void bios_attach(void) { struct regs regs; @@ -188,7 +189,7 @@ static void bios_detach(void) call_bios(®s); } -static u8 __devinit bios_get_cmos_address(void) +static u8 bios_get_cmos_address(void) { struct regs regs; @@ -200,7 +201,7 @@ static u8 __devinit bios_get_cmos_address(void) return regs.ecx; } -static u16 __devinit bios_get_default_setting(u8 subsys) +static u16 bios_get_default_setting(u8 subsys) { struct regs regs; @@ -224,28 +225,17 @@ static void bios_set_state(u8 subsys, int enable) /* Hardware database */ -struct key_entry { - char type; /* See KE_* below */ - u8 code; - union { - u16 keycode; /* For KE_KEY */ - struct { /* For KE_SW */ - u8 code; - u8 value; - } sw; - }; -}; - -enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH }; +#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 int have_wifi; -static int have_bluetooth; -static int have_leds; +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) { @@ -254,11 +244,11 @@ static int __init dmi_matched(const struct dmi_system_id *dmi) keymap = dmi->driver_data; for (key = keymap; key->type != KE_END; key++) { if (key->type == KE_WIFI) - have_wifi = 1; + have_wifi = true; else if (key->type == KE_BLUETOOTH) - have_bluetooth = 1; + have_bluetooth = true; } - have_leds = key->code & (FE_MAIL_LED | FE_WIFI_LED); + leds_present = key->code & (FE_MAIL_LED | FE_WIFI_LED); return 1; } @@ -277,6 +267,26 @@ static struct key_entry keymap_fs_amilo_pro_v2000[] __initdata = { { 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} }, @@ -562,7 +572,7 @@ static struct key_entry keymap_wistron_md96500[] __initdata = { { KE_KEY, 0x36, {KEY_WWW} }, { KE_WIFI, 0x30 }, { KE_BLUETOOTH, 0x44 }, - { KE_END, FE_UNTESTED } + { KE_END, 0 } }; static struct key_entry keymap_wistron_generic[] __initdata = { @@ -601,15 +611,43 @@ static struct key_entry keymap_wistron_generic[] __initdata = { { KE_END, 0 } }; +static struct key_entry keymap_aopen_1557[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, + { 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_prestigio[] __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 } +}; + + /* * 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 * with force=1) and the output of dmidecode to $MODULE_AUTHOR. */ -static struct dmi_system_id dmi_ids[] __initdata = { +static const struct dmi_system_id dmi_ids[] __initconst = { { + /* Fujitsu-Siemens Amilo Pro V2000 */ .callback = dmi_matched, - .ident = "Fujitsu-Siemens Amilo Pro V2000", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro V2000"), @@ -617,8 +655,26 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_fs_amilo_pro_v2000 }, { + /* Fujitsu-Siemens Amilo Pro Edition V3505 */ + .callback = dmi_matched, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Edition V3505"), + }, + .driver_data = keymap_fs_amilo_pro_v3505 + }, + { + /* Fujitsu-Siemens Amilo Pro Edition V8210 */ + .callback = dmi_matched, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Series V8210"), + }, + .driver_data = keymap_fs_amilo_pro_v8210 + }, + { + /* Fujitsu-Siemens Amilo M7400 */ .callback = dmi_matched, - .ident = "Fujitsu-Siemens Amilo M7400", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), DMI_MATCH(DMI_PRODUCT_NAME, "AMILO M "), @@ -626,8 +682,17 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_fs_amilo_pro_v2000 }, { + /* Maxdata Pro 7000 DX */ + .callback = dmi_matched, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MAXDATA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Pro 7000"), + }, + .driver_data = keymap_fs_amilo_pro_v2000 + }, + { + /* Fujitsu N3510 */ .callback = dmi_matched, - .ident = "Fujitsu N3510", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), DMI_MATCH(DMI_PRODUCT_NAME, "N3510"), @@ -635,8 +700,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_fujitsu_n3510 }, { + /* Acer Aspire 1500 */ .callback = dmi_matched, - .ident = "Acer Aspire 1500", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1500"), @@ -644,8 +709,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_aspire_1500 }, { + /* Acer Aspire 1600 */ .callback = dmi_matched, - .ident = "Acer Aspire 1600", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1600"), @@ -653,8 +718,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_aspire_1600 }, { + /* Acer Aspire 3020 */ .callback = dmi_matched, - .ident = "Acer Aspire 3020", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3020"), @@ -662,8 +727,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_aspire_5020 }, { + /* Acer Aspire 5020 */ .callback = dmi_matched, - .ident = "Acer Aspire 5020", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5020"), @@ -671,8 +736,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_aspire_5020 }, { + /* Acer TravelMate 2100 */ .callback = dmi_matched, - .ident = "Acer TravelMate 2100", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2100"), @@ -680,8 +745,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_aspire_5020 }, { + /* Acer TravelMate 2410 */ .callback = dmi_matched, - .ident = "Acer TravelMate 2410", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2410"), @@ -689,8 +754,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_travelmate_2410 }, { + /* Acer TravelMate C300 */ .callback = dmi_matched, - .ident = "Acer TravelMate C300", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C300"), @@ -698,8 +763,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_travelmate_300 }, { + /* Acer TravelMate C100 */ .callback = dmi_matched, - .ident = "Acer TravelMate C100", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C100"), @@ -707,8 +772,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_travelmate_300 }, { + /* Acer TravelMate C110 */ .callback = dmi_matched, - .ident = "Acer TravelMate C110", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C110"), @@ -716,8 +781,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_travelmate_110 }, { + /* Acer TravelMate 380 */ .callback = dmi_matched, - .ident = "Acer TravelMate 380", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 380"), @@ -725,8 +790,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_travelmate_380 }, { + /* Acer TravelMate 370 */ .callback = dmi_matched, - .ident = "Acer TravelMate 370", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 370"), @@ -734,8 +799,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_travelmate_380 /* keyboard minus 1 key */ }, { + /* Acer TravelMate 220 */ .callback = dmi_matched, - .ident = "Acer TravelMate 220", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 220"), @@ -743,8 +808,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_travelmate_220 }, { + /* Acer TravelMate 260 */ .callback = dmi_matched, - .ident = "Acer TravelMate 260", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 260"), @@ -752,8 +817,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_travelmate_220 }, { + /* Acer TravelMate 230 */ .callback = dmi_matched, - .ident = "Acer TravelMate 230", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 230"), @@ -762,8 +827,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_travelmate_230 }, { + /* Acer TravelMate 280 */ .callback = dmi_matched, - .ident = "Acer TravelMate 280", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 280"), @@ -771,8 +836,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_travelmate_230 }, { + /* Acer TravelMate 240 */ .callback = dmi_matched, - .ident = "Acer TravelMate 240", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 240"), @@ -780,8 +845,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_travelmate_240 }, { + /* Acer TravelMate 250 */ .callback = dmi_matched, - .ident = "Acer TravelMate 250", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 250"), @@ -789,8 +854,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_travelmate_240 }, { + /* Acer TravelMate 2424NWXCi */ .callback = dmi_matched, - .ident = "Acer TravelMate 2424NWXCi", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2420"), @@ -798,8 +863,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_travelmate_240 }, { + /* Acer TravelMate 350 */ .callback = dmi_matched, - .ident = "Acer TravelMate 350", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 350"), @@ -807,8 +872,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_travelmate_350 }, { + /* Acer TravelMate 360 */ .callback = dmi_matched, - .ident = "Acer TravelMate 360", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), @@ -816,8 +881,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_travelmate_360 }, { + /* Acer TravelMate 610 */ .callback = dmi_matched, - .ident = "Acer TravelMate 610", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ACER"), DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 610"), @@ -825,8 +890,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_travelmate_610 }, { + /* Acer TravelMate 620 */ .callback = dmi_matched, - .ident = "Acer TravelMate 620", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 620"), @@ -834,8 +899,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_travelmate_630 }, { + /* Acer TravelMate 630 */ .callback = dmi_matched, - .ident = "Acer TravelMate 630", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 630"), @@ -843,8 +908,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_acer_travelmate_630 }, { + /* AOpen 1559AS */ .callback = dmi_matched, - .ident = "AOpen 1559AS", .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "E2U"), DMI_MATCH(DMI_BOARD_NAME, "E2U"), @@ -852,8 +917,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_aopen_1559as }, { + /* Medion MD 9783 */ .callback = dmi_matched, - .ident = "Medion MD 9783", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), DMI_MATCH(DMI_PRODUCT_NAME, "MD 9783"), @@ -861,8 +926,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_wistron_ms2111 }, { + /* Medion MD 40100 */ .callback = dmi_matched, - .ident = "Medion MD 40100", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), DMI_MATCH(DMI_PRODUCT_NAME, "WID2000"), @@ -870,8 +935,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_wistron_md40100 }, { + /* Medion MD 2900 */ .callback = dmi_matched, - .ident = "Medion MD 2900", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2000"), @@ -879,8 +944,17 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_wistron_md2900 }, { + /* Medion MD 42200 */ + .callback = dmi_matched, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Medion"), + DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2030"), + }, + .driver_data = keymap_fs_amilo_pro_v2000 + }, + { + /* Medion MD 96500 */ .callback = dmi_matched, - .ident = "Medion MD 96500", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"), DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2040"), @@ -888,8 +962,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_wistron_md96500 }, { + /* Medion MD 95400 */ .callback = dmi_matched, - .ident = "Medion MD 95400", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"), DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2050"), @@ -897,8 +971,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_wistron_md96500 }, { + /* Fujitsu Siemens Amilo D7820 */ .callback = dmi_matched, - .ident = "Fujitsu Siemens Amilo D7820", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), /* not sure */ DMI_MATCH(DMI_PRODUCT_NAME, "Amilo D"), @@ -906,8 +980,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { .driver_data = keymap_fs_amilo_d88x0 }, { + /* Fujitsu Siemens Amilo D88x0 */ .callback = dmi_matched, - .ident = "Fujitsu Siemens Amilo D88x0", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), DMI_MATCH(DMI_PRODUCT_NAME, "AMILO D"), @@ -916,6 +990,7 @@ static struct dmi_system_id dmi_ids[] __initdata = { }, { NULL, } }; +MODULE_DEVICE_TABLE(dmi, dmi_ids); /* Copy the good keymap, as the original ones are free'd */ static int __init copy_keymap(void) @@ -927,11 +1002,11 @@ static int __init copy_keymap(void) for (key = keymap; key->type != KE_END; key++) length++; - new_keymap = kmalloc(length * sizeof(struct key_entry), GFP_KERNEL); + new_keymap = kmemdup(keymap, length * sizeof(struct key_entry), + GFP_KERNEL); if (!new_keymap) return -ENOMEM; - memcpy(new_keymap, keymap, length * sizeof(struct key_entry)); keymap = new_keymap; return 0; @@ -943,6 +1018,10 @@ static int __init select_keymap(void) if (keymap_name != NULL) { if (strcmp (keymap_name, "1557/MS2141") == 0) keymap = keymap_wistron_ms2141; + else if (strcmp (keymap_name, "aopen1557") == 0) + keymap = keymap_aopen_1557; + else if (strcmp (keymap_name, "prestigio") == 0) + keymap = keymap_prestigio; else if (strcmp (keymap_name, "generic") == 0) keymap = keymap_wistron_generic; else { @@ -965,23 +1044,8 @@ static int __init select_keymap(void) static struct input_polled_dev *wistron_idev; static unsigned long jiffies_last_press; -static int wifi_enabled; -static int bluetooth_enabled; - -static void report_key(struct input_dev *dev, unsigned int keycode) -{ - input_report_key(dev, keycode, 1); - input_sync(dev); - input_report_key(dev, keycode, 0); - input_sync(dev); -} - -static void report_switch(struct input_dev *dev, unsigned int code, int value) -{ - input_report_switch(dev, code, value); - input_sync(dev); -} - +static bool wifi_enabled; +static bool bluetooth_enabled; /* led management */ static void wistron_mail_led_set(struct led_classdev *led_cdev, @@ -1007,95 +1071,65 @@ static struct led_classdev wistron_wifi_led = { .brightness_set = wistron_wifi_led_set, }; -static void __devinit wistron_led_init(struct device *parent) +static void wistron_led_init(struct device *parent) { - if (have_leds & FE_WIFI_LED) { + if (leds_present & FE_WIFI_LED) { u16 wifi = bios_get_default_setting(WIFI); if (wifi & 1) { wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF; if (led_classdev_register(parent, &wistron_wifi_led)) - have_leds &= ~FE_WIFI_LED; + leds_present &= ~FE_WIFI_LED; else bios_set_state(WIFI, wistron_wifi_led.brightness); } else - have_leds &= ~FE_WIFI_LED; + leds_present &= ~FE_WIFI_LED; } - if (have_leds & FE_MAIL_LED) { + if (leds_present & FE_MAIL_LED) { /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */ wistron_mail_led.brightness = LED_OFF; if (led_classdev_register(parent, &wistron_mail_led)) - have_leds &= ~FE_MAIL_LED; + leds_present &= ~FE_MAIL_LED; else bios_set_state(MAIL_LED, wistron_mail_led.brightness); } } -static void __devexit wistron_led_remove(void) +static void wistron_led_remove(void) { - if (have_leds & FE_MAIL_LED) + if (leds_present & FE_MAIL_LED) led_classdev_unregister(&wistron_mail_led); - if (have_leds & FE_WIFI_LED) + if (leds_present & FE_WIFI_LED) led_classdev_unregister(&wistron_wifi_led); } static inline void wistron_led_suspend(void) { - if (have_leds & FE_MAIL_LED) + if (leds_present & FE_MAIL_LED) led_classdev_suspend(&wistron_mail_led); - if (have_leds & FE_WIFI_LED) + if (leds_present & FE_WIFI_LED) led_classdev_suspend(&wistron_wifi_led); } static inline void wistron_led_resume(void) { - if (have_leds & FE_MAIL_LED) + if (leds_present & FE_MAIL_LED) led_classdev_resume(&wistron_mail_led); - if (have_leds & FE_WIFI_LED) + if (leds_present & FE_WIFI_LED) led_classdev_resume(&wistron_wifi_led); } -static struct key_entry *wistron_get_entry_by_scancode(int code) -{ - struct key_entry *key; - - for (key = keymap; key->type != KE_END; key++) - if (code == key->code) - return key; - - return NULL; -} - -static struct key_entry *wistron_get_entry_by_keycode(int keycode) -{ - struct key_entry *key; - - for (key = keymap; key->type != KE_END; key++) - if (key->type == KE_KEY && keycode == key->keycode) - return key; - - return NULL; -} - static void handle_key(u8 code) { - const struct key_entry *key = wistron_get_entry_by_scancode(code); + const struct key_entry *key = + sparse_keymap_entry_from_scancode(wistron_idev->input, code); if (key) { switch (key->type) { - case KE_KEY: - report_key(wistron_idev->input, key->keycode); - break; - - case KE_SW: - report_switch(wistron_idev->input, - key->sw.code, key->sw.value); - break; - case KE_WIFI: if (have_wifi) { wifi_enabled = !wifi_enabled; @@ -1111,7 +1145,9 @@ static void handle_key(u8 code) break; default: - BUG(); + sparse_keymap_report_entry(wistron_idev->input, + key, 1, true); + break; } jiffies_last_press = jiffies; } else @@ -1151,42 +1187,39 @@ static void wistron_poll(struct input_polled_dev *dev) dev->poll_interval = POLL_INTERVAL_DEFAULT; } -static int wistron_getkeycode(struct input_dev *dev, int scancode, int *keycode) +static int wistron_setup_keymap(struct input_dev *dev, + struct key_entry *entry) { - const struct key_entry *key = wistron_get_entry_by_scancode(scancode); - - if (key && key->type == KE_KEY) { - *keycode = key->keycode; - return 0; - } + switch (entry->type) { - return -EINVAL; -} + /* if wifi or bluetooth are not available, create normal keys */ + case KE_WIFI: + if (!have_wifi) { + entry->type = KE_KEY; + entry->keycode = KEY_WLAN; + } + break; -static int wistron_setkeycode(struct input_dev *dev, int scancode, int keycode) -{ - struct key_entry *key; - int old_keycode; - - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; - - key = wistron_get_entry_by_scancode(scancode); - if (key && key->type == KE_KEY) { - old_keycode = key->keycode; - key->keycode = keycode; - set_bit(keycode, dev->keybit); - if (!wistron_get_entry_by_keycode(old_keycode)) - clear_bit(old_keycode, dev->keybit); - return 0; + case KE_BLUETOOTH: + if (!have_bluetooth) { + entry->type = KE_KEY; + entry->keycode = KEY_BLUETOOTH; + } + break; + + case KE_END: + if (entry->code & FE_UNTESTED) + printk(KERN_WARNING "Untested laptop multimedia keys, " + "please report success or failure to " + "eric.piel@tremplin-utc.net\n"); + break; } - return -EINVAL; + return 0; } -static int __devinit setup_input_dev(void) +static int setup_input_dev(void) { - const struct key_entry *key; struct input_dev *input_dev; int error; @@ -1194,7 +1227,7 @@ static int __devinit setup_input_dev(void) if (!wistron_idev) return -ENOMEM; - wistron_idev->flush = wistron_flush; + wistron_idev->open = wistron_flush; wistron_idev->poll = wistron_poll; wistron_idev->poll_interval = POLL_INTERVAL_DEFAULT; @@ -1204,44 +1237,26 @@ static int __devinit setup_input_dev(void) input_dev->id.bustype = BUS_HOST; input_dev->dev.parent = &wistron_device->dev; - input_dev->getkeycode = wistron_getkeycode; - input_dev->setkeycode = wistron_setkeycode; - - for (key = keymap; key->type != KE_END; key++) { - switch (key->type) { - case KE_KEY: - set_bit(EV_KEY, input_dev->evbit); - set_bit(key->keycode, input_dev->keybit); - break; - - case KE_SW: - set_bit(EV_SW, input_dev->evbit); - set_bit(key->sw.code, input_dev->swbit); - break; - - default: - break; - } - } - - /* reads information flags on KE_END */ - if (key->code & FE_UNTESTED) - printk(KERN_WARNING "Untested laptop multimedia keys, " - "please report success or failure to eric.piel" - "@tremplin-utc.net\n"); + error = sparse_keymap_setup(input_dev, keymap, wistron_setup_keymap); + if (error) + goto err_free_dev; error = input_register_polled_device(wistron_idev); - if (error) { - input_free_polled_device(wistron_idev); - return error; - } + if (error) + goto err_free_keymap; return 0; + + err_free_keymap: + sparse_keymap_free(input_dev); + err_free_dev: + input_free_polled_device(wistron_idev); + return error; } /* Driver core */ -static int __devinit wistron_probe(struct platform_device *dev) +static int wistron_probe(struct platform_device *dev) { int err; @@ -1251,7 +1266,7 @@ static int __devinit wistron_probe(struct platform_device *dev) if (have_wifi) { u16 wifi = bios_get_default_setting(WIFI); if (wifi & 1) - wifi_enabled = (wifi & 2) ? 1 : 0; + wifi_enabled = wifi & 2; else have_wifi = 0; @@ -1262,15 +1277,16 @@ static int __devinit wistron_probe(struct platform_device *dev) if (have_bluetooth) { u16 bt = bios_get_default_setting(BLUETOOTH); if (bt & 1) - bluetooth_enabled = (bt & 2) ? 1 : 0; + bluetooth_enabled = bt & 2; else - have_bluetooth = 0; + have_bluetooth = false; if (have_bluetooth) bios_set_state(BLUETOOTH, bluetooth_enabled); } wistron_led_init(&dev->dev); + err = setup_input_dev(); if (err) { bios_detach(); @@ -1280,10 +1296,11 @@ static int __devinit wistron_probe(struct platform_device *dev) return 0; } -static int __devexit wistron_remove(struct platform_device *dev) +static int wistron_remove(struct platform_device *dev) { wistron_led_remove(); input_unregister_polled_device(wistron_idev); + sparse_keymap_free(wistron_idev->input); input_free_polled_device(wistron_idev); bios_detach(); @@ -1291,7 +1308,7 @@ static int __devexit wistron_remove(struct platform_device *dev) } #ifdef CONFIG_PM -static int wistron_suspend(struct platform_device *dev, pm_message_t state) +static int wistron_suspend(struct device *dev) { if (have_wifi) bios_set_state(WIFI, 0); @@ -1300,10 +1317,11 @@ static int wistron_suspend(struct platform_device *dev, pm_message_t state) bios_set_state(BLUETOOTH, 0); wistron_led_suspend(); + return 0; } -static int wistron_resume(struct platform_device *dev) +static int wistron_resume(struct device *dev) { if (have_wifi) bios_set_state(WIFI, wifi_enabled); @@ -1312,24 +1330,30 @@ static int wistron_resume(struct platform_device *dev) bios_set_state(BLUETOOTH, bluetooth_enabled); wistron_led_resume(); + poll_bios(true); return 0; } -#else -#define wistron_suspend NULL -#define wistron_resume NULL + +static const struct dev_pm_ops wistron_pm_ops = { + .suspend = wistron_suspend, + .resume = wistron_resume, + .poweroff = wistron_suspend, + .restore = wistron_resume, +}; #endif static struct platform_driver wistron_driver = { .driver = { .name = "wistron-bios", .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &wistron_pm_ops, +#endif }, .probe = wistron_probe, - .remove = __devexit_p(wistron_remove), - .suspend = wistron_suspend, - .resume = wistron_resume, + .remove = wistron_remove, }; static int __init wb_module_init(void) @@ -1342,7 +1366,7 @@ static int __init wb_module_init(void) err = map_bios(); if (err) - return err; + goto err_free_keymap; err = platform_driver_register(&wistron_driver); if (err) @@ -1366,6 +1390,8 @@ static int __init wb_module_init(void) platform_driver_unregister(&wistron_driver); err_unmap_bios: unmap_bios(); + err_free_keymap: + kfree(keymap); return err; } |
