wistron_btns.c (389679d8faa38bb6d069d9e1805f15e3cb9a6d7f) | wistron_btns.c (c2554c91425a86e5d0409a76b7ddcb328362f08b) |
---|---|
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 --- 6 unchanged lines hidden (view full) --- 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> | 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 --- 6 unchanged lines hidden (view full) --- 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.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> | 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/timer.h> | |
32#include <linux/types.h> 33#include <linux/platform_device.h> 34#include <linux/leds.h> 35 | 31#include <linux/types.h> 32#include <linux/platform_device.h> 33#include <linux/leds.h> 34 |
36/* 37 * Number of attempts to read data from queue per poll; 38 * the queue can hold up to 31 entries 39 */ 40#define MAX_POLL_ITERATIONS 64 | 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 */ |
41 | 38 |
42#define POLL_FREQUENCY 2 /* Number of polls per second when idle */ 43#define POLL_FREQUENCY_BURST 10 /* Polls per second when a key was recently pressed */ 44 45#if POLL_FREQUENCY_BURST > HZ 46#error "POLL_FREQUENCY too high" 47#endif 48 | |
49/* BIOS subsystem IDs */ 50#define WIFI 0x35 51#define BLUETOOTH 0x34 52#define MAIL_LED 0x31 53 54MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>"); 55MODULE_DESCRIPTION("Wistron laptop button driver"); 56MODULE_LICENSE("GPL v2"); --- 911 unchanged lines hidden (view full) --- 968 keymap = keymap_empty; 969 } 970 971 return copy_keymap(); 972} 973 974 /* Input layer interface */ 975 | 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"); --- 911 unchanged lines hidden (view full) --- 958 keymap = keymap_empty; 959 } 960 961 return copy_keymap(); 962} 963 964 /* Input layer interface */ 965 |
976static struct input_dev *input_dev; | 966static struct input_polled_dev *wistron_idev; 967static unsigned long jiffies_last_press; 968static int wifi_enabled; 969static int bluetooth_enabled; |
977 | 970 |
978static int __devinit setup_input_dev(void) | 971static void report_key(struct input_dev *dev, unsigned int keycode) |
979{ | 972{ |
980 const struct key_entry *key; 981 int error; 982 983 input_dev = input_allocate_device(); 984 if (!input_dev) 985 return -ENOMEM; 986 987 input_dev->name = "Wistron laptop buttons"; 988 input_dev->phys = "wistron/input0"; 989 input_dev->id.bustype = BUS_HOST; 990 input_dev->cdev.dev = &wistron_device->dev; 991 992 for (key = keymap; key->type != KE_END; key++) { 993 switch (key->type) { 994 case KE_KEY: 995 set_bit(EV_KEY, input_dev->evbit); 996 set_bit(key->keycode, input_dev->keybit); 997 break; 998 999 case KE_SW: 1000 set_bit(EV_SW, input_dev->evbit); 1001 set_bit(key->sw.code, input_dev->swbit); 1002 break; 1003 1004 default: 1005 ; 1006 } 1007 } 1008 1009 /* reads information flags on KE_END */ 1010 if (key->code & FE_UNTESTED) 1011 printk(KERN_WARNING "Untested laptop multimedia keys, " 1012 "please report success or failure to eric.piel" 1013 "@tremplin-utc.net\n"); 1014 1015 error = input_register_device(input_dev); 1016 if (error) { 1017 input_free_device(input_dev); 1018 return error; 1019 } 1020 1021 return 0; | 973 input_report_key(dev, keycode, 1); 974 input_sync(dev); 975 input_report_key(dev, keycode, 0); 976 input_sync(dev); |
1022} 1023 | 977} 978 |
1024static void report_key(unsigned keycode) | 979static void report_switch(struct input_dev *dev, unsigned int code, int value) |
1025{ | 980{ |
1026 input_report_key(input_dev, keycode, 1); 1027 input_sync(input_dev); 1028 input_report_key(input_dev, keycode, 0); 1029 input_sync(input_dev); | 981 input_report_switch(dev, code, value); 982 input_sync(dev); |
1030} 1031 | 983} 984 |
1032static void report_switch(unsigned code, int value) 1033{ 1034 input_report_switch(input_dev, code, value); 1035 input_sync(input_dev); 1036} | |
1037 | 985 |
1038 | |
1039 /* led management */ 1040static 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 */ --- 60 unchanged lines hidden (view full) --- 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 | 986 /* led management */ 987static void wistron_mail_led_set(struct led_classdev *led_cdev, 988 enum led_brightness value) 989{ 990 bios_set_state(MAIL_LED, (value != LED_OFF) ? 1 : 0); 991} 992 993/* same as setting up wifi card, but for laptops on which the led is managed */ --- 60 unchanged lines hidden (view full) --- 1054{ 1055 if (have_leds & FE_MAIL_LED) 1056 led_classdev_resume(&wistron_mail_led); 1057 1058 if (have_leds & FE_WIFI_LED) 1059 led_classdev_resume(&wistron_wifi_led); 1060} 1061 |
1115 /* Driver core */ 1116 1117static int wifi_enabled; 1118static int bluetooth_enabled; 1119 1120static void poll_bios(unsigned long); 1121 1122static struct timer_list poll_timer = TIMER_INITIALIZER(poll_bios, 0, 0); 1123 | |
1124static void handle_key(u8 code) 1125{ 1126 const struct key_entry *key; 1127 1128 for (key = keymap; key->type != KE_END; key++) { 1129 if (code == key->code) { 1130 switch (key->type) { 1131 case KE_KEY: | 1062static void handle_key(u8 code) 1063{ 1064 const struct key_entry *key; 1065 1066 for (key = keymap; key->type != KE_END; key++) { 1067 if (code == key->code) { 1068 switch (key->type) { 1069 case KE_KEY: |
1132 report_key(key->keycode); | 1070 report_key(wistron_idev->input, key->keycode); |
1133 break; 1134 1135 case KE_SW: | 1071 break; 1072 1073 case KE_SW: |
1136 report_switch(key->sw.code, key->sw.value); | 1074 report_switch(wistron_idev->input, 1075 key->sw.code, key->sw.value); |
1137 break; 1138 1139 case KE_WIFI: 1140 if (have_wifi) { 1141 wifi_enabled = !wifi_enabled; 1142 bios_set_state(WIFI, wifi_enabled); 1143 } 1144 break; 1145 1146 case KE_BLUETOOTH: 1147 if (have_bluetooth) { 1148 bluetooth_enabled = !bluetooth_enabled; 1149 bios_set_state(BLUETOOTH, bluetooth_enabled); 1150 } 1151 break; 1152 1153 case KE_END: 1154 break; | 1076 break; 1077 1078 case KE_WIFI: 1079 if (have_wifi) { 1080 wifi_enabled = !wifi_enabled; 1081 bios_set_state(WIFI, wifi_enabled); 1082 } 1083 break; 1084 1085 case KE_BLUETOOTH: 1086 if (have_bluetooth) { 1087 bluetooth_enabled = !bluetooth_enabled; 1088 bios_set_state(BLUETOOTH, bluetooth_enabled); 1089 } 1090 break; 1091 1092 case KE_END: 1093 break; |
1094 |
|
1155 default: 1156 BUG(); 1157 } | 1095 default: 1096 BUG(); 1097 } |
1098 jiffies_last_press = jiffies; |
|
1158 return; 1159 } 1160 } 1161 printk(KERN_NOTICE "wistron_btns: Unknown key code %02X\n", code); 1162} 1163 | 1099 return; 1100 } 1101 } 1102 printk(KERN_NOTICE "wistron_btns: Unknown key code %02X\n", code); 1103} 1104 |
1164static void poll_bios(unsigned long discard) | 1105static void poll_bios(bool discard) |
1165{ | 1106{ |
1166 static unsigned long jiffies_last_press; 1167 unsigned long jiffies_now = jiffies; | |
1168 u8 qlen; 1169 u16 val; 1170 1171 for (;;) { 1172 qlen = CMOS_READ(cmos_address); 1173 if (qlen == 0) 1174 break; 1175 val = bios_pop_queue(); | 1107 u8 qlen; 1108 u16 val; 1109 1110 for (;;) { 1111 qlen = CMOS_READ(cmos_address); 1112 if (qlen == 0) 1113 break; 1114 val = bios_pop_queue(); |
1176 if (val != 0 && !discard) { | 1115 if (val != 0 && !discard) |
1177 handle_key((u8)val); | 1116 handle_key((u8)val); |
1178 jiffies_last_press = jiffies_now; 1179 } | |
1180 } | 1117 } |
1118} |
|
1181 | 1119 |
1182 /* Increase precision if user is currently pressing keys (< 2s ago) */ 1183 if (time_after(jiffies_last_press, jiffies_now - (HZ * 2))) 1184 mod_timer(&poll_timer, jiffies_now + HZ / POLL_FREQUENCY_BURST); | 1120static void wistron_flush(struct input_polled_dev *dev) 1121{ 1122 /* Flush stale event queue */ 1123 poll_bios(true); 1124} 1125 1126static void wistron_poll(struct input_polled_dev *dev) 1127{ 1128 poll_bios(false); 1129 1130 /* Increase poll frequency if user is currently pressing keys (< 2s ago) */ 1131 if (time_before(jiffies, jiffies_last_press + 2 * HZ)) 1132 dev->poll_interval = POLL_INTERVAL_BURST; |
1185 else | 1133 else |
1186 mod_timer(&poll_timer, jiffies_now + HZ / POLL_FREQUENCY); | 1134 dev->poll_interval = POLL_INTERVAL_DEFAULT; |
1187} 1188 | 1135} 1136 |
1137static int __devinit setup_input_dev(void) 1138{ 1139 const struct key_entry *key; 1140 struct input_dev *input_dev; 1141 int error; 1142 1143 wistron_idev = input_allocate_polled_device(); 1144 if (!wistron_idev) 1145 return -ENOMEM; 1146 1147 wistron_idev->flush = wistron_flush; 1148 wistron_idev->poll = wistron_poll; 1149 wistron_idev->poll_interval = POLL_INTERVAL_DEFAULT; 1150 1151 input_dev = wistron_idev->input; 1152 input_dev->name = "Wistron laptop buttons"; 1153 input_dev->phys = "wistron/input0"; 1154 input_dev->id.bustype = BUS_HOST; 1155 input_dev->cdev.dev = &wistron_device->dev; 1156 1157 for (key = keymap; key->type != KE_END; key++) { 1158 switch (key->type) { 1159 case KE_KEY: 1160 set_bit(EV_KEY, input_dev->evbit); 1161 set_bit(key->keycode, input_dev->keybit); 1162 break; 1163 1164 case KE_SW: 1165 set_bit(EV_SW, input_dev->evbit); 1166 set_bit(key->sw.code, input_dev->swbit); 1167 break; 1168 1169 default: 1170 break; 1171 } 1172 } 1173 1174 /* reads information flags on KE_END */ 1175 if (key->code & FE_UNTESTED) 1176 printk(KERN_WARNING "Untested laptop multimedia keys, " 1177 "please report success or failure to eric.piel" 1178 "@tremplin-utc.net\n"); 1179 1180 error = input_register_polled_device(wistron_idev); 1181 if (error) { 1182 input_free_polled_device(wistron_idev); 1183 return error; 1184 } 1185 1186 return 0; 1187} 1188 1189/* Driver core */ 1190 |
|
1189static int __devinit wistron_probe(struct platform_device *dev) 1190{ | 1191static int __devinit wistron_probe(struct platform_device *dev) 1192{ |
1191 int err = setup_input_dev(); 1192 if (err) 1193 return err; | 1193 int err; |
1194 1195 bios_attach(); 1196 cmos_address = bios_get_cmos_address(); 1197 1198 if (have_wifi) { 1199 u16 wifi = bios_get_default_setting(WIFI); 1200 if (wifi & 1) 1201 wifi_enabled = (wifi & 2) ? 1 : 0; --- 11 unchanged lines hidden (view full) --- 1213 else 1214 have_bluetooth = 0; 1215 1216 if (have_bluetooth) 1217 bios_set_state(BLUETOOTH, bluetooth_enabled); 1218 } 1219 1220 wistron_led_init(&dev->dev); | 1194 1195 bios_attach(); 1196 cmos_address = bios_get_cmos_address(); 1197 1198 if (have_wifi) { 1199 u16 wifi = bios_get_default_setting(WIFI); 1200 if (wifi & 1) 1201 wifi_enabled = (wifi & 2) ? 1 : 0; --- 11 unchanged lines hidden (view full) --- 1213 else 1214 have_bluetooth = 0; 1215 1216 if (have_bluetooth) 1217 bios_set_state(BLUETOOTH, bluetooth_enabled); 1218 } 1219 1220 wistron_led_init(&dev->dev); |
1221 poll_bios(1); /* Flush stale event queue and arm timer */ | 1221 err = setup_input_dev(); 1222 if (err) { 1223 bios_detach(); 1224 return err; 1225 } |
1222 1223 return 0; 1224} 1225 1226static int __devexit wistron_remove(struct platform_device *dev) 1227{ | 1226 1227 return 0; 1228} 1229 1230static int __devexit wistron_remove(struct platform_device *dev) 1231{ |
1228 del_timer_sync(&poll_timer); | |
1229 wistron_led_remove(); | 1232 wistron_led_remove(); |
1230 input_unregister_device(input_dev); | 1233 input_unregister_polled_device(wistron_idev); 1234 input_free_polled_device(wistron_idev); |
1231 bios_detach(); 1232 1233 return 0; 1234} 1235 1236#ifdef CONFIG_PM 1237static int wistron_suspend(struct platform_device *dev, pm_message_t state) 1238{ | 1235 bios_detach(); 1236 1237 return 0; 1238} 1239 1240#ifdef CONFIG_PM 1241static int wistron_suspend(struct platform_device *dev, pm_message_t state) 1242{ |
1239 del_timer_sync(&poll_timer); 1240 | |
1241 if (have_wifi) 1242 bios_set_state(WIFI, 0); 1243 1244 if (have_bluetooth) 1245 bios_set_state(BLUETOOTH, 0); 1246 1247 wistron_led_suspend(); 1248 return 0; 1249} 1250 1251static int wistron_resume(struct platform_device *dev) 1252{ 1253 if (have_wifi) 1254 bios_set_state(WIFI, wifi_enabled); 1255 1256 if (have_bluetooth) 1257 bios_set_state(BLUETOOTH, bluetooth_enabled); 1258 1259 wistron_led_resume(); | 1243 if (have_wifi) 1244 bios_set_state(WIFI, 0); 1245 1246 if (have_bluetooth) 1247 bios_set_state(BLUETOOTH, 0); 1248 1249 wistron_led_suspend(); 1250 return 0; 1251} 1252 1253static int wistron_resume(struct platform_device *dev) 1254{ 1255 if (have_wifi) 1256 bios_set_state(WIFI, wifi_enabled); 1257 1258 if (have_bluetooth) 1259 bios_set_state(BLUETOOTH, bluetooth_enabled); 1260 1261 wistron_led_resume(); |
1260 poll_bios(1); | 1262 poll_bios(true); |
1261 1262 return 0; 1263} 1264#else 1265#define wistron_suspend NULL 1266#define wistron_resume NULL 1267#endif 1268 --- 59 unchanged lines hidden --- | 1263 1264 return 0; 1265} 1266#else 1267#define wistron_suspend NULL 1268#define wistron_resume NULL 1269#endif 1270 --- 59 unchanged lines hidden --- |