]>
Commit | Line | Data |
---|---|---|
648cd9e8 | 1 | --- acerhk-0.5.35/acerhk.c 2007-02-10 16:46:23.000000000 +0100 |
2 | +++ acerhk/acerhk.c 2009-07-02 23:48:23.000000000 +0200 | |
3 | @@ -2,14 +2,14 @@ | |
4 | * Filename: acerhk.c | |
5 | * Version: 0.5 | |
6 | * | |
7 | - * Copyright (C) 2002-2006, Olaf Tauber (olaf-tauber@versanet.de) | |
8 | + * Copyright (C) 2002-2007, Olaf Tauber (olaf-tauber@versanet.de) | |
9 | * | |
10 | * Description: kernel driver for Acer Travelmate and similar | |
11 | * laptops special keys | |
12 | * Author: Olaf Tauber <olaf-tauber@versanet.de> | |
13 | * Created at: Mon Apr 29 22:16:42 2002 | |
14 | - * Modified at: Mon Oct 16 21:36:44 2006 | |
15 | - * Modified by: Olaf Tauber <olaf-tauber@versanet.de> | |
16 | + * Modified at: Mon Nov 12 20:53:56 2007 | |
17 | + * Modified by: Olaf Tauber <ole@smeagol> | |
18 | * Modified at: Thu Nov 24 13:03:01 2005 | |
19 | * Modified by: Antonio Cuni <cuni@programmazione.it> | |
20 | * Modified at: Wed Oct 27 19:47:11 CEST 2004 | |
21 | @@ -63,6 +63,7 @@ | |
22 | #include <linux/init.h> | |
23 | #include <linux/kmod.h> | |
24 | #include <linux/miscdevice.h> | |
25 | +#include <linux/platform_device.h> | |
26 | #include <linux/mc146818rtc.h> | |
27 | #include <linux/input.h> | |
28 | #include <linux/interrupt.h> | |
29 | @@ -550,6 +551,7 @@ | |
30 | */ | |
31 | static asmlinkage void call_bios_6xx(struct register_buffer *buf) | |
32 | { | |
33 | +#ifndef __x86_64__ | |
34 | if (bios_routine) { | |
35 | local_irq_disable(); | |
36 | __asm__ __volatile__( | |
37 | @@ -578,10 +580,12 @@ | |
38 | ); | |
39 | local_irq_enable(); | |
40 | } | |
41 | +#endif | |
42 | } | |
43 | ||
44 | static asmlinkage void call_bios_52x(struct register_buffer *buf) | |
45 | { | |
46 | +#ifndef __x86_64__ | |
47 | if (bios_routine) { | |
48 | local_irq_disable(); | |
49 | __asm__ __volatile__( | |
50 | @@ -611,6 +615,7 @@ | |
51 | ); | |
52 | local_irq_enable(); | |
53 | } | |
54 | +#endif | |
55 | } | |
56 | ||
57 | #define PRINT_BUFFER(x) \ | |
58 | @@ -783,7 +788,8 @@ | |
59 | unsigned char c = 0; | |
60 | ||
61 | spin_lock_irqsave (&rtc_lock, flags); | |
62 | -#ifndef DUMMYHW | |
63 | +/* #ifndef DUMMYHW */ | |
64 | +#if !(defined(DUMMYHW) || defined(__x86_64__)) | |
65 | if (cmos_index) | |
66 | c = CMOS_READ(cmos_index); | |
67 | else if (verbose > 3) | |
68 | @@ -867,9 +873,9 @@ | |
69 | ||
70 | static struct proc_dir_entry *proc_acer_dir; | |
71 | ||
72 | -static unsigned int __init find_hk_area(void) | |
73 | +static unsigned long __init find_hk_area(void) | |
74 | { | |
75 | - int offset, sig; | |
76 | + long offset, sig; | |
77 | unsigned int fkt; | |
78 | fkt = 0; | |
79 | sig = -1; /* offset to signature in io area */ | |
80 | @@ -887,9 +893,9 @@ | |
81 | fkt = readl(reg1 + sig + 5); | |
82 | /* adjust fkt to address of mapped IO area */ | |
83 | if (fkt >= 0xf0000) | |
84 | - fkt = (unsigned int)reg1 + fkt - 0xf0000; | |
85 | + fkt = (unsigned long)reg1 + fkt - 0xf0000; | |
86 | else if (fkt >= 0xe0000) | |
87 | - fkt = (unsigned int)reg1 + fkt - 0xe0000; | |
88 | + fkt = (unsigned long)reg1 + fkt - 0xe0000; | |
89 | else | |
90 | fkt = 0; | |
91 | } | |
92 | @@ -1144,6 +1150,7 @@ | |
93 | case 2000: | |
94 | case 2010: | |
95 | case 2020: | |
96 | + case 5100: | |
97 | /* Aspire 13xx series laptops use dritek hardware, no | |
98 | acerhk-mapping needed | |
99 | VolUp and VolDown are managed as normal keys | |
100 | @@ -1231,6 +1238,17 @@ | |
101 | acerhk_key2name[5] = k_display; /* FN+F3 (Display switch) */ | |
102 | acerhk_key2name[6] = k_res; /* FN+F4 (Display ein/ausschalten) */ | |
103 | break; | |
104 | + case 97600: | |
105 | + /* Medion MD97600, 7 keys, no setup */ | |
106 | + acerhk_key2name[1] = k_help; /* FN+F1 (Help) */ | |
107 | + acerhk_key2name[2] = k_none; | |
108 | + acerhk_key2name[5] = k_display; /* FN+F3 (Display switch) */ | |
109 | + acerhk_key2name[6] = k_res; /* FN+F4 (Display ein/ausschalten) */ | |
110 | + acerhk_key2name[17] = k_p1; | |
111 | + acerhk_key2name[18] = k_p2; | |
112 | + acerhk_key2name[19] = k_p3; | |
113 | + acerhk_key2name[48] = k_wireless; | |
114 | + break; | |
115 | case 42200: | |
116 | /* Medion MD42200, 7 keys, no setup */ | |
117 | acerhk_key2name[2] = k_none; | |
118 | @@ -1288,6 +1306,22 @@ | |
119 | acerhk_key2name[19] = k_p3; | |
120 | acerhk_key2name[8] = k_mute; | |
121 | break; | |
122 | + case 6805: /* Added by damagedspline@aim.com */ | |
123 | + /* Amilo A1xxx does not have Setup key nor a mail key */ | |
124 | + acerhk_key2name[2] = k_none; | |
125 | + acerhk_key2name[54] = k_www; | |
126 | + acerhk_key2name[5] = k_display; | |
127 | + acerhk_key2name[110] = k_setup; //This is the Fancy Fan (cool-n'-quiet) key on A1650g | |
128 | + acerhk_key2name[48] = k_wireless; | |
129 | + break; | |
130 | + case 98200: | |
131 | + /* Medion MD98200, 4 keys, no setup */ | |
132 | + acerhk_key2name[2] = k_none; | |
133 | + acerhk_key2name[48] = k_wireless; | |
134 | + acerhk_key2name[0x79] = k_play; | |
135 | + acerhk_key2name[17] = k_p1; | |
136 | + acerhk_key2name[18] = k_p2; | |
137 | + break; | |
138 | } | |
139 | } | |
140 | ||
141 | @@ -1313,11 +1347,24 @@ | |
142 | acerhk_model_features = 0x00f00000; | |
143 | acerhk_type = TM_new; | |
144 | break; | |
145 | + case 97600: | |
146 | + /* has WLAN button */ | |
147 | + /* The MD97600 seems to require TM_F_CONNECT at least | |
148 | + once after cold boot, otherwise enabling the WLAN | |
149 | + radio does not work */ | |
150 | + acerhk_model_features = TM_F_WBUTTON | TM_F_CONNECT; | |
151 | + acerhk_type = TM_new; | |
152 | + break; | |
153 | case 42200: /* Medion MD42200 */ | |
154 | /* has WLAN button, should call connect() */ | |
155 | acerhk_model_features = TM_F_WBUTTON | TM_F_CONNECT; | |
156 | acerhk_type = TM_old; | |
157 | break; | |
158 | + case 98200: /* Medion MD98200 */ | |
159 | + /* has WLAN button, should call connect() */ | |
160 | + acerhk_model_features = TM_F_WBUTTON; | |
161 | + acerhk_type = TM_old; | |
162 | + break; | |
163 | case 9783: /* Medion MD9783 */ | |
164 | /* only email led */ | |
165 | acerhk_model_features = TM_F_MAIL_LED; | |
166 | @@ -1363,6 +1410,11 @@ | |
167 | acerhk_model_features = TM_F_MAIL_LED | 0x00f00000; | |
168 | acerhk_type = TM_new; | |
169 | break; | |
170 | + case 6805: /* Added by damagedspline@aim.com */ | |
171 | + /* Amilo A1xxx does not have a mail led */ | |
172 | + acerhk_model_features = 0x00f00000; | |
173 | + acerhk_type = TM_new; | |
174 | + break; | |
175 | case 2350: | |
176 | case 4050: | |
177 | acerhk_wlan_state = 1; // Default state is on | |
178 | @@ -1458,6 +1510,7 @@ | |
179 | case 1800: | |
180 | case 2010: | |
181 | case 2020: | |
182 | + case 5100: | |
183 | /* Dritek EC, bluetooth, wifi, mail */ | |
184 | acerhk_type = TM_dritek; | |
185 | acerhk_model_features = TM_F_MAIL_LED_EC2 | TM_F_WLAN_EC2 | TM_F_BLUE_EC2; | |
186 | @@ -1792,6 +1845,8 @@ | |
187 | break; | |
188 | case '2': series = 5020; break; | |
189 | } | |
190 | + } else if (str[8] == '1' && str[9] == '0') { | |
191 | + series = 5100; | |
192 | } else { | |
193 | if (verbose > 1) | |
194 | printk(KERN_INFO"acerhk: model string indicates unknown Aspire 5xxx series\n"); | |
195 | @@ -1854,6 +1909,15 @@ | |
196 | printk(KERN_INFO"acerhk: model string indicates FS AMILO Pro (V2000) series\n"); | |
197 | series = 7400; | |
198 | break; | |
199 | + case 'A': /* AMILO Axxxx - added by damagedspline@aim.com */ | |
200 | + switch (str[7]) { | |
201 | + case '1': /* AMILO A1xxx */ | |
202 | + if (verbose > 1) | |
203 | + printk(KERN_INFO"acerhk: model string indicates FS AMILO A1xxx series\n"); | |
204 | + series = 6805; | |
205 | + break; | |
206 | + }; | |
207 | + break; | |
208 | default: | |
209 | if (verbose > 1) | |
210 | printk(KERN_INFO"acerhk: model string indicates unknown FS AMILO XX series\n"); | |
211 | @@ -1862,7 +1926,11 @@ | |
212 | } | |
213 | else if (strncmp(str, "MEDIONPC", 8) == 0) { | |
214 | uint medionmodel; | |
215 | - if ((medionmodel = COLUSSI("WIM 2040", 4, reg1, AREA_SIZE)) >= 0) { | |
216 | + if ((medionmodel = COLUSSI("WIM 2090", 8, reg1, AREA_SIZE)) >= 0) { | |
217 | + printk(KERN_INFO"acerhk: found Medion model string:'%s'\n", (char*)reg1+medionmodel); | |
218 | + series = 97600; | |
219 | + } | |
220 | + else if ((medionmodel = COLUSSI("WIM 2040", 4, reg1, AREA_SIZE)) >= 0) { | |
221 | printk(KERN_INFO"acerhk: found Medion model string:'%s'\n", (char*)reg1+medionmodel); | |
222 | series = 96500; | |
223 | } else { | |
224 | @@ -1893,6 +1961,12 @@ | |
225 | printk(KERN_INFO"acerhk: model string indicates a medion MD40100\n"); | |
226 | series = 40100; | |
227 | } | |
228 | + } else if (strncmp(str, "MEDION", 6) == 0) { | |
229 | + if (COLUSSI("WIM2120", 7, reg1, AREA_SIZE) >= 0) { | |
230 | + if (verbose>1) | |
231 | + printk(KERN_INFO"acerhk: model string indicates a Medion MD 98200\n"); | |
232 | + series = 98200; | |
233 | + } | |
234 | } else if (strncmp(str, "AOpen", 5) == 0) { | |
235 | if (strncmp(str, "AOpen*EzRestore", 15) == 0) { | |
236 | if (verbose > 1) | |
237 | @@ -2117,7 +2191,8 @@ | |
238 | /* polling timer handler */ | |
239 | static void acerhk_poll_event(unsigned long save_size) | |
240 | { | |
241 | -#ifndef DUMMYHW | |
242 | +/* #ifndef DUMMYHW */ | |
243 | +#if !(defined(DUMMYHW) || defined(__x86_64__)) | |
244 | unsigned int max = MAX_POLLING_LOOPS; | |
245 | /* make sure not to loop more then 32 times */ | |
246 | if (!max || max > 32) | |
247 | @@ -2139,7 +2214,8 @@ | |
248 | { | |
249 | if (acerhk_blueled_blinking != -1) { | |
250 | acerhk_blueled_blinking = !acerhk_blueled_blinking; | |
251 | -#ifndef DUMMYHW | |
252 | +/* #ifndef DUMMYHW */ | |
253 | +#if !(defined(DUMMYHW) || defined(__x86_64__)) | |
254 | wbutton_fct_1(acerhk_blueled_blinking); | |
255 | #endif | |
256 | acerhk_timer_blinking.expires = jiffies + acerhk_blueled_blinking_delay; | |
257 | @@ -2626,7 +2702,9 @@ | |
258 | printk(KERN_INFO"acerhk: could not create /proc/driver/acerhk\n"); | |
259 | } | |
260 | else { | |
261 | +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) | |
262 | proc_acer_dir->owner = THIS_MODULE; | |
263 | +#endif | |
264 | /* now create several files, first general info ... */ | |
265 | entry = create_proc_read_entry("info", | |
266 | 0444, proc_acer_dir, acerhk_proc_info, NULL); | |
267 | @@ -2635,7 +2713,9 @@ | |
268 | remove_proc_entry("driver/acerhk", NULL); | |
269 | retval = 0; | |
270 | } else { | |
271 | +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) | |
272 | entry->owner = THIS_MODULE; | |
273 | +#endif | |
274 | /* ... last pressed key ... */ | |
275 | entry = create_proc_read_entry("key", | |
276 | 0444, proc_acer_dir, acerhk_proc_key, NULL); | |
277 | @@ -2645,7 +2725,9 @@ | |
278 | remove_proc_entry("driver/acerhk", NULL); | |
279 | retval = 0; | |
280 | } else { | |
281 | +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) | |
282 | entry->owner = THIS_MODULE; | |
283 | +#endif | |
284 | /* ... and led control file */ | |
285 | entry = create_proc_entry("led", 0222, proc_acer_dir); | |
286 | if (entry == NULL) { | |
287 | @@ -2657,7 +2739,9 @@ | |
288 | } | |
289 | else { | |
290 | entry->write_proc = acerhk_proc_led; | |
291 | +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) | |
292 | entry->owner = THIS_MODULE; | |
293 | +#endif | |
294 | /* ... and wireless led controll file */ | |
295 | entry = create_proc_entry("wirelessled", 0222, proc_acer_dir); | |
296 | if (entry == NULL) { | |
297 | @@ -2670,7 +2754,9 @@ | |
298 | } | |
299 | else { | |
300 | entry->write_proc = acerhk_proc_wirelessled; | |
301 | +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) | |
302 | entry->owner = THIS_MODULE; | |
303 | +#endif | |
304 | /* ... and bluetooth led controll file */ | |
305 | entry = create_proc_entry("blueled", 0222, proc_acer_dir); | |
306 | if (entry == NULL) { | |
307 | @@ -2683,7 +2769,9 @@ | |
308 | retval = 0; | |
309 | } else { | |
310 | entry->write_proc = acerhk_proc_blueled; | |
311 | +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) | |
312 | entry->owner = THIS_MODULE; | |
313 | +#endif | |
314 | retval = 1; | |
315 | #ifdef ACERDEBUG | |
316 | /* add extra file for debugging purposes */ | |
317 | @@ -2700,7 +2788,9 @@ | |
318 | } | |
319 | else { | |
320 | entry->write_proc = acerhk_proc_debug; | |
321 | +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) | |
322 | entry->owner = THIS_MODULE; | |
323 | +#endif | |
324 | retval = 1; | |
325 | } | |
326 | #endif | |
327 | @@ -2832,6 +2922,20 @@ | |
328 | return 0; | |
329 | } | |
330 | ||
331 | +#ifdef CONFIG_PM | |
332 | +static int acerhk_resume(struct platform_device *dev) | |
333 | +{ | |
334 | + printk(KERN_INFO"acerhk: Resuming. Setting wlan_state to: %d\n", acerhk_wlan_state); | |
335 | + | |
336 | + if (acerhk_wlan_state) | |
337 | + wbutton_fct_2(1); | |
338 | + else | |
339 | + wbutton_fct_2(0); | |
340 | + | |
341 | + return 0; | |
342 | +} | |
343 | +#endif | |
344 | + | |
345 | static struct file_operations acerhk_fops = { | |
346 | owner: THIS_MODULE, | |
347 | ioctl: acerhk_ioctl, | |
348 | @@ -2842,15 +2946,15 @@ | |
349 | release: acerhk_release, | |
350 | }; | |
351 | ||
352 | -static struct miscdevice acerhk_dev = { | |
353 | - MISC_DYNAMIC_MINOR, | |
354 | - "acerhk", | |
355 | - &acerhk_fops | |
356 | +static struct miscdevice acerhk_misc_dev = { | |
357 | + .minor = MISC_DYNAMIC_MINOR, | |
358 | + .name = "acerhk", | |
359 | + .fops = &acerhk_fops, | |
360 | }; | |
361 | ||
362 | /* }}} */ | |
363 | ||
364 | -static void __init model_init(void) | |
365 | +static void __devinit model_init(void) | |
366 | { | |
367 | /* set callroutine, features and keymap for model */ | |
368 | setup_model_features(acerhk_series); | |
369 | @@ -2875,12 +2979,13 @@ | |
370 | } | |
371 | ||
372 | ||
373 | -static void __exit acerhk_cleanup_module (void); | |
374 | -static int __init acerhk_init(void) | |
375 | +static int __devexit acerhk_remove(struct platform_device *dev); | |
376 | + | |
377 | +static int __devinit acerhk_probe(struct platform_device *dev) | |
378 | { | |
379 | int ret; | |
380 | ||
381 | - ret = misc_register( &acerhk_dev ); | |
382 | + ret = misc_register(&acerhk_misc_dev); | |
383 | if (ret) { | |
384 | printk(KERN_ERR "acerhk: can't misc_register on minor=%d\n", ACERHK_MINOR); | |
385 | ret = -EAGAIN; | |
386 | @@ -2888,7 +2993,7 @@ | |
387 | else if (!acerhk_proc_init()) { | |
388 | printk(KERN_ERR "acerhk: can't create procfs entries\n"); | |
389 | ret = -ENOMEM; | |
390 | - misc_deregister( &acerhk_dev ); | |
391 | + misc_deregister( &acerhk_misc_dev ); | |
392 | } | |
393 | else { | |
394 | reg1 = ioremap(0xf0000, 0xffff); | |
395 | @@ -2904,7 +3009,8 @@ | |
396 | /* attach to input system */ | |
397 | init_input(); | |
398 | memset(acerhk_model_string, 0x00, ACERHK_MODEL_STRLEN); | |
399 | -#ifdef DUMMYHW | |
400 | +/* #ifdef DUMMYHW */ | |
401 | +#if (defined(DUMMYHW) || defined(__x86_64__)) | |
402 | acerhk_model_addr = (void*)0x12345678; | |
403 | /* copy the string, but not more than 15 characters */ | |
404 | strncpy(acerhk_model_string, "TravelmateDummy", ACERHK_MODEL_STRLEN-1); | |
405 | @@ -2950,14 +3056,14 @@ | |
406 | } else { | |
407 | printk(KERN_ERR "acerhk: can't find bios routine, cannot do anything for you, sorry!\n"); | |
408 | ret = -ENOMEM; | |
409 | - acerhk_cleanup_module(); | |
410 | + return acerhk_remove(dev); | |
411 | } | |
412 | #endif | |
413 | } | |
414 | return ret; | |
415 | } | |
416 | ||
417 | -static void __exit acerhk_cleanup_module (void) | |
418 | +static int __devexit acerhk_remove(struct platform_device *dev) | |
419 | { | |
420 | acerhk_proc_cleanup(); | |
421 | stop_blinking(); | |
422 | @@ -2968,16 +3074,68 @@ | |
423 | if (preg400) | |
424 | iounmap(preg400); | |
425 | release_input(); | |
426 | - misc_deregister( &acerhk_dev ); | |
427 | + misc_deregister(&acerhk_misc_dev); | |
428 | if ( acerhk_type == TM_dritek ) { | |
429 | disable_dritek_keyboard(); | |
430 | } | |
431 | if (verbose > 2) | |
432 | printk(KERN_INFO "acerhk: unloaded\n"); | |
433 | + | |
434 | + return 0; | |
435 | +} | |
436 | + | |
437 | +static struct platform_driver acerhk_driver = { | |
438 | + .driver = { | |
439 | + .name = "acerhk", | |
440 | + .owner = THIS_MODULE, | |
441 | + }, | |
442 | + .probe = acerhk_probe, | |
443 | + .remove = __devexit_p(acerhk_remove), | |
444 | +#ifdef CONFIG_PM | |
445 | + .resume = acerhk_resume, | |
446 | +#endif | |
447 | +}; | |
448 | + | |
449 | +static struct platform_device *acerhk_platform_device; | |
450 | + | |
451 | +static int __init acerhk_init(void) | |
452 | +{ | |
453 | + int error; | |
454 | + | |
455 | + error = platform_driver_register(&acerhk_driver); | |
456 | + if (error) | |
457 | + return error; | |
458 | + | |
459 | + acerhk_platform_device = platform_device_alloc("acerhk", -1); | |
460 | + if (!acerhk_platform_device) { | |
461 | + error = -ENOMEM; | |
462 | + goto err_driver_unregister; | |
463 | + } | |
464 | + | |
465 | + error = platform_device_add(acerhk_platform_device); | |
466 | + if (error) | |
467 | + goto err_free_device; | |
468 | + | |
469 | + | |
470 | + return 0; | |
471 | + | |
472 | + err_free_device: | |
473 | + platform_device_put(acerhk_platform_device); | |
474 | + err_driver_unregister: | |
475 | + platform_driver_unregister(&acerhk_driver); | |
476 | + return error; | |
477 | } | |
478 | ||
479 | +static void __exit acerhk_exit(void) | |
480 | +{ | |
481 | + platform_device_unregister(acerhk_platform_device); | |
482 | + platform_driver_unregister(&acerhk_driver); | |
483 | + printk(KERN_INFO "acerhk: removed.\n"); | |
484 | +} | |
485 | + | |
486 | + | |
487 | module_init(acerhk_init); | |
488 | -module_exit(acerhk_cleanup_module); | |
489 | +module_exit(acerhk_exit); | |
490 | ||
491 | MODULE_AUTHOR("Olaf Tauber"); | |
492 | MODULE_DESCRIPTION("AcerHotkeys extra buttons keyboard driver"); | |
493 | --- acerhk-0.5.35/doc/FAQ 2005-11-10 18:45:33.000000000 +0100 | |
494 | +++ acerhk/doc/FAQ 2007-09-21 21:58:40.000000000 +0200 | |
495 | @@ -1,5 +1,15 @@ | |
496 | ****************************************************************************** | |
497 | ||
498 | +Q: The driver works perfectly when using force_series, what is needed to add | |
499 | +autodetection? | |
500 | + | |
501 | +A: I need the model name of the laptop, if you do not see a usable name in | |
502 | +/proc/driver/acerhk/info please try the tools dmidecode/biosdecode/vpddecode | |
503 | +to find this name. You can also load the driver and then look into the bios | |
504 | +directly by scanning the memory which is mapped by the driver. | |
505 | + | |
506 | +****************************************************************************** | |
507 | + | |
508 | Q: I have a (non Acer) notebook which is not recognized by your driver but I | |
509 | think it should. What information do you need? | |
510 |