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
7 - * Copyright (C) 2002-2006, Olaf Tauber (olaf-tauber@versanet.de)
8 + * Copyright (C) 2002-2007, Olaf Tauber (olaf-tauber@versanet.de)
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
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>
31 static asmlinkage void call_bios_6xx(struct register_buffer *buf)
44 static asmlinkage void call_bios_52x(struct register_buffer *buf)
57 #define PRINT_BUFFER(x) \
61 spin_lock_irqsave (&rtc_lock, flags);
63 +/* #ifndef DUMMYHW */
64 +#if !(defined(DUMMYHW) || defined(__x86_64__))
66 c = CMOS_READ(cmos_index);
70 static struct proc_dir_entry *proc_acer_dir;
72 -static unsigned int __init find_hk_area(void)
73 +static unsigned long __init find_hk_area(void)
79 sig = -1; /* offset to signature in io area */
81 fkt = readl(reg1 + sig + 5);
82 /* adjust fkt to address of mapped IO area */
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;
97 /* Aspire 13xx series laptops use dritek hardware, no
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) */
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;
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;
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;
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;
141 @@ -1313,11 +1347,24 @@
142 acerhk_model_features = 0x00f00000;
143 acerhk_type = TM_new;
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;
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;
158 + case 98200: /* Medion MD98200 */
159 + /* has WLAN button, should call connect() */
160 + acerhk_model_features = TM_F_WBUTTON;
161 + acerhk_type = TM_old;
163 case 9783: /* Medion MD9783 */
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;
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;
177 acerhk_wlan_state = 1; // Default state is on
178 @@ -1458,6 +1510,7 @@
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 @@
188 case '2': series = 5020; break;
190 + } else if (str[8] == '1' && str[9] == '0') {
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");
199 + case 'A': /* AMILO Axxxx - added by damagedspline@aim.com */
201 + case '1': /* AMILO A1xxx */
203 + printk(KERN_INFO"acerhk: model string indicates FS AMILO A1xxx series\n");
210 printk(KERN_INFO"acerhk: model string indicates unknown FS AMILO XX series\n");
211 @@ -1862,7 +1926,11 @@
213 else if (strncmp(str, "MEDIONPC", 8) == 0) {
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);
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);
224 @@ -1893,6 +1961,12 @@
225 printk(KERN_INFO"acerhk: model string indicates a medion MD40100\n");
228 + } else if (strncmp(str, "MEDION", 6) == 0) {
229 + if (COLUSSI("WIM2120", 7, reg1, AREA_SIZE) >= 0) {
231 + printk(KERN_INFO"acerhk: model string indicates a Medion MD 98200\n");
234 } else if (strncmp(str, "AOpen", 5) == 0) {
235 if (strncmp(str, "AOpen*EzRestore", 15) == 0) {
237 @@ -2117,7 +2191,8 @@
238 /* polling timer handler */
239 static void acerhk_poll_event(unsigned long save_size)
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 @@
249 if (acerhk_blueled_blinking != -1) {
250 acerhk_blueled_blinking = !acerhk_blueled_blinking;
252 +/* #ifndef DUMMYHW */
253 +#if !(defined(DUMMYHW) || defined(__x86_64__))
254 wbutton_fct_1(acerhk_blueled_blinking);
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");
261 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
262 proc_acer_dir->owner = THIS_MODULE;
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);
271 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
272 entry->owner = THIS_MODULE;
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);
281 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
282 entry->owner = THIS_MODULE;
284 /* ... and led control file */
285 entry = create_proc_entry("led", 0222, proc_acer_dir);
287 @@ -2657,7 +2739,9 @@
290 entry->write_proc = acerhk_proc_led;
291 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
292 entry->owner = THIS_MODULE;
294 /* ... and wireless led controll file */
295 entry = create_proc_entry("wirelessled", 0222, proc_acer_dir);
297 @@ -2670,7 +2754,9 @@
300 entry->write_proc = acerhk_proc_wirelessled;
301 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
302 entry->owner = THIS_MODULE;
304 /* ... and bluetooth led controll file */
305 entry = create_proc_entry("blueled", 0222, proc_acer_dir);
307 @@ -2683,7 +2769,9 @@
310 entry->write_proc = acerhk_proc_blueled;
311 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
312 entry->owner = THIS_MODULE;
316 /* add extra file for debugging purposes */
317 @@ -2700,7 +2788,9 @@
320 entry->write_proc = acerhk_proc_debug;
321 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
322 entry->owner = THIS_MODULE;
327 @@ -2832,6 +2922,20 @@
332 +static int acerhk_resume(struct platform_device *dev)
334 + printk(KERN_INFO"acerhk: Resuming. Setting wlan_state to: %d\n", acerhk_wlan_state);
336 + if (acerhk_wlan_state)
345 static struct file_operations acerhk_fops = {
348 @@ -2842,15 +2946,15 @@
349 release: acerhk_release,
352 -static struct miscdevice acerhk_dev = {
353 - MISC_DYNAMIC_MINOR,
356 +static struct miscdevice acerhk_misc_dev = {
357 + .minor = MISC_DYNAMIC_MINOR,
359 + .fops = &acerhk_fops,
364 -static void __init model_init(void)
365 +static void __devinit model_init(void)
367 /* set callroutine, features and keymap for model */
368 setup_model_features(acerhk_series);
369 @@ -2875,12 +2979,13 @@
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);
377 +static int __devinit acerhk_probe(struct platform_device *dev)
381 - ret = misc_register( &acerhk_dev );
382 + ret = misc_register(&acerhk_misc_dev);
384 printk(KERN_ERR "acerhk: can't misc_register on minor=%d\n", ACERHK_MINOR);
386 @@ -2888,7 +2993,7 @@
387 else if (!acerhk_proc_init()) {
388 printk(KERN_ERR "acerhk: can't create procfs entries\n");
390 - misc_deregister( &acerhk_dev );
391 + misc_deregister( &acerhk_misc_dev );
394 reg1 = ioremap(0xf0000, 0xffff);
395 @@ -2904,7 +3009,8 @@
396 /* attach to input system */
398 memset(acerhk_model_string, 0x00, ACERHK_MODEL_STRLEN);
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 @@
407 printk(KERN_ERR "acerhk: can't find bios routine, cannot do anything for you, sorry!\n");
409 - acerhk_cleanup_module();
410 + return acerhk_remove(dev);
417 -static void __exit acerhk_cleanup_module (void)
418 +static int __devexit acerhk_remove(struct platform_device *dev)
420 acerhk_proc_cleanup();
422 @@ -2968,16 +3074,68 @@
426 - misc_deregister( &acerhk_dev );
427 + misc_deregister(&acerhk_misc_dev);
428 if ( acerhk_type == TM_dritek ) {
429 disable_dritek_keyboard();
432 printk(KERN_INFO "acerhk: unloaded\n");
437 +static struct platform_driver acerhk_driver = {
440 + .owner = THIS_MODULE,
442 + .probe = acerhk_probe,
443 + .remove = __devexit_p(acerhk_remove),
445 + .resume = acerhk_resume,
449 +static struct platform_device *acerhk_platform_device;
451 +static int __init acerhk_init(void)
455 + error = platform_driver_register(&acerhk_driver);
459 + acerhk_platform_device = platform_device_alloc("acerhk", -1);
460 + if (!acerhk_platform_device) {
462 + goto err_driver_unregister;
465 + error = platform_device_add(acerhk_platform_device);
467 + goto err_free_device;
473 + platform_device_put(acerhk_platform_device);
474 + err_driver_unregister:
475 + platform_driver_unregister(&acerhk_driver);
479 +static void __exit acerhk_exit(void)
481 + platform_device_unregister(acerhk_platform_device);
482 + platform_driver_unregister(&acerhk_driver);
483 + printk(KERN_INFO "acerhk: removed.\n");
487 module_init(acerhk_init);
488 -module_exit(acerhk_cleanup_module);
489 +module_exit(acerhk_exit);
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
496 ******************************************************************************
498 +Q: The driver works perfectly when using force_series, what is needed to add
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.
506 +******************************************************************************
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?