4213 lines
141 KiB
Diff
4213 lines
141 KiB
Diff
3rdparty/acerhk/AUTHORS | 1
|
|
3rdparty/acerhk/COPYING | 340 ++++
|
|
3rdparty/acerhk/INSTALL | 109 +
|
|
3rdparty/acerhk/Makefile | 65
|
|
3rdparty/acerhk/NEWS | 16
|
|
3rdparty/acerhk/README | 215 ++
|
|
3rdparty/acerhk/acerhk.c | 2999 ++++++++++++++++++++++++++++++++++++++++
|
|
3rdparty/acerhk/acerhk.h | 91 +
|
|
3rdparty/acerhk/doc/FAQ | 150 ++
|
|
3rdparty/acerhk/doc/IOCTL | 61
|
|
3rdparty/acerhk/doc/acertm.def | 56
|
|
3rdparty/acerhk/doc/keycodes | 26
|
|
3rdparty/acerhk/doc/md95400.def | 14
|
|
13 files changed, 4143 insertions(+)
|
|
diff -Nurp linux-2.6.37/3rdparty/acerhk/acerhk.c linux-2.6.37.3rdparty/3rdparty/acerhk/acerhk.c
|
|
--- linux-2.6.37/3rdparty/acerhk/acerhk.c 1970-01-01 02:00:00.000000000 +0200
|
|
+++ linux-2.6.37.3rdparty/3rdparty/acerhk/acerhk.c 2007-02-10 17:46:23.000000000 +0200
|
|
@@ -0,0 +1,2999 @@
|
|
+/*********************************************************************
|
|
+ * Filename: acerhk.c
|
|
+ * Version: 0.5
|
|
+ *
|
|
+ * Copyright (C) 2002-2006, Olaf Tauber (olaf-tauber@versanet.de)
|
|
+ *
|
|
+ * Description: kernel driver for Acer Travelmate and similar
|
|
+ * laptops special keys
|
|
+ * Author: Olaf Tauber <olaf-tauber@versanet.de>
|
|
+ * Created at: Mon Apr 29 22:16:42 2002
|
|
+ * Modified at: Mon Oct 16 21:36:44 2006
|
|
+ * Modified by: Olaf Tauber <olaf-tauber@versanet.de>
|
|
+ * Modified at: Thu Nov 24 13:03:01 2005
|
|
+ * Modified by: Antonio Cuni <cuni@programmazione.it>
|
|
+ * Modified at: Wed Oct 27 19:47:11 CEST 2004
|
|
+ * Modified by: Joachim Fenkes <acerhk@dojoe.net>
|
|
+ *
|
|
+ * This program is free software; you can redistribute
|
|
+ * it and/or modify it under the terms of the GNU General
|
|
+ * Public License as published by the Free Software
|
|
+ * Foundation; either version 2 of the License, or (at your
|
|
+ * option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be
|
|
+ * useful, but WITHOUT ANY WARRANTY; without even the implied
|
|
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
+ * PURPOSE. See the GNU General Public License for more
|
|
+ * details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public
|
|
+ * License along with this program; if not, write to the
|
|
+ * Free Software Foundation, Inc., 59 Temple Place,
|
|
+ * Suite 330, Boston, MA 02111-1307 USA
|
|
+ *
|
|
+ *
|
|
+ */
|
|
+
|
|
+#ifndef AUTOCONF_INCLUDED
|
|
+#include <linux/config.h>
|
|
+#endif
|
|
+
|
|
+/* This driver is heavily dependent on the architecture, don't let
|
|
+ * anyone without an X86 machine use it. On laptops with AMD64
|
|
+ * architecture this driver is only useable in 32 bit mode.
|
|
+ */
|
|
+#ifdef CONFIG_X86
|
|
+
|
|
+#include <linux/version.h>
|
|
+
|
|
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
|
+#define KERNEL26
|
|
+#include <linux/moduleparam.h>
|
|
+#else
|
|
+#include <linux/modversions.h>
|
|
+#endif
|
|
+
|
|
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
|
|
+#define STATIC_INPUT_DEV
|
|
+#endif
|
|
+
|
|
+#include <linux/module.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/kmod.h>
|
|
+#include <linux/miscdevice.h>
|
|
+#include <linux/mc146818rtc.h>
|
|
+#include <linux/input.h>
|
|
+#include <linux/interrupt.h>
|
|
+#include <linux/proc_fs.h>
|
|
+#include <asm/uaccess.h>
|
|
+#include <linux/delay.h>
|
|
+
|
|
+#include "acerhk.h"
|
|
+
|
|
+/* #define ACERDEBUG */
|
|
+/* #define DUMMYHW */
|
|
+
|
|
+#define ACERHK_VERSION "0.5.35"
|
|
+#define MODULE_NAME "acerhk"
|
|
+
|
|
+/* maximum number of polling loops, adjust it if needed to values between
|
|
+ * 1 and 32
|
|
+ */
|
|
+#define MAX_POLLING_LOOPS 16U
|
|
+
|
|
+/* maximum length for model string */
|
|
+#define ACERHK_MODEL_STRLEN 16
|
|
+/* size of mapped areas */
|
|
+#define AREA_SIZE 0xffff
|
|
+/* needed for colussi algorithm */
|
|
+#define XSIZE 20
|
|
+
|
|
+/* Module parameters */
|
|
+static int poll=1;
|
|
+static int autowlan;
|
|
+static int usedritek=1;
|
|
+static int wlan_state=-1;
|
|
+static int bluetooth_state=-1;
|
|
+static int verbose;
|
|
+static unsigned int force_series;
|
|
+#ifdef KERNEL26
|
|
+module_param(poll, int, 0444);
|
|
+module_param(autowlan, int, 0444);
|
|
+module_param(usedritek, int, 0444);
|
|
+module_param(verbose, int, 0444);
|
|
+module_param(wlan_state, int, 0444);
|
|
+module_param(bluetooth_state, int, 0444);
|
|
+module_param(force_series, uint, 0444);
|
|
+#else
|
|
+MODULE_PARM(poll, "i");
|
|
+MODULE_PARM(autowlan, "i");
|
|
+MODULE_PARM(wlan_state, "i");
|
|
+MODULE_PARM(bluetooth_state, "i");
|
|
+MODULE_PARM(usedritek, "i");
|
|
+MODULE_PARM(verbose, "i");
|
|
+MODULE_PARM(force_series, "i");
|
|
+#endif
|
|
+MODULE_PARM_DESC(poll, "start polling timer");
|
|
+MODULE_PARM_DESC(autowlan, "automatic switching of wlan hardware");
|
|
+MODULE_PARM_DESC(wlan_state, "(assumed) initial state of WLAN LED/hardware");
|
|
+MODULE_PARM_DESC(bluetooth_state, "(assumed) initial state of Bluetooth LED/hardware");
|
|
+MODULE_PARM_DESC(usedritek, "enable dritek keyboard extension");
|
|
+MODULE_PARM_DESC(verbose, "output additional information");
|
|
+MODULE_PARM_DESC(force_series, "force laptop series, skip autodetection");
|
|
+
|
|
+/* input device */
|
|
+static struct input_dev *acerhk_input_dev_ptr;
|
|
+#ifdef STATIC_INPUT_DEV
|
|
+static struct input_dev acerhk_input_dev;
|
|
+#endif
|
|
+
|
|
+/* mapped IO area from 0xf0000 */
|
|
+static void *reg1;
|
|
+/* mapped IO area from 0xe0000 */
|
|
+static void *reg2;
|
|
+/* Pointer to mapped area at 0x400 on 520 series */
|
|
+static void *preg400;
|
|
+/* location of IO routine in mapped area */
|
|
+static unsigned int bios_routine;
|
|
+/* index of CMOS port to get key event */
|
|
+static unsigned int cmos_index;
|
|
+/* function for bios call */
|
|
+static bios_call call_bios;
|
|
+/* address of model string */
|
|
+static char *acerhk_model_addr;
|
|
+/* copied string, maximum length 16 ('TravelMate xxx') */
|
|
+static char acerhk_model_string[ACERHK_MODEL_STRLEN];
|
|
+/* type of hardware access */
|
|
+static t_acer_type acerhk_type;
|
|
+/* travelmate series */
|
|
+static unsigned int acerhk_series;
|
|
+/* supported features for this model */
|
|
+static unsigned int acerhk_model_features;
|
|
+/* map of acer key codes to acer key names */
|
|
+static unsigned char acerhk_key2name[0xff];
|
|
+/* map of acer key names to key events */
|
|
+static t_map_name2event acerhk_name2event;
|
|
+/* timer for polling key presses */
|
|
+static struct timer_list acerhk_timer_poll;
|
|
+/* polling active */
|
|
+static int acerhk_polling_state;
|
|
+/* polling delay */
|
|
+static unsigned acerhk_polling_delay = HZ/5;
|
|
+/* wlan hardware toggle */
|
|
+static int acerhk_wlan_state;
|
|
+/* bluetooth hardware toggle */
|
|
+static int acerhk_bluetooth_state;
|
|
+
|
|
+/* bluetooth blinking state; added by Antonio Cuni
|
|
+ possible values:
|
|
+ -1: blinking disabled (default)
|
|
+ 0: blinking enabled, led currently off
|
|
+ 1: blinking enabled, led currently on
|
|
+*/
|
|
+static int acerhk_blueled_blinking = -1;
|
|
+/* delay between two changes of state, in jiffies */
|
|
+static unsigned acerhk_blueled_blinking_delay;
|
|
+/* timer for blinking */
|
|
+static struct timer_list acerhk_timer_blinking;
|
|
+
|
|
+/* function prototypes */
|
|
+static void start_polling(void);
|
|
+static void stop_polling(void);
|
|
+
|
|
+/* Added by Antonio Cuni */
|
|
+static void start_blinking(void);
|
|
+static void stop_blinking(void);
|
|
+
|
|
+/* {{{ Experimental use of dritek keyboard extension */
|
|
+
|
|
+#define EC_STATUS_REG 0x66 /* Status register of EC (R) */
|
|
+#define EC_CNTL_REG 0x66 /* Controller command register of EC (W) */
|
|
+#define EC_DATA_REG 0x62 /* EC data register (R/W) */
|
|
+
|
|
+#ifdef KERNEL26
|
|
+
|
|
+#include <linux/preempt.h>
|
|
+
|
|
+#define KBD_STATUS_REG 0x64 /* Status register (R) */
|
|
+#define KBD_CNTL_REG 0x64 /* Controller command register (W) */
|
|
+#define KBD_DATA_REG 0x60 /* Keyboard data register (R/W) */
|
|
+
|
|
+#else
|
|
+
|
|
+#ifndef KEY_MEDIA
|
|
+#define KEY_MEDIA 226
|
|
+#endif
|
|
+
|
|
+#define preempt_disable() do { } while (0)
|
|
+#define preempt_enable_no_resched() do { } while (0)
|
|
+#define preempt_enable() do { } while (0)
|
|
+#define preempt_check_resched() do { } while (0)
|
|
+#include <linux/pc_keyb.h>
|
|
+
|
|
+#endif
|
|
+
|
|
+static inline int my_i8042_read_status(void)
|
|
+{
|
|
+ return inb(KBD_STATUS_REG);
|
|
+}
|
|
+static int my_i8042_wait_write(void)
|
|
+{
|
|
+ int i = 0;
|
|
+ while ((my_i8042_read_status() & 0x02) && (i < 10000)) {
|
|
+ udelay(50);
|
|
+ i++;
|
|
+ }
|
|
+ return -(i == 10000);
|
|
+}
|
|
+static void send_kbd_cmd(unsigned char cmd, unsigned char val)
|
|
+{
|
|
+ if (usedritek) {
|
|
+ preempt_disable();
|
|
+ if (!my_i8042_wait_write())
|
|
+ outb(cmd, KBD_CNTL_REG);
|
|
+ if (!my_i8042_wait_write())
|
|
+ outb(val, KBD_DATA_REG);
|
|
+ preempt_enable_no_resched();
|
|
+ } else {
|
|
+ printk(KERN_INFO"acerhk: request for accessing EC ignored\n"
|
|
+ KERN_INFO"acerhk: Use of dritek keyboard extension not enabled, use module\n"
|
|
+ KERN_INFO"acerhk: parameter usedritek=1 to do that (possibly dangerous)\n");
|
|
+ }
|
|
+}
|
|
+#ifdef ACERDEBUG
|
|
+static inline int my_i8042_read_ecstatus(void)
|
|
+{
|
|
+ return inb(EC_STATUS_REG);
|
|
+}
|
|
+static int my_i8042_wait_ecwrite(void)
|
|
+{
|
|
+ int i = 0;
|
|
+ while ((my_i8042_read_ecstatus() & 0x02) && (i < 10000)) {
|
|
+ udelay(50);
|
|
+ i++;
|
|
+ }
|
|
+ return -(i == 10000);
|
|
+}
|
|
+static void send_ec_cmd(unsigned char cmd, unsigned char val)
|
|
+{
|
|
+ if (usedritek) {
|
|
+ preempt_disable();
|
|
+ if (!my_i8042_wait_ecwrite())
|
|
+ outb(cmd, EC_CNTL_REG);
|
|
+ if (!my_i8042_wait_ecwrite())
|
|
+ outb(val, EC_DATA_REG);
|
|
+ preempt_enable_no_resched();
|
|
+ } else {
|
|
+ printk(KERN_INFO"acerhk: request for accessing EC ignored\n"
|
|
+ KERN_INFO"acerhk: Use of dritek keyboard extension not enabled, use module\n"
|
|
+ KERN_INFO"acerhk: parameter usedritek=1 to do that (possibly dangerous)\n");
|
|
+ }
|
|
+}
|
|
+#endif
|
|
+#ifdef ACERDEBUG
|
|
+static void enable_mute_led_ec(void)
|
|
+{
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: enabling mute led via EC\n");
|
|
+ send_kbd_cmd(0x59, 0x94);
|
|
+}
|
|
+static void disable_mute_led_ec(void)
|
|
+{
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: disabling mute led via EC\n");
|
|
+ send_kbd_cmd(0x59, 0x95);
|
|
+}
|
|
+static void enable_dmm_function(void)
|
|
+{
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: enabling WLAN via EC variant 2\n");
|
|
+ send_kbd_cmd(0x45, 0xd3);
|
|
+}
|
|
+#endif
|
|
+static void enable_wlan_ec_1(void)
|
|
+{
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: enabling WLAN via EC variant 1\n");
|
|
+ send_kbd_cmd(0xe7, 0x01);
|
|
+ acerhk_wlan_state = 1;
|
|
+}
|
|
+static void disable_wlan_ec_1(void)
|
|
+{
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: disabling WLAN via EC variant 1\n");
|
|
+ send_kbd_cmd(0xe7, 0x00);
|
|
+ acerhk_wlan_state = 0;
|
|
+}
|
|
+static void enable_bluetooth_ec_1(void)
|
|
+{
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: enabling Bluetooth via EC variant 1\n");
|
|
+ send_kbd_cmd(0xe7, 0x03);
|
|
+ acerhk_bluetooth_state = 1;
|
|
+}
|
|
+static void disable_bluetooth_ec_1(void)
|
|
+{
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: disabling Bluetooth via EC variant 1\n");
|
|
+ send_kbd_cmd(0xe7, 0x02);
|
|
+ acerhk_bluetooth_state = 0;
|
|
+}
|
|
+static void enable_wlan_ec_2(void)
|
|
+{
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: enabling WLAN via EC variant 2\n");
|
|
+ send_kbd_cmd(0x45, acerhk_bluetooth_state ? 0xa2 : 0xa0);
|
|
+ acerhk_wlan_state = 1;
|
|
+}
|
|
+static void disable_wlan_ec_2(void)
|
|
+{
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: disabling WLAN via EC variant 2\n");
|
|
+ send_kbd_cmd(0x45, acerhk_bluetooth_state ? 0xa1 : 0xa3);
|
|
+ acerhk_wlan_state = 0;
|
|
+}
|
|
+static void enable_bluetooth_ec_2(void)
|
|
+{
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: enabling Bluetooth via EC variant 2\n");
|
|
+ send_kbd_cmd(0x45, acerhk_wlan_state ? 0xa2 : 0xa1);
|
|
+ acerhk_bluetooth_state = 1;
|
|
+}
|
|
+static void disable_bluetooth_ec_2(void)
|
|
+{
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: disabling Bluetooth via EC variant 2\n");
|
|
+ send_kbd_cmd(0x45, acerhk_wlan_state ? 0xa0 : 0xa3);
|
|
+ acerhk_bluetooth_state = 0;
|
|
+}
|
|
+#ifdef ACERDEBUG
|
|
+static void enable_wireless_ec(void)
|
|
+{
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: enabling wireless hardware\n");
|
|
+ if (usedritek) {
|
|
+ preempt_disable();
|
|
+ if (!my_i8042_wait_ecwrite())
|
|
+ outb(0x4d, EC_CNTL_REG);
|
|
+ if (!my_i8042_wait_ecwrite())
|
|
+ outb(0xd2, EC_DATA_REG);
|
|
+ if (!my_i8042_wait_ecwrite())
|
|
+ outb(0x01, EC_DATA_REG);
|
|
+ preempt_enable_no_resched();
|
|
+ }
|
|
+ acerhk_wlan_state = 1;
|
|
+}
|
|
+static void disable_wireless_ec(void)
|
|
+{
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: disabling wireless hardware\n");
|
|
+ if (usedritek) {
|
|
+ preempt_disable();
|
|
+ if (!my_i8042_wait_ecwrite())
|
|
+ outb(0x4d, EC_CNTL_REG);
|
|
+ if (!my_i8042_wait_ecwrite())
|
|
+ outb(0xd2, EC_DATA_REG);
|
|
+ if (!my_i8042_wait_ecwrite())
|
|
+ outb(0x00, EC_DATA_REG);
|
|
+ preempt_enable_no_resched();
|
|
+ }
|
|
+ acerhk_wlan_state = 0;
|
|
+}
|
|
+#endif
|
|
+static void enable_dritek_keyboard(void)
|
|
+{
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: enabling dritek keyboard extension\n");
|
|
+ send_kbd_cmd(0x59, 0x90);
|
|
+}
|
|
+static void disable_dritek_keyboard(void)
|
|
+{
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: disabling dritek keyboard extension\n");
|
|
+ send_kbd_cmd(0x59, 0x91);
|
|
+}
|
|
+static void enable_mail_led_ec_1(void)
|
|
+{
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: enabling mail led via EC variant 1\n");
|
|
+ send_kbd_cmd(0xe8, 0x01);
|
|
+}
|
|
+static void disable_mail_led_ec_1(void)
|
|
+{
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: disabling mail led via EC variant 1\n");
|
|
+ send_kbd_cmd(0xe8, 0x00);
|
|
+}
|
|
+
|
|
+static void enable_mail_led_ec_2(void)
|
|
+{
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: enabling mail led via EC variant 2\n");
|
|
+ send_kbd_cmd(0x59, 0x92);
|
|
+}
|
|
+static void disable_mail_led_ec_2(void)
|
|
+{
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: disabling mail led via EC variant 2\n");
|
|
+ send_kbd_cmd(0x59, 0x93);
|
|
+}
|
|
+static void enable_mail_led_ec_3(void)
|
|
+{
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: enabling mail led via EC variant 3\n");
|
|
+ if (usedritek) {
|
|
+ preempt_disable();
|
|
+ if (!my_i8042_wait_write())
|
|
+ outl(0x80008894, 0xCF8);
|
|
+ if (!my_i8042_wait_write())
|
|
+ outw(0xC061, 0xCFC);
|
|
+ preempt_enable_no_resched();
|
|
+ }
|
|
+}
|
|
+static void disable_mail_led_ec_3(void)
|
|
+{
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: disabling mail led via EC variant 3\n");
|
|
+ if (usedritek) {
|
|
+ preempt_disable();
|
|
+ if (!my_i8042_wait_write())
|
|
+ outl(0x80008894, 0xCF8);
|
|
+ if (!my_i8042_wait_write())
|
|
+ outw(0xC060, 0xCFC);
|
|
+ preempt_enable_no_resched();
|
|
+ }
|
|
+}
|
|
+
|
|
+/* }}} */
|
|
+
|
|
+/* {{{ string search functions */
|
|
+
|
|
+/* This is the Colussi algorithm, the code is taken from
|
|
+ http://www-igm.univ-mlv.fr/~lecroq/string
|
|
+*/
|
|
+int preColussi(char *x, int m, int *h, int *next, int *shift)
|
|
+{
|
|
+ int i, k, nd, q, r, s;
|
|
+ int hmax[XSIZE], kmin[XSIZE], nhd0[XSIZE], rmin[XSIZE];
|
|
+ /* Computation of hmax */
|
|
+ i = k = 1;
|
|
+ do {
|
|
+ while (x[i] == x[i - k])
|
|
+ i++;
|
|
+ hmax[k] = i;
|
|
+ q = k + 1;
|
|
+ while (hmax[q - k] + k < i) {
|
|
+ hmax[q] = hmax[q - k] + k;
|
|
+ q++;
|
|
+ }
|
|
+ k = q;
|
|
+ if (k == i + 1)
|
|
+ i = k;
|
|
+ } while (k <= m); /* Computation of kmin */
|
|
+ memset(kmin, 0, m*sizeof(int));
|
|
+ r = 0;
|
|
+ for (i = m; i >= 1; --i)
|
|
+ if (hmax[i] < m)
|
|
+ kmin[hmax[i]] = i; /* Computation of rmin */
|
|
+ for (i = m - 1; i >= 0; --i) {
|
|
+ if (hmax[i + 1] == m)
|
|
+ r = i + 1;
|
|
+ if (kmin[i] == 0)
|
|
+ rmin[i] = r;
|
|
+ else
|
|
+ rmin[i] = 0;
|
|
+ } /* Computation of h */
|
|
+ s = -1;
|
|
+ r = m;
|
|
+ for (i = 0; i < m; ++i)
|
|
+ if (kmin[i] == 0)
|
|
+ h[--r] = i;
|
|
+ else
|
|
+ h[++s] = i;
|
|
+ nd = s; /* Computation of shift */
|
|
+ for (i = 0; i <= nd; ++i)
|
|
+ shift[i] = kmin[h[i]];
|
|
+ for (i = nd + 1; i < m; ++i)
|
|
+ shift[i] = rmin[h[i]];
|
|
+ shift[m] = rmin[0]; /* Computation of nhd0 */
|
|
+ s = 0;
|
|
+ for (i = 0; i < m; ++i) {
|
|
+ nhd0[i] = s;
|
|
+ if (kmin[i] > 0)
|
|
+ ++s;
|
|
+ } /* Computation of next */
|
|
+ for (i = 0; i <= nd; ++i)
|
|
+ next[i] = nhd0[h[i] - kmin[h[i]]];
|
|
+ for (i = nd + 1; i < m; ++i)
|
|
+ next[i] = nhd0[m - rmin[h[i]]];
|
|
+ next[m] = nhd0[m - rmin[h[m - 1]]]; return(nd);
|
|
+}
|
|
+
|
|
+int COLUSSI(char *x, int m, char *y, int n) {
|
|
+ int i, j, last, nd,
|
|
+ h[XSIZE], next[XSIZE], shift[XSIZE]; /* Processing */
|
|
+ int match_pos; /* position of first match */
|
|
+ nd = preColussi(x, m, h, next, shift); /* Searching */
|
|
+ i = j = 0;
|
|
+ last = -1;
|
|
+ match_pos = -1;
|
|
+ while ( (match_pos == -1)
|
|
+ && (j <= n - m) ) {
|
|
+ while (i < m && last < j + h[i] &&
|
|
+ x[h[i]] == y[j + h[i]])
|
|
+ i++;
|
|
+ if (i >= m || last >= j + h[i]) {
|
|
+ /* Match found, bail out */
|
|
+ match_pos = j;
|
|
+ i = m;
|
|
+ }
|
|
+ if (i > nd)
|
|
+ last = j + m - 1;
|
|
+ j += shift[i];
|
|
+ i = next[i];
|
|
+ }
|
|
+ return match_pos;
|
|
+}
|
|
+
|
|
+/* }}} */
|
|
+
|
|
+/* {{{ hardware access functions */
|
|
+
|
|
+/* call_bios_<model family>
|
|
+ *
|
|
+ * call request handler in mapped system rom
|
|
+ *
|
|
+ * the request is handed over via all 6 general purpose registers, results are
|
|
+ * taken from them and copied back to buf
|
|
+ */
|
|
+static asmlinkage void call_bios_6xx(struct register_buffer *buf)
|
|
+{
|
|
+ if (bios_routine) {
|
|
+ local_irq_disable();
|
|
+ __asm__ __volatile__(
|
|
+ "movl %1,%%edx\n\t"
|
|
+ "pusha\n\t"
|
|
+ "movl %%edx,%%ebp\n\t"
|
|
+ "movl (%%ebp),%%eax\n\t"
|
|
+ "movl 4(%%ebp),%%ebx\n\t"
|
|
+ "movl 8(%%ebp),%%ecx\n\t"
|
|
+ "movl 12(%%ebp),%%edx\n\t"
|
|
+ "movl 16(%%ebp),%%edi\n\t"
|
|
+ "movl 20(%%ebp),%%esi\n\t"
|
|
+ "pushl %%ebp\n\t"
|
|
+ "call *%0\n\t"
|
|
+ "popl %%ebp\n\t"
|
|
+ "movl %%eax, (%%ebp)\n\t"
|
|
+ "movl %%ebx, 4(%%ebp)\n\t"
|
|
+ "movl %%ecx, 8(%%ebp)\n\t"
|
|
+ "movl %%edx, 12(%%ebp)\n\t"
|
|
+ "movl %%edi, 16(%%ebp)\n\t"
|
|
+ "movl %%esi, 20(%%ebp)\n\t"
|
|
+ "popa\n\t"
|
|
+ :
|
|
+ :"m" (bios_routine), "m" (buf)
|
|
+ :"%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi", "%ebp"
|
|
+ );
|
|
+ local_irq_enable();
|
|
+ }
|
|
+}
|
|
+
|
|
+static asmlinkage void call_bios_52x(struct register_buffer *buf)
|
|
+{
|
|
+ if (bios_routine) {
|
|
+ local_irq_disable();
|
|
+ __asm__ __volatile__(
|
|
+ "movl %2,%%edx\n\t"
|
|
+ "pusha\n\t"
|
|
+ "movl %%edx,%%ebp\n\t"
|
|
+ "movl (%%ebp),%%eax\n\t"
|
|
+ "movl 4(%%ebp),%%ebx\n\t"
|
|
+ "movl 8(%%ebp),%%ecx\n\t"
|
|
+ "movl 12(%%ebp),%%edx\n\t"
|
|
+ "movl 16(%%ebp),%%edi\n\t"
|
|
+ "movl 20(%%ebp),%%esi\n\t"
|
|
+ "pushl %%ebp\n\t"
|
|
+ "movl %1, %%ebp\n\t"
|
|
+ "call *%0\n\t"
|
|
+ "popl %%ebp\n\t"
|
|
+ "movl %%eax, (%%ebp)\n\t"
|
|
+ "movl %%ebx, 4(%%ebp)\n\t"
|
|
+ "movl %%ecx, 8(%%ebp)\n\t"
|
|
+ "movl %%edx, 12(%%ebp)\n\t"
|
|
+ "movl %%edi, 16(%%ebp)\n\t"
|
|
+ "movl %%esi, 20(%%ebp)\n\t"
|
|
+ "popa\n\t"
|
|
+ :
|
|
+ :"m" (bios_routine), "m" (preg400), "m" (buf)
|
|
+ :"%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi", "%ebp"
|
|
+ );
|
|
+ local_irq_enable();
|
|
+ }
|
|
+}
|
|
+
|
|
+#define PRINT_BUFFER(x) \
|
|
+ printk(KERN_INFO"acerhk: eax=0x%x ebx=0x%x ecx=0x%x edx=0x%x\n" \
|
|
+ "acerhk: edi=0x%x esi=0x%x ebp=0x%x\n", \
|
|
+ x.eax, x.ebx, x.ecx, x.edx, x.edi, x.esi, x.ebp);
|
|
+
|
|
+/* get_fnkey_event
|
|
+ *
|
|
+ * gets the first (oldest) key id from the queue of events
|
|
+ *
|
|
+ * return value: id of key
|
|
+ */
|
|
+static int get_fnkey_event(void)
|
|
+{
|
|
+ struct register_buffer regs;
|
|
+ regs.eax = 0x9610;
|
|
+ regs.ebx = 0x61C;
|
|
+ /* clear other registers, some models need this */
|
|
+ regs.ecx = 0;
|
|
+ regs.edx = 0;
|
|
+ preempt_disable();
|
|
+ call_bios(®s);
|
|
+ preempt_enable_no_resched();
|
|
+ return regs.eax & 0xffff;
|
|
+}
|
|
+
|
|
+/* get_thermal_event
|
|
+ *
|
|
+ * does what?
|
|
+ *
|
|
+ * return value: event ?
|
|
+ */
|
|
+static int get_thermal_event(void)
|
|
+{
|
|
+ struct register_buffer regs;
|
|
+ if (acerhk_model_features & TM_F_THERMAL) {
|
|
+ regs.eax = 0x9612;
|
|
+ regs.ebx = 0x12e;
|
|
+ preempt_disable();
|
|
+ call_bios(®s);
|
|
+ preempt_enable_no_resched();
|
|
+ if (verbose > 3)
|
|
+ printk(KERN_INFO"acerhk: thermal event = 0x%x\n", regs.eax);
|
|
+ } else {
|
|
+ regs.eax = 0x00;
|
|
+ if (verbose > 3)
|
|
+ printk(KERN_INFO"acerhk: thermal event not supported\n");
|
|
+ }
|
|
+ return regs.eax & 0xffff;
|
|
+}
|
|
+
|
|
+#ifdef ACERDEBUG
|
|
+/* pbutton_fct
|
|
+ *
|
|
+ * does what?
|
|
+ *
|
|
+ * return value: ?
|
|
+ */
|
|
+static int pbutton_fct(void)
|
|
+{
|
|
+ struct register_buffer regs;
|
|
+ if (acerhk_model_features & TM_F_PBUTTON) {
|
|
+ regs.eax = 0x9612;
|
|
+ regs.ebx = 0x10b;
|
|
+ regs.ecx = 0x2;
|
|
+ preempt_disable();
|
|
+ call_bios(®s);
|
|
+ preempt_enable_no_resched();
|
|
+ if (verbose > 3)
|
|
+ printk(KERN_INFO"acerhk: pbutton = 0x%x\n", regs.eax);
|
|
+ } else {
|
|
+ if (verbose > 3)
|
|
+ printk(KERN_INFO"acerhk: pbutton function not supported\n");
|
|
+ regs.eax = 0x00;
|
|
+ }
|
|
+ return regs.eax & 0xffff;
|
|
+}
|
|
+#endif
|
|
+
|
|
+/* wbutton_fct_1
|
|
+ *
|
|
+ * turn on installed Bluetooth hardware together with the corresponding LED
|
|
+ *
|
|
+ * val: 0 turns off the LED
|
|
+ * 1 turns the LED to green/blue
|
|
+ *
|
|
+ * return value: ?
|
|
+ */
|
|
+static int wbutton_fct_1(int val)
|
|
+{
|
|
+ struct register_buffer regs;
|
|
+ if (acerhk_model_features & TM_F_WBUTTON) {
|
|
+ acerhk_bluetooth_state = val;
|
|
+ regs.eax = 0x9610;
|
|
+ regs.ebx = ((val & 0xff) << 8) | 0x34;
|
|
+ preempt_disable();
|
|
+ call_bios(®s);
|
|
+ preempt_enable_no_resched();
|
|
+ if (verbose > 3)
|
|
+ printk(KERN_INFO"acerhk: wbutton1 = 0x%x\n", regs.eax);
|
|
+ } else {
|
|
+ if (verbose > 3)
|
|
+ printk(KERN_INFO"acerhk: wbutton function 1 not supported\n");
|
|
+ regs.eax = 0x00;
|
|
+ }
|
|
+ return regs.eax & 0xffff;
|
|
+}
|
|
+
|
|
+/* wbutton_fct_2
|
|
+ *
|
|
+ * turn on installed WLAN hardware together with the corresponding LED
|
|
+ *
|
|
+ * val: 0 turns off the LED
|
|
+ * 1 turns the LED to orange
|
|
+ *
|
|
+ * return value: ?
|
|
+ */
|
|
+static int wbutton_fct_2(int val)
|
|
+{
|
|
+ struct register_buffer regs;
|
|
+ if (acerhk_model_features & TM_F_WBUTTON) {
|
|
+ acerhk_wlan_state = val;
|
|
+ regs.eax = 0x9610;
|
|
+ regs.ebx = ((val & 0xff) << 8) | 0x35;
|
|
+ preempt_disable();
|
|
+ call_bios(®s);
|
|
+ preempt_enable_no_resched();
|
|
+ if (verbose > 3)
|
|
+ printk(KERN_INFO"acerhk: wbutton2 = 0x%x\n", regs.eax);
|
|
+ } else {
|
|
+ if (verbose > 3)
|
|
+ printk(KERN_INFO"acerhk: wbutton function 2 not supported\n");
|
|
+ regs.eax = 0x00;
|
|
+ }
|
|
+ return regs.eax & 0xffff;
|
|
+}
|
|
+
|
|
+/* get_cmos_index
|
|
+ *
|
|
+ * gets index of CMOS port from ROM. The number of events is monitored
|
|
+ * in this port.
|
|
+ *
|
|
+ * return value: index of CMOS port
|
|
+ */
|
|
+static int get_cmos_index(void)
|
|
+{
|
|
+ struct register_buffer regs;
|
|
+ regs.eax = 0x9610;
|
|
+ regs.ebx = 0x51C;
|
|
+ preempt_disable();
|
|
+ call_bios(®s);
|
|
+ preempt_enable_no_resched();
|
|
+ cmos_index = regs.ecx & 0xff;
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO"acerhk: cmos index set to 0x%x\n", cmos_index);
|
|
+ return cmos_index;
|
|
+}
|
|
+
|
|
+/* get_nr_events
|
|
+ *
|
|
+ * gets the number of cached events (keys pressed) in queue. Up to 31 events
|
|
+ * are cached.
|
|
+ *
|
|
+ * return value: number of events in queue
|
|
+ */
|
|
+static int get_nr_events(void)
|
|
+{
|
|
+ unsigned long flags;
|
|
+ unsigned char c = 0;
|
|
+
|
|
+ spin_lock_irqsave (&rtc_lock, flags);
|
|
+#ifndef DUMMYHW
|
|
+ if (cmos_index)
|
|
+ c = CMOS_READ(cmos_index);
|
|
+ else if (verbose > 3)
|
|
+ printk(KERN_INFO"acerhk: get_nr_events - no valid cmos index set\n");
|
|
+#endif
|
|
+ spin_unlock_irqrestore (&rtc_lock, flags);
|
|
+ return c;
|
|
+}
|
|
+
|
|
+/* set_mail_led
|
|
+ *
|
|
+ * change state of mail led
|
|
+ *
|
|
+ * val: 0 - switch led off
|
|
+ * 1 - switch led on (blinking)
|
|
+ *
|
|
+ * return value: 1 - action succesfull (val valid)
|
|
+ * 0 - no action taken (val invalid)
|
|
+ */
|
|
+static int set_mail_led(int val)
|
|
+{
|
|
+ struct register_buffer regs;
|
|
+ if (acerhk_model_features & TM_F_MAIL_LED) {
|
|
+ regs.eax = 0x9610;
|
|
+ regs.ebx = ((val & 0xff) << 8) | 0x31;
|
|
+ preempt_disable();
|
|
+ call_bios(®s);
|
|
+ preempt_enable_no_resched();
|
|
+ if (verbose > 3)
|
|
+ printk(KERN_INFO"acerhk: mail led set to = 0x%x\n", val);
|
|
+ } else if (acerhk_model_features & TM_F_MAIL_LED_EC) {
|
|
+ if (val == 1)
|
|
+ enable_mail_led_ec_1();
|
|
+ else if (val == 0)
|
|
+ disable_mail_led_ec_1();
|
|
+ } else if (acerhk_model_features & TM_F_MAIL_LED_EC2) {
|
|
+ if (val == 1)
|
|
+ enable_mail_led_ec_2();
|
|
+ else if (val == 0)
|
|
+ disable_mail_led_ec_2();
|
|
+ } else if (acerhk_model_features & TM_F_MAIL_LED_EC3) {
|
|
+ if (val == 1)
|
|
+ enable_mail_led_ec_3();
|
|
+ else if (val == 0)
|
|
+ disable_mail_led_ec_3();
|
|
+ } else {
|
|
+ if (verbose > 3)
|
|
+ printk(KERN_INFO"acerhk: mail led not supported\n");
|
|
+ regs.eax = 0x00;
|
|
+ }
|
|
+ return regs.eax & 0xffff;
|
|
+}
|
|
+
|
|
+/* launch_connect
|
|
+ *
|
|
+ * does what?
|
|
+ * val: 1 - only known value from windows driver
|
|
+ */
|
|
+static int launch_connect(int val)
|
|
+{
|
|
+ struct register_buffer regs;
|
|
+ if (acerhk_model_features & TM_F_CONNECT) {
|
|
+ regs.eax = 0x9610;
|
|
+ regs.ebx = ((val & 0xff) << 8) | 0x2e;
|
|
+ preempt_disable();
|
|
+ call_bios(®s);
|
|
+ preempt_enable_no_resched();
|
|
+ if (verbose > 3)
|
|
+ printk(KERN_INFO"acerhk: connect(%d) = 0x%x\n", val, regs.eax);
|
|
+ } else {
|
|
+ if (verbose > 3)
|
|
+ printk(KERN_INFO"acerhk: connect not supported\n");
|
|
+ regs.eax = 0x00;
|
|
+ }
|
|
+ return regs.eax & 0xffff;
|
|
+}
|
|
+
|
|
+/* }}} */
|
|
+
|
|
+/* {{{ hardware probing */
|
|
+
|
|
+static struct proc_dir_entry *proc_acer_dir;
|
|
+
|
|
+static unsigned int __init find_hk_area(void)
|
|
+{
|
|
+ int offset, sig;
|
|
+ unsigned int fkt;
|
|
+ fkt = 0;
|
|
+ sig = -1; /* offset to signature in io area */
|
|
+ /* Look for signature, start at 0xf0000, search until 0xffff0 */
|
|
+ for (offset = 0;offset < 0xfffd; offset += 16) {
|
|
+ if (readl(reg1 + offset) == 0x30552142) {
|
|
+ sig = offset;
|
|
+ offset = 0xffff;
|
|
+ }
|
|
+ }
|
|
+ if (sig < 0)
|
|
+ printk(KERN_WARNING"acerhk: could not find request handler, possibly not all functions available\n");
|
|
+ else {
|
|
+ /* compute location of bios routine */
|
|
+ fkt = readl(reg1 + sig + 5);
|
|
+ /* adjust fkt to address of mapped IO area */
|
|
+ if (fkt >= 0xf0000)
|
|
+ fkt = (unsigned int)reg1 + fkt - 0xf0000;
|
|
+ else if (fkt >= 0xe0000)
|
|
+ fkt = (unsigned int)reg1 + fkt - 0xe0000;
|
|
+ else
|
|
+ fkt = 0;
|
|
+ }
|
|
+ return fkt;
|
|
+}
|
|
+
|
|
+static void print_features(void)
|
|
+{
|
|
+ int i;
|
|
+ printk(KERN_INFO"acerhk: supported keys:");
|
|
+ for (i = 0; i < 255; i++) {
|
|
+ switch (acerhk_key2name[i]) {
|
|
+ case k_help: printk(" help"); break;
|
|
+ case k_setup: printk(" setup"); break;
|
|
+ case k_p1: printk(" p1"); break;
|
|
+ case k_p2: printk(" p2"); break;
|
|
+ case k_p3: printk(" p3"); break;
|
|
+ case k_www: printk(" www"); break;
|
|
+ case k_mail: printk(" mail"); break;
|
|
+ case k_wireless: printk(" wireless"); break;
|
|
+ case k_power: printk(" power"); break;
|
|
+ case k_mute: printk(" mute"); break;
|
|
+ case k_volup: printk(" volup"); break;
|
|
+ case k_voldn: printk(" voldn"); break;
|
|
+ case k_res: printk(" res"); break;
|
|
+ case k_close: printk(" close"); break;
|
|
+ case k_open: printk(" open"); break;
|
|
+ case k_wireless2: printk(" wireless2"); break;
|
|
+ case k_play: printk(" play"); break;
|
|
+ case k_stop: printk(" stop"); break;
|
|
+ case k_prev: printk(" prev"); break;
|
|
+ case k_next: printk(" next"); break;
|
|
+ case k_display: printk(" display"); break;
|
|
+ default: break;
|
|
+ }
|
|
+ }
|
|
+ printk("\n");
|
|
+ if (acerhk_model_features & TM_F_MUTE_LED_EC)
|
|
+ printk(KERN_INFO"acerhk: mute led is supported\n");
|
|
+ if (acerhk_model_features & TM_F_MAIL_LED)
|
|
+ printk(KERN_INFO"acerhk: mail led is supported\n");
|
|
+ else if (acerhk_model_features & TM_F_MAIL_LED_EC)
|
|
+ printk(KERN_INFO"acerhk: mail led (EC) is supported\n");
|
|
+ else if (acerhk_model_features & TM_F_MAIL_LED_EC2)
|
|
+ printk(KERN_INFO"acerhk: mail led (EC2) is supported\n");
|
|
+ else if (acerhk_model_features & TM_F_MAIL_LED_EC3)
|
|
+ printk(KERN_INFO"acerhk: mail led (EC3) is supported\n");
|
|
+ if (acerhk_model_features & TM_F_WLAN_EC1)
|
|
+ printk(KERN_INFO"acerhk: wlan control (EC1) is supported\n");
|
|
+ else if (acerhk_model_features & TM_F_WLAN_EC2)
|
|
+ printk(KERN_INFO"acerhk: wlan control (EC2) is supported\n");
|
|
+ if (acerhk_model_features & TM_F_BLUE_EC1)
|
|
+ printk(KERN_INFO"acerhk: bluetooth control (EC1) is supported\n");
|
|
+ else if (acerhk_model_features & TM_F_BLUE_EC2)
|
|
+ printk(KERN_INFO"acerhk: bluetooth control (EC2) is supported\n");
|
|
+ printk(KERN_INFO"acerhk: supported functions:");
|
|
+ if (acerhk_model_features & TM_F_CONNECT)
|
|
+ printk(" connect");
|
|
+ if (acerhk_model_features & TM_F_THERMAL)
|
|
+ printk(" thermal");
|
|
+ if (acerhk_model_features & TM_F_PBUTTON)
|
|
+ printk(" pbutton");
|
|
+ if (acerhk_model_features & TM_F_WBUTTON)
|
|
+ printk(" wbutton");
|
|
+ printk("\n");
|
|
+}
|
|
+
|
|
+static void __init setup_keymap_model(unsigned int series)
|
|
+{
|
|
+ /* clear mapping keycode -> keyname, */
|
|
+ memset(&acerhk_key2name[0], k_none, sizeof(acerhk_key2name));
|
|
+ /* first set the common keys, namely FnF1 and FnF2, */
|
|
+ acerhk_key2name[1] = k_help;
|
|
+ acerhk_key2name[2] = k_setup;
|
|
+ /* then set known keycodes according to model */
|
|
+ switch (series) {
|
|
+ case 110:
|
|
+ acerhk_key2name[48] = k_wireless;
|
|
+ acerhk_key2name[17] = k_p1;
|
|
+ acerhk_key2name[18] = k_p2;
|
|
+ acerhk_key2name[54] = k_www;
|
|
+ acerhk_key2name[49] = k_mail;
|
|
+ acerhk_key2name[3] = k_power;
|
|
+ acerhk_key2name[8] = k_mute;
|
|
+ acerhk_key2name[32] = k_volup;
|
|
+ acerhk_key2name[33] = k_voldn;
|
|
+ /* C110 generates 2 extra codes when opening/closing the lid */
|
|
+ acerhk_key2name[74] = k_close;
|
|
+ acerhk_key2name[75] = k_open;
|
|
+ break;
|
|
+ case 300: /* treat C300 like C100 with Bluetooth button */
|
|
+ acerhk_key2name[68] = k_wireless2;
|
|
+ case 100:
|
|
+ acerhk_key2name[48] = k_wireless;
|
|
+ acerhk_key2name[17] = k_p1;
|
|
+ acerhk_key2name[18] = k_p2;
|
|
+ acerhk_key2name[49] = k_www;
|
|
+ acerhk_key2name[54] = k_mail;
|
|
+ acerhk_key2name[3] = k_power;
|
|
+ acerhk_key2name[8] = k_mute;
|
|
+ acerhk_key2name[32] = k_volup;
|
|
+ acerhk_key2name[33] = k_voldn;
|
|
+ break;
|
|
+ default:
|
|
+ /* only the two common keys are supported */
|
|
+ break;
|
|
+ case 210:
|
|
+ acerhk_key2name[19] = k_p1;
|
|
+ acerhk_key2name[20] = k_p2;
|
|
+ acerhk_key2name[17] = k_www;
|
|
+ acerhk_key2name[18] = k_mail;
|
|
+ break;
|
|
+ case 220:
|
|
+ case 260: /* 260 with same keys? */
|
|
+ acerhk_key2name[49] = k_p1;
|
|
+ acerhk_key2name[19] = k_p2;
|
|
+ acerhk_key2name[18] = k_www;
|
|
+ acerhk_key2name[17] = k_mail;
|
|
+ break;
|
|
+ case 230:
|
|
+ case 280: /* 280 with same keys? */
|
|
+ acerhk_key2name[17] = k_p1;
|
|
+ acerhk_key2name[18] = k_p2;
|
|
+ acerhk_key2name[49] = k_mail;
|
|
+ acerhk_key2name[54] = k_www;
|
|
+ break;
|
|
+ case 1500:
|
|
+ acerhk_key2name[0x49] = k_setup;
|
|
+ acerhk_key2name[0x36] = k_www;
|
|
+ acerhk_key2name[0x31] = k_mail;
|
|
+ acerhk_key2name[0x11] = k_p1;
|
|
+ acerhk_key2name[0x12] = k_p2;
|
|
+ acerhk_key2name[0x30] = k_wireless;
|
|
+ acerhk_key2name[0x44] = k_wireless2;
|
|
+ acerhk_key2name[0x03] = k_power;
|
|
+ break;
|
|
+ case 240:
|
|
+ acerhk_key2name[0x31] = k_www;
|
|
+ acerhk_key2name[0x36] = k_mail;
|
|
+ acerhk_key2name[0x11] = k_p1;
|
|
+ acerhk_key2name[0x12] = k_p2;
|
|
+ acerhk_key2name[0x44] = k_wireless;
|
|
+ acerhk_key2name[0x30] = k_wireless2;
|
|
+ acerhk_key2name[0x03] = k_power;
|
|
+ acerhk_key2name[0x08] = k_mute;
|
|
+ // acerhk_key2name[] = k_volup;
|
|
+ // acerhk_key2name[] = k_voldn;
|
|
+ break;
|
|
+ case 2900:
|
|
+ acerhk_key2name[0x31] = k_mail; /* with led */
|
|
+ acerhk_key2name[0x36] = k_www;
|
|
+ acerhk_key2name[0x11] = k_p1;
|
|
+ acerhk_key2name[0x12] = k_p2;
|
|
+ acerhk_key2name[0x30] = k_wireless; /* wireless, with led, related with autowlan=1 */
|
|
+ break;
|
|
+ case 250: /* enriqueg@altern.org */
|
|
+ /* TravelMate 254LMi_DT manual common for 240/250 series, but key order
|
|
+ differ from 240 already present on acerhk driver */
|
|
+ /* TravelMate 254LMi_DT: 6 buttons: left to right: mail, www, p1, p2, bluetooth, wireless */
|
|
+ acerhk_key2name[0x31] = k_mail; /* with led */
|
|
+ acerhk_key2name[0x36] = k_www;
|
|
+ acerhk_key2name[0x11] = k_p1;
|
|
+ acerhk_key2name[0x12] = k_p2;
|
|
+ acerhk_key2name[0x44] = k_wireless2; /* bluetooth, hw optional */
|
|
+ acerhk_key2name[0x30] = k_wireless; /* wireless, with led, related with autowlan=1 */
|
|
+ acerhk_key2name[0x03] = k_power; /* Fn+F3 */
|
|
+ acerhk_key2name[0x08] = k_mute; /* Fn+F8 */
|
|
+ break;
|
|
+ case 380:
|
|
+ /* TM 380 has same codes as TM 370, with an additional one */
|
|
+ acerhk_key2name[0x03] = k_power;
|
|
+ case 370:
|
|
+ acerhk_key2name[0x30] = k_wireless;
|
|
+ acerhk_key2name[0x11] = k_p1;
|
|
+ acerhk_key2name[0x12] = k_p2;
|
|
+ acerhk_key2name[0x13] = k_p3;
|
|
+ acerhk_key2name[0x36] = k_www;
|
|
+ acerhk_key2name[0x31] = k_mail;
|
|
+ break;
|
|
+ case 360:
|
|
+ /* 360 series has the same layout as 350, with an
|
|
+ additional wireless key */
|
|
+ acerhk_key2name[64] = k_wireless;
|
|
+ case 350:
|
|
+ acerhk_key2name[17] = k_p1;
|
|
+ acerhk_key2name[18] = k_p2;
|
|
+ acerhk_key2name[20] = k_p3;
|
|
+ acerhk_key2name[21] = k_www;
|
|
+ acerhk_key2name[19] = k_mail;
|
|
+ break;
|
|
+ case 520:
|
|
+ acerhk_key2name[19] = k_p1;
|
|
+ acerhk_key2name[20] = k_p2;
|
|
+ acerhk_key2name[17] = k_www;
|
|
+ acerhk_key2name[18] = k_mail;
|
|
+ break;
|
|
+ case 610:
|
|
+ acerhk_key2name[17] = k_p1;
|
|
+ acerhk_key2name[18] = k_p2;
|
|
+ acerhk_key2name[19] = k_p3;
|
|
+ acerhk_key2name[21] = k_www;
|
|
+ acerhk_key2name[20] = k_mail;
|
|
+ acerhk_key2name[64] = k_wireless;
|
|
+ break;
|
|
+ case 630:
|
|
+ /* 630 has all keys of 620 plus one */
|
|
+ acerhk_key2name[8] = k_mute;
|
|
+ case 620:
|
|
+ acerhk_key2name[17] = k_p1;
|
|
+ acerhk_key2name[18] = k_p2;
|
|
+ acerhk_key2name[19] = k_p3;
|
|
+ acerhk_key2name[54] = k_www;
|
|
+ acerhk_key2name[49] = k_mail;
|
|
+ acerhk_key2name[48] = k_wireless;
|
|
+ acerhk_key2name[3] = k_power;
|
|
+ acerhk_key2name[32] = k_volup;
|
|
+ acerhk_key2name[33] = k_voldn;
|
|
+ break;
|
|
+ case 290:
|
|
+ case 420:
|
|
+ case 430:
|
|
+ case 530:
|
|
+ case 540:
|
|
+ case 650:
|
|
+ case 660:
|
|
+ case 800:
|
|
+ case 1450:
|
|
+ case 2300:
|
|
+ case 2350:
|
|
+ case 4000:
|
|
+ case 4050:
|
|
+ case 6000:
|
|
+ case 8000:
|
|
+ case 4100:
|
|
+ case 4150:
|
|
+ case 4500:
|
|
+ case 4600:
|
|
+ case 4650:
|
|
+ case 1680:
|
|
+ case 1690:
|
|
+ /* keys are handled by dritek EC */
|
|
+ acerhk_key2name[1] = k_none;
|
|
+ acerhk_key2name[2] = k_none;
|
|
+ break;
|
|
+ case 1300:
|
|
+ case 1310:
|
|
+ case 1350:
|
|
+ case 1360:
|
|
+ case 1400:
|
|
+ case 1700:
|
|
+ case 1800:
|
|
+ case 2000:
|
|
+ case 2010:
|
|
+ case 2020:
|
|
+ /* Aspire 13xx series laptops use dritek hardware, no
|
|
+ acerhk-mapping needed
|
|
+ VolUp and VolDown are managed as normal keys
|
|
+ 1300/1310 series should have P1, P2, Mail, WWW, Mute buttons
|
|
+ 1353 has bluetooth, wifi, p1, p2, www, mail, help, setup, power
|
|
+ and mute
|
|
+ Aspire 1400/1450/Ferrari use dritek EC, too
|
|
+ 1450 should have bluetooth, wifi, p1, p2, www, mail, help,
|
|
+ setup, power and mute
|
|
+ Aspire 1700 uses dritek EC, too
|
|
+ 1700 should have bluetooth, wifi, p1, p2, www, mail, help,
|
|
+ setup, power and mute
|
|
+ need the MM-buttons Activation? (forward, shuffle, ...)
|
|
+ 2000 hast lots of MM buttons
|
|
+ 2010 should have bluetooth, wifi, p1, p2, www, mail, help,
|
|
+ setup, power and mute
|
|
+ */
|
|
+ acerhk_key2name[1] = k_none;
|
|
+ acerhk_key2name[2] = k_none;
|
|
+ break;
|
|
+ case 1600:
|
|
+ /* Aspire 1600 has acer keycode 0x49 for FnF2 */
|
|
+ acerhk_key2name[73] = k_setup;
|
|
+ acerhk_key2name[48] = k_wireless;
|
|
+ acerhk_key2name[49] = k_mail;
|
|
+ acerhk_key2name[54] = k_www;
|
|
+ acerhk_key2name[17] = k_p1;
|
|
+ acerhk_key2name[18] = k_p2;
|
|
+ acerhk_key2name[19] = k_p3;
|
|
+ acerhk_key2name[3] = k_power;
|
|
+ acerhk_key2name[8] = k_mute;
|
|
+ /* VolUp and VolDown keys doesn't seem to be managed as special keys
|
|
+ but as normal keys ! */
|
|
+ break;
|
|
+ case 5020: /* Aspire 5020 has 0x6a for Fn+F2 */
|
|
+ acerhk_key2name[2] = k_none;
|
|
+ acerhk_key2name[106] = k_setup;
|
|
+ acerhk_key2name[3] = k_power;
|
|
+ acerhk_key2name[5] = k_display;
|
|
+ acerhk_key2name[49] = k_mail;
|
|
+ acerhk_key2name[54] = k_www;
|
|
+ acerhk_key2name[17] = k_p1;
|
|
+ acerhk_key2name[18] = k_p2;
|
|
+ acerhk_key2name[48] = k_wireless;
|
|
+ acerhk_key2name[68] = k_wireless2;
|
|
+ break;
|
|
+ case 2410: /* TM 2410 is very similar to Aspire 5020, but has 0x6s for Fn-F3 */
|
|
+ acerhk_key2name[2] = k_none;
|
|
+ acerhk_key2name[106] = k_setup;
|
|
+ acerhk_key2name[109] = k_power;
|
|
+ acerhk_key2name[49] = k_mail;
|
|
+ acerhk_key2name[54] = k_www;
|
|
+ acerhk_key2name[17] = k_p1;
|
|
+ acerhk_key2name[18] = k_p2;
|
|
+ acerhk_key2name[48] = k_wireless;
|
|
+ acerhk_key2name[68] = k_wireless2;
|
|
+ break;
|
|
+ case 40100:
|
|
+ /* Medion MD40100, 4 keys */
|
|
+ acerhk_key2name[54] = k_www;
|
|
+ acerhk_key2name[49] = k_mail;
|
|
+ acerhk_key2name[48] = k_wireless;
|
|
+ acerhk_key2name[55] = k_res;
|
|
+ break;
|
|
+ case 96500:
|
|
+ case 95400:
|
|
+ /* Medion MD95400, many keys */
|
|
+ acerhk_key2name[49] = k_mail; /* 1 */
|
|
+ acerhk_key2name[54] = k_www; /* 2 */
|
|
+ acerhk_key2name[48] = k_wireless; /* 3 */
|
|
+ acerhk_key2name[68] = k_wireless2; /* 4 (Bluetooth) */
|
|
+
|
|
+ acerhk_key2name[17] = k_p1; /* 5 */
|
|
+ acerhk_key2name[18] = k_p2; /* 6 */
|
|
+ acerhk_key2name[36] = k_play; /* 7 */
|
|
+ acerhk_key2name[37] = k_stop; /* 8 */
|
|
+ acerhk_key2name[34] = k_prev; /* 9 */
|
|
+ acerhk_key2name[35] = k_next; /* 10 */
|
|
+ acerhk_key2name[33] = k_voldn; /* 11 */
|
|
+ acerhk_key2name[32] = k_volup; /* 12 */
|
|
+ acerhk_key2name[38] = k_p3; /* 13 */
|
|
+ acerhk_key2name[8] = k_mute; /* 14 */
|
|
+
|
|
+ acerhk_key2name[1] = k_help; /* FN+F1 (Help) */
|
|
+ acerhk_key2name[5] = k_display; /* FN+F3 (Display switch) */
|
|
+ acerhk_key2name[6] = k_res; /* FN+F4 (Display ein/ausschalten) */
|
|
+ break;
|
|
+ case 42200:
|
|
+ /* Medion MD42200, 7 keys, no setup */
|
|
+ acerhk_key2name[2] = k_none;
|
|
+ acerhk_key2name[5] = k_display;
|
|
+ acerhk_key2name[54] = k_www;
|
|
+ acerhk_key2name[48] = k_wireless;
|
|
+ acerhk_key2name[49] = k_mail;
|
|
+ acerhk_key2name[17] = k_p1;
|
|
+ acerhk_key2name[18] = k_p2;
|
|
+ break;
|
|
+ case 9783:
|
|
+ /* Medion MD9783, 6 keys + info, no setup */
|
|
+ acerhk_key2name[2] = k_none;
|
|
+ acerhk_key2name[54] = k_www;
|
|
+ acerhk_key2name[49] = k_mail;
|
|
+ acerhk_key2name[17] = k_p1;
|
|
+ acerhk_key2name[18] = k_p2;
|
|
+ acerhk_key2name[19] = k_p3;
|
|
+ acerhk_key2name[8] = k_mute;
|
|
+ break;
|
|
+ case 7400:
|
|
+ /* Amilo Pro V2000 does not have Help and Setup key (?)
|
|
+ Amilo M 7400 has Help key, disabling only setup
|
|
+ */
|
|
+ acerhk_key2name[2] = k_none;
|
|
+ acerhk_key2name[48] = k_wireless;
|
|
+ acerhk_key2name[49] = k_mail;
|
|
+ acerhk_key2name[54] = k_www;
|
|
+ acerhk_key2name[17] = k_p1;
|
|
+ acerhk_key2name[18] = k_p2;
|
|
+ break;
|
|
+ case 1559:
|
|
+ acerhk_key2name[6] = k_display; /* FN+F4 (Display ein/ausschalten) */
|
|
+ case 1555:
|
|
+ /* AOpen (Ahtec Signal 1555M) is similar to FS Amilo M */
|
|
+ acerhk_key2name[2] = k_none;
|
|
+ acerhk_key2name[48] = k_wireless;
|
|
+ acerhk_key2name[49] = k_mail;
|
|
+ acerhk_key2name[54] = k_www;
|
|
+ acerhk_key2name[17] = k_p1;
|
|
+ acerhk_key2name[18] = k_p2;
|
|
+ acerhk_key2name[34] = k_prev;
|
|
+ acerhk_key2name[35] = k_next;
|
|
+ acerhk_key2name[36] = k_play;
|
|
+ acerhk_key2name[37] = k_stop;
|
|
+ break;
|
|
+ case 6800:
|
|
+ case 7820:
|
|
+ /* Amilo D does not have Setup key */
|
|
+ acerhk_key2name[2] = k_none;
|
|
+ acerhk_key2name[49] = k_mail;
|
|
+ acerhk_key2name[54] = k_www;
|
|
+ acerhk_key2name[17] = k_p1;
|
|
+ acerhk_key2name[18] = k_p2;
|
|
+ acerhk_key2name[19] = k_p3;
|
|
+ acerhk_key2name[8] = k_mute;
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void __init setup_model_features(unsigned int series)
|
|
+{
|
|
+ switch (series) {
|
|
+ case 200:
|
|
+ case 210:
|
|
+ case 520:
|
|
+ /* nothing special */
|
|
+ acerhk_model_features = 0;
|
|
+ acerhk_type = TM_old;
|
|
+ break;
|
|
+ case 220:
|
|
+ case 230:
|
|
+ case 260:
|
|
+ case 280:
|
|
+ case 360:
|
|
+ case 40100: /* Medion MD40100 */
|
|
+ case 95400: /* Medion MD95400 */
|
|
+ case 96500: /* Medion MD96500 */
|
|
+ /* all special functions, no mail led */
|
|
+ acerhk_model_features = 0x00f00000;
|
|
+ acerhk_type = TM_new;
|
|
+ break;
|
|
+ case 42200: /* Medion MD42200 */
|
|
+ /* has WLAN button, should call connect() */
|
|
+ acerhk_model_features = TM_F_WBUTTON | TM_F_CONNECT;
|
|
+ acerhk_type = TM_old;
|
|
+ break;
|
|
+ case 9783: /* Medion MD9783 */
|
|
+ /* only email led */
|
|
+ acerhk_model_features = TM_F_MAIL_LED;
|
|
+ acerhk_type = TM_new;
|
|
+ break;
|
|
+ case 1600:
|
|
+ acerhk_type = TM_new;
|
|
+ /* Do Aspire 1600 series have special functions or not ? I enable
|
|
+ them, perhaps it helps with problems Francois Valenduc has */
|
|
+ acerhk_model_features = 0x00f00000;
|
|
+ break;
|
|
+ case 300:
|
|
+ case 100:
|
|
+ case 110:
|
|
+ case 240:
|
|
+ case 350:
|
|
+ case 610:
|
|
+ case 620:
|
|
+ case 630:
|
|
+ /* all special functions, mail led */
|
|
+ acerhk_model_features = TM_F_MAIL_LED | 0x00f00000;
|
|
+ acerhk_type = TM_new;
|
|
+ break;
|
|
+ case 370:
|
|
+ case 380:
|
|
+ case 2410:
|
|
+ case 2900: /* Medion MD2900 */
|
|
+ case 2100: /* TM 2100 uses same driver as 5020 */
|
|
+ case 5020: /* Aspire 5020 is still old hardware */
|
|
+ acerhk_model_features = TM_F_MAIL_LED | TM_F_CONNECT| TM_F_WBUTTON;
|
|
+ acerhk_type = TM_new;
|
|
+ break;
|
|
+ case 7400:
|
|
+ case 1555:
|
|
+ case 1559:
|
|
+ /* all special functions for Fujitsu-Siemens Amilo M7400, Pro V2000; AOpen */
|
|
+ acerhk_model_features = 0x00f00000;
|
|
+ acerhk_type = TM_new;
|
|
+ break;
|
|
+ case 6800:
|
|
+ case 7820:
|
|
+ /* mail led and all special functions for FS Amilo D */
|
|
+ acerhk_model_features = TM_F_MAIL_LED | 0x00f00000;
|
|
+ acerhk_type = TM_new;
|
|
+ break;
|
|
+ case 2350:
|
|
+ case 4050:
|
|
+ acerhk_wlan_state = 1; // Default state is on
|
|
+ case 290:
|
|
+ /* no special functions, wireless hardware controlled by EC */
|
|
+ acerhk_model_features = TM_F_WLAN_EC2 | TM_F_BLUE_EC2;
|
|
+ acerhk_type = TM_dritek;
|
|
+ break;
|
|
+ case 650:
|
|
+ case 1300:
|
|
+ case 1310:
|
|
+ case 1400:
|
|
+ case 1700:
|
|
+ /* all special functions, wireless hardware can be controlled */
|
|
+ acerhk_model_features = 0x00f00000;
|
|
+ acerhk_type = TM_dritek;
|
|
+ break;
|
|
+ case 4100:
|
|
+ case 4600:
|
|
+ case 1680:
|
|
+ case 1690: /* Aspire 1680/1690 should be similar to TM 4100/4600 */
|
|
+ /* mail led, wireless and bluetooth controlled the old way, but keys are
|
|
+ controlled by normal keyboard controller, so mark as dritek and
|
|
+ deactivate dritek use */
|
|
+ acerhk_model_features = TM_F_MAIL_LED | TM_F_WBUTTON;
|
|
+ acerhk_type = TM_dritek;
|
|
+ usedritek=0;
|
|
+ break;
|
|
+ case 660:
|
|
+ case 800:
|
|
+ /* all special functions, mail led */
|
|
+ acerhk_model_features = TM_F_MAIL_LED | 0x00f00000;
|
|
+ acerhk_type = TM_dritek;
|
|
+ break;
|
|
+ case 1350:
|
|
+ case 1360:
|
|
+ /* mail led, handled by EC, wireless HW is not (yet) controllable ? */
|
|
+ acerhk_model_features = TM_F_MAIL_LED_EC|TM_F_WLAN_EC1;
|
|
+ acerhk_type = TM_dritek;
|
|
+ break;
|
|
+ case 1450:
|
|
+ /* Bluetooth/Wlan led, Mail led handled by EC (variant 3) */
|
|
+ acerhk_model_features = TM_F_MAIL_LED_EC3|TM_F_WBUTTON;
|
|
+ acerhk_type = TM_dritek;
|
|
+ break;
|
|
+ case 1500:
|
|
+ /* Bluetooth/Wlan led */
|
|
+ acerhk_model_features = TM_F_WBUTTON;
|
|
+ acerhk_type = TM_new;
|
|
+ break;
|
|
+ case 420:
|
|
+ case 430:
|
|
+ /* all functions and dritek EC, mail LED is handled by EC, second
|
|
+ variant. An additional led is available, mute. (really?)
|
|
+ */
|
|
+ acerhk_type = TM_dritek;
|
|
+ acerhk_model_features = TM_F_MUTE_LED_EC|TM_F_MAIL_LED_EC2;
|
|
+ break;
|
|
+ case 2300:
|
|
+ case 4000:
|
|
+ case 4500:
|
|
+ /* wireless hardware, hopefully under control of my driver */
|
|
+ acerhk_type = TM_dritek;
|
|
+ acerhk_model_features = TM_F_BLUE_EC1|TM_F_WLAN_EC1;
|
|
+ break;
|
|
+ case 3200:
|
|
+ /* test, if this model uses old style wlan control */
|
|
+ acerhk_model_features = TM_F_WBUTTON;
|
|
+ acerhk_type = TM_dritek;
|
|
+ break;
|
|
+ case 6000:
|
|
+ case 8000:
|
|
+ /* 6000 and 8000 have wireless hardware, but I don't know how to handle,
|
|
+ so I choose no features */
|
|
+ acerhk_type = TM_dritek;
|
|
+ break;
|
|
+ case 530:
|
|
+ case 540:
|
|
+ case 2000:
|
|
+ /* No features (?) dritek EC, mail LED is handled by EC but
|
|
+ different from other Aspire series */
|
|
+ acerhk_type = TM_dritek;
|
|
+ acerhk_model_features = TM_F_MAIL_LED_EC2;
|
|
+ break;
|
|
+ case 4150:
|
|
+ case 4650:
|
|
+ /* Dritek EC, bluetooth, wifi, mail */
|
|
+ /* According to Andreas Stumpfl his TM 4652LMi does also work as series
|
|
+ 3200, which might mean that the BIOS function accesses the EC */
|
|
+ acerhk_type = TM_dritek;
|
|
+ acerhk_model_features = TM_F_MAIL_LED_EC2 | TM_F_WLAN_EC2 | TM_F_BLUE_EC2;
|
|
+ break;
|
|
+ case 1800:
|
|
+ case 2010:
|
|
+ case 2020:
|
|
+ /* Dritek EC, bluetooth, wifi, mail */
|
|
+ acerhk_type = TM_dritek;
|
|
+ acerhk_model_features = TM_F_MAIL_LED_EC2 | TM_F_WLAN_EC2 | TM_F_BLUE_EC2;
|
|
+ acerhk_wlan_state = 1; // Default state is on
|
|
+ break;
|
|
+ case 250: /* enriqueg@altern.org */
|
|
+ /* TravelMate254LMi_DT : mail led, bluetooth (button present, hw optional), wifi (with led) */
|
|
+ acerhk_model_features = TM_F_MAIL_LED|
|
|
+ TM_F_WBUTTON ;
|
|
+ acerhk_type = TM_new;
|
|
+ acerhk_wlan_state = 0; //Initial state is off on 254LMi_DT
|
|
+ break;
|
|
+ default:
|
|
+ /* nothing special */
|
|
+ acerhk_model_features = 0;
|
|
+ acerhk_type = TM_unknown;
|
|
+ break;
|
|
+ }
|
|
+ /* set the correct bios call function according to type */
|
|
+ if ((acerhk_type == TM_new) || (acerhk_type == TM_dritek)) {
|
|
+ call_bios = call_bios_6xx;
|
|
+ if (verbose > 2)
|
|
+ printk(KERN_INFO"acerhk: using call_bios_6xx mode\n");
|
|
+ } else {
|
|
+ call_bios = call_bios_52x;
|
|
+ if (verbose > 2)
|
|
+ printk(KERN_INFO"acerhk: using call_bios_52x mode\n");
|
|
+ }
|
|
+ /* remove key file on dritek hardware */
|
|
+ if (acerhk_type == TM_dritek) {
|
|
+ remove_proc_entry("key", proc_acer_dir);
|
|
+ }
|
|
+ /* setup available keys */
|
|
+ setup_keymap_model(acerhk_series);
|
|
+ if (verbose > 1)
|
|
+ print_features();
|
|
+}
|
|
+
|
|
+static unsigned int __init determine_laptop_series(char * str)
|
|
+{
|
|
+ /* 0 means unknown series, handled like TM 200 */
|
|
+ unsigned int series = 0;
|
|
+ if (strncmp(str, "TravelMate ", 11) == 0) {
|
|
+ switch (str[11]) {
|
|
+ case 'C':
|
|
+ if (str[12] == '1') {
|
|
+ if (str[13] == '0') {
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates TM C100 series\n");
|
|
+ series = 100;
|
|
+ } else if (str[13] == '1') {
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates TM C110 series\n");
|
|
+ series = 110;
|
|
+ }
|
|
+ } else if (str[12] == '3') {
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates TM C300 series\n");
|
|
+ series = 300;
|
|
+ }
|
|
+ break;
|
|
+ case 'F':
|
|
+ if (str[12] == '4') {
|
|
+ series = 230;
|
|
+ }
|
|
+ break;
|
|
+ case '2':
|
|
+ if (str[14] == '0') {
|
|
+ /* newer Travelmate 2xxx series */
|
|
+ switch (str[12]) {
|
|
+ case '0':
|
|
+ case '5':
|
|
+ series = 2000; // 2000 and 2500 are the same
|
|
+ break;
|
|
+ case '1':
|
|
+ if (str[13] == '0')
|
|
+ series = 2100;
|
|
+ break;
|
|
+ case '2':
|
|
+ case '7':
|
|
+ series = 2200; // 2200 and 2700 are the same
|
|
+ break;
|
|
+ case '3':
|
|
+ if (str[13] == '0')
|
|
+ series = 4000; // 2300 is the same as 4000
|
|
+ else if (str[13] == '5')
|
|
+ series = 4050; // 2350 is the same as 4050
|
|
+ break;
|
|
+ case '4':
|
|
+ if (str[13] == '1')
|
|
+ series = 2410;
|
|
+ break;
|
|
+ default:
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown TM 2xxx series\n");
|
|
+ break;
|
|
+ }
|
|
+ } else {
|
|
+ /* older Travelmate 2xx series */
|
|
+ switch (str[12]) {
|
|
+ case '0': series = 200; break;
|
|
+ case '1': series = 210; break;
|
|
+ case '2': series = 220; break;
|
|
+ case '4': series = 240; break;
|
|
+ case '5': series = 250; break; /* enriqueg@altern.org */
|
|
+ case '6': series = 260; break;
|
|
+ default:
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown TM 2xx series\n");
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+ case '3':
|
|
+ switch (str[12]) {
|
|
+ case '0': series = 3200; break; /* TM 3000 works like TM 3200 */
|
|
+ /* Travelmate 3xx series */
|
|
+ case '5': series = 350; break;
|
|
+ case '6': series = 360; break;
|
|
+ case '7': series = 370; break;
|
|
+ case '8': series = 380; break;
|
|
+ default:
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown TM 3xx series\n");
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+ case '4':
|
|
+ if ( (strnlen(str, ACERHK_MODEL_STRLEN-1) == 15) &&
|
|
+ (str[14] == '0') ) { /* Travelmate 4xxx series */
|
|
+ switch (str[12]) {
|
|
+ case '0': /* 4000 and 4500 are the same */
|
|
+ case '5':
|
|
+ series = 4000;
|
|
+ break;
|
|
+ case '1':
|
|
+ case '6': /* 4100 and 4600 are the same */
|
|
+ series = 4100;
|
|
+ break;
|
|
+ default:
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown TM 4xxx series\n");
|
|
+ break;
|
|
+ }
|
|
+ } else { /* Travelmate 4xx series */
|
|
+ switch (str[12]) {
|
|
+ case '2': series = 420; break;
|
|
+ case '3': series = 430; break;
|
|
+ default:
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown TM 4xx series\n");
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+ case '5': /* Travelmate 5xx series */
|
|
+ if (str[12] == '2')
|
|
+ series = 520;
|
|
+ else if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown TM 5xx series\n");
|
|
+ break;
|
|
+ case '6': /* older Travelmate 6xx series */
|
|
+ switch (str[12]) {
|
|
+ case '1': series = 610; break;
|
|
+ case '2': series = 620; break;
|
|
+ case '3': series = 630; break;
|
|
+ default:
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown TM 6xx series\n");
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown TM xxx series\n");
|
|
+ break;
|
|
+ }
|
|
+ if (series && verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates TM %d series\n", series);
|
|
+ }
|
|
+ /* newer Travelmate series do not have a space after 'TravelMate' */
|
|
+ else if (strncmp(str, "TravelMate", 10) == 0) {
|
|
+ switch (str[10]) {
|
|
+ case '2':
|
|
+ if (str[11] == '9') {
|
|
+ series = 290;
|
|
+ } else {
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown TM2xx series\n");
|
|
+ }
|
|
+ break;
|
|
+ case '3':
|
|
+ if (str[11] == '2' && str[14] == '3') {
|
|
+ // TM 3200 uses "TravelMate32003"
|
|
+ series = 3200;
|
|
+ } else {
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown TM3xxx series\n");
|
|
+ }
|
|
+ break;
|
|
+ case '4':
|
|
+ switch (str[11]) {
|
|
+ case '3': series = 430; break;
|
|
+ default:
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown TM4xx series\n");
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+ case '5':
|
|
+ switch (str[11]) {
|
|
+ case '3': series = 530; break;
|
|
+ case '4': series = 540; break;
|
|
+ default:
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown TM5xx series\n");
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+ case '6':
|
|
+ switch (str[11]) {
|
|
+ case '5': series = 650; break;
|
|
+ case '6': series = 660; break;
|
|
+ case '0':
|
|
+ if (strncmp(str, "TravelMate60003", 15) == 0) {
|
|
+ series = 6000; break;
|
|
+ }
|
|
+ default:
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown TM6xx series\n");
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+ case '8':
|
|
+ if (strncmp(str, "TravelMate80003", 15) == 0) {
|
|
+ series = 8000;
|
|
+ } else if (str[11] == '0') {
|
|
+ series = 800;
|
|
+ } else {
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown TM8xx series\n");
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown TMxxx series\n");
|
|
+ break;
|
|
+ }
|
|
+ if (series && verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates TM%d series\n", series);
|
|
+ }
|
|
+ else if (strncmp(str, "Aspire ", 7) == 0) {
|
|
+ switch(str[7]) {
|
|
+ case '1': /* Aspire 1xxx series */
|
|
+ switch(str[8]) {
|
|
+ case '3': /* Aspire 13xx series */
|
|
+ switch (str[9]) {
|
|
+ case '0': series = 1300; break;
|
|
+ case '1': series = 1310; break;
|
|
+ case '5': series = 1350; break;
|
|
+ case '6': series = 1360; break;
|
|
+ default:
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown Aspire 13xx series\n");
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+ case '4': /* Aspire 14xx series */
|
|
+ switch (str[9]) {
|
|
+ case '0': series = 1400; break;
|
|
+ case '5': series = 1450; break;
|
|
+ default:
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown Aspire 14xx series\n");
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+ case '5': series = 1500; break;
|
|
+ case '6': /* Aspire 14xx series */
|
|
+ switch (str[9]) {
|
|
+ case '0': series = 1600; break;
|
|
+ case '8':
|
|
+ case '9': series = 1680; break;
|
|
+ default:
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown Aspire 16xx series\n");
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+ case '7': series = 1700; break;
|
|
+ case '8': series = 1800; break;
|
|
+ default:
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown Aspire 1xxx series\n");
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+ case '2': /* Aspire 2xxx series */
|
|
+ if (str[8] == '0') {
|
|
+ switch (str[9]) {
|
|
+ default:
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown Aspire 20xx series\n");
|
|
+ break;
|
|
+ case '0': series = 2000; break;
|
|
+ case '1': series = 2010; break;
|
|
+ case '2': series = 2020; break;
|
|
+ }
|
|
+ } else {
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown Aspire 2xxx series\n");
|
|
+ }
|
|
+ break;
|
|
+ case '3': /* Aspire 3xxx series */
|
|
+ if (str[8] == '0') {
|
|
+ switch (str[9]) {
|
|
+ default:
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown Aspire 30xx series\n");
|
|
+ break;
|
|
+ case '2': series = 5020; break; /* Aspire 3020/5020 are identical */
|
|
+ }
|
|
+ } else {
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown Aspire 3xxx series\n");
|
|
+ }
|
|
+ break;
|
|
+ case '5': /* Aspire 5xxx series */
|
|
+ if (str[8] == '0') {
|
|
+ switch (str[9]) {
|
|
+ default:
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown Aspire 50xx series\n");
|
|
+ break;
|
|
+ case '2': series = 5020; break;
|
|
+ }
|
|
+ } else {
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown Aspire 5xxx series\n");
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown Aspire series\n");
|
|
+ break;
|
|
+ }
|
|
+ if (series && verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates Aspire %d series\n", series);
|
|
+ }
|
|
+ else if (strncmp(str, "Extensa ", 8) == 0) {
|
|
+ /* Extensa series */
|
|
+ switch (str[8]) {
|
|
+ case '3':
|
|
+ switch (str[9]) {
|
|
+ case '0':
|
|
+ series = 3000; break;
|
|
+ default: break;
|
|
+ }
|
|
+ break;
|
|
+ default: break;
|
|
+ }
|
|
+ if (series && verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates Extensa %d series\n", series);
|
|
+ else if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown Extensa series\n");
|
|
+ }
|
|
+ else if (strncmp(str, "Amilo ", 6) == 0) {
|
|
+ switch (str[6]) {
|
|
+ case 'D': /* complete string is "Amilo D-Series", there seems to be no model number */
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates FS Amilo D series\n");
|
|
+ /* this is the model number of my Amilo */
|
|
+ series = 7820;
|
|
+ break;
|
|
+ default:
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown FS Amilo XX series\n");
|
|
+ series = 7820;
|
|
+ }
|
|
+ }
|
|
+ else if (strncmp(str, "AMILO ", 6) == 0) {
|
|
+ switch (str[6]) {
|
|
+ case 'D': /* AMILO D 6800 P4-2000 */
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates FS AMILO D series\n");
|
|
+ series = 6800;
|
|
+ break;
|
|
+ case 'M':
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates FS AMILO M(7400) series\n");
|
|
+ series = 7400;
|
|
+ break;
|
|
+ case 'P':
|
|
+ /* it is assumed, that 'AMILO P' appears only on Amilo Pro Series */
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates FS AMILO Pro (V2000) series\n");
|
|
+ series = 7400;
|
|
+ break;
|
|
+ default:
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates unknown FS AMILO XX series\n");
|
|
+ series = 6800;
|
|
+ }
|
|
+ }
|
|
+ else if (strncmp(str, "MEDIONPC", 8) == 0) {
|
|
+ uint medionmodel;
|
|
+ if ((medionmodel = COLUSSI("WIM 2040", 4, reg1, AREA_SIZE)) >= 0) {
|
|
+ printk(KERN_INFO"acerhk: found Medion model string:'%s'\n", (char*)reg1+medionmodel);
|
|
+ series = 96500;
|
|
+ } else {
|
|
+ if ((medionmodel = COLUSSI("MD 9", 4, reg1, AREA_SIZE)) >= 0) {
|
|
+ printk(KERN_INFO"acerhk: found Medion model string:'%s'\n", (char*)reg1+medionmodel);
|
|
+ }
|
|
+ series = 95400;
|
|
+ }
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates a medion MD %d\n", series);
|
|
+ }
|
|
+ else if (strncmp(str, "MEDIONNB", 8) == 0) {
|
|
+ /* Search for the Product string of the MD9783. */
|
|
+ if (COLUSSI("MD 42200", 8, reg1, AREA_SIZE) >= 0) {
|
|
+ if (verbose>1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates a Medion MD 42200\n");
|
|
+ series = 42200;
|
|
+ } else if (COLUSSI("MD 9783", 7, reg1, AREA_SIZE) >= 0){
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates a medion MD 9783\n");
|
|
+ series = 9783;
|
|
+ } else if (COLUSSI("WIM 2000", 7, reg1, AREA_SIZE) >= 0){
|
|
+ if (verbose>1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates a Medion MD 2900\n");
|
|
+ series = 2900;
|
|
+ } else {
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates a medion MD40100\n");
|
|
+ series = 40100;
|
|
+ }
|
|
+ } else if (strncmp(str, "AOpen", 5) == 0) {
|
|
+ if (strncmp(str, "AOpen*EzRestore", 15) == 0) {
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates a AOpen 1559\n");
|
|
+ series = 1559;
|
|
+ } else {
|
|
+ /* Unless I know of other models no further differentiation,
|
|
+ although there is a second part of the model string */
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates a AOpen\n");
|
|
+ series = 1555;
|
|
+ }
|
|
+ } else if (strncmp(str, "CL56", 4) == 0) {
|
|
+ /* Unless I know of other models no further differentiation,
|
|
+ although there are strings with more numbers ("CL561" on a Compal
|
|
+ CL56/Zepto 4200, reported by Stian B. Barmen)
|
|
+ It has the same functions as Acer Aspire 2010
|
|
+ */
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates a Compal CL56 (or similar)\n");
|
|
+ series = 2010;
|
|
+ } else if (strncmp(str, "Geneva2", 7) == 0) {
|
|
+ /* This might be an Aspire 9110 which is very similar to 4650 */
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates an Aspire 9110\n");
|
|
+ series = 4650;
|
|
+ } else {
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: model string indicates no supported hardware\n");
|
|
+ }
|
|
+ return (series);
|
|
+}
|
|
+
|
|
+static void __init probe_model(void) {
|
|
+ int offset; /* offset from beginning of reg1 to Model string */
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO"acerhk: start search for model string at %p\n", reg1);
|
|
+ /* first we look for Travelmate, if it isn't one we try to identify other
|
|
+ laptops, such as Medion or Aspire */
|
|
+ offset = COLUSSI("Travel", 6, reg1, AREA_SIZE);
|
|
+ /* Try to detect Aspire laptops */
|
|
+ if (offset < 0)
|
|
+ offset = COLUSSI("Aspire", 6, reg1, AREA_SIZE);
|
|
+ /* Try to detect Extensa laptops */
|
|
+ if (offset < 0)
|
|
+ offset = COLUSSI("Extensa", 7, reg1, AREA_SIZE);
|
|
+ /* Try to detect Medion laptops */
|
|
+ if (offset < 0)
|
|
+ offset = COLUSSI("MEDION", 6, reg1, AREA_SIZE);
|
|
+ /* Try to detect AOpen laptops */
|
|
+ if (offset < 0)
|
|
+ offset = COLUSSI("AOpen", 5, reg1, AREA_SIZE);
|
|
+ /* Try to detect Fujitsu Siemens Amilo laptops */
|
|
+ if (offset < 0)
|
|
+ offset = COLUSSI("Amilo", 5, reg1, AREA_SIZE);
|
|
+ if (offset < 0)
|
|
+ offset = COLUSSI("AMILO", 5, reg1, AREA_SIZE);
|
|
+ /* Try to detect Compal */
|
|
+ if (offset < 0)
|
|
+ offset = COLUSSI("CL56", 4, reg1, AREA_SIZE);
|
|
+ /* That might be an Aspire 9110 */
|
|
+ if (offset < 0)
|
|
+ offset = COLUSSI("Geneva2", 7, reg1, AREA_SIZE);
|
|
+ if (offset >= 0) {
|
|
+ acerhk_model_addr = reg1 + offset;
|
|
+ /* copy the string, but not more than 15 characters */
|
|
+ strncpy(acerhk_model_string, acerhk_model_addr, ACERHK_MODEL_STRLEN-1);
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO"acerhk: found model string '%s' at %p\n",
|
|
+ acerhk_model_string, acerhk_model_addr);
|
|
+ if (bios_routine && verbose > 2)
|
|
+ printk(KERN_INFO"acerhk: offset from model string to function address: 0x%lx\n",
|
|
+ bios_routine - (unsigned long)acerhk_model_addr);
|
|
+ acerhk_series = determine_laptop_series(acerhk_model_string);
|
|
+ } else {
|
|
+ printk(KERN_WARNING"acerhk: Could not find model string, will assume type 200 series\n");
|
|
+ acerhk_series = 200;
|
|
+ }
|
|
+}
|
|
+
|
|
+/* }}} */
|
|
+
|
|
+/* {{{ key polling and translation */
|
|
+
|
|
+static void print_mapping(void)
|
|
+{
|
|
+ printk(KERN_INFO"acerhk: key mapping:\n");
|
|
+ printk("acerhk: help 0x%x\n", acerhk_name2event[k_help]);
|
|
+ printk("acerhk: setup 0x%x\n", acerhk_name2event[k_setup]);
|
|
+ printk("acerhk: p1 0x%x\n", acerhk_name2event[k_p1]);
|
|
+ printk("acerhk: p2 0x%x\n", acerhk_name2event[k_p2]);
|
|
+ printk("acerhk: p3 0x%x\n", acerhk_name2event[k_p3]);
|
|
+ printk("acerhk: www 0x%x\n", acerhk_name2event[k_www]);
|
|
+ printk("acerhk: mail 0x%x\n", acerhk_name2event[k_mail]);
|
|
+ printk("acerhk: wireless 0x%x\n", acerhk_name2event[k_wireless]);
|
|
+ printk("acerhk: power 0x%x\n", acerhk_name2event[k_power]);
|
|
+ printk("acerhk: mute 0x%x\n", acerhk_name2event[k_mute]);
|
|
+ printk("acerhk: volup 0x%x\n", acerhk_name2event[k_volup]);
|
|
+ printk("acerhk: voldn 0x%x\n", acerhk_name2event[k_voldn]);
|
|
+ printk("acerhk: res 0x%x\n", acerhk_name2event[k_res]);
|
|
+ printk("acerhk: close 0x%x\n", acerhk_name2event[k_close]);
|
|
+ printk("acerhk: open 0x%x\n", acerhk_name2event[k_open]);
|
|
+ printk("acerhk: wireless2 0x%x\n", acerhk_name2event[k_wireless2]);
|
|
+ printk("acerhk: play 0x%x\n", acerhk_name2event[k_play]);
|
|
+ printk("acerhk: stop 0x%x\n", acerhk_name2event[k_stop]);
|
|
+ printk("acerhk: prev 0x%x\n", acerhk_name2event[k_prev]);
|
|
+ printk("acerhk: next 0x%x\n", acerhk_name2event[k_next]);
|
|
+ printk("acerhk: display 0x%x\n", acerhk_name2event[k_display]);
|
|
+}
|
|
+
|
|
+static void set_keymap_name(t_key_names name, unsigned int key)
|
|
+{
|
|
+ acerhk_name2event[name] = key;
|
|
+}
|
|
+
|
|
+static void init_keymap_input(void)
|
|
+{
|
|
+ /* these values for input keys are chosen to match the key names on the
|
|
+ actual Acer laptop */
|
|
+ set_keymap_name(k_none, KEY_RESERVED);
|
|
+ set_keymap_name(k_help, KEY_HELP);
|
|
+ set_keymap_name(k_setup, KEY_CONFIG);
|
|
+ set_keymap_name(k_p1, KEY_PROG1);
|
|
+ set_keymap_name(k_p2, KEY_PROG2);
|
|
+ set_keymap_name(k_p3, KEY_PROG3);
|
|
+ set_keymap_name(k_www, KEY_WWW);
|
|
+ set_keymap_name(k_mail, KEY_MAIL);
|
|
+ set_keymap_name(k_wireless, KEY_XFER);
|
|
+ set_keymap_name(k_power, KEY_POWER);
|
|
+ set_keymap_name(k_mute, KEY_MUTE);
|
|
+ set_keymap_name(k_volup, KEY_VOLUMEUP);
|
|
+ set_keymap_name(k_voldn, KEY_VOLUMEDOWN);
|
|
+ set_keymap_name(k_res, KEY_CONFIG);
|
|
+ set_keymap_name(k_close, KEY_CLOSE);
|
|
+ set_keymap_name(k_open, KEY_OPEN);
|
|
+ /* I am not really happy with the selections for wireless and wireless2,
|
|
+ but coffee looks good. Michal Veselenyi proposed this value */
|
|
+ set_keymap_name(k_wireless2, KEY_COFFEE);
|
|
+ set_keymap_name(k_play, KEY_PLAYPAUSE);
|
|
+ set_keymap_name(k_stop, KEY_STOPCD);
|
|
+ set_keymap_name(k_prev, KEY_PREVIOUSSONG);
|
|
+ set_keymap_name(k_next, KEY_NEXTSONG);
|
|
+ set_keymap_name(k_display, KEY_MEDIA); /* also not happy with this */
|
|
+ if (verbose > 1)
|
|
+ print_mapping();
|
|
+}
|
|
+
|
|
+static int filter_idle_value(int keycode)
|
|
+{
|
|
+ int validkey = 0;
|
|
+ if (keycode != 0x0 &&
|
|
+ keycode != 0x9610 &&
|
|
+ keycode != 0xc100 && /* Francois Valenduc, Aspire 1601 LC */
|
|
+ keycode != 0x8610 &&
|
|
+ keycode != 0x861 &&
|
|
+ keycode != 0x8650 &&
|
|
+ keycode != 0x865)
|
|
+ validkey = keycode;
|
|
+ if (verbose > 4 && !validkey)
|
|
+ printk(KERN_INFO"acerhk: throw away idle value 0x%x\n", keycode);
|
|
+ return validkey;
|
|
+}
|
|
+
|
|
+static void send_key_event(t_key_names key)
|
|
+{
|
|
+ unsigned int input_key;
|
|
+ if (key != k_none) {
|
|
+ /* convert key name to kernel keycode */
|
|
+ input_key = acerhk_name2event[key];
|
|
+ if (verbose > 2)
|
|
+ printk(KERN_INFO"acerhk: translated acer key name 0x%x to input key 0x%x\n",
|
|
+ key, input_key);
|
|
+ /* send press and release together, as there is no such event from acer as 'release' */
|
|
+ input_report_key(acerhk_input_dev_ptr, input_key, 1);
|
|
+ input_report_key(acerhk_input_dev_ptr, input_key, 0);
|
|
+ }
|
|
+}
|
|
+
|
|
+static t_key_names transl8_key_code(int keycode)
|
|
+{
|
|
+ t_key_names keyname = k_none;
|
|
+ /* first filter out idle values */
|
|
+ if ( (keycode = filter_idle_value(keycode)) ) {
|
|
+ if (verbose > 3)
|
|
+ printk(KERN_INFO"acerhk: received key code 0x%x\n", keycode);
|
|
+ /* translate keycode to key name */
|
|
+ if (keycode >= 0 && keycode <= 255)
|
|
+ keyname = acerhk_key2name[keycode];
|
|
+ else {
|
|
+ if (verbose > 3)
|
|
+ printk(KERN_INFO"acerhk: keycode 0x%x too big, will use only 8 bits\n", keycode);
|
|
+ /* use only lower 8 bits of value to distinguish keys */
|
|
+ keyname = acerhk_key2name[keycode&0xff];
|
|
+ }
|
|
+ /* produce some log information for higher verbosity levels */
|
|
+ if (keyname != k_none && verbose > 2)
|
|
+ printk(KERN_INFO"acerhk: translated acer key code 0x%x to key name 0x%x\n",
|
|
+ keycode, keyname);
|
|
+ else if (keyname == k_none && verbose > 3)
|
|
+ printk(KERN_INFO"acerhk: translated acer key code 0x%x to no key\n",
|
|
+ keycode);
|
|
+ if (autowlan) {
|
|
+ /* if automatic switching of wlan hardware is enabled, do it here
|
|
+ on wireless key press */
|
|
+ if (keyname == k_wireless2) {
|
|
+ if (acerhk_bluetooth_state)
|
|
+ wbutton_fct_1(0);
|
|
+ else
|
|
+ wbutton_fct_1(1);
|
|
+ }
|
|
+ if (keyname == k_wireless) {
|
|
+ if (acerhk_wlan_state)
|
|
+ wbutton_fct_2(0);
|
|
+ else
|
|
+ wbutton_fct_2(1);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return keyname;
|
|
+}
|
|
+
|
|
+/* polling timer handler */
|
|
+static void acerhk_poll_event(unsigned long save_size)
|
|
+{
|
|
+#ifndef DUMMYHW
|
|
+ unsigned int max = MAX_POLLING_LOOPS;
|
|
+ /* make sure not to loop more then 32 times */
|
|
+ if (!max || max > 32)
|
|
+ max = 32;
|
|
+ if (acerhk_type != TM_dritek) {
|
|
+ while (get_nr_events() && max--) {
|
|
+ send_key_event(transl8_key_code(get_fnkey_event()));
|
|
+ }
|
|
+ } else {
|
|
+ send_key_event(transl8_key_code(get_fnkey_event()));
|
|
+ }
|
|
+#endif
|
|
+ acerhk_timer_poll.expires = jiffies + acerhk_polling_delay;
|
|
+ add_timer(&acerhk_timer_poll);
|
|
+}
|
|
+
|
|
+/* blinking timer handler; added by Antonio Cuni */
|
|
+static void acerhk_blink_event(unsigned long not_used)
|
|
+{
|
|
+ if (acerhk_blueled_blinking != -1) {
|
|
+ acerhk_blueled_blinking = !acerhk_blueled_blinking;
|
|
+#ifndef DUMMYHW
|
|
+ wbutton_fct_1(acerhk_blueled_blinking);
|
|
+#endif
|
|
+ acerhk_timer_blinking.expires = jiffies + acerhk_blueled_blinking_delay;
|
|
+ add_timer(&acerhk_timer_blinking);
|
|
+ }
|
|
+ else
|
|
+ printk(KERN_WARNING "acerhk: blinking event called, but blinking not active\n");
|
|
+}
|
|
+
|
|
+static void init_input(void)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+#ifndef KERNEL26
|
|
+ /* request keyboard input module */
|
|
+ request_module("keybdev");
|
|
+ if (verbose > 3)
|
|
+ printk(KERN_INFO"requested keyboard input driver\n");
|
|
+#endif
|
|
+
|
|
+#ifndef STATIC_INPUT_DEV
|
|
+ /* allocate acerhk input device */
|
|
+ acerhk_input_dev_ptr=input_allocate_device();
|
|
+ /* enter some name */
|
|
+ acerhk_input_dev_ptr->name = "Acer hotkey driver";
|
|
+#else
|
|
+ acerhk_input_dev_ptr=&acerhk_input_dev;
|
|
+#endif
|
|
+
|
|
+ /* some laptops have a mail led, should I announce it here? */
|
|
+ acerhk_input_dev_ptr->evbit[0] = BIT(EV_KEY);
|
|
+ /* announce keys to input system
|
|
+ * the generated keys can be changed on runtime,
|
|
+ * but to publish those changes the device needs to
|
|
+ * get reconnected (I dont't know any other way)
|
|
+ * Therefore I enable all possible keys */
|
|
+ for (i = KEY_RESERVED; i < BTN_MISC; i++)
|
|
+ set_bit(i, acerhk_input_dev_ptr->keybit);
|
|
+ /* set mapping keyname -> input event */
|
|
+ init_keymap_input();
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO"acerhk: registered input device\n");
|
|
+ input_register_device(acerhk_input_dev_ptr);
|
|
+ init_timer(&acerhk_timer_poll);
|
|
+ acerhk_polling_state = 0;
|
|
+}
|
|
+
|
|
+static void stop_polling(void)
|
|
+{
|
|
+ if (acerhk_polling_state == 1) {
|
|
+ del_timer(&acerhk_timer_poll);
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO"acerhk: key polling stopped\n");
|
|
+ acerhk_polling_state = 0;
|
|
+ } else
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO"acerhk: key polling not active\n");
|
|
+}
|
|
+
|
|
+static void start_polling(void)
|
|
+{
|
|
+ if (acerhk_polling_state != 1) {
|
|
+ acerhk_timer_poll.function = acerhk_poll_event;
|
|
+ acerhk_timer_poll.expires = jiffies + acerhk_polling_delay;
|
|
+ acerhk_timer_poll.data = get_nr_events();
|
|
+ add_timer(&acerhk_timer_poll);
|
|
+ acerhk_polling_state = 1;
|
|
+ if (acerhk_type == TM_dritek) {
|
|
+ printk(KERN_INFO"acerhk: Your hardware does not need polling enabled for hotkeys to work, "
|
|
+ "you can safely disable polling by using the module parameter poll=0 (unless you "
|
|
+ "want to play around with the driver and see if there are buttons which need polling).\n");
|
|
+ }
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO"acerhk: starting key polling, every %d ms\n", acerhk_polling_delay);
|
|
+ } else
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO"acerhk: key polling already active\n");
|
|
+}
|
|
+
|
|
+/* addedd by Antonio Cuni */
|
|
+static void start_blinking(void)
|
|
+{
|
|
+ if (acerhk_blueled_blinking == -1) {
|
|
+ // blinking was disabled... enable it!
|
|
+ acerhk_timer_blinking.function = acerhk_blink_event;
|
|
+ acerhk_timer_blinking.expires = jiffies + acerhk_blueled_blinking_delay;
|
|
+ acerhk_timer_blinking.data = 0; // not used
|
|
+ add_timer(&acerhk_timer_blinking);
|
|
+ acerhk_blueled_blinking = 0;
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: starting blueled blinking\n");
|
|
+ } else
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: blueled already blinking\n");
|
|
+}
|
|
+
|
|
+/* Added by Antonio Cuni */
|
|
+static void stop_blinking(void)
|
|
+{
|
|
+ if (acerhk_blueled_blinking != -1) {
|
|
+ del_timer(&acerhk_timer_blinking);
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO "acerhk: blueled blinking stopped\n");
|
|
+ acerhk_blueled_blinking = -1;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void release_input(void)
|
|
+{
|
|
+ stop_polling();
|
|
+ input_unregister_device(acerhk_input_dev_ptr);
|
|
+}
|
|
+
|
|
+/* }}} */
|
|
+
|
|
+/* {{{ procfs functions */
|
|
+
|
|
+#ifndef CONFIG_PROC_FS
|
|
+
|
|
+static int acerhk_proc_init(void)
|
|
+{
|
|
+ return 1;
|
|
+}
|
|
+#else
|
|
+
|
|
+/* This macro frees the machine specific function from bounds checking and
|
|
+ * things like that... */
|
|
+#define PRINT_PROC(fmt,args...) \
|
|
+ do { \
|
|
+ *len += sprintf( buffer+*len, fmt, ##args ); \
|
|
+ if (*begin + *len > offset + size) \
|
|
+ return( 0 ); \
|
|
+ if (*begin + *len < offset) { \
|
|
+ *begin += *len; \
|
|
+ *len = 0; \
|
|
+ } \
|
|
+ } while(0)
|
|
+
|
|
+static int pc_proc_infos( char *buffer, int *len,
|
|
+ off_t *begin, off_t offset, int size )
|
|
+{
|
|
+ PRINT_PROC( "Acer hotkeys version %s\n", ACERHK_VERSION);
|
|
+ PRINT_PROC( "Model(Type)\t: %s(", acerhk_model_string);
|
|
+ switch(acerhk_type) {
|
|
+ default:
|
|
+ PRINT_PROC( "unknown)\n");
|
|
+ break;
|
|
+ case TM_old:
|
|
+ PRINT_PROC( "old)\n");
|
|
+ break;
|
|
+ case TM_new:
|
|
+ PRINT_PROC( "new)\n");
|
|
+ break;
|
|
+ case TM_dritek:
|
|
+ PRINT_PROC( "Dritek)\n");
|
|
+ break;
|
|
+ }
|
|
+ if (bios_routine != 0) {
|
|
+ PRINT_PROC( "request handler\t: 0x%x\n", bios_routine);
|
|
+ if (cmos_index) {
|
|
+ PRINT_PROC( "CMOS index\t: 0x%x\n", cmos_index);
|
|
+ PRINT_PROC( "events pending\t: %u\n", get_nr_events());
|
|
+ } else {
|
|
+ PRINT_PROC( "CMOS index\t: not available\n");
|
|
+ }
|
|
+ if (acerhk_polling_state == 1)
|
|
+ PRINT_PROC( "kernel polling\t: active\n");
|
|
+ else
|
|
+ PRINT_PROC( "kernel polling\t: inactive\n");
|
|
+ PRINT_PROC( "autoswitch wlan\t: ");
|
|
+ if (autowlan == 1)
|
|
+ PRINT_PROC( "enabled\n");
|
|
+ else
|
|
+ PRINT_PROC( "disabled\n");
|
|
+ } else {
|
|
+ PRINT_PROC( "request handler\t: not found\n");
|
|
+ PRINT_PROC( "kernel polling\t: not possible\n");
|
|
+ }
|
|
+ /* model specific infos */
|
|
+ if (acerhk_type == TM_dritek) {
|
|
+ PRINT_PROC( "use of Dritek EC: ");
|
|
+ if (usedritek)
|
|
+ PRINT_PROC( "enabled\n");
|
|
+ else
|
|
+ PRINT_PROC( "disabled\n");
|
|
+ }
|
|
+ if (acerhk_type == TM_old)
|
|
+ PRINT_PROC( "preg400\t\t: 0x%p\n", preg400);
|
|
+ return (1);
|
|
+}
|
|
+
|
|
+static int acerhk_proc_info( char *buffer, char **start, off_t offset,
|
|
+ int size, int *eof, void *data )
|
|
+{
|
|
+ int len = 0;
|
|
+ off_t begin = 0;
|
|
+
|
|
+ *eof = pc_proc_infos( buffer, &len, &begin, offset, size );
|
|
+
|
|
+ if (offset >= begin + len)
|
|
+ return( 0 );
|
|
+ *start = buffer + (offset - begin);
|
|
+ return( size < begin + len - offset ? size : begin + len - offset );
|
|
+
|
|
+}
|
|
+
|
|
+static int acerhk_proc_key( char *buffer, char **start, off_t offset,
|
|
+ int size, int *eof, void *data )
|
|
+{
|
|
+ if (size >= 5 && offset == 0) {
|
|
+ if (acerhk_type == TM_dritek || acerhk_polling_state == 1) {
|
|
+ snprintf(buffer+offset, size, "n/a\n");
|
|
+ } else {
|
|
+ snprintf(buffer+offset, size, "0x%02x\n", filter_idle_value(get_fnkey_event()));
|
|
+ }
|
|
+ *eof = 1;
|
|
+ return 5;
|
|
+ }
|
|
+ *eof = 1;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int acerhk_proc_led(struct file* file, const char* buffer,
|
|
+ unsigned long count, void* data)
|
|
+{
|
|
+ char str[4];
|
|
+ int len;
|
|
+ if (count > 4)
|
|
+ len = 4;
|
|
+ else
|
|
+ len = count;
|
|
+ if (copy_from_user(str, buffer, len))
|
|
+ return -EFAULT;
|
|
+ str[3] = '\0';
|
|
+ if ( ( (len >= 2) && (!strncmp(str, "on", 2) || !strncmp(str, "an", 2)) )
|
|
+ || str[0] == '1')
|
|
+ set_mail_led(1);
|
|
+ else
|
|
+ set_mail_led(0);
|
|
+ return len;
|
|
+}
|
|
+
|
|
+static int acerhk_proc_wirelessled(struct file* file, const char* buffer,
|
|
+ unsigned long count, void* data)
|
|
+{
|
|
+ char str[4];
|
|
+ int len;
|
|
+ if (count > 4)
|
|
+ len = 4;
|
|
+ else
|
|
+ len = count;
|
|
+ if (copy_from_user(str, buffer, len))
|
|
+ return -EFAULT;
|
|
+ str[3] = '\0';
|
|
+ if ( ( (len >= 2) && (!strncmp(str, "on", 2) || !strncmp(str, "an", 2)) )
|
|
+ || str[0] == '1') {
|
|
+ if (acerhk_model_features & TM_F_WLAN_EC1)
|
|
+ enable_wlan_ec_1();
|
|
+ else if (acerhk_model_features & TM_F_WLAN_EC2)
|
|
+ enable_wlan_ec_2();
|
|
+ else
|
|
+ wbutton_fct_2(1);
|
|
+ }
|
|
+ else {
|
|
+ if (acerhk_model_features & TM_F_WLAN_EC1)
|
|
+ disable_wlan_ec_1();
|
|
+ else if (acerhk_model_features & TM_F_WLAN_EC2)
|
|
+ disable_wlan_ec_2();
|
|
+ else
|
|
+ wbutton_fct_2(0);
|
|
+ }
|
|
+ return len;
|
|
+}
|
|
+
|
|
+
|
|
+/* Modified by Antonio Cuni: added support for blinking
|
|
+ possible values:
|
|
+ - off, 0: led always off
|
|
+ - on, an, 1: led alway on
|
|
+ - n (a number): led blinking; n is the delay between
|
|
+ two changes of state, in jiffies; n must
|
|
+ be > 50, to prevent the user from overloading
|
|
+ the kernel.
|
|
+
|
|
+ */
|
|
+static int acerhk_proc_blueled(struct file* file, const char* buffer,
|
|
+ unsigned long count, void* data)
|
|
+{
|
|
+ const int MAXLEN=11;
|
|
+ char str[MAXLEN];
|
|
+ int len;
|
|
+ int isNumber;
|
|
+
|
|
+ if (count > MAXLEN)
|
|
+ len = MAXLEN;
|
|
+ else
|
|
+ len = count;
|
|
+ if (copy_from_user(str, buffer, len))
|
|
+ return -EFAULT;
|
|
+ str[MAXLEN - 1] = '\0';
|
|
+
|
|
+ /* try to parse a number */
|
|
+ isNumber = sscanf(str, "%u", &acerhk_blueled_blinking_delay);
|
|
+ /* if the delay is 0, turn off the led */
|
|
+ if (isNumber && acerhk_blueled_blinking_delay != 0 && acerhk_blueled_blinking_delay != 1) {
|
|
+ if (acerhk_blueled_blinking_delay < 50)
|
|
+ printk(KERN_INFO"acerhk: blinking request rejected. The delay must be > 50.\n");
|
|
+ else {
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO"acerhk: blinking delay set to %u.\n", acerhk_blueled_blinking_delay);
|
|
+ start_blinking();
|
|
+ }
|
|
+ } else if (acerhk_blueled_blinking_delay == 1 || !strncmp(str, "on", 2) || !strncmp(str, "an", 2)) {
|
|
+ stop_blinking();
|
|
+ if (acerhk_model_features & TM_F_BLUE_EC1)
|
|
+ enable_bluetooth_ec_1();
|
|
+ else if (acerhk_model_features & TM_F_BLUE_EC2)
|
|
+ enable_bluetooth_ec_2();
|
|
+ else
|
|
+ wbutton_fct_1(1);
|
|
+ } else {
|
|
+ /* it's 0 or everything else */
|
|
+ stop_blinking();
|
|
+ if (acerhk_model_features & TM_F_BLUE_EC1)
|
|
+ disable_bluetooth_ec_1();
|
|
+ else if (acerhk_model_features & TM_F_BLUE_EC2)
|
|
+ disable_bluetooth_ec_2();
|
|
+ else
|
|
+ wbutton_fct_1(0);
|
|
+ }
|
|
+ return len;
|
|
+}
|
|
+
|
|
+#ifdef ACERDEBUG
|
|
+static void do_debug(const char* buffer, unsigned long len)
|
|
+{
|
|
+ unsigned int h, i;
|
|
+ switch (buffer[0]) {
|
|
+ case 'b':
|
|
+ /* test WLAN on TM 4001 */
|
|
+ switch (buffer[1]) {
|
|
+ case '0':
|
|
+ disable_wlan_ec_1();
|
|
+ break;
|
|
+ case '1':
|
|
+ default:
|
|
+ enable_wlan_ec_1();
|
|
+ }
|
|
+ break;
|
|
+ case 'B':
|
|
+ /* test BLUETOOTH on TM 4001 */
|
|
+ switch (buffer[1]) {
|
|
+ case '0':
|
|
+ disable_bluetooth_ec_1();
|
|
+ break;
|
|
+ case '1':
|
|
+ default:
|
|
+ enable_bluetooth_ec_1();
|
|
+ }
|
|
+ break;
|
|
+ case 'D':
|
|
+ /* test "DMM Function Enabled" entry of TM 4150/4650 */
|
|
+ enable_dmm_function();
|
|
+ break;
|
|
+ case 'i':
|
|
+ case '1':
|
|
+#ifndef KERNEL26
|
|
+ MOD_INC_USE_COUNT;
|
|
+#endif
|
|
+ break;
|
|
+ case 'e':
|
|
+ switch (buffer[1]) {
|
|
+ case '1':
|
|
+ start_polling();
|
|
+ break;
|
|
+ default:
|
|
+ stop_polling();
|
|
+ }
|
|
+ break;
|
|
+ case 'k':
|
|
+ for (i = 0; i <= 255;i++) {
|
|
+ input_report_key(acerhk_input_dev_ptr, i, 1);
|
|
+ input_report_key(acerhk_input_dev_ptr, i, 0);
|
|
+ }
|
|
+ break;
|
|
+ case 'm':
|
|
+ /* set mapping key names -> input events */
|
|
+ sscanf(&buffer[2],"%x", &i);
|
|
+ h = buffer[1] - '0' + 1;
|
|
+ printk("acerhk: key name %x maps to %x\n", h, i);
|
|
+ acerhk_name2event[h] = i;
|
|
+ break;
|
|
+ case 'M':
|
|
+ /* test mute LED on dritek hardware */
|
|
+ switch (buffer[1]) {
|
|
+ case '0':
|
|
+ disable_mute_led_ec();
|
|
+ break;
|
|
+ case '1':
|
|
+ default:
|
|
+ enable_mute_led_ec();
|
|
+ }
|
|
+ break;
|
|
+ case 'p':
|
|
+ printk("acerhk: pbutton = 0x%x\n", pbutton_fct());
|
|
+ break;
|
|
+ case 's':
|
|
+ /* send key event to test the key translation in input system */
|
|
+ sscanf(&buffer[1],"%x", &h);
|
|
+ printk("acerhk: sending key event 0x%x\n", h);
|
|
+ input_report_key(acerhk_input_dev_ptr, h, 1);
|
|
+ input_report_key(acerhk_input_dev_ptr, h, 0);
|
|
+ break;
|
|
+ case 'S':
|
|
+ /* simulate key codes to test the key translation in acerhk */
|
|
+ sscanf(&buffer[1],"%x", &h);
|
|
+ send_key_event(transl8_key_code(h));
|
|
+ break;
|
|
+ case 't':
|
|
+ printk("acerhk: thermal event = 0x%x\n", get_thermal_event());
|
|
+ break;
|
|
+ case 'w':
|
|
+ /* test the wbutton functions, someone really needs to have another look
|
|
+ at the windows driver */
|
|
+ switch (buffer[1]) {
|
|
+ case '2':
|
|
+ printk("acerhk: wbutton_2(%d) = 0x%x\n", buffer[2]-'0', wbutton_fct_2(buffer[2]-'0'));
|
|
+ break;
|
|
+ case '1':
|
|
+ default:
|
|
+ printk("acerhk: wbutton_1(%d) = 0x%x\n", buffer[2]-'0', wbutton_fct_1(buffer[2]-'0'));
|
|
+ }
|
|
+ break;
|
|
+ case 'W':
|
|
+ /* test wireless HW/LED on some models using dritek hardware */
|
|
+ switch (buffer[1]) {
|
|
+ case '0':
|
|
+ disable_wireless_ec();
|
|
+ break;
|
|
+ case '1':
|
|
+ default:
|
|
+ enable_wireless_ec();
|
|
+ }
|
|
+ break;
|
|
+ case 'v':
|
|
+ verbose = buffer[1]-'0';
|
|
+ printk("acerhk: verbosity level changed to %d\n", verbose);
|
|
+ break;
|
|
+ case 'd':
|
|
+ case '0':
|
|
+ default:
|
|
+#ifndef KERNEL26
|
|
+ MOD_DEC_USE_COUNT;
|
|
+#endif
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+static int acerhk_proc_debug(struct file* file, const char* buffer,
|
|
+ unsigned long count, void* data)
|
|
+{
|
|
+ char str[5];
|
|
+ int len;
|
|
+ if (count > 5)
|
|
+ len = 5;
|
|
+ else
|
|
+ len = count;
|
|
+ if (copy_from_user(str, buffer, len))
|
|
+ return -EFAULT;
|
|
+ str[4] = '\0';
|
|
+ do_debug(str, len);
|
|
+ return len;
|
|
+}
|
|
+#endif
|
|
+
|
|
+static int acerhk_proc_init(void)
|
|
+{
|
|
+ int retval;
|
|
+ struct proc_dir_entry *entry;
|
|
+ /* create own directory */
|
|
+ proc_acer_dir = proc_mkdir("driver/acerhk", NULL);
|
|
+ if (proc_acer_dir == NULL) {
|
|
+ retval = 0;
|
|
+ printk(KERN_INFO"acerhk: could not create /proc/driver/acerhk\n");
|
|
+ }
|
|
+ else {
|
|
+ proc_acer_dir->owner = THIS_MODULE;
|
|
+ /* now create several files, first general info ... */
|
|
+ entry = create_proc_read_entry("info",
|
|
+ 0444, proc_acer_dir, acerhk_proc_info, NULL);
|
|
+ if (entry == NULL) {
|
|
+ printk(KERN_INFO"acerhk: cannot create info file\n");
|
|
+ remove_proc_entry("driver/acerhk", NULL);
|
|
+ retval = 0;
|
|
+ } else {
|
|
+ entry->owner = THIS_MODULE;
|
|
+ /* ... last pressed key ... */
|
|
+ entry = create_proc_read_entry("key",
|
|
+ 0444, proc_acer_dir, acerhk_proc_key, NULL);
|
|
+ if (entry == NULL) {
|
|
+ printk(KERN_INFO"acerhk: cannot create key file\n");
|
|
+ remove_proc_entry("info", proc_acer_dir);
|
|
+ remove_proc_entry("driver/acerhk", NULL);
|
|
+ retval = 0;
|
|
+ } else {
|
|
+ entry->owner = THIS_MODULE;
|
|
+ /* ... and led control file */
|
|
+ entry = create_proc_entry("led", 0222, proc_acer_dir);
|
|
+ if (entry == NULL) {
|
|
+ printk(KERN_INFO"acerhk: cannot create LED file\n");
|
|
+ remove_proc_entry("info", proc_acer_dir);
|
|
+ remove_proc_entry("key", proc_acer_dir);
|
|
+ remove_proc_entry("driver/acerhk", NULL);
|
|
+ retval = 0;
|
|
+ }
|
|
+ else {
|
|
+ entry->write_proc = acerhk_proc_led;
|
|
+ entry->owner = THIS_MODULE;
|
|
+ /* ... and wireless led controll file */
|
|
+ entry = create_proc_entry("wirelessled", 0222, proc_acer_dir);
|
|
+ if (entry == NULL) {
|
|
+ printk(KERN_INFO"acerhk: cannot create wirelessled file\n");
|
|
+ remove_proc_entry("info", proc_acer_dir);
|
|
+ remove_proc_entry("key", proc_acer_dir);
|
|
+ remove_proc_entry("led", proc_acer_dir);
|
|
+ remove_proc_entry("driver/acerhk", NULL);
|
|
+ retval = 0;
|
|
+ }
|
|
+ else {
|
|
+ entry->write_proc = acerhk_proc_wirelessled;
|
|
+ entry->owner = THIS_MODULE;
|
|
+ /* ... and bluetooth led controll file */
|
|
+ entry = create_proc_entry("blueled", 0222, proc_acer_dir);
|
|
+ if (entry == NULL) {
|
|
+ printk(KERN_INFO"acerhk: cannot create blueled file\n");
|
|
+ remove_proc_entry("info", proc_acer_dir);
|
|
+ remove_proc_entry("key", proc_acer_dir);
|
|
+ remove_proc_entry("led", proc_acer_dir);
|
|
+ remove_proc_entry("wirelessled", proc_acer_dir);
|
|
+ remove_proc_entry("driver/acerhk", NULL);
|
|
+ retval = 0;
|
|
+ } else {
|
|
+ entry->write_proc = acerhk_proc_blueled;
|
|
+ entry->owner = THIS_MODULE;
|
|
+ retval = 1;
|
|
+#ifdef ACERDEBUG
|
|
+ /* add extra file for debugging purposes */
|
|
+ entry = create_proc_entry("debug", 0222, proc_acer_dir);
|
|
+ if (entry == NULL) {
|
|
+ printk(KERN_INFO"acerhk: cannot create debug file\n");
|
|
+ remove_proc_entry("info", proc_acer_dir);
|
|
+ remove_proc_entry("key", proc_acer_dir);
|
|
+ remove_proc_entry("led", proc_acer_dir);
|
|
+ remove_proc_entry("wirelessled", proc_acer_dir);
|
|
+ remove_proc_entry("blueled", proc_acer_dir);
|
|
+ remove_proc_entry("driver/acerhk", NULL);
|
|
+ retval = 0;
|
|
+ }
|
|
+ else {
|
|
+ entry->write_proc = acerhk_proc_debug;
|
|
+ entry->owner = THIS_MODULE;
|
|
+ retval = 1;
|
|
+ }
|
|
+#endif
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return retval;
|
|
+}
|
|
+
|
|
+static void acerhk_proc_cleanup(void)
|
|
+{
|
|
+ if (proc_acer_dir) {
|
|
+ remove_proc_entry("info", proc_acer_dir);
|
|
+ /* On dritek type hardware key file is already removed */
|
|
+ if (acerhk_type != TM_dritek)
|
|
+ remove_proc_entry("key", proc_acer_dir);
|
|
+ remove_proc_entry("led", proc_acer_dir);
|
|
+ remove_proc_entry("wirelessled", proc_acer_dir);
|
|
+ remove_proc_entry("blueled", proc_acer_dir);
|
|
+#ifdef ACERDEBUG
|
|
+ remove_proc_entry("debug", proc_acer_dir);
|
|
+#endif
|
|
+ remove_proc_entry("driver/acerhk", NULL);
|
|
+ proc_acer_dir = NULL;
|
|
+ }
|
|
+}
|
|
+
|
|
+#endif /* CONFIG_PROC_FS */
|
|
+
|
|
+/* }}} */
|
|
+
|
|
+/* {{{ file operations */
|
|
+
|
|
+static int acerhk_ioctl( struct inode *inode, struct file *file,
|
|
+ unsigned int cmd, unsigned long arg )
|
|
+{
|
|
+ int retval;
|
|
+ switch( cmd ) {
|
|
+ case ACERHK_GET_KEYCOUNT:
|
|
+ {
|
|
+ char nr;
|
|
+ nr = get_nr_events();
|
|
+ put_user(nr, (char*)arg);
|
|
+ retval = 0;
|
|
+ break;
|
|
+ }
|
|
+ case ACERHK_GET_KEYID:
|
|
+ {
|
|
+ char id;
|
|
+ id = get_fnkey_event();
|
|
+ put_user(id, (char*)arg);
|
|
+ retval = 0;
|
|
+ break;
|
|
+ }
|
|
+ case ACERHK_CONNECT:
|
|
+ launch_connect(1);
|
|
+ retval = 0;
|
|
+ break;
|
|
+ case ACERHK_START_POLLING:
|
|
+ start_polling();
|
|
+ retval = 0;
|
|
+ break;
|
|
+ case ACERHK_STOP_POLLING:
|
|
+ stop_polling();
|
|
+ retval = 0;
|
|
+ break;
|
|
+ case ACERHK_DISCONNECT:
|
|
+ launch_connect(0);
|
|
+ retval = 0;
|
|
+ break;
|
|
+ case ACERHK_GET_THERMAL_EVENT:
|
|
+ {
|
|
+ short event;
|
|
+ event = get_thermal_event();
|
|
+ put_user(event, (short*)arg);
|
|
+ retval = 0;
|
|
+ break;
|
|
+ }
|
|
+ case ACERHK_MAIL_LED_OFF:
|
|
+ set_mail_led(0);
|
|
+ retval = 0;
|
|
+ break;
|
|
+ case ACERHK_MAIL_LED_ON:
|
|
+ set_mail_led(1);
|
|
+ retval = 0;
|
|
+ break;
|
|
+ case ACERHK_GET_KEY_MAP:
|
|
+ if (copy_to_user((t_map_name2event*)arg, &acerhk_name2event, sizeof(acerhk_name2event)))
|
|
+ retval = -EFAULT;
|
|
+ else
|
|
+ retval = 0;
|
|
+ break;
|
|
+ case ACERHK_SET_KEY_MAP:
|
|
+ if (copy_from_user(&acerhk_name2event, (t_map_name2event*)arg, sizeof(acerhk_name2event)))
|
|
+ retval = -EFAULT;
|
|
+ else {
|
|
+ if (verbose) {
|
|
+ printk(KERN_INFO"acerhk: changed key mapping\n");
|
|
+ print_mapping();
|
|
+ }
|
|
+ retval = 0;
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ retval = -EINVAL;
|
|
+ }
|
|
+ return retval;
|
|
+}
|
|
+
|
|
+#ifdef ACERDEBUG
|
|
+static ssize_t acerhk_write (struct file* file, const char* buffer, size_t length, loff_t* offset)
|
|
+{
|
|
+ if (length)
|
|
+ do_debug(buffer, length);
|
|
+ return length;
|
|
+}
|
|
+#endif
|
|
+
|
|
+static int acerhk_open( struct inode *inode, struct file *file )
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int acerhk_release( struct inode *inode, struct file *file )
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static struct file_operations acerhk_fops = {
|
|
+ owner: THIS_MODULE,
|
|
+ ioctl: acerhk_ioctl,
|
|
+ open: acerhk_open,
|
|
+#ifdef ACERDEBUG
|
|
+ write: acerhk_write,
|
|
+#endif
|
|
+ release: acerhk_release,
|
|
+};
|
|
+
|
|
+static struct miscdevice acerhk_dev = {
|
|
+ MISC_DYNAMIC_MINOR,
|
|
+ "acerhk",
|
|
+ &acerhk_fops
|
|
+};
|
|
+
|
|
+/* }}} */
|
|
+
|
|
+static void __init model_init(void)
|
|
+{
|
|
+ /* set callroutine, features and keymap for model */
|
|
+ setup_model_features(acerhk_series);
|
|
+ /* override initial state of wireless hardware if specified by module options */
|
|
+ if (wlan_state >= 0) acerhk_wlan_state = wlan_state;
|
|
+ if (bluetooth_state >= 0) acerhk_bluetooth_state = bluetooth_state;
|
|
+ /* Launch connect only if available */
|
|
+ if (acerhk_model_features & TM_F_CONNECT) {
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO"acerhk: Model type %d, calling launch_connect(1)\n",
|
|
+ acerhk_type);
|
|
+ launch_connect(1);
|
|
+ }
|
|
+ if ( acerhk_type != TM_dritek ) {
|
|
+ get_cmos_index();
|
|
+ }
|
|
+ if ( acerhk_type == TM_dritek ) {
|
|
+ enable_dritek_keyboard();
|
|
+ }
|
|
+ /* added by Antonio Cuni */
|
|
+ init_timer(&acerhk_timer_blinking);
|
|
+}
|
|
+
|
|
+
|
|
+static void __exit acerhk_cleanup_module (void);
|
|
+static int __init acerhk_init(void)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ ret = misc_register( &acerhk_dev );
|
|
+ if (ret) {
|
|
+ printk(KERN_ERR "acerhk: can't misc_register on minor=%d\n", ACERHK_MINOR);
|
|
+ ret = -EAGAIN;
|
|
+ }
|
|
+ else if (!acerhk_proc_init()) {
|
|
+ printk(KERN_ERR "acerhk: can't create procfs entries\n");
|
|
+ ret = -ENOMEM;
|
|
+ misc_deregister( &acerhk_dev );
|
|
+ }
|
|
+ else {
|
|
+ reg1 = ioremap(0xf0000, 0xffff);
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: area from 0xf000 to 0xffff mapped to %p\n", reg1);
|
|
+ reg2 = ioremap(0xe0000, 0xffff);
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: area from 0xe000 to 0xffff mapped to %p\n", reg2);
|
|
+ /* the area 0x400 is used as data area by earlier (520) series */
|
|
+ preg400 = ioremap(0x400, 0xfff);
|
|
+ if (verbose > 1)
|
|
+ printk(KERN_INFO"acerhk: area from 0x400 to 0x13ff mapped to %p\n", preg400);
|
|
+ /* attach to input system */
|
|
+ init_input();
|
|
+ memset(acerhk_model_string, 0x00, ACERHK_MODEL_STRLEN);
|
|
+#ifdef DUMMYHW
|
|
+ acerhk_model_addr = (void*)0x12345678;
|
|
+ /* copy the string, but not more than 15 characters */
|
|
+ strncpy(acerhk_model_string, "TravelmateDummy", ACERHK_MODEL_STRLEN-1);
|
|
+ /* set callroutine for model */
|
|
+ if (force_series)
|
|
+ acerhk_series = force_series;
|
|
+ else
|
|
+ acerhk_series = 2000;
|
|
+ setup_model_features(acerhk_series);
|
|
+ printk(KERN_INFO "Acer Travelmate hotkey driver v" ACERHK_VERSION " dummy\n");
|
|
+ if ( acerhk_type == TM_dritek )
|
|
+ enable_dritek_keyboard();
|
|
+ if (poll)
|
|
+ start_polling();
|
|
+ init_timer(&acerhk_timer_blinking);
|
|
+#else
|
|
+ bios_routine = find_hk_area();
|
|
+ if (!force_series)
|
|
+ probe_model();
|
|
+ else {
|
|
+ if (verbose)
|
|
+ printk(KERN_INFO"acerhk: forced laptop series to %d\n", force_series);
|
|
+ acerhk_series = force_series;
|
|
+ }
|
|
+ /* do model specific initialization */
|
|
+ model_init();
|
|
+ /* Without a bios routine we cannot do anything except on dritek
|
|
+ type HW, unload on other types */
|
|
+ if (bios_routine || (acerhk_type == TM_dritek)) {
|
|
+ ret = 0;
|
|
+ if (verbose && bios_routine)
|
|
+ printk(KERN_INFO"acerhk: bios routine found at 0x%x\n", bios_routine);
|
|
+ printk(KERN_INFO "Acer Travelmate hotkey driver v" ACERHK_VERSION "\n");
|
|
+ /* If automatic switching of wlan is wanted but polling is disabled,
|
|
+ automatically enable it */
|
|
+ if (!poll && autowlan) {
|
|
+ printk(KERN_INFO "Automatic switching of wireless hardware needs polling, enabling it\n");
|
|
+ poll = 1;
|
|
+ }
|
|
+ /* start automatic polling of key presses if wanted and bios routine found */
|
|
+ if (poll && bios_routine)
|
|
+ start_polling();
|
|
+ } else {
|
|
+ printk(KERN_ERR "acerhk: can't find bios routine, cannot do anything for you, sorry!\n");
|
|
+ ret = -ENOMEM;
|
|
+ acerhk_cleanup_module();
|
|
+ }
|
|
+#endif
|
|
+ }
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static void __exit acerhk_cleanup_module (void)
|
|
+{
|
|
+ acerhk_proc_cleanup();
|
|
+ stop_blinking();
|
|
+ if (reg1)
|
|
+ iounmap(reg1);
|
|
+ if (reg2)
|
|
+ iounmap(reg2);
|
|
+ if (preg400)
|
|
+ iounmap(preg400);
|
|
+ release_input();
|
|
+ misc_deregister( &acerhk_dev );
|
|
+ if ( acerhk_type == TM_dritek ) {
|
|
+ disable_dritek_keyboard();
|
|
+ }
|
|
+ if (verbose > 2)
|
|
+ printk(KERN_INFO "acerhk: unloaded\n");
|
|
+}
|
|
+
|
|
+module_init(acerhk_init);
|
|
+module_exit(acerhk_cleanup_module);
|
|
+
|
|
+MODULE_AUTHOR("Olaf Tauber");
|
|
+MODULE_DESCRIPTION("AcerHotkeys extra buttons keyboard driver");
|
|
+MODULE_LICENSE("GPL");
|
|
+
|
|
+#ifndef KERNEL26
|
|
+EXPORT_NO_SYMBOLS;
|
|
+#endif
|
|
+
|
|
+#else
|
|
+#error This driver is only available for X86 architecture
|
|
+#endif
|
|
+/*
|
|
+ * Local variables:
|
|
+ * c-indent-level: 4
|
|
+ * tab-width: 4
|
|
+ * End:
|
|
+ */
|
|
+
|
|
diff -Nurp linux-2.6.37/3rdparty/acerhk/acerhk.h linux-2.6.37.3rdparty/3rdparty/acerhk/acerhk.h
|
|
--- linux-2.6.37/3rdparty/acerhk/acerhk.h 1970-01-01 02:00:00.000000000 +0200
|
|
+++ linux-2.6.37.3rdparty/3rdparty/acerhk/acerhk.h 2005-06-17 00:10:12.000000000 +0300
|
|
@@ -0,0 +1,91 @@
|
|
+#ifndef __ACERHK_H__
|
|
+#define __ACERHK_H__
|
|
+
|
|
+#include <linux/ioctl.h>
|
|
+
|
|
+#define ACERHK_MINOR MISC_DYNAMIC_MINOR
|
|
+
|
|
+#define ACERHK_GET_KEYCOUNT _IOR('p', 0x01, char) /* Get number of cached key presses */
|
|
+#define ACERHK_GET_KEYID _IOR('p', 0x02, char) /* Get first key in queue */
|
|
+#define ACERHK_CONNECT _IO('p', 0x03) /* ? */
|
|
+#define ACERHK_DISCONNECT _IO('p', 0x04) /* ? */
|
|
+#define ACERHK_GET_THERMAL_EVENT _IOR('p', 0x05, short) /* ? */
|
|
+#define ACERHK_MAIL_LED_OFF _IO('p', 0x10) /* switch mail LED off */
|
|
+#define ACERHK_MAIL_LED_ON _IO('p', 0x11) /* switch mail LED on (blinking) */
|
|
+#define ACERHK_START_POLLING _IO('p', 0x12) /* poll keys in kernel, send real key events */
|
|
+#define ACERHK_STOP_POLLING _IO('p', 0x13) /* stop key polling in kernel */
|
|
+#define ACERHK_GET_KEY_MAP _IOR('p', 0x20, int) /* Get mapping of key names to key events, */
|
|
+#define ACERHK_SET_KEY_MAP _IOW('p', 0x21, int) /* Set mapping of key names to key events */
|
|
+
|
|
+/* all possible keys (known to me) */
|
|
+typedef enum e_key_names {
|
|
+ k_none = 0,
|
|
+ k_help = 1, /* Fn+F1 */
|
|
+ k_setup = 2, /* Fn+F2 */
|
|
+ k_p1 = 3,
|
|
+ k_p2 = 4,
|
|
+ k_p3 = 5,
|
|
+ k_www = 6,
|
|
+ k_mail = 7,
|
|
+ k_wireless = 8,
|
|
+ k_power = 9, /* Fn+F3 */
|
|
+ k_mute = 10, /* Fn+F8 */
|
|
+ k_volup = 11, /* Fn+Up */
|
|
+ k_voldn = 12, /* Fn+Down */
|
|
+ k_res = 13, /* resolution change on Medion MD 40100 */
|
|
+ k_close = 14, /* if lid is closed in tablet mode */
|
|
+ k_open = 15, /* if lid is opend in tablet mode */
|
|
+ k_wireless2 = 16, /* second wireless button on TM 243LC */
|
|
+ k_play = 17, /* Play/Pause found on AOpen */
|
|
+ k_stop = 18, /* Stop/Eject found on AOpen */
|
|
+ k_prev = 19, /* Prev found on AOpen */
|
|
+ k_next = 20, /* Next found on AOpen */
|
|
+ k_display = 21 /* Change internal/external display on MD 42200 */
|
|
+} t_key_names;
|
|
+#define NR_KEY_NAMES 22
|
|
+typedef unsigned int t_map_name2event[NR_KEY_NAMES];
|
|
+
|
|
+#ifdef __KERNEL__
|
|
+
|
|
+/* available features */
|
|
+#define TM_F_WLAN_EC1 0x00000010
|
|
+#define TM_F_BLUE_EC1 0x00000020
|
|
+#define TM_F_WLAN_EC2 0x00000040
|
|
+#define TM_F_BLUE_EC2 0x00000080
|
|
+#define TM_F_MUTE_LED_EC 0x00001000
|
|
+#define TM_F_MAIL_LED 0x00010000
|
|
+#define TM_F_MAIL_LED_EC 0x00020000
|
|
+#define TM_F_MAIL_LED_EC2 0x00040000
|
|
+#define TM_F_MAIL_LED_EC3 0x00080000
|
|
+
|
|
+#define TM_F_CONNECT 0x00100000
|
|
+#define TM_F_THERMAL 0x00200000
|
|
+#define TM_F_PBUTTON 0x00400000
|
|
+#define TM_F_WBUTTON 0x00800000
|
|
+
|
|
+typedef enum acer_type {
|
|
+ TM_unknown,
|
|
+ /* 200, 210, 520, 600 and 730 series, Medion MD42200 */
|
|
+ TM_old,
|
|
+ /* C100, C110, 220, 230, 240, 260, 350, 360, 610, 620, 630, 740 series
|
|
+ Medion MD40100, Aspire 1600, FS Amilo */
|
|
+ TM_new,
|
|
+ /* Aspire 13xx, 14xx, 1700, TM 290, 650, 660, 800 */
|
|
+ TM_dritek
|
|
+} t_acer_type;
|
|
+
|
|
+struct register_buffer {
|
|
+ unsigned int eax;
|
|
+ unsigned int ebx;
|
|
+ unsigned int ecx;
|
|
+ unsigned int edx;
|
|
+ unsigned int edi;
|
|
+ unsigned int esi;
|
|
+ unsigned int ebp;
|
|
+};
|
|
+
|
|
+typedef asmlinkage void (*bios_call) (struct register_buffer *);
|
|
+
|
|
+#endif
|
|
+
|
|
+#endif
|
|
diff -Nurp linux-2.6.37/3rdparty/acerhk/AUTHORS linux-2.6.37.3rdparty/3rdparty/acerhk/AUTHORS
|
|
--- linux-2.6.37/3rdparty/acerhk/AUTHORS 1970-01-01 02:00:00.000000000 +0200
|
|
+++ linux-2.6.37.3rdparty/3rdparty/acerhk/AUTHORS 2006-11-10 00:02:55.000000000 +0200
|
|
@@ -0,0 +1 @@
|
|
+Olaf Tauber <otauber@web.de>
|
|
\ Ingen nyrad vid filslut
|
|
diff -Nurp linux-2.6.37/3rdparty/acerhk/COPYING linux-2.6.37.3rdparty/3rdparty/acerhk/COPYING
|
|
--- linux-2.6.37/3rdparty/acerhk/COPYING 1970-01-01 02:00:00.000000000 +0200
|
|
+++ linux-2.6.37.3rdparty/3rdparty/acerhk/COPYING 2002-05-08 22:01:52.000000000 +0300
|
|
@@ -0,0 +1,340 @@
|
|
+ GNU GENERAL PUBLIC LICENSE
|
|
+ Version 2, June 1991
|
|
+
|
|
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
|
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
+ Everyone is permitted to copy and distribute verbatim copies
|
|
+ of this license document, but changing it is not allowed.
|
|
+
|
|
+ Preamble
|
|
+
|
|
+ The licenses for most software are designed to take away your
|
|
+freedom to share and change it. By contrast, the GNU General Public
|
|
+License is intended to guarantee your freedom to share and change free
|
|
+software--to make sure the software is free for all its users. This
|
|
+General Public License applies to most of the Free Software
|
|
+Foundation's software and to any other program whose authors commit to
|
|
+using it. (Some other Free Software Foundation software is covered by
|
|
+the GNU Library General Public License instead.) You can apply it to
|
|
+your programs, too.
|
|
+
|
|
+ When we speak of free software, we are referring to freedom, not
|
|
+price. Our General Public Licenses are designed to make sure that you
|
|
+have the freedom to distribute copies of free software (and charge for
|
|
+this service if you wish), that you receive source code or can get it
|
|
+if you want it, that you can change the software or use pieces of it
|
|
+in new free programs; and that you know you can do these things.
|
|
+
|
|
+ To protect your rights, we need to make restrictions that forbid
|
|
+anyone to deny you these rights or to ask you to surrender the rights.
|
|
+These restrictions translate to certain responsibilities for you if you
|
|
+distribute copies of the software, or if you modify it.
|
|
+
|
|
+ For example, if you distribute copies of such a program, whether
|
|
+gratis or for a fee, you must give the recipients all the rights that
|
|
+you have. You must make sure that they, too, receive or can get the
|
|
+source code. And you must show them these terms so they know their
|
|
+rights.
|
|
+
|
|
+ We protect your rights with two steps: (1) copyright the software, and
|
|
+(2) offer you this license which gives you legal permission to copy,
|
|
+distribute and/or modify the software.
|
|
+
|
|
+ Also, for each author's protection and ours, we want to make certain
|
|
+that everyone understands that there is no warranty for this free
|
|
+software. If the software is modified by someone else and passed on, we
|
|
+want its recipients to know that what they have is not the original, so
|
|
+that any problems introduced by others will not reflect on the original
|
|
+authors' reputations.
|
|
+
|
|
+ Finally, any free program is threatened constantly by software
|
|
+patents. We wish to avoid the danger that redistributors of a free
|
|
+program will individually obtain patent licenses, in effect making the
|
|
+program proprietary. To prevent this, we have made it clear that any
|
|
+patent must be licensed for everyone's free use or not licensed at all.
|
|
+
|
|
+ The precise terms and conditions for copying, distribution and
|
|
+modification follow.
|
|
+
|
|
+ GNU GENERAL PUBLIC LICENSE
|
|
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
+
|
|
+ 0. This License applies to any program or other work which contains
|
|
+a notice placed by the copyright holder saying it may be distributed
|
|
+under the terms of this General Public License. The "Program", below,
|
|
+refers to any such program or work, and a "work based on the Program"
|
|
+means either the Program or any derivative work under copyright law:
|
|
+that is to say, a work containing the Program or a portion of it,
|
|
+either verbatim or with modifications and/or translated into another
|
|
+language. (Hereinafter, translation is included without limitation in
|
|
+the term "modification".) Each licensee is addressed as "you".
|
|
+
|
|
+Activities other than copying, distribution and modification are not
|
|
+covered by this License; they are outside its scope. The act of
|
|
+running the Program is not restricted, and the output from the Program
|
|
+is covered only if its contents constitute a work based on the
|
|
+Program (independent of having been made by running the Program).
|
|
+Whether that is true depends on what the Program does.
|
|
+
|
|
+ 1. You may copy and distribute verbatim copies of the Program's
|
|
+source code as you receive it, in any medium, provided that you
|
|
+conspicuously and appropriately publish on each copy an appropriate
|
|
+copyright notice and disclaimer of warranty; keep intact all the
|
|
+notices that refer to this License and to the absence of any warranty;
|
|
+and give any other recipients of the Program a copy of this License
|
|
+along with the Program.
|
|
+
|
|
+You may charge a fee for the physical act of transferring a copy, and
|
|
+you may at your option offer warranty protection in exchange for a fee.
|
|
+
|
|
+ 2. You may modify your copy or copies of the Program or any portion
|
|
+of it, thus forming a work based on the Program, and copy and
|
|
+distribute such modifications or work under the terms of Section 1
|
|
+above, provided that you also meet all of these conditions:
|
|
+
|
|
+ a) You must cause the modified files to carry prominent notices
|
|
+ stating that you changed the files and the date of any change.
|
|
+
|
|
+ b) You must cause any work that you distribute or publish, that in
|
|
+ whole or in part contains or is derived from the Program or any
|
|
+ part thereof, to be licensed as a whole at no charge to all third
|
|
+ parties under the terms of this License.
|
|
+
|
|
+ c) If the modified program normally reads commands interactively
|
|
+ when run, you must cause it, when started running for such
|
|
+ interactive use in the most ordinary way, to print or display an
|
|
+ announcement including an appropriate copyright notice and a
|
|
+ notice that there is no warranty (or else, saying that you provide
|
|
+ a warranty) and that users may redistribute the program under
|
|
+ these conditions, and telling the user how to view a copy of this
|
|
+ License. (Exception: if the Program itself is interactive but
|
|
+ does not normally print such an announcement, your work based on
|
|
+ the Program is not required to print an announcement.)
|
|
+
|
|
+These requirements apply to the modified work as a whole. If
|
|
+identifiable sections of that work are not derived from the Program,
|
|
+and can be reasonably considered independent and separate works in
|
|
+themselves, then this License, and its terms, do not apply to those
|
|
+sections when you distribute them as separate works. But when you
|
|
+distribute the same sections as part of a whole which is a work based
|
|
+on the Program, the distribution of the whole must be on the terms of
|
|
+this License, whose permissions for other licensees extend to the
|
|
+entire whole, and thus to each and every part regardless of who wrote it.
|
|
+
|
|
+Thus, it is not the intent of this section to claim rights or contest
|
|
+your rights to work written entirely by you; rather, the intent is to
|
|
+exercise the right to control the distribution of derivative or
|
|
+collective works based on the Program.
|
|
+
|
|
+In addition, mere aggregation of another work not based on the Program
|
|
+with the Program (or with a work based on the Program) on a volume of
|
|
+a storage or distribution medium does not bring the other work under
|
|
+the scope of this License.
|
|
+
|
|
+ 3. You may copy and distribute the Program (or a work based on it,
|
|
+under Section 2) in object code or executable form under the terms of
|
|
+Sections 1 and 2 above provided that you also do one of the following:
|
|
+
|
|
+ a) Accompany it with the complete corresponding machine-readable
|
|
+ source code, which must be distributed under the terms of Sections
|
|
+ 1 and 2 above on a medium customarily used for software interchange; or,
|
|
+
|
|
+ b) Accompany it with a written offer, valid for at least three
|
|
+ years, to give any third party, for a charge no more than your
|
|
+ cost of physically performing source distribution, a complete
|
|
+ machine-readable copy of the corresponding source code, to be
|
|
+ distributed under the terms of Sections 1 and 2 above on a medium
|
|
+ customarily used for software interchange; or,
|
|
+
|
|
+ c) Accompany it with the information you received as to the offer
|
|
+ to distribute corresponding source code. (This alternative is
|
|
+ allowed only for noncommercial distribution and only if you
|
|
+ received the program in object code or executable form with such
|
|
+ an offer, in accord with Subsection b above.)
|
|
+
|
|
+The source code for a work means the preferred form of the work for
|
|
+making modifications to it. For an executable work, complete source
|
|
+code means all the source code for all modules it contains, plus any
|
|
+associated interface definition files, plus the scripts used to
|
|
+control compilation and installation of the executable. However, as a
|
|
+special exception, the source code distributed need not include
|
|
+anything that is normally distributed (in either source or binary
|
|
+form) with the major components (compiler, kernel, and so on) of the
|
|
+operating system on which the executable runs, unless that component
|
|
+itself accompanies the executable.
|
|
+
|
|
+If distribution of executable or object code is made by offering
|
|
+access to copy from a designated place, then offering equivalent
|
|
+access to copy the source code from the same place counts as
|
|
+distribution of the source code, even though third parties are not
|
|
+compelled to copy the source along with the object code.
|
|
+
|
|
+ 4. You may not copy, modify, sublicense, or distribute the Program
|
|
+except as expressly provided under this License. Any attempt
|
|
+otherwise to copy, modify, sublicense or distribute the Program is
|
|
+void, and will automatically terminate your rights under this License.
|
|
+However, parties who have received copies, or rights, from you under
|
|
+this License will not have their licenses terminated so long as such
|
|
+parties remain in full compliance.
|
|
+
|
|
+ 5. You are not required to accept this License, since you have not
|
|
+signed it. However, nothing else grants you permission to modify or
|
|
+distribute the Program or its derivative works. These actions are
|
|
+prohibited by law if you do not accept this License. Therefore, by
|
|
+modifying or distributing the Program (or any work based on the
|
|
+Program), you indicate your acceptance of this License to do so, and
|
|
+all its terms and conditions for copying, distributing or modifying
|
|
+the Program or works based on it.
|
|
+
|
|
+ 6. Each time you redistribute the Program (or any work based on the
|
|
+Program), the recipient automatically receives a license from the
|
|
+original licensor to copy, distribute or modify the Program subject to
|
|
+these terms and conditions. You may not impose any further
|
|
+restrictions on the recipients' exercise of the rights granted herein.
|
|
+You are not responsible for enforcing compliance by third parties to
|
|
+this License.
|
|
+
|
|
+ 7. If, as a consequence of a court judgment or allegation of patent
|
|
+infringement or for any other reason (not limited to patent issues),
|
|
+conditions are imposed on you (whether by court order, agreement or
|
|
+otherwise) that contradict the conditions of this License, they do not
|
|
+excuse you from the conditions of this License. If you cannot
|
|
+distribute so as to satisfy simultaneously your obligations under this
|
|
+License and any other pertinent obligations, then as a consequence you
|
|
+may not distribute the Program at all. For example, if a patent
|
|
+license would not permit royalty-free redistribution of the Program by
|
|
+all those who receive copies directly or indirectly through you, then
|
|
+the only way you could satisfy both it and this License would be to
|
|
+refrain entirely from distribution of the Program.
|
|
+
|
|
+If any portion of this section is held invalid or unenforceable under
|
|
+any particular circumstance, the balance of the section is intended to
|
|
+apply and the section as a whole is intended to apply in other
|
|
+circumstances.
|
|
+
|
|
+It is not the purpose of this section to induce you to infringe any
|
|
+patents or other property right claims or to contest validity of any
|
|
+such claims; this section has the sole purpose of protecting the
|
|
+integrity of the free software distribution system, which is
|
|
+implemented by public license practices. Many people have made
|
|
+generous contributions to the wide range of software distributed
|
|
+through that system in reliance on consistent application of that
|
|
+system; it is up to the author/donor to decide if he or she is willing
|
|
+to distribute software through any other system and a licensee cannot
|
|
+impose that choice.
|
|
+
|
|
+This section is intended to make thoroughly clear what is believed to
|
|
+be a consequence of the rest of this License.
|
|
+
|
|
+ 8. If the distribution and/or use of the Program is restricted in
|
|
+certain countries either by patents or by copyrighted interfaces, the
|
|
+original copyright holder who places the Program under this License
|
|
+may add an explicit geographical distribution limitation excluding
|
|
+those countries, so that distribution is permitted only in or among
|
|
+countries not thus excluded. In such case, this License incorporates
|
|
+the limitation as if written in the body of this License.
|
|
+
|
|
+ 9. The Free Software Foundation may publish revised and/or new versions
|
|
+of the General Public License from time to time. Such new versions will
|
|
+be similar in spirit to the present version, but may differ in detail to
|
|
+address new problems or concerns.
|
|
+
|
|
+Each version is given a distinguishing version number. If the Program
|
|
+specifies a version number of this License which applies to it and "any
|
|
+later version", you have the option of following the terms and conditions
|
|
+either of that version or of any later version published by the Free
|
|
+Software Foundation. If the Program does not specify a version number of
|
|
+this License, you may choose any version ever published by the Free Software
|
|
+Foundation.
|
|
+
|
|
+ 10. If you wish to incorporate parts of the Program into other free
|
|
+programs whose distribution conditions are different, write to the author
|
|
+to ask for permission. For software which is copyrighted by the Free
|
|
+Software Foundation, write to the Free Software Foundation; we sometimes
|
|
+make exceptions for this. Our decision will be guided by the two goals
|
|
+of preserving the free status of all derivatives of our free software and
|
|
+of promoting the sharing and reuse of software generally.
|
|
+
|
|
+ NO WARRANTY
|
|
+
|
|
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
|
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
|
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
|
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
|
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
|
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
|
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
|
+REPAIR OR CORRECTION.
|
|
+
|
|
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
|
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
|
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
|
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
|
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
|
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
|
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
|
+POSSIBILITY OF SUCH DAMAGES.
|
|
+
|
|
+ END OF TERMS AND CONDITIONS
|
|
+
|
|
+ How to Apply These Terms to Your New Programs
|
|
+
|
|
+ If you develop a new program, and you want it to be of the greatest
|
|
+possible use to the public, the best way to achieve this is to make it
|
|
+free software which everyone can redistribute and change under these terms.
|
|
+
|
|
+ To do so, attach the following notices to the program. It is safest
|
|
+to attach them to the start of each source file to most effectively
|
|
+convey the exclusion of warranty; and each file should have at least
|
|
+the "copyright" line and a pointer to where the full notice is found.
|
|
+
|
|
+ <one line to give the program's name and a brief idea of what it does.>
|
|
+ Copyright (C) 19yy <name of author>
|
|
+
|
|
+ This program is free software; you can redistribute it and/or modify
|
|
+ it under the terms of the GNU General Public License as published by
|
|
+ the Free Software Foundation; either version 2 of the License, or
|
|
+ (at your option) any later version.
|
|
+
|
|
+ This program is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ GNU General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU General Public License
|
|
+ along with this program; if not, write to the Free Software
|
|
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
+
|
|
+
|
|
+Also add information on how to contact you by electronic and paper mail.
|
|
+
|
|
+If the program is interactive, make it output a short notice like this
|
|
+when it starts in an interactive mode:
|
|
+
|
|
+ Gnomovision version 69, Copyright (C) 19yy name of author
|
|
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
|
+ This is free software, and you are welcome to redistribute it
|
|
+ under certain conditions; type `show c' for details.
|
|
+
|
|
+The hypothetical commands `show w' and `show c' should show the appropriate
|
|
+parts of the General Public License. Of course, the commands you use may
|
|
+be called something other than `show w' and `show c'; they could even be
|
|
+mouse-clicks or menu items--whatever suits your program.
|
|
+
|
|
+You should also get your employer (if you work as a programmer) or your
|
|
+school, if any, to sign a "copyright disclaimer" for the program, if
|
|
+necessary. Here is a sample; alter the names:
|
|
+
|
|
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
|
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
|
|
+
|
|
+ <signature of Ty Coon>, 1 April 1989
|
|
+ Ty Coon, President of Vice
|
|
+
|
|
+This General Public License does not permit incorporating your program into
|
|
+proprietary programs. If your program is a subroutine library, you may
|
|
+consider it more useful to permit linking proprietary applications with the
|
|
+library. If this is what you want to do, use the GNU Library General
|
|
+Public License instead of this License.
|
|
diff -Nurp linux-2.6.37/3rdparty/acerhk/doc/acertm.def linux-2.6.37.3rdparty/3rdparty/acerhk/doc/acertm.def
|
|
--- linux-2.6.37/3rdparty/acerhk/doc/acertm.def 1970-01-01 02:00:00.000000000 +0200
|
|
+++ linux-2.6.37.3rdparty/3rdparty/acerhk/doc/acertm.def 2003-08-24 19:46:37.000000000 +0300
|
|
@@ -0,0 +1,56 @@
|
|
+<?xml version="1.0"?>
|
|
+<CONFIG model="Acer Travelmate 610 series">
|
|
+
|
|
+<!--
|
|
+Possible tags are (not all are implemented) :
|
|
+
|
|
+ PrevTrack
|
|
+ Play
|
|
+ Eject
|
|
+ Stop
|
|
+ Pause
|
|
+ NextTrack
|
|
+ VolUp
|
|
+ VolDown
|
|
+ Mute
|
|
+ WebBrowser
|
|
+ Email
|
|
+ Help
|
|
+ WakeUp
|
|
+ PowerDown
|
|
+ Communities
|
|
+ Search
|
|
+ Idea
|
|
+ Shopping
|
|
+ Print
|
|
+ Go
|
|
+ Record
|
|
+ Shell
|
|
+ Transfer
|
|
+ MyDocuments
|
|
+ MyComputer
|
|
+ Calculator
|
|
+ iNews
|
|
+ Sleep
|
|
+ Suspend
|
|
+ Rewind
|
|
+ Rotate
|
|
+-->
|
|
+
|
|
+
|
|
+ <!-- User define functions -->
|
|
+
|
|
+ <userdef keycode="129" command="gnomecc">Konfiguration</userdef>
|
|
+
|
|
+ <userdef keycode="93" command="/home/ole/bin/audiotoggle.sh">Mute/Unmute</userdef>
|
|
+ <userdef keycode="176" command="aumix -v+5">Lauter</userdef>
|
|
+ <userdef keycode="174" command="aumix -v-5">Leiser</userdef>
|
|
+ <Help keycode="226"/>
|
|
+ <userdef keycode="153" command="multi-gnome-terminal --use-factory --start-factory-server --tclass=ole --geometry=80x49">Terminal</userdef>
|
|
+ <userdef keycode="144" command="xemacs">XEmacs</userdef>
|
|
+ <userdef keycode="171" command="xmms --play-pause">Play/Pause</userdef>
|
|
+ <userdef keycode="147" command="xmms --play-pause">Play/Pause</userdef>
|
|
+ <Email keycode="236"/>
|
|
+ <Webbrowser keycode="178"/>
|
|
+
|
|
+</CONFIG>
|
|
diff -Nurp linux-2.6.37/3rdparty/acerhk/doc/FAQ linux-2.6.37.3rdparty/3rdparty/acerhk/doc/FAQ
|
|
--- linux-2.6.37/3rdparty/acerhk/doc/FAQ 1970-01-01 02:00:00.000000000 +0200
|
|
+++ linux-2.6.37.3rdparty/3rdparty/acerhk/doc/FAQ 2005-11-10 19:45:33.000000000 +0200
|
|
@@ -0,0 +1,150 @@
|
|
+******************************************************************************
|
|
+
|
|
+Q: I have a (non Acer) notebook which is not recognized by your driver but I
|
|
+think it should. What information do you need?
|
|
+
|
|
+A: If it is a non-Acer laptop I would like to know, what makes you think that
|
|
+your laptop would work with my driver. A windows driver/utility package of the
|
|
+name "LaunchManager" or "EasyButton" is a good hint. If it is clear that your
|
|
+hardware is okay, I need the string with your model name from BIOS. Please
|
|
+don't ask me how to do it. To find out which functions of your laptop the
|
|
+driver will support, it is best, if you can tell me where to get this
|
|
+"LaunchManager" or "EasyButton" package.
|
|
+If it is a model from 2003 or newer then chances are good that it's a dritek
|
|
+type one. In this case try the option "force_series=6000" to at least enable
|
|
+the keys.
|
|
+
|
|
+******************************************************************************
|
|
+
|
|
+Q: Why can't I activate my wireless hardware on Acer TM 420/430/6000/8000 ...?
|
|
+
|
|
+A: On many newer laptops (Dritek type) I do not now how to do this,
|
|
+sorry. Someone would need to find out how windows does it. Volunteers?
|
|
+
|
|
+******************************************************************************
|
|
+
|
|
+Q: I know that wireless hardware is supported on my Aspire 1690/TravelMate4600,
|
|
+but I cannot get it to work, why?
|
|
+
|
|
+A: On these model (and similar) the wireless hardware is controlled on two
|
|
+different levels. One is controlled by acerhk's xxxled file, the other level
|
|
+is controlled by the key itself. To actually activate the hardware you need to
|
|
+write '1' to the xxled file and you need to press the corresponding button.
|
|
+Example:
|
|
+echo 1 > /proc/driver/acerhk/wirelessled
|
|
+<if still not working, press Wlan button>
|
|
+
|
|
+******************************************************************************
|
|
+
|
|
+Q: Why do I always get 0x00 from /proc/driver/acerhk/key?
|
|
+
|
|
+A1: Check the type of your laptop if /proc/driver/acerhk/info. If it is
|
|
+"Dritek", you cannot read the keys from the driver. Starting from version
|
|
+0.5.17 you get "n/a" out of the key file in this case.
|
|
+A2: If you have polling enabled (default) you will almost always read 0x00
|
|
+from this file. This is because in every polling cycle it is checked for key
|
|
+events and if there is one, it is instantly translated and sent to the kernel
|
|
+input system. Starting with version 0.5.20 you get "n/a" out of the key file
|
|
+in this case.
|
|
+
|
|
+******************************************************************************
|
|
+
|
|
+Q: When I press a key, nothing happens. Why are they not working?
|
|
+
|
|
+A: Most keys won't do anything by themself. If nothing happens, that is
|
|
+because no programm knows what to do with the new keys. You need to assign
|
|
+actions to them, use the hotkey manager of your desktop to do that. If
|
|
+using Gnome, you find it under desktop settings - keyboard shortcuts.
|
|
+
|
|
+******************************************************************************
|
|
+
|
|
+Q: The driver works for my laptop, but not all of the keys are working. What
|
|
+can I do?
|
|
+
|
|
+A: There are some keys/key combinations which generate an ACPI event,
|
|
+e.g. Fn+F4 on some models or the lid button.
|
|
+If you have a different laptop than the one which got detected (or you used
|
|
+"force_series=xxx" anyway), then it is possible that the mapping acerhk uses
|
|
+to translate the codes from the buttons to key events is wrong.
|
|
+In this case, load the driver with "verbose=4" and press the buttons which do
|
|
+not work. Then look for messages from acerhk of the form "translated acer key
|
|
+code xxx to no key". Note these codes together with the button they belong to
|
|
+and send me this list along with the model name of your laptop.
|
|
+If you do not see a usable name in /proc/driver/acerhk/info please try the
|
|
+tools dmidecode/biosdecode/vpddecode to find this name.
|
|
+
|
|
+******************************************************************************
|
|
+Q: I press the wireless key but the hardware doesn't get activated, what's wrong?
|
|
+
|
|
+A: The driver is only on older models (non-Dritek type) able to read
|
|
+keypresses by itself and toggle the hardware/LED automatically (with option
|
|
+autowlan=1). On Dritek type models this must be done by writing the desired
|
|
+value to one of the wireless files in the proc filesystem. In most
|
|
+cases this would be /proc/drivers/acerhk/wirelessled to control wlan
|
|
+hardware (blueled for Bluetooth hardware):
|
|
+
|
|
+echo 1 > /proc/driver/acerhk/wirelessled
|
|
+
|
|
+But you could use a hotkey manager to do that automatically when you press the
|
|
+button. In this case be aware that on some models the button generates
|
|
+different key events according to the actual state of the wireless hardware.
|
|
+
|
|
+******************************************************************************
|
|
+
|
|
+Q: My keys do not work, I only get kernel messages of the form:
|
|
+atkbd.c: Unknown key pressed (translated set 2, code 0xf4 on isa0060/serio0).
|
|
+atkbd.c: Use 'setkeycodes e074 <keycode>' to make it known.
|
|
+
|
|
+A: Press each of the buttons and note the mentioned
|
|
+code for it (e074 in this example). You should get a list like this:
|
|
+P1 e074
|
|
+P2 e075
|
|
+...
|
|
+If you are finished with it, look into /usr/include/linux/input.h, using
|
|
+your favourite text viewer/editor. Search for "KEY_STOP". You should see
|
|
+the following line in the file:
|
|
+
|
|
+#define KEY_STOP 128
|
|
+
|
|
+After it many more lines with equal #defines should be visible. Look for
|
|
+key names which best match the names of your buttons, e.g. KEY_PROG1,
|
|
+KEY_WWW and so on. Note the numbers assigned to the names, for KEY_STOP
|
|
+this would be 128, for KEY_PROG1 148.
|
|
+Now you have a list with three items per entry, your button, a code
|
|
+from the kernel messages and a corresponding number from the file
|
|
+linux.h:
|
|
+P1 e074 148
|
|
+P2 e075 149
|
|
+...
|
|
+For each line in this list, issue the setkeycodes command as mentioned
|
|
+in the kernel message:
|
|
+setkeycodes e074 148
|
|
+setkeycodes e075 149
|
|
+...
|
|
+After doing that, the keys should be available for your hotkey manager.
|
|
+
|
|
+******************************************************************************
|
|
+
|
|
+Q: My WLAN hardware gets activated through /proc/driver/acerhk/wirelessled,
|
|
+but the LED is not working. Why not?
|
|
+
|
|
+A: Try if adding the option "led=1" to your wireless module helps. For the
|
|
+ipw2200 driver it works, as Didier CLERC <didier@linuxbourg.ch> found out:
|
|
+
|
|
+ I have to load the module "ipw2200" with the option "led=1", then
|
|
+ the wifi button blinks until a network is detected.
|
|
+
|
|
+******************************************************************************
|
|
+
|
|
+Q: I have an unsupported laptop, but the driver works when I force the series
|
|
+to a type like 610 or 2100. Only my buttons doesn't get recognized, why?
|
|
+
|
|
+A: On models of the type TM_new (like TravelMate 600, 2100 and many other, see
|
|
+acerhk.c, function setup_model_features for details) the buttons use different
|
|
+codes on different models. Therefore the driver needs to know these codes. You
|
|
+can get them if you load the driver with verbose=4, press the buttons and key
|
|
+combinations (Fn+xx) you are interested in and look for kernel messages of the
|
|
+form "acerhk: translated acer key code 0xnn to ...". Write down the key code
|
|
+for each button/key combination and send them to me so I can patch the
|
|
+driver. I also need your model string to make autodetection work, so include
|
|
+/proc/driver/acerk/info.
|
|
\ Ingen nyrad vid filslut
|
|
diff -Nurp linux-2.6.37/3rdparty/acerhk/doc/IOCTL linux-2.6.37.3rdparty/3rdparty/acerhk/doc/IOCTL
|
|
--- linux-2.6.37/3rdparty/acerhk/doc/IOCTL 1970-01-01 02:00:00.000000000 +0200
|
|
+++ linux-2.6.37.3rdparty/3rdparty/acerhk/doc/IOCTL 2004-01-31 22:38:17.000000000 +0200
|
|
@@ -0,0 +1,61 @@
|
|
+Documentation of possible IOCTLs used by acerhk
|
|
++++++++++++++++++++++++++++++++++++++++++++++++
|
|
+
|
|
+ACERHK_GET_KEYCOUNT
|
|
+ Read the number of unread key presses in queue
|
|
+ Parameter: pointer to char
|
|
+
|
|
+ACERHK_GET_KEYID
|
|
+ Read the code of the first key press (oldest) in queue
|
|
+ Parameter: pointer to char
|
|
+
|
|
+ACERHK_CONNECT
|
|
+ Don't know what it does, used in windows driver
|
|
+
|
|
+ACERHK_DISCONNECT
|
|
+ Don't know what it does, used in windows driver
|
|
+
|
|
+ACERHK_GET_THERMAL_EVENT
|
|
+ Don't know what it does, used in windows driver
|
|
+ Parameter: pointer to short
|
|
+
|
|
+ACERHK_MAIL_LED_OFF
|
|
+ Switch off the LED of the mail button(if available)
|
|
+
|
|
+ACERHK_MAIL_LED_ON
|
|
+ Switch on the LED of the mail button (if available)
|
|
+
|
|
+ACERHK_START_POLLING
|
|
+ Start polling (and translation to key events) in kernel
|
|
+
|
|
+ACERHK_STOP_POLLING
|
|
+ Stop polling in kernel
|
|
+
|
|
+ACERHK_GET_KEY_MAP
|
|
+ Get mapping of key names to key events
|
|
+ Parameter: pointer to t_map_name2event
|
|
+
|
|
+ACERHK_SET_KEY_MAP
|
|
+ Set mapping of key names to key events
|
|
+ Parameter: pointer to t_map_name2event
|
|
+
|
|
+IOCTLs used by windows driver
|
|
++++++++++++++++++++++++++++++
|
|
+device name:
|
|
+\DosDevices\HOTKEY
|
|
+\Device\HOTKEY
|
|
+
|
|
+
|
|
+630 series:
|
|
+0x222404
|
|
+ Get CMOS index
|
|
+0x222408
|
|
+ ACERHK_GET_KEYCOUNT
|
|
+0x22240C
|
|
+ ACERHK_GET_KEYID
|
|
+0x222410
|
|
+ ACERHK_MAIL_LED_OFF/ACERHK_MAIL_LED_ON
|
|
+0x222414
|
|
+ ACERHK_CONNECT/ACERHK_DISCONNECT
|
|
+0x222418
|
|
+ ACERHK_GET_THERMAL_EVENT
|
|
diff -Nurp linux-2.6.37/3rdparty/acerhk/doc/keycodes linux-2.6.37.3rdparty/3rdparty/acerhk/doc/keycodes
|
|
--- linux-2.6.37/3rdparty/acerhk/doc/keycodes 1970-01-01 02:00:00.000000000 +0200
|
|
+++ linux-2.6.37.3rdparty/3rdparty/acerhk/doc/keycodes 2004-04-18 20:42:59.000000000 +0300
|
|
@@ -0,0 +1,26 @@
|
|
+standard X keycodes with older (acerhk controlled) hardware from Acer
|
|
+*********************************************************************
|
|
+help (Fn+F1) 226
|
|
+setup (Fn+F2) 129
|
|
+p1 153
|
|
+p2 144
|
|
+p3 171
|
|
+www 178
|
|
+mail 236
|
|
+wireless 147
|
|
+power (Fn+F3) 222
|
|
+mute (Fn+F8) 166
|
|
+volup (Fn+Up) 158
|
|
+voldn (Fn+Down) 165
|
|
+
|
|
+standard X keycodes with newer (acerhk activated) hardware from Dritek
|
|
+**********************************************************************
|
|
+help (Fn+F1) 226
|
|
+setup (Fn+F2) 129
|
|
+p1 153
|
|
+p2 144
|
|
+www 178
|
|
+mail 236
|
|
+volup (Fn+Up) 176
|
|
+voldn (Fn+Down) 174
|
|
+mute (Fn+F8) 160
|
|
diff -Nurp linux-2.6.37/3rdparty/acerhk/doc/md95400.def linux-2.6.37.3rdparty/3rdparty/acerhk/doc/md95400.def
|
|
--- linux-2.6.37/3rdparty/acerhk/doc/md95400.def 1970-01-01 02:00:00.000000000 +0200
|
|
+++ linux-2.6.37.3rdparty/3rdparty/acerhk/doc/md95400.def 2005-03-01 22:46:53.000000000 +0200
|
|
@@ -0,0 +1,14 @@
|
|
+<?xml version="1.0"?>
|
|
+<CONFIG model="Medion MD 95400 series">
|
|
+
|
|
+<userdef keycode="236" command="/usr/bin/thunderbird">Mail</userdef>
|
|
+<userdef keycode="178" command="/usr/bin/firefox">Web</userdef>
|
|
+<userdef keycode="162" command="/usr/bin/xmms --play-pause">Play/Pause</userdef>
|
|
+<userdef keycode="164" command="/usr/bin/xmms --stop">Stop</userdef>
|
|
+<userdef keycode="144" command="/usr/bin/xmms --rew">Previous</userdef>
|
|
+<userdef keycode="153" command="/usr/bin/xmms --fwd">Next</userdef>
|
|
+<userdef keycode="174" command="/usr/bin/aumix -v -5">Leiser</userdef>
|
|
+<userdef keycode="176" command="/usr/bin/aumix -v +5">Lauter</userdef>
|
|
+<userdef keycode="160" command="/usr/bin/aumix -v 0"></userdef>
|
|
+
|
|
+</CONFIG>
|
|
diff -Nurp linux-2.6.37/3rdparty/acerhk/INSTALL linux-2.6.37.3rdparty/3rdparty/acerhk/INSTALL
|
|
--- linux-2.6.37/3rdparty/acerhk/INSTALL 1970-01-01 02:00:00.000000000 +0200
|
|
+++ linux-2.6.37.3rdparty/3rdparty/acerhk/INSTALL 2005-12-07 14:27:16.000000000 +0200
|
|
@@ -0,0 +1,109 @@
|
|
+Installation
|
|
+************
|
|
+
|
|
+1. You need the kernel sources (or kernel headers for your kernel)
|
|
+installed to compile the driver.
|
|
+
|
|
+2. Your kernel needs loadable module support with version information for
|
|
+modules enabled. Usage of procfs is highly recommended.
|
|
+If you want the driver to generate regular keyboard events using
|
|
+kernel version 2.4 you need the input system of the kernel enabled
|
|
+(Input core support AND keyboard support). In kernel version 2.6 all
|
|
+needed functionality should be available by default.
|
|
+
|
|
+In most cases you can skip the next step, the Makefile tries do determine
|
|
+the correct directory on its own. Change KERNELSRC only if the autodetection
|
|
+does not work for you. Otherwise proceed directly with step 4.
|
|
+
|
|
+3. Before you compile the driver, change KERNELSRC in the makefile to your
|
|
+path to the kernel build environment. If you are using a self compiled kernel,
|
|
+point it to the root of your sources. If you are using a packaged kernel of
|
|
+your distribution, install the package with kernel headers
|
|
+(Debian:kernel-headers) and point KERNELSRC to where the headers and config
|
|
+files are located. If you are using Debian, this
|
|
+would be "/lib/modules/<kernelversion>/build".
|
|
+
|
|
+4. Do:
|
|
+ make
|
|
+to compile the driver. If you run into problems because of the makefile not
|
|
+recognizing your kernel version correctly, try this:
|
|
+ make acerhk.o - kernel version 2.4
|
|
+ make acerhk.ko - kernel version 2.6
|
|
+
|
|
+5. Do:
|
|
+ make install
|
|
+to automatically copy the driver into the kernel module library. If you've
|
|
+done so, proceed directly with step 8. If you want to install the module
|
|
+binary yourself (because you want a different location), use steps 6 and 7
|
|
+instead.
|
|
+
|
|
+6. Copy the created file "acerhk.o" ("acerhk.ko" with version 2.6) to your
|
|
+kernel modules path. In Debian this could be
|
|
+"/lib/modules/<kernelversion>/kernel/drivers/extra/".
|
|
+
|
|
+7. Update module dependencies: depmod -a
|
|
+
|
|
+8. Try loading the module with:
|
|
+ insmod/modprobe acerhk
|
|
+If it succeeds - congratulations! If you have procfs enabled, you can try the
|
|
+following to test the driver:
|
|
+
|
|
+Non-Dritek models:
|
|
+Press one of the special keys and after that:
|
|
+ cat /proc/driver/acerhk/key
|
|
+to read the (hexadezimal) code of the key pressed. It should
|
|
+be different from 0x00.
|
|
+(Note: You mustn't have the polling feature enabled for this to work, so load
|
|
+ the module with poll=0)
|
|
+
|
|
+Dritek-models:
|
|
+Press one of the special keys and look for the generated key with "xev". If
|
|
+there is none, then you should see at least kernel messages about using
|
|
+setkeycodes.
|
|
+
|
|
+If your notebook has a mail led you can try this:
|
|
+ echo on > /proc/driver/acerhk/led
|
|
+This should sete the mail led to blinking mode.
|
|
+ echo off > /proc/driver/acerhk/led
|
|
+turns it off again.
|
|
+See README for further usage information.
|
|
+
|
|
+If the module didn't load look into your kernel messages what went wrong. If
|
|
+you see something like the following lines:
|
|
+ acerhk: could not find request handler
|
|
+ acerhk: can't find ROM area
|
|
+ acerhk: unloaded
|
|
+then your hardware is not recognized. See README for supported models. If it
|
|
+won't work on your notebook, please contact me and I will see if I can fix
|
|
+that.
|
|
+
|
|
+Integrating the driver into kernel tree version 2.6
|
|
+***************************************************
|
|
+
|
|
+If you want the driver to fully integrate into the kernel tree of version 2.6
|
|
+proceed as follows:
|
|
+1. Copy the acerhk directory into the source tree, for instance
|
|
+ /usr/src/linux/drivers/misc/acerhk
|
|
+2. Include the driver directory in the config files. Add to the Kconfig
|
|
+file of the parent directory(/usr/src/linux/drivers/misc/Kconfig):
|
|
+
|
|
+config ACERHK
|
|
+ tristate "Acerhk driver"
|
|
+ depends on EXPERIMENTAL
|
|
+ ---help---
|
|
+ This is an experimental acer keyboard driver for
|
|
+ acer laptops
|
|
+
|
|
+3. Include the acer directory in it's parents
|
|
+Makefile(/usr/src/linux/drivers/misc/Makefile):
|
|
+
|
|
+obj-$(CONFIG_ACERHK) += acerhk/
|
|
+
|
|
+4. In this case you also need to activate the misc drivers first
|
|
+(/usr/src/linux/drivers/Kconfig):
|
|
+
|
|
+source "drivers/misc/Kconfig"
|
|
+
|
|
+If that's done, you should be able to select the driver from the configuration
|
|
+programm and build the module.
|
|
+
|
|
diff -Nurp linux-2.6.37/3rdparty/acerhk/Makefile linux-2.6.37.3rdparty/3rdparty/acerhk/Makefile
|
|
--- linux-2.6.37/3rdparty/acerhk/Makefile 1970-01-01 02:00:00.000000000 +0200
|
|
+++ linux-2.6.37.3rdparty/3rdparty/acerhk/Makefile 2006-08-16 19:11:08.000000000 +0300
|
|
@@ -0,0 +1,65 @@
|
|
+# change KERNELSRC to the location of your kernel build tree only if
|
|
+# autodetection does not work
|
|
+#KERNELSRC=/usr/src/linux
|
|
+KERNELSRC?=/lib/modules/`uname -r`/build
|
|
+# Starting with 2.6.18, the kernel version is in utsrelease.h instead of version.h, accomodate both cases
|
|
+KERNELVERSION=$(shell awk -F\" '/REL/ {print $$2}' $(shell grep -s -l REL $(KERNELSRC)/include/linux/version.h $(KERNELSRC)/include/linux/utsrelease.h))
|
|
+KERNELMAJOR=$(shell echo $(KERNELVERSION)|head -c3)
|
|
+
|
|
+# next line is for kernel 2.6, if you integrate the driver in the kernel tree
|
|
+# /usr/src/linux/drivers/acerhk - or something similar
|
|
+# don't forget to add the following line to the parent dir's Makefile:
|
|
+# (/usr/src/linux/drivers/Makefile)
|
|
+# obj-m += acerhk/
|
|
+CONFIG_ACERHK?=m
|
|
+obj-$(CONFIG_ACERHK) += acerhk.o
|
|
+
|
|
+CFLAGS+=-c -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe
|
|
+INCLUDE=-I$(KERNELSRC)/include
|
|
+
|
|
+ifeq ($(KERNELMAJOR), 2.6)
|
|
+TARGET := acerhk.ko
|
|
+else
|
|
+TARGET := acerhk.o
|
|
+endif
|
|
+
|
|
+SOURCE := acerhk.c
|
|
+
|
|
+all: $(TARGET)
|
|
+
|
|
+help:
|
|
+ @echo Possible targets:
|
|
+ @echo -e all\\t- default target, builds kernel module
|
|
+ @echo -e install\\t- copies module binary to /lib/modules/$(KERNELVERSION)/extra/
|
|
+ @echo -e clean\\t- removes all binaries and temporary files
|
|
+
|
|
+# this target is only for me, don't use it yourself (Olaf)
|
|
+export:
|
|
+ sh export.sh
|
|
+
|
|
+acerhk.ko: $(SOURCE) acerhk.h
|
|
+ $(MAKE) -C $(KERNELSRC) SUBDIRS=$(PWD) modules
|
|
+
|
|
+acerhk.o: $(SOURCE) acerhk.h
|
|
+ $(CC) $(INCLUDE) $(CFLAGS) -DMODVERSIONS -DMODULE -D__KERNEL__ -o $(TARGET) $(SOURCE)
|
|
+
|
|
+asm: $(SOURCE)
|
|
+ifeq ($(KERNELMAJOR), 2.6)
|
|
+ $(CC) $(INCLUDE) $(INCLUDE)/asm-i386/mach-default $(CFLAGS) -fverbose-asm -S -DMODVERSIONS -DMODULE -D__KERNEL__ $(SOURCE)
|
|
+else
|
|
+ $(CC) $(INCLUDE) $(CFLAGS) -fverbose-asm -S -DMODVERSIONS -DMODULE -D__KERNEL__ $(SOURCE)
|
|
+endif
|
|
+
|
|
+clean:
|
|
+ rm -f *~ *.o *.s *.ko .acerhk* *.mod.c
|
|
+
|
|
+load: $(TARGET)
|
|
+ insmod $(TARGET)
|
|
+
|
|
+unload:
|
|
+ rmmod acerhk
|
|
+
|
|
+install: $(TARGET)
|
|
+ mkdir -p /lib/modules/$(KERNELVERSION)/extra
|
|
+ cp -v $(TARGET) /lib/modules/$(KERNELVERSION)/extra/
|
|
+ depmod -a
|
|
diff -Nurp linux-2.6.37/3rdparty/acerhk/NEWS linux-2.6.37.3rdparty/3rdparty/acerhk/NEWS
|
|
--- linux-2.6.37/3rdparty/acerhk/NEWS 1970-01-01 02:00:00.000000000 +0200
|
|
+++ linux-2.6.37.3rdparty/3rdparty/acerhk/NEWS 2003-02-28 02:47:18.000000000 +0200
|
|
@@ -0,0 +1,16 @@
|
|
+2003-02-28 Version 0.5.0
|
|
+ completely changed key polling/translation
|
|
+ support for more series
|
|
+2002-07-06 Version 0.4.2
|
|
+ added debug functionality
|
|
+ bugfix with 520/210
|
|
+2002-06-24 Version 0.4.1
|
|
+ added support for TM 210 series
|
|
+ removed nvram dependency
|
|
+2002-06-15 Version 0.4
|
|
+ added model recognition
|
|
+ added kernel polling an key event generation
|
|
+ added support for 520 series
|
|
+
|
|
+2002-04-29 Version 0.3
|
|
+ Initial release
|
|
\ Ingen nyrad vid filslut
|
|
diff -Nurp linux-2.6.37/3rdparty/acerhk/README linux-2.6.37.3rdparty/3rdparty/acerhk/README
|
|
--- linux-2.6.37/3rdparty/acerhk/README 1970-01-01 02:00:00.000000000 +0200
|
|
+++ linux-2.6.37.3rdparty/3rdparty/acerhk/README 2006-11-10 00:01:46.000000000 +0200
|
|
@@ -0,0 +1,215 @@
|
|
+
|
|
+What is this driver good for?
|
|
+*****************************
|
|
+
|
|
+This driver will give access to the special keys on notebooks of the
|
|
+Acer Travelmate series, which are not handled by the keyboard
|
|
+driver.
|
|
+It also works on notebooks from other manufacturers (some Medion,
|
|
+Fujitsu-Siemens, ...).
|
|
+
|
|
+It also has some other related functionality (depending on the model):
|
|
+- controlling LEDs (Mail, Wireless)
|
|
+- enable/disable wireless hardware
|
|
+
|
|
+Usage
|
|
+*****
|
|
+
|
|
+The driver provides a device /dev/misc/acerhk where you can access all
|
|
+functions through IOCTL's, look into acerhk.h for their definitions.
|
|
+I use devfs and don't care about the minor number. You may want to change
|
|
+ACERHK_MINOR in acerhk.h.
|
|
+If you don't use devfs you need to create the device node. The device uses
|
|
+major 10 (misc character devices), the minor is chosen by the kernel (if
|
|
+ACERHK_MINOR equals MISC_DYNAMIC_MINOR) or by yourself (any other value).
|
|
+Use something like
|
|
+ mknod /dev/acerhk c 10 123
|
|
+to create the device node.
|
|
+You can also use most functions through procfs. You will find some files in
|
|
+/proc/driver/acerhk:
|
|
+ led - write "on" or "off" to set the mail led state
|
|
+ key - read it to get a key press, only useful on non-dritek models
|
|
+ and only if polling is disabled
|
|
+ This file exists only on non-dritek models
|
|
+ info - some information about the driver, including the number of
|
|
+ pending keys
|
|
+ wirelessled - write "on" or "off" to set the led state and enable
|
|
+ wlan hardware
|
|
+ On some laptops you need to load the ipw2200 (others
|
|
+ too?) with option "led=1" to make the led work.
|
|
+ blueled - write "on" or "off" to set the led state and enable
|
|
+ bluetooth hardware
|
|
+ write a value n >= 50 to let the led blink every n jiffies
|
|
+ Do not use blinking mode where not only the led but also the
|
|
+ bluetooth hardware is controlled!
|
|
+
|
|
+Probably the best way to use the driver is to let it poll for the keys itself
|
|
+and generate real key events. this is the normal case when loading the module
|
|
+without an additional parameter :
|
|
+
|
|
+ modprobe acerhk
|
|
+
|
|
+or you can use the ioctl as specified in acerhk.h to control the polling. If
|
|
+your kernel has keyboard input support you will get real key events when
|
|
+pressing the special keys.
|
|
+You can then use whatever software you like to make use of those keys,
|
|
+i.e. 'hotkeys' or Linux Easy Access Keyboard 'lineakd'. I prefer hotkeys, just
|
|
+in case anyone is interested, you can find a sample configuration for this
|
|
+programm in doc/acertm.def.
|
|
+Gnome >= 2.4 has built in support for multimedia keys (acme), that's
|
|
+what I use now.
|
|
+
|
|
+Have a look at
|
|
+ http://mmkc.sourceforge.net/
|
|
+
|
|
+Note: If you have one of the newer models using dritek hardware you don't need
|
|
+polling (nor the file /proc/driver/acerhk/key) to use your buttons. On this
|
|
+hardware the driver only needs to send a special command to the keyboard
|
|
+controller to make them work. The actual key presses are then handled by the
|
|
+normal keyboard driver of the kernel. You can switch of polling by
|
|
+loading the module with poll=0. It saves you precious cpu time.
|
|
+
|
|
+
|
|
+Module parameters
|
|
+*****************
|
|
+name values meaning
|
|
+autowlan 0,1 disable(default)/enable automatic switching of wlan hardware
|
|
+ on wireless keypress, only useful for older (no
|
|
+ dritek-hardware) models, works only will poll=1
|
|
+poll 0,1 disable/enable(default) kernel polling of key events
|
|
+verbose 0-4 verbosity level, see below
|
|
+usedritek 0,1 disable/enable(default) use of dritek hardware on newer
|
|
+ series, needed to activate the keys on such models
|
|
+force_series set this to the laptop series number you want the driver to
|
|
+ assume, skip autodetection (look at function
|
|
+ setup_model_features() for possible values)
|
|
+
|
|
+Debugging
|
|
+*********
|
|
+
|
|
+You can make the the driver be more verbose. To do this, add the following
|
|
+parameter when loading the module:
|
|
+
|
|
+ verbose=<n>
|
|
+
|
|
+n is an integer, 0 (default) means no additional information while increasing
|
|
+values provide an increasing amount of information. Currently 3 is maximum,
|
|
+bigger values will have the same effect as 3. The existing verbosity levels
|
|
+will generate information about:
|
|
+ Level Information
|
|
+ 1 state changes and variable initialization
|
|
+ 2 model probing
|
|
+ 3 key translation, only known keys
|
|
+ 4 key translation, also unknown keys
|
|
+ 5 misc. information (idle values)
|
|
+
|
|
+If you have rather serious problems you can activate debugging functionality
|
|
+in the driver. To do this, uncomment the '#define ACERDEBUG' in acerhk.c. You
|
|
+will find a new file in /proc/driver/acerhk, named 'debug'. You cannot read
|
|
+from this file, but you can write commands consisting of up to 4 digits. The
|
|
+first one specifies the action, while the latter can give additional
|
|
+parameters. Implemented are:
|
|
+ 'd' decrement module usage counter
|
|
+ 'i' increment module usage counter
|
|
+
|
|
+ 'p' call function pbutton_fct()
|
|
+ 't' call function get_thermal_event()
|
|
+ 'w1x' call function wbutton_fct_1() with parameter x (0-9)
|
|
+ 'w2x' call function wbutton_fct_2() with parameter x (0-9)
|
|
+
|
|
+ 'vx' change verbosity level to x (0-9)
|
|
+
|
|
+ 'mxyy' set mapping of key name x to key event yy (hex)
|
|
+ 'sxx' send key event xx (hex) to input system
|
|
+ 'Sxx' simulate acer key press with code xx (hex)
|
|
+
|
|
+ 'e0' stop kernel polling
|
|
+ 'e1' start kernel polling
|
|
+
|
|
+Example:
|
|
+
|
|
+1) echo d > /proc/driver/acerhk/debug
|
|
+
|
|
+will decrement the usage counter, very useful if a program using the driver
|
|
+segfaulted. This way you can still unload the driver.
|
|
+
|
|
+2) echo v4 > /proc/driver/acerhk/debug
|
|
+
|
|
+will set the verbosity level to maximum.
|
|
+
|
|
+Keycodes
|
|
+********
|
|
+
|
|
+see doc/keycodes
|
|
+Also see http://bernd-wurst.de/linux/tm800.php#mmkeys (only in german)
|
|
+
|
|
+If you have one of the newer models with the dritek hardware, use kernel 2.6
|
|
+and get (after enabling it) kernel messages of the form:
|
|
+
|
|
+ atkbd.c: Unknown key pressed (translated set 2, code 0xf4 on
|
|
+ isa0060/serio0).
|
|
+ atkbd.c: Use 'setkeycodes e074 <keycode>' to make it known.
|
|
+
|
|
+then you should do exactly what your told. In this case you could do
|
|
+
|
|
+ setkeycodes e074 158
|
|
+
|
|
+to map the button with scancode e074 (hex) to keycode 158 (decimal). To find
|
|
+out the scancodes of the buttons either look into the kernel log or into the
|
|
+file MMKEYBD.CFG of the windows launch manager package. There you should find
|
|
+lines like this:
|
|
+
|
|
+Key 1 = 1,E0,74,E0,F4,F500,P1
|
|
+ ** ** **
|
|
+
|
|
+The important information is marked in the example above. The numbers give the
|
|
+scancode produced by the button which's name is given last.
|
|
+The keycode you give as parameter to setkeycodes is one out of the header file
|
|
+linux/input.h, in the example above the one for KEY_BACK.
|
|
+Important note: I received mails from a number of people where setkeycodes
|
|
+rejected keycodes above a certain value. This is caused by an outdated version
|
|
+of setkeycodes, use a more recent one.
|
|
+To ease the setup of keymappings for the newer series I will try to include
|
|
+setup scripts for the different notebook series. If I have enough time to
|
|
+spare I will perhaps expand the driver itself do to that.
|
|
+
|
|
+How does it work?
|
|
+*****************
|
|
+
|
|
+The driver is based on the windows Me for series 610 driver and
|
|
+resembles its structure and functionality.
|
|
+Key presses are events, which are stored in a FIFO queue with 31
|
|
+entries. You can access the event count via CMOS nvram, but the access to
|
|
+the actual queue (and other functionality like switching the mail led) is
|
|
+done through calling a system ROM function.
|
|
+Upon loading the driver looks for this function, if it cannot find it,
|
|
+loading aborts.
|
|
+Newer Dritek Hardware:
|
|
+Button handling is done entirely by the EC (embbedded/environment
|
|
+controller) which behaves like an extended keyboard controller. My
|
|
+driver only enables/disables this extension.
|
|
+
|
|
+
|
|
+Credits
|
|
+*******
|
|
+
|
|
+Leif Jensen, whose driver inspired me to do the probing stuff
|
|
+http://www.math.columbia.edu/~jensen/linux/acertm/
|
|
+
|
|
+Thanks to all who contributed patches to this driver or who just tried it out
|
|
+on their laptops, without them it wouldn't support anything else but my
|
|
+TM 613.
|
|
+
|
|
+Contact
|
|
+*******
|
|
+
|
|
+If you have problems with the driver, please include the following information:
|
|
+1. name of your laptop (e.g. Acer TM 4001)
|
|
+2. content of /proc/driver/acerhk/info, if available
|
|
+3. kernel output after loading the module with verbose=2
|
|
+
|
|
+Email: Olaf Tauber <otauber@web.de>
|
|
+
|
|
+The latest version can be found here:
|
|
+
|
|
+http://www.informatik.hu-berlin.de/~tauber/acerhk
|