diff options
-rw-r--r-- | drivers/input/misc/Kconfig | 5 | ||||
-rw-r--r-- | drivers/input/misc/wistron_btns.c | 88 |
2 files changed, 91 insertions, 2 deletions
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 88e29074ac90..4326f536f849 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -65,9 +65,12 @@ config INPUT_COBALT_BTNS | |||
65 | config INPUT_WISTRON_BTNS | 65 | config INPUT_WISTRON_BTNS |
66 | tristate "x86 Wistron laptop button interface" | 66 | tristate "x86 Wistron laptop button interface" |
67 | depends on X86 && !X86_64 | 67 | depends on X86 && !X86_64 |
68 | select NEW_LEDS | ||
69 | select LEDS_CLASS | ||
68 | help | 70 | help |
69 | Say Y here for support of Winstron laptop button interface, used on | 71 | Say Y here for support of Winstron laptop button interface, used on |
70 | laptops of various brands, including Acer and Fujitsu-Siemens. | 72 | laptops of various brands, including Acer and Fujitsu-Siemens. If |
73 | available, mail and wifi leds will be controlable via /sys/class/leds. | ||
71 | 74 | ||
72 | To compile this driver as a module, choose M here: the module will | 75 | To compile this driver as a module, choose M here: the module will |
73 | be called wistron_btns. | 76 | be called wistron_btns. |
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 320262aa4c17..d58ddcab601f 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/timer.h> | 31 | #include <linux/timer.h> |
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | #include <linux/platform_device.h> | 33 | #include <linux/platform_device.h> |
34 | #include <linux/leds.h> | ||
34 | 35 | ||
35 | /* | 36 | /* |
36 | * Number of attempts to read data from queue per poll; | 37 | * Number of attempts to read data from queue per poll; |
@@ -48,11 +49,12 @@ | |||
48 | /* BIOS subsystem IDs */ | 49 | /* BIOS subsystem IDs */ |
49 | #define WIFI 0x35 | 50 | #define WIFI 0x35 |
50 | #define BLUETOOTH 0x34 | 51 | #define BLUETOOTH 0x34 |
52 | #define MAIL_LED 0x31 | ||
51 | 53 | ||
52 | MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>"); | 54 | MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>"); |
53 | MODULE_DESCRIPTION("Wistron laptop button driver"); | 55 | MODULE_DESCRIPTION("Wistron laptop button driver"); |
54 | MODULE_LICENSE("GPL v2"); | 56 | MODULE_LICENSE("GPL v2"); |
55 | MODULE_VERSION("0.2"); | 57 | MODULE_VERSION("0.3"); |
56 | 58 | ||
57 | static int force; /* = 0; */ | 59 | static int force; /* = 0; */ |
58 | module_param(force, bool, 0); | 60 | module_param(force, bool, 0); |
@@ -253,6 +255,7 @@ enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH }; | |||
253 | static const struct key_entry *keymap; /* = NULL; Current key map */ | 255 | static const struct key_entry *keymap; /* = NULL; Current key map */ |
254 | static int have_wifi; | 256 | static int have_wifi; |
255 | static int have_bluetooth; | 257 | static int have_bluetooth; |
258 | static int have_leds; | ||
256 | 259 | ||
257 | static int __init dmi_matched(struct dmi_system_id *dmi) | 260 | static int __init dmi_matched(struct dmi_system_id *dmi) |
258 | { | 261 | { |
@@ -265,6 +268,8 @@ static int __init dmi_matched(struct dmi_system_id *dmi) | |||
265 | else if (key->type == KE_BLUETOOTH) | 268 | else if (key->type == KE_BLUETOOTH) |
266 | have_bluetooth = 1; | 269 | have_bluetooth = 1; |
267 | } | 270 | } |
271 | have_leds = key->code & (FE_MAIL_LED | FE_WIFI_LED); | ||
272 | |||
268 | return 1; | 273 | return 1; |
269 | } | 274 | } |
270 | 275 | ||
@@ -1030,6 +1035,83 @@ static void report_switch(unsigned code, int value) | |||
1030 | input_sync(input_dev); | 1035 | input_sync(input_dev); |
1031 | } | 1036 | } |
1032 | 1037 | ||
1038 | |||
1039 | /* led management */ | ||
1040 | static void wistron_mail_led_set(struct led_classdev *led_cdev, | ||
1041 | enum led_brightness value) | ||
1042 | { | ||
1043 | bios_set_state(MAIL_LED, (value != LED_OFF) ? 1 : 0); | ||
1044 | } | ||
1045 | |||
1046 | /* same as setting up wifi card, but for laptops on which the led is managed */ | ||
1047 | static void wistron_wifi_led_set(struct led_classdev *led_cdev, | ||
1048 | enum led_brightness value) | ||
1049 | { | ||
1050 | bios_set_state(WIFI, (value != LED_OFF) ? 1 : 0); | ||
1051 | } | ||
1052 | |||
1053 | static struct led_classdev wistron_mail_led = { | ||
1054 | .name = "mail:green", | ||
1055 | .brightness_set = wistron_mail_led_set, | ||
1056 | }; | ||
1057 | |||
1058 | static struct led_classdev wistron_wifi_led = { | ||
1059 | .name = "wifi:red", | ||
1060 | .brightness_set = wistron_wifi_led_set, | ||
1061 | }; | ||
1062 | |||
1063 | static void __devinit wistron_led_init(struct device *parent) | ||
1064 | { | ||
1065 | if (have_leds & FE_WIFI_LED) { | ||
1066 | u16 wifi = bios_get_default_setting(WIFI); | ||
1067 | if (wifi & 1) { | ||
1068 | wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF; | ||
1069 | if (led_classdev_register(parent, &wistron_wifi_led)) | ||
1070 | have_leds &= ~FE_WIFI_LED; | ||
1071 | else | ||
1072 | bios_set_state(WIFI, wistron_wifi_led.brightness); | ||
1073 | |||
1074 | } else | ||
1075 | have_leds &= ~FE_WIFI_LED; | ||
1076 | } | ||
1077 | |||
1078 | if (have_leds & FE_MAIL_LED) { | ||
1079 | /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */ | ||
1080 | wistron_mail_led.brightness = LED_OFF; | ||
1081 | if (led_classdev_register(parent, &wistron_mail_led)) | ||
1082 | have_leds &= ~FE_MAIL_LED; | ||
1083 | else | ||
1084 | bios_set_state(MAIL_LED, wistron_mail_led.brightness); | ||
1085 | } | ||
1086 | } | ||
1087 | |||
1088 | static void __devexit wistron_led_remove(void) | ||
1089 | { | ||
1090 | if (have_leds & FE_MAIL_LED) | ||
1091 | led_classdev_unregister(&wistron_mail_led); | ||
1092 | |||
1093 | if (have_leds & FE_WIFI_LED) | ||
1094 | led_classdev_unregister(&wistron_wifi_led); | ||
1095 | } | ||
1096 | |||
1097 | static inline void wistron_led_suspend(void) | ||
1098 | { | ||
1099 | if (have_leds & FE_MAIL_LED) | ||
1100 | led_classdev_suspend(&wistron_mail_led); | ||
1101 | |||
1102 | if (have_leds & FE_WIFI_LED) | ||
1103 | led_classdev_suspend(&wistron_wifi_led); | ||
1104 | } | ||
1105 | |||
1106 | static inline void wistron_led_resume(void) | ||
1107 | { | ||
1108 | if (have_leds & FE_MAIL_LED) | ||
1109 | led_classdev_resume(&wistron_mail_led); | ||
1110 | |||
1111 | if (have_leds & FE_WIFI_LED) | ||
1112 | led_classdev_resume(&wistron_wifi_led); | ||
1113 | } | ||
1114 | |||
1033 | /* Driver core */ | 1115 | /* Driver core */ |
1034 | 1116 | ||
1035 | static int wifi_enabled; | 1117 | static int wifi_enabled; |
@@ -1135,6 +1217,7 @@ static int __devinit wistron_probe(struct platform_device *dev) | |||
1135 | bios_set_state(BLUETOOTH, bluetooth_enabled); | 1217 | bios_set_state(BLUETOOTH, bluetooth_enabled); |
1136 | } | 1218 | } |
1137 | 1219 | ||
1220 | wistron_led_init(&dev->dev); | ||
1138 | poll_bios(1); /* Flush stale event queue and arm timer */ | 1221 | poll_bios(1); /* Flush stale event queue and arm timer */ |
1139 | 1222 | ||
1140 | return 0; | 1223 | return 0; |
@@ -1143,6 +1226,7 @@ static int __devinit wistron_probe(struct platform_device *dev) | |||
1143 | static int __devexit wistron_remove(struct platform_device *dev) | 1226 | static int __devexit wistron_remove(struct platform_device *dev) |
1144 | { | 1227 | { |
1145 | del_timer_sync(&poll_timer); | 1228 | del_timer_sync(&poll_timer); |
1229 | wistron_led_remove(); | ||
1146 | input_unregister_device(input_dev); | 1230 | input_unregister_device(input_dev); |
1147 | bios_detach(); | 1231 | bios_detach(); |
1148 | 1232 | ||
@@ -1160,6 +1244,7 @@ static int wistron_suspend(struct platform_device *dev, pm_message_t state) | |||
1160 | if (have_bluetooth) | 1244 | if (have_bluetooth) |
1161 | bios_set_state(BLUETOOTH, 0); | 1245 | bios_set_state(BLUETOOTH, 0); |
1162 | 1246 | ||
1247 | wistron_led_suspend(); | ||
1163 | return 0; | 1248 | return 0; |
1164 | } | 1249 | } |
1165 | 1250 | ||
@@ -1171,6 +1256,7 @@ static int wistron_resume(struct platform_device *dev) | |||
1171 | if (have_bluetooth) | 1256 | if (have_bluetooth) |
1172 | bios_set_state(BLUETOOTH, bluetooth_enabled); | 1257 | bios_set_state(BLUETOOTH, bluetooth_enabled); |
1173 | 1258 | ||
1259 | wistron_led_resume(); | ||
1174 | poll_bios(1); | 1260 | poll_bios(1); |
1175 | 1261 | ||
1176 | return 0; | 1262 | return 0; |