Imported Upstream version 2.20070211+git20110911.4e1e3fc upstream upstream/2.20070211+git20110911.4e1e3fc
authorJulien Valroff <julien@kirya.net>
Sun, 11 Sep 2011 05:47:20 +0000 (07:47 +0200)
committerJulien Valroff <julien@kirya.net>
Sun, 11 Sep 2011 05:47:20 +0000 (07:47 +0200)
51 files changed:
Makefile [new file with mode: 0644]
ac.c [new file with mode: 0644]
acpi.c [new file with mode: 0644]
battery.c [new file with mode: 0644]
blank.c [new file with mode: 0644]
bluetooth.c [new file with mode: 0644]
compal.c [new file with mode: 0644]
compat.h [new file with mode: 0644]
cooling.c [new file with mode: 0644]
display.c [new file with mode: 0644]
doc/BUGS [new file with mode: 0644]
doc/COPYING [new file with mode: 0644]
doc/CREDITS [new file with mode: 0644]
doc/ChangeLog [new file with mode: 0644]
doc/INSTALL [new file with mode: 0644]
doc/README [new file with mode: 0644]
dock.c [new file with mode: 0644]
dump.c [new file with mode: 0644]
ec.c [new file with mode: 0644]
fan.c [new file with mode: 0644]
fan_policy.c [new file with mode: 0644]
hardware.h [new file with mode: 0644]
hotkeys.c [new file with mode: 0644]
info.c [new file with mode: 0644]
init.c [new file with mode: 0644]
kbc.c [new file with mode: 0644]
laptop.h [new file with mode: 0644]
lcd.c [new file with mode: 0644]
lib.c [new file with mode: 0644]
misc/README.mmkeys [new file with mode: 0644]
misc/dmi_strings.txt [new file with mode: 0644]
misc/hotkeys/README.hotkeys [new file with mode: 0644]
misc/hotkeys/nx9xxx.def [new file with mode: 0644]
misc/hotkeys/ob5xx.def [new file with mode: 0644]
misc/hotkeys/xe3gc.def [new file with mode: 0644]
misc/hotkeys/xe3gf.def [new file with mode: 0644]
misc/hotkeys/xe4xxx.def [new file with mode: 0644]
misc/hotkeys/xt155.def [new file with mode: 0644]
misc/mmkeys.patch [new file with mode: 0644]
misc/omnibook-integration.patch [new file with mode: 0644]
misc/onetouch-xkb-2003-02-10.patch [new file with mode: 0644]
muteled.c [new file with mode: 0644]
nbsmi.c [new file with mode: 0644]
omnibook.h [new file with mode: 0644]
pio.c [new file with mode: 0644]
polling.c [new file with mode: 0644]
sections.lds [new file with mode: 0644]
temperature.c [new file with mode: 0644]
throttling.c [new file with mode: 0644]
touchpad.c [new file with mode: 0644]
wireless.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..b414f22
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,170 @@
+#
+# Makefile -- makefile for the HP OmniBook support module
+#
+# 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, 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.
+#
+# Written by Soós Péter <sp@osb.hu>, 2002-2004
+# Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006-2007
+#
+
+#Module informations
+
+MODULE_NAME = omnibook
+MODULE_VERSION = 2.20090707
+MODULE_BRANCH = trunk
+
+# Out-of-tree configuration
+ifndef CONFIG_OMNIBOOK
+OMNIBOOK_STANDALONE=y
+CONFIG_OMNIBOOK=m
+
+#Uncomment and set to force debug behavior
+#NOTE: Default (commented) behavior is to enable debug in trunk or branch svn 
+#      snapshot and to disable it for release
+#OMNIBOOK_WANT_DEBUG=n
+
+#comment to disable backlight device support
+OMNIBOOK_WANT_BACKLIGHT=y
+
+#Uncomment to force legacy (pre-ACPI system) features support
+#OMNIBOOK_WANT_LEGACY=y
+
+endif
+
+ifeq ($(KERNELRELEASE),)
+# Support for direct Makefile invocation
+
+DESTDIR        = 
+MODDIR = $(DESTDIR)/lib/modules
+KVERS  = $(shell uname -r)
+KVER   = $(KVERS)
+VMODDIR = $(MODDIR)/$(KVER)
+INSTDIR        = extra
+#KSRC  = /usr/src/linux
+KSRC   = $(VMODDIR)/build
+KMODDIR        = $(KSRC)/drivers/misc/omnibook
+KDOCDIR        = $(KSRC)/Documentation/omnibook
+PWD    = $(shell pwd)
+TODAY  = $(shell date +%Y%m%d)
+DEPMOD = /sbin/depmod -aq
+RMMOD  = /sbin/modprobe -r
+INSMOD = /sbin/modprobe
+INSTALL        = install -m 644
+MKDIR  = mkdir -p
+RM     = rm -f
+FIND   = find
+
+all:            $(MODULE_NAME).ko
+
+clean:
+               make -C $(KSRC) M=$(PWD) clean
+               $(RM) -r *~ "#*#" .swp
+               $(RM) -r debian/omnibook-source *-stamp
+               $(RM) -r Module.symvers Modules.symvers
+
+install:       all
+               # Removing module from locations used by previous versions
+               $(RM) $(VMODDIR)/kernel/drivers/char/$(MODULE_NAME).ko
+               $(RM) $(VMODDIR)/kernel/drivers/misc/$(MODULE_NAME).ko
+               make INSTALL_MOD_PATH=$(DESTDIR) INSTALL_MOD_DIR=$(INSTDIR) -C $(KSRC) M=$(PWD) modules_install
+
+unload:
+               $(RMMOD) $(MODULE_NAME) || :
+
+load:          install unload
+               $(DEPMOD)
+               $(INSMOD) $(MODULE_NAME)
+
+uninstall:     unload
+               $(FIND) $(VMODDIR) -name "$(MODULE_NAME).ko" -exec $(RM) {} \;
+               $(DEPMOD)
+
+$(MODULE_NAME).ko:
+               $(MAKE) -C $(KSRC) SUBDIRS=$(PWD) modules
+
+kinstall:
+               $(RM) -r $(KMODDIR)
+               $(MKDIR) $(KMODDIR)
+               $(INSTALL) *.h *.c sections.lds $(KMODDIR)
+               $(MKDIR) $(KDOCDIR)
+               $(INSTALL) doc/README $(KDOCDIR)
+               
+kpatch:                kinstall
+               (cd $(KSRC); patch -p1 < $(PWD)/misc/omnibook-integration.patch)
+
+version:       
+               sed -i "s|^\(MODULE_VERSION = \).*|\1 2.$(TODAY)|" Makefile
+               sed -i "s|^\(MODULE_BRANCH = \).*|\1 release|" Makefile
+               sed -i "s|^\(2\.\)X\{8\}|\1$(TODAY)|" doc/ChangeLog
+               
+
+release:       clean version
+               mkdir -p ../$(MODULE_NAME)-2.$(TODAY)
+               cp -a *.h *.c *.lds Makefile doc misc ../$(MODULE_NAME)-2.$(TODAY)
+               rm -f ../$(MODULE_NAME)-2.$(TODAY).tar ../$(MODULE_NAME)-2.$(TODAY).tar.gz
+               (cd ..; tar cvf $(MODULE_NAME)-2.$(TODAY).tar $(MODULE_NAME)-2.$(TODAY); gzip -9 $(MODULE_NAME)-2.$(TODAY).tar)
+
+else
+# Support for kernel build system invocation
+
+ifneq ($(MODULE_BRANCH), release)
+EXTRA_CFLAGS += -DOMNIBOOK_MODULE_VERSION='"$(MODULE_VERSION)-$(MODULE_BRANCH)"'
+else
+EXTRA_CFLAGS += -DOMNIBOOK_MODULE_VERSION='"$(MODULE_VERSION)"'
+endif
+
+ifeq ($(OMNIBOOK_STANDALONE),y)
+
+ifeq ($(OMNIBOOK_WANT_BACKLIGHT),y)
+ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+# we support backlight interface only after 2.6.16
+ifeq ($(shell if [ $(SUBLEVEL) -gt 16 ] ; then echo -n 'y'; fi),y)
+EXTRA_CFLAGS += -DCONFIG_OMNIBOOK_BACKLIGHT
+else
+$(warning "Backlight support in only supported for kernel version newer than 2.6.16")
+$(warning "Disabling backlight sysfs interface")
+endif
+endif
+endif
+
+ifeq ($(OMNIBOOK_WANT_LEGACY),y)
+EXTRA_CFLAGS += -DCONFIG_OMNIBOOK_LEGACY
+endif
+
+ifndef CONFIG_ACPI_EC
+EXTRA_CFLAGS += -DCONFIG_OMNIBOOK_LEGACY
+endif
+
+ifneq ($(MODULE_BRANCH), release)
+ifneq ($(OMNIBOOK_WANT_DEBUG),n)       
+EXTRA_CFLAGS += -DCONFIG_OMNIBOOK_DEBUG # -Wa -g0
+endif
+else
+ifeq ($(OMNIBOOK_WANT_DEBUG),y)        
+EXTRA_CFLAGS += -DCONFIG_OMNIBOOK_DEBUG # -Wa -g0
+endif
+
+endif
+
+endif
+
+EXTRA_CFLAGS += -DOMNIBOOK_MODULE_NAME='"$(MODULE_NAME)"'
+EXTRA_LDFLAGS +=  $(src)/sections.lds
+
+obj-$(CONFIG_OMNIBOOK) += $(MODULE_NAME).o
+omnibook-objs := init.o lib.o ec.o kbc.o pio.o compal.o acpi.o nbsmi.o \
+          ac.o battery.o blank.o bluetooth.o cooling.o display.o dock.o \
+         dump.o fan.o fan_policy.o hotkeys.o info.o lcd.o muteled.o \
+         polling.o temperature.o touchpad.o wireless.o throttling.o 
+
+endif # End of kernel build system part
+
+# End of file
diff --git a/ac.c b/ac.c
new file mode 100644 (file)
index 0000000..f03cefb
--- /dev/null
+++ b/ac.c
@@ -0,0 +1,60 @@
+/*
+ * ac.c -- AC adapter related functions
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+static int omnibook_ac_read(char *buffer, struct omnibook_operation *io_op)
+{
+       int len = 0;
+       u8 ac;
+       int retval;
+
+       retval = backend_byte_read(io_op, &ac);
+       if (retval < 0)
+               return retval;
+
+       len += sprintf(buffer + len, "AC %s\n", (!!ac) ? "on-line" : "off-line");
+
+       return len;
+}
+
+static struct omnibook_tbl ac_table[] __initdata = {
+       {XE3GF | TSP10 | TSM30X | TSM70, SIMPLE_BYTE(EC, XE3GF_ADP, XE3GF_ADP_MASK)},
+       {XE3GC | AMILOD, SIMPLE_BYTE(EC, XE3GC_STA1, XE3GC_ADP_MASK)},
+       {OB500 | OB510 | OB6000 | OB6100 | XE4500, SIMPLE_BYTE(EC, OB500_STA2, OB500_ADP_MASK)},
+       {OB4150, SIMPLE_BYTE(EC, OB4150_ADP, OB4150_ADP_MASK)},
+       {XE2, SIMPLE_BYTE(EC, XE2_STA1, XE2_ADP_MASK)},
+       {0,}
+};
+
+static struct omnibook_feature __declared_feature ac_driver = {
+       .name = "ac",
+#ifdef CONFIG_OMNIBOOK_LEGACY
+       .enabled = 1,
+#else
+       .enabled = 0,
+#endif
+       .read = omnibook_ac_read,
+       .ectypes = XE3GF | XE3GC | OB500 | OB510 | OB6000 | OB6100 | XE4500 | OB4150 | XE2 | AMILOD | TSP10 | TSM70 | TSM30X,
+       .tbl = ac_table,
+};
+
+module_param_named(ac, ac_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(ac, "Use 0 to disable, 1 to enable AC adapter status monitoring");
+
+/* End of file */
diff --git a/acpi.c b/acpi.c
new file mode 100644 (file)
index 0000000..df1d13b
--- /dev/null
+++ b/acpi.c
@@ -0,0 +1,1160 @@
+/*
+ * acpi.c -- ACPI methods low-level access code for TSM70 class laptops
+ * 
+ * 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, 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.
+ *
+ * Written by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ *
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+#ifdef CONFIG_ACPI
+
+#include <acpi/acpi_drivers.h>
+#include <linux/workqueue.h>
+
+/* copied from drivers/input/serio/i8042-io.h */
+#define I8042_KBD_PHYS_DESC "isa0060/serio0"
+
+/*
+ * ACPI backend masks and strings
+ */
+
+#define GET_WIRELESS_METHOD "ANTR"
+#define SET_WIRELESS_METHOD "ANTW"
+#define WLEX_MASK      0x4
+#define WLAT_MASK      0x1
+#define BTEX_MASK      0x8
+#define BTAT_MASK      0x2
+#define KLSW_MASK      0x10
+
+#define GET_DISPLAY_METHOD "DOSS"
+#define SET_DISPLAY_METHOD "DOSW"
+/* Display reading masks CADL = detected, CSTE = enabled */
+#define        LCD_CADL        0x10
+#define        CRT_CADL        0x20
+#define        TVO_CADL        0x40
+#define        DVI_CADL        0x80
+#define        LCD_CSTE        0x1
+#define        CRT_CSTE        0x2
+#define        TVO_CSTE        0x4
+#define DVI_CSTE       0x8
+
+/* TSX205 Video-Out methods and return values */
+#define TSX205_SET_DISPLAY_METHOD "STBL"
+#define TSX205_SLI_DISPLAY_METHOD "SL01.VGA1.STBL"
+/* NOTE: Method DSSW seems to be some sort of auto-detect method */
+#define TSX205_AUTO_DISPLAY_METHOD "DSSW"
+#define TSX205_DSPY_DE 0x1F    /* DE - Detected and Enabled */
+#define TSX205_DSPY_DN 0x1D    /* DN - Detected and Not enabled */
+#define TSX205_DSPY_NE 0x0F    /* NE - Not detected and Enabled */
+#define TSX205_DSPY_NN 0x0D    /* NN - Not detected and Not enabled */
+
+#define GET_THROTTLE_METHOD "THRO"
+#define        SET_THROTTLE_METHOD "CLCK"
+
+static char ec_dev_list[][20] = {
+       "\\_SB.PCI0.LPCB.EC0",
+       "\\_SB.PCI0.LPC0.EC0",
+};
+
+/* TSX205 HCI and display handles */
+static char tsx205_dev_list[][20] = {
+       "\\_SB.VALZ",
+       "\\_SB.PCI0.PEGP.VGA"
+};
+
+/* TSX205 GET video-out methods */
+static char tsx205_video_list[][20] = {
+       "LCD._DCS",
+       "CRT._DCS",
+       "TV._DCS",
+       "DVI._DCS",
+       "SL01.VGA1.LCD._DCS",
+       "SL01.VGA1.CRT._DCS",
+       "SL01.VGA1.TV._DCS",
+       "SL01.VGA1.DVI._DCS",
+};
+
+#define TOSHIBA_ACPI_BT_CLASS "bluetooth"
+#define TOSHIBA_ACPI_DEVICE_NAME "bluetooth adapter"
+
+#define TOSH_BT_ACTIVATE_USB   "AUSB"
+#define TOSH_BT_DISABLE_USB    "DUSB"
+#define TOSH_BT_POWER_ON       "BTPO"
+#define TOSH_BT_POWER_OFF      "BTPF"
+#define TOSH_BT_STATUS         "BTST"
+#define        TOSH_BT_KSST_MASK       0x1
+#define        TOSH_BT_USB_MASK        0x40
+#define        TOSH_BT_POWER_MASK      0x80
+
+/*
+ * ACPI driver for Toshiba Bluetooth device
+ */
+static int omnibook_acpi_bt_add(struct acpi_device *device);
+static int omnibook_acpi_bt_remove(struct acpi_device *device, int type);
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
+static const struct acpi_device_id omnibook_bt_ids[] = {
+       {"TOS6205", 0},
+       {"", 0},
+};
+
+static struct acpi_driver omnibook_bt_driver = {
+       .name   = OMNIBOOK_MODULE_NAME,
+       .class  = TOSHIBA_ACPI_BT_CLASS,
+       .ids    = omnibook_bt_ids,
+       .ops    = {
+                       .add    =  omnibook_acpi_bt_add,
+                       .remove =  omnibook_acpi_bt_remove,
+                 },
+};
+#else /* 2.6.23 */
+static struct acpi_driver omnibook_bt_driver = {
+       .name   = OMNIBOOK_MODULE_NAME,
+       .class  = TOSHIBA_ACPI_BT_CLASS,
+       .ids    = "TOS6205",
+       .ops    = {
+                       .add    =  omnibook_acpi_bt_add,
+                       .remove =  omnibook_acpi_bt_remove,
+                 },
+};
+#endif /* 2.6.23 */
+
+
+/*
+ * ACPI backend private data structure
+ */
+struct acpi_backend_data {
+       acpi_handle ec_handle;  /* Handle on ACPI EC device */
+       acpi_handle bt_handle;  /* Handle on ACPI BT device */
+       acpi_handle hci_handle; /* Handle on ACPI HCI device */
+       acpi_handle dis_handle; /* Handle on ACPI Display device */
+       unsigned has_antr_antw:1; /* Are there ANTR/ANTW methods in the EC device ? */
+       unsigned has_doss_dosw:1; /* Are there DOSS/DOSW methods in the EC device ? */
+       unsigned has_sli:1; /* Does the laptop has SLI enabled ? */
+       struct input_dev *acpi_input_dev;
+       struct work_struct fnkey_work;
+};
+
+/*
+ * Hotkeys workflow:
+ * 1. Fn+Foo pressed
+ * 2. Scancode 0x6e generated by kbd controller
+ * 3. Scancode 0x6e caught by omnibook input handler
+ * 4. INFO method has keycode of last actually pressed Fn key
+ * 5. acpi_scan_table used to associate a detected keycode with a generated one
+ * 6. Generated keycode issued using the omnibook input device
+ */
+
+/*
+ * The input handler should only bind with the standard AT keyboard.
+ * XXX: Scancode 0x6e won't be detected if the keyboard has already been
+ * grabbed (the Xorg event input driver do that)
+ */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21))
+static int hook_connect(struct input_handler *handler,
+                                        struct input_dev *dev,
+                                        const struct input_device_id *id)
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
+static struct input_handle *hook_connect(struct input_handler *handler,
+                                        struct input_dev *dev,
+                                        const struct input_device_id *id)
+#else
+static struct input_handle *hook_connect(struct input_handler *handler,
+                                        struct input_dev *dev,
+                                        struct input_device_id *id)
+#endif
+{
+       struct input_handle *handle;
+       int error;
+
+       /* the 0x0001 vendor magic number is found in atkbd.c */
+       if(!(dev->id.bustype == BUS_I8042 && dev->id.vendor == 0x0001))
+               goto out_nobind;
+
+       if(!strstr(dev->phys, I8042_KBD_PHYS_DESC))
+               goto out_nobind;
+
+       dprintk("hook_connect for device %s.\n", dev->name);
+
+       if(dev->grab)
+               printk(O_WARN "Input device is grabbed by %s, Fn hotkeys won't work.\n",
+                       dev->grab->name);
+
+       handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
+       if (!handle)
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21))
+               return -ENOMEM;
+#else
+               return NULL;
+#endif
+
+       handle->dev = dev;
+       handle->handler = handler;
+       handle->name = "omnibook_scancode_hook";
+       handle->private = handler->private;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21))
+       error = input_register_handle(handle);
+       if (error) {
+               dprintk("register_handle failed\n");
+               goto out_nobind_free;
+       } 
+       error = input_open_device(handle);
+       if (error) {
+               dprintk("register_handle failed\n");
+               input_unregister_handle(handle);
+               goto out_nobind_free;
+       } 
+       
+#else
+       status=input_open_device(handle);
+       if (error==0) dprintk("Input device opened\n");
+       else { 
+               dprintk("opening input device failed\n");
+               goto out_nobind_free;
+       }
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21))
+       return 0;
+out_nobind_free:
+       kfree(handle);
+out_nobind:
+       return -ENODEV;
+#else
+       return handle;
+out_nobind_free:
+       kfree(handle);
+out_nobind:
+       return NULL;
+#endif 
+}
+
+static void hook_disconnect(struct input_handle *handle)
+{
+       dprintk("hook_disconnect.\n");
+       input_close_device(handle);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21))
+       input_unregister_handle(handle);
+#endif
+       kfree(handle);
+}
+
+/*
+ * Hook for scancode 0x6e. Actual handling is done in a workqueue.
+ */
+static void hook_event(struct input_handle *handle, unsigned int event_type,
+                     unsigned int event_code, int value)
+{
+       if (event_type == EV_MSC && event_code == MSC_SCAN && value == ACPI_FN_SCAN)
+               schedule_work(&((struct acpi_backend_data *)handle->private)->fnkey_work);
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
+static const struct input_device_id hook_ids[] = {
+#else
+static struct input_device_id hook_ids[] = {
+#endif
+       {
+                .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
+                .evbit = { BIT(EV_KEY) },
+        },
+       { },    /* Terminating entry */
+};
+
+static struct input_handler hook_handler = {
+       .event          = hook_event,
+       .connect        = hook_connect,
+       .disconnect     = hook_disconnect,
+       .name           = OMNIBOOK_MODULE_NAME,
+       .id_table       = hook_ids,
+};
+
+/*
+ * Detected scancode to keycode table
+ */
+static const struct {
+       unsigned int scancode;
+       unsigned int keycode;
+} acpi_scan_table[] = {
+       { HCI_FN_RELEASED,    KEY_FN},
+       { HCI_MUTE,           KEY_MUTE},
+       { HCI_BREAK,          KEY_COFFEE},
+       { HCI_1,              KEY_ZOOMOUT},
+       { HCI_2,              KEY_ZOOMIN},
+       { HCI_SPACE,          KEY_ZOOMRESET},
+       { HCI_BSM,            KEY_BATTERY},
+       { HCI_SUSPEND,        KEY_SLEEP},
+       { HCI_HIBERNATE,      KEY_SUSPEND},
+       { HCI_VIDEOOUT,       KEY_SWITCHVIDEOMODE},
+       { HCI_BRIGHTNESSDOWN, KEY_BRIGHTNESSDOWN},
+       { HCI_BRIGHTNESSUP,   KEY_BRIGHTNESSUP},
+       { HCI_WLAN,           KEY_WLAN},
+       { HCI_TOUCHPAD,       KEY_PROG1},
+       { HCI_FN_PRESSED,     KEY_FN},
+       { 0, 0},
+};
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
+static void omnibook_handle_fnkey(struct work_struct *work);
+#else
+static void omnibook_handle_fnkey(void* data);
+#endif
+
+/*
+ * Register the input handler and the input device in the input subsystem
+ */
+static int register_input_subsystem(struct acpi_backend_data *priv_data)
+{
+       int i, retval = 0;
+       struct input_dev *acpi_input_dev;
+
+       acpi_input_dev = input_allocate_device();
+       if (!acpi_input_dev) {
+               retval = -ENOMEM;
+               goto out;
+       }
+
+       acpi_input_dev->name = "Omnibook ACPI scancode generator";
+       acpi_input_dev->phys = "omnibook/input0";
+       acpi_input_dev->id.bustype = BUS_HOST;
+       
+       set_bit(EV_KEY, acpi_input_dev->evbit);
+       
+       for(i=0 ; i < ARRAY_SIZE(acpi_scan_table); i++)
+               set_bit(acpi_scan_table[i].keycode, acpi_input_dev->keybit);
+
+       retval = input_register_device(acpi_input_dev);
+       if (retval) {
+               input_free_device(acpi_input_dev);
+               goto out;
+       }
+
+       priv_data->acpi_input_dev = acpi_input_dev;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
+       INIT_WORK(&priv_data->fnkey_work, *omnibook_handle_fnkey);
+#else
+       INIT_WORK(&priv_data->fnkey_work, *omnibook_handle_fnkey, priv_data);
+#endif
+
+
+       hook_handler.private = priv_data;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
+       retval = input_register_handler(&hook_handler); 
+#else
+       input_register_handler(&hook_handler);
+#endif
+
+       out:    
+       return retval;
+}
+
+/*
+ * Execute an ACPI method which return either an integer or nothing
+ * and that require 0 or 1 numerical argument
+ * (acpi_evaluate_object wrapper)
+ */
+static int omnibook_acpi_execute(acpi_handle dev_handle, char *method, const int *param, int *result)
+{
+
+       struct acpi_object_list args_list;
+       struct acpi_buffer buff;
+       union acpi_object arg, out_objs[1];
+       
+       if (param) {
+               args_list.count = 1;
+               args_list.pointer = &arg;
+               arg.type = ACPI_TYPE_INTEGER;
+               arg.integer.value = *param;
+       } else
+               args_list.count = 0;
+
+       buff.length = sizeof(out_objs);
+       buff.pointer = out_objs;
+
+       if (acpi_evaluate_object(dev_handle, method, &args_list, &buff) != AE_OK) {
+               printk(O_ERR "ACPI method execution failed\n");
+               return -EIO;
+       }
+
+       if (!result)            /* We don't care what the method returned here */
+               return 0;
+
+       if (out_objs[0].type != ACPI_TYPE_INTEGER) {
+               printk(O_ERR "ACPI method result is not a number\n");
+               return -EINVAL;
+       }
+
+       *result = out_objs[0].integer.value;
+       return 0;
+}
+
+/*
+ * Probe for expected ACPI devices
+ */
+static int omnibook_acpi_init(const struct omnibook_operation *io_op)
+{
+       int retval = 0; 
+       acpi_handle dev_handle, method_handle, hci_handle, dis_handle;
+       int i;
+       int has_sli = 0;
+       struct acpi_backend_data *priv_data;
+       
+       if (unlikely(acpi_disabled)) {
+               printk(O_ERR "ACPI is disabled: feature unavailable.\n");
+               return -ENODEV;
+       }
+
+       if (!io_op->backend->data) {
+               dprintk("Try to init ACPI backend\n");
+               mutex_init(&io_op->backend->mutex);
+               mutex_lock(&io_op->backend->mutex);
+               kref_init(&io_op->backend->kref);
+               priv_data = kzalloc(sizeof(struct acpi_backend_data), GFP_KERNEL);
+               if (!priv_data) {
+                       retval = -ENOMEM;
+                       goto error0;
+               }
+
+               /* Locate ACPI EC device, acpi_get_handle set dev_handle to NULL if not found */
+               for (i = 0; i < ARRAY_SIZE(ec_dev_list); i++) {
+                       if (acpi_get_handle(NULL, ec_dev_list[i], &dev_handle) == AE_OK) {
+                               dprintk("ACPI EC device found\n");
+                               priv_data->ec_handle = dev_handle;
+                               break;
+                       }
+               }
+               
+               if (!dev_handle) {
+                       printk(O_ERR "Can't get handle on ACPI EC device.\n");
+                       retval = -ENODEV;
+                       goto error1;
+               }
+
+               /* Probe for HCI and Display devices only on TSX205 models */
+               if (omnibook_ectype & TSX205) {
+                       if (acpi_get_handle(NULL, tsx205_dev_list[0], &hci_handle) == AE_OK) {
+                               dprintk("Toshiba X205 HCI device found\n");
+                               priv_data->hci_handle = hci_handle;
+                       }
+
+                       if (!hci_handle) {
+                               printk(O_ERR "Couldn't get HCI handle.\n");
+                               retval = -ENODEV;
+                               goto error1;
+                       }
+
+                       if (acpi_get_handle(NULL, tsx205_dev_list[1], &dis_handle) == AE_OK)
+                               priv_data->dis_handle = dis_handle;
+
+                       if (!dis_handle) {
+                               printk(O_ERR "Couldn't get X205 Display handle.\n");
+                               retval = -ENODEV;
+                               goto error1;
+                       }
+
+                       /* Does the laptop has SLI enabled? */
+                       omnibook_acpi_execute(dis_handle, (char *)TSX205_SLIVDO_METHOD, NULL, &has_sli);
+                       if (has_sli)
+                               dprintk("Toshiba X205 Display device found (SLI).\n");
+                       else
+                               dprintk("Toshiba X205 Display device found.\n");
+
+                       priv_data->has_sli = has_sli;
+               }
+
+               if ((acpi_get_handle( dev_handle, GET_WIRELESS_METHOD, &method_handle) == AE_OK) &&
+                   (acpi_get_handle( dev_handle, SET_WIRELESS_METHOD, &method_handle) == AE_OK))
+                       priv_data->has_antr_antw = 1;
+
+               if (omnibook_ectype & TSX205) {
+                       if ((acpi_get_handle(dis_handle, TSX205_AUTO_DISPLAY_METHOD, &method_handle) ==  AE_OK) &&
+                           (acpi_get_handle(dis_handle, TSX205_AUTO_DISPLAY_METHOD, &method_handle) ==  AE_OK))
+                               priv_data->has_doss_dosw = 1;
+               } else {
+                       if ((acpi_get_handle( dev_handle, GET_DISPLAY_METHOD, &method_handle) == AE_OK) &&
+                           (acpi_get_handle( dev_handle, SET_DISPLAY_METHOD, &method_handle) == AE_OK))
+                               priv_data->has_doss_dosw = 1;
+               }
+
+               retval = register_input_subsystem(priv_data);
+               if(retval)
+                       goto error1;
+
+               io_op->backend->data = (void *) priv_data;
+               
+               mutex_unlock(&io_op->backend->mutex);
+               
+               /* attempt to register Toshiba bluetooth ACPI driver */
+               acpi_bus_register_driver(&omnibook_bt_driver);
+
+               dprintk("ACPI backend init OK\n");
+               
+               return 0;
+
+       } else {
+               dprintk("ACPI backend has already been initialized\n");
+               kref_get(&io_op->backend->kref);
+               return 0;
+       }
+               
+       error1:
+       kfree(priv_data);
+       io_op->backend->data = NULL;
+       error0:
+       mutex_unlock(&io_op->backend->mutex);
+       mutex_destroy(&io_op->backend->mutex);
+       return retval;
+}
+
+static void omnibook_acpi_free(struct kref *ref)
+{
+       struct omnibook_backend *backend;
+       struct acpi_backend_data *priv_data;
+
+       backend = container_of(ref, struct omnibook_backend, kref);
+       priv_data = backend->data;
+
+       dprintk("ACPI backend not used anymore: disposing\n");
+
+       
+       dprintk("ptr addr: %p driver name: %s\n",&omnibook_bt_driver, omnibook_bt_driver.name);
+       acpi_bus_unregister_driver(&omnibook_bt_driver);
+
+       flush_scheduled_work();
+       input_unregister_handler(&hook_handler);
+       input_unregister_device(priv_data->acpi_input_dev);
+       
+       mutex_lock(&backend->mutex);
+       kfree(backend->data);
+       backend->data = NULL;
+       mutex_unlock(&backend->mutex);
+       mutex_destroy(&backend->mutex);
+}
+
+static void omnibook_acpi_exit(const struct omnibook_operation *io_op)
+{
+       dprintk("Trying to dispose ACPI backend\n");
+       kref_put(&io_op->backend->kref, omnibook_acpi_free);
+}
+
+/* forward declaration */
+struct omnibook_backend acpi_backend;
+
+/* Function taken from toshiba_acpi */
+static acpi_status hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
+{
+       struct acpi_backend_data *priv_data = acpi_backend.data;
+       struct acpi_object_list params;
+       union acpi_object in_objs[HCI_WORDS];
+       struct acpi_buffer results;
+       union acpi_object out_objs[HCI_WORDS + 1];
+       acpi_status status;
+       int i;
+
+       params.count = HCI_WORDS;
+       params.pointer = in_objs;
+       for (i = 0; i < HCI_WORDS; ++i) {
+               in_objs[i].type = ACPI_TYPE_INTEGER;
+               in_objs[i].integer.value = in[i];
+       }
+
+       results.length = sizeof(out_objs);
+       results.pointer = out_objs;
+
+       status = acpi_evaluate_object(priv_data->hci_handle, (char *)HCI_METHOD, &params,
+                                     &results);
+       if ((status == AE_OK) && (out_objs->package.count <= HCI_WORDS)) {
+               for (i = 0; i < out_objs->package.count; ++i) {
+                       out[i] = out_objs->package.elements[i].integer.value;
+               }
+       }
+
+       return status;
+}
+
+/*
+ * Set Bluetooth device state using the Toshiba BT device
+ */
+static int set_bt_status(const struct acpi_backend_data *priv_data, unsigned int state)
+{
+       int retval = 0;
+
+       if (state) {
+               retval = omnibook_acpi_execute(priv_data->bt_handle, TOSH_BT_ACTIVATE_USB, NULL, NULL);
+               if (retval)
+                       goto out;
+               retval = omnibook_acpi_execute(priv_data->bt_handle, TOSH_BT_POWER_ON, NULL, NULL);
+               if (retval)
+                       goto out;
+       } else {
+               retval = omnibook_acpi_execute(priv_data->bt_handle, TOSH_BT_DISABLE_USB, NULL, NULL);
+               if (retval)
+                       goto out;
+               retval = omnibook_acpi_execute(priv_data->bt_handle, TOSH_BT_POWER_OFF, NULL, NULL);
+               if (retval)
+                       goto out;
+       }
+       out:
+       return retval;
+}
+
+static int omnibook_acpi_bt_add(struct acpi_device *device)
+{
+       int retval;
+       struct acpi_backend_data *priv_data = acpi_backend.data;
+       
+       dprintk("Enabling Toshiba Bluetooth ACPI device.\n");
+       strcpy(acpi_device_name(device), TOSHIBA_ACPI_DEVICE_NAME);
+       strcpy(acpi_device_class(device), TOSHIBA_ACPI_BT_CLASS);
+
+       /* Save handle in backend private data structure. ugly. */
+
+       mutex_lock(&acpi_backend.mutex);
+       priv_data->bt_handle = device->handle;
+       retval = set_bt_status(priv_data, 1);
+       mutex_unlock(&acpi_backend.mutex);
+
+       return retval;
+}
+
+static int omnibook_acpi_bt_remove(struct acpi_device *device, int type)
+{
+       int retval;
+       struct acpi_backend_data *priv_data = acpi_backend.data;
+
+       mutex_lock(&acpi_backend.mutex);
+       dprintk("Disabling Toshiba Bluetooth ACPI device.\n");
+       retval = set_bt_status(priv_data, 0);
+       priv_data->bt_handle = NULL;
+       mutex_unlock(&acpi_backend.mutex);
+       
+       return retval;
+}
+
+/*
+ * Get Bluetooth status using the BTST method
+ */
+static int get_bt_status(const struct acpi_backend_data *priv_data, unsigned int *state)
+{
+       int retval = 0;
+       int raw_state;
+
+       if ((retval = omnibook_acpi_execute(priv_data->bt_handle, TOSH_BT_STATUS, NULL, &raw_state)))
+               return retval;
+
+       dprintk("BTST raw_state: %x\n", raw_state);
+
+       *state = BT_EX;
+       *state |= ((raw_state & TOSH_BT_USB_MASK) && (raw_state & TOSH_BT_POWER_MASK)) ? BT_STA : 0;
+
+       return retval;
+}
+
+/*
+ * Get the Bluetooth + Wireless status using the ANTR method
+ * FIXME: what if ANTR and BTST disagree ? we thrust ANTR for now
+ */
+static int get_wireless_status(const struct acpi_backend_data *priv_data, unsigned int *state)
+{
+       int retval = 0;
+       int raw_state;
+
+       if ((retval = omnibook_acpi_execute(priv_data->ec_handle, GET_WIRELESS_METHOD, NULL, &raw_state)))
+               return retval;
+
+       dprintk("get_wireless raw_state: %x\n", raw_state);
+
+       *state = (raw_state & WLEX_MASK) ? WIFI_EX : 0;
+       *state |= (raw_state & WLAT_MASK) ? WIFI_STA : 0;
+       *state |= (raw_state & KLSW_MASK) ? KILLSWITCH : 0;
+       *state |= (raw_state & BTEX_MASK) ? BT_EX : 0;
+       *state |= (raw_state & BTAT_MASK) ? BT_STA : 0;
+
+       return retval;
+}
+
+static int get_tsx205_wireless_status(const struct acpi_backend_data *priv_data, unsigned int *state)
+{
+       int retval = 0;
+       int raw_state;
+       u32 in[HCI_WORDS] = { HCI_GET, HCI_RF_CONTROL, 0, HCI_WIRELESS_CHECK, 0, 0 };
+       u32 out[HCI_WORDS];
+
+       hci_raw(in, out);
+
+       /* Now let's check the killswitch */
+       if ((retval = omnibook_acpi_execute(priv_data->ec_handle, TSX205_KILLSW_METHOD, NULL, &raw_state)))
+               return retval;
+
+       dprintk("get_wireless raw_state: %x\n", out[2]);
+
+       *state = ((out[2] & 0xff)) ? WIFI_EX : 0;
+       *state |= (raw_state) ? WIFI_STA : 0;
+       *state |= (!raw_state) ? KILLSWITCH : 0;
+
+       /* And finally BT */
+       if ((retval = omnibook_acpi_execute(priv_data->bt_handle, TOSH_BT_STATUS, NULL, &raw_state)))
+               return retval;
+       
+       *state |= BT_EX;
+       *state |= ((raw_state & TOSH_BT_USB_MASK) && (raw_state & TOSH_BT_POWER_MASK)) ? BT_STA : 0;
+
+       return retval;
+}
+
+static int omnibook_acpi_get_wireless(const struct omnibook_operation *io_op, unsigned int *state)
+{
+       int retval;
+       struct acpi_backend_data *priv_data = io_op->backend->data;
+
+       /* use BTST (BT device) if we don't have ANTR/ANTW (EC device) */
+       if (omnibook_ectype & TSX205)
+               retval = get_tsx205_wireless_status(priv_data, state);
+       else if (priv_data->has_antr_antw)
+               retval = get_wireless_status(priv_data, state);
+       else if(priv_data->bt_handle)
+               retval = get_bt_status(priv_data, state);
+       else
+               retval = -ENODEV;
+
+       return retval;
+}
+
+/*
+ * Set the Bluetooth + Wireless status using the ANTW method
+ */
+static int set_wireless_status(const struct acpi_backend_data *priv_data, unsigned int state)
+{
+       int retval;
+       int raw_state;
+
+       raw_state = !!(state & WIFI_STA);       /* bit 0 */
+       raw_state |= !!(state & BT_STA) << 0x1; /* bit 1 */
+
+       dprintk("set_wireless raw_state: %x\n", raw_state);
+
+       retval = omnibook_acpi_execute(priv_data->ec_handle, SET_WIRELESS_METHOD, &raw_state, NULL);
+
+       return retval;
+}
+
+static int set_tsx205_wireless_status(const struct acpi_backend_data *priv_data, unsigned int state)
+{
+       int retval;
+       int raw_state = !!(state & WIFI_STA);
+       u32 in[HCI_WORDS] = { HCI_SET, HCI_RF_CONTROL, raw_state, HCI_WIRELESS_POWER, 0, 0 };
+       u32 out[HCI_WORDS];
+
+       dprintk("set_wireless raw_state: %x\n", raw_state);
+
+       hci_raw(in, out);
+
+       raw_state |= !!(state & BT_STA) << 0x1; /* bit 1 */
+
+       /* BT status */
+       retval = set_bt_status(priv_data->bt_handle, state);
+
+       return retval;
+}
+
+static int omnibook_acpi_set_wireless(const struct omnibook_operation *io_op, unsigned int state)
+{
+       int retval = -ENODEV;
+       struct acpi_backend_data *priv_data = io_op->backend->data;
+
+       /* First try the TSX205 methods */
+       if(omnibook_ectype & TSX205)
+               retval = set_tsx205_wireless_status(priv_data, state);
+
+       /* Then try the ANTR/ANTW methods */
+       if(priv_data->has_antr_antw)
+               retval = set_wireless_status(priv_data, state);
+       
+       /* Then try the bluetooth ACPI device if present */
+       if(priv_data->bt_handle)
+               retval = set_bt_status(priv_data, (state & BT_STA));
+
+       return retval;
+}
+
+static int tsx205_get_display(const struct acpi_backend_data *priv_data, unsigned int *state, unsigned int device)
+{
+       int retval = 0;
+       int raw_state = 0;
+
+       retval = omnibook_acpi_execute(priv_data->dis_handle, tsx205_video_list[device], NULL, &raw_state);
+       if (retval < 0) {
+               dprintk(O_ERR "Failed to get video device (%d) state.\n", device);
+               return retval;
+       }
+
+       /* Ugly, but better than nothing... */
+       switch (device) {
+       case 0:
+       case 4: /* LCD device */
+               dprintk("get_display LCD (%d) raw_state: %x\n", device, raw_state);
+               if (raw_state == TSX205_DSPY_DE) {
+                       *state |= DISPLAY_LCD_DET;
+                       *state |= DISPLAY_LCD_ON;
+               } else
+               if (raw_state == TSX205_DSPY_DN)
+                       *state |= DISPLAY_LCD_DET;
+               else if (raw_state == TSX205_DSPY_NE)
+                       *state |= DISPLAY_LCD_ON;
+               break;
+       case 1:
+       case 5: /* CRT device */
+               dprintk("get_display CRT (%d) raw_state: %x\n", device, raw_state);
+               if (raw_state == TSX205_DSPY_DE) {
+                       *state |= DISPLAY_CRT_DET;
+                       *state |= DISPLAY_CRT_ON;
+               } else
+               if (raw_state == TSX205_DSPY_DN)
+                       *state |= DISPLAY_CRT_DET;
+               else if (raw_state == TSX205_DSPY_NE)
+                       *state |= DISPLAY_CRT_ON;
+               break;
+       case 2:
+       case 6: /* TV-OUT device */
+               dprintk("get_display TV-OUT (%d) raw_state: %x\n", device, raw_state);
+               if (raw_state == TSX205_DSPY_DE) {
+                       *state |= DISPLAY_TVO_DET;
+                       *state |= DISPLAY_TVO_ON;
+               } else
+               if (raw_state == TSX205_DSPY_DN)
+                       *state |= DISPLAY_TVO_DET;
+               else if (raw_state == TSX205_DSPY_NE)
+                       *state |= DISPLAY_TVO_ON;
+               break;
+       case 3:
+       case 7: /* DVI device */
+               dprintk("get_display DVI (%d) raw_state: %x\n", device, raw_state);
+               if (raw_state == TSX205_DSPY_DE) {
+                       *state |= DISPLAY_DVI_DET;
+                       *state |= DISPLAY_DVI_ON;
+               } else
+               if (raw_state == TSX205_DSPY_DN)
+                       *state |= DISPLAY_DVI_DET;
+               else if (raw_state == TSX205_DSPY_NE)
+                       *state |= DISPLAY_DVI_ON;
+               break;
+       }
+
+       return retval;
+}
+
+static int omnibook_acpi_get_display(const struct omnibook_operation *io_op, unsigned int *state)
+{
+       int retval = 0;
+       int raw_state = 0;
+       struct acpi_backend_data *priv_data = io_op->backend->data;
+       
+       if(!priv_data->has_doss_dosw)
+               return -ENODEV;
+
+       if (omnibook_ectype & TSX205) {
+               int i;
+
+               /* Loop 'tru the different Video-Out devices */
+               if (priv_data->has_sli)
+                       for (i = 4; i < ARRAY_SIZE(tsx205_video_list); i++)
+                               retval = tsx205_get_display(priv_data, state, i);
+               else
+                       for (i = 0; i < 4; i++)
+                               retval = tsx205_get_display(priv_data, state, i);
+
+               if (retval < 0)
+                       return -EIO;
+       
+               goto vidout;
+       }
+
+       retval = omnibook_acpi_execute(priv_data->ec_handle, GET_DISPLAY_METHOD, NULL, &raw_state);
+       if (retval < 0)
+               return retval;
+
+       dprintk("get_display raw_state: %x\n", raw_state);
+
+       /* Backend specific to backend-neutral conversion */
+       *state = (raw_state & LCD_CSTE) ? DISPLAY_LCD_ON : 0;
+       *state |= (raw_state & CRT_CSTE) ? DISPLAY_CRT_ON : 0;
+       *state |= (raw_state & TVO_CSTE) ? DISPLAY_TVO_ON : 0;
+       *state |= (raw_state & DVI_CSTE) ? DISPLAY_DVI_ON : 0;
+
+       *state |= (raw_state & LCD_CADL) ? DISPLAY_LCD_DET : 0;
+       *state |= (raw_state & CRT_CADL) ? DISPLAY_CRT_DET : 0;
+       *state |= (raw_state & TVO_CADL) ? DISPLAY_TVO_DET : 0;
+       *state |= (raw_state & DVI_CADL) ? DISPLAY_DVI_DET : 0;
+
+vidout:
+       return DISPLAY_LCD_ON | DISPLAY_CRT_ON | DISPLAY_TVO_ON | DISPLAY_DVI_ON
+           | DISPLAY_LCD_DET | DISPLAY_CRT_DET | DISPLAY_TVO_DET | DISPLAY_DVI_DET;
+}
+
+static const unsigned int acpi_display_mode_list[] = {
+       DISPLAY_LCD_ON,
+       DISPLAY_CRT_ON,
+       DISPLAY_LCD_ON | DISPLAY_CRT_ON,
+       DISPLAY_TVO_ON,
+       DISPLAY_LCD_ON | DISPLAY_TVO_ON,
+       DISPLAY_CRT_ON | DISPLAY_TVO_ON,
+       DISPLAY_LCD_ON | DISPLAY_CRT_ON | DISPLAY_TVO_ON,
+       DISPLAY_DVI_ON,
+       DISPLAY_LCD_ON | DISPLAY_DVI_ON,
+};
+
+static int omnibook_acpi_set_display(const struct omnibook_operation *io_op, unsigned int state)
+{
+       int retval = 0;
+       int i; 
+       int matched = -1;
+       struct acpi_backend_data *priv_data = io_op->backend->data;
+
+       if(!priv_data->has_doss_dosw)
+               return -ENODEV;
+
+       for (i = 0; i < ARRAY_SIZE(acpi_display_mode_list); i++) {
+               if (acpi_display_mode_list[i] == state) {
+                       matched = i + 1;        /* raw state is array row number + 1 */
+                       break;
+               }
+       }
+       if (matched == -1) {
+               printk("Display mode %x is unsupported.\n", state);
+               return -EINVAL;
+       }
+
+       dprintk("set_display raw_state: %x\n", matched);
+
+       if (omnibook_ectype & TSX205) {
+               if (priv_data->has_sli)
+                       retval = omnibook_acpi_execute(priv_data->dis_handle, TSX205_SLI_DISPLAY_METHOD, &matched, NULL);
+               else
+                       retval = omnibook_acpi_execute(priv_data->dis_handle, TSX205_SET_DISPLAY_METHOD, &matched, NULL);
+       } else
+               retval = omnibook_acpi_execute(priv_data->ec_handle, SET_DISPLAY_METHOD, &matched, NULL);
+       if (retval < 0)
+               return retval;
+
+       return DISPLAY_LCD_ON | DISPLAY_CRT_ON | DISPLAY_TVO_ON | DISPLAY_DVI_ON;
+}
+
+static int omnibook_acpi_get_throttle(const struct omnibook_operation *io_op, unsigned int *state)
+{
+       int retval;
+       int thtl_en = 0, thtl_dty = 0;
+       int param;
+       struct acpi_backend_data *priv_data = io_op->backend->data;
+       
+       param = 0;
+       /* Read THEN aka THTL_EN in ICH6M datasheets */
+       retval = omnibook_acpi_execute(priv_data->ec_handle, GET_THROTTLE_METHOD, &param, &thtl_en); 
+       if ( thtl_en == 0 ) {
+               *state = 0;
+               return retval;
+       }
+       param = 1;
+       /* Read DUTY aka THTL_DTY in ICH6M datasheets */
+       retval = omnibook_acpi_execute(priv_data->ec_handle, GET_THROTTLE_METHOD, &param, &thtl_dty);
+       WARN_ON(thtl_dty > 7); /* We shouldn't encounter more than 7 throttling level */
+       *state = 8 - thtl_dty; /* THTL_DTY and ACPI T-state are reverse mapped */
+       return retval;
+}
+
+static int omnibook_acpi_set_throttle(const struct omnibook_operation *io_op, unsigned int state)
+{
+       struct acpi_backend_data *priv_data = io_op->backend->data;
+       /* THTL_DTY and ACPI T-state are reverse mapped */
+       /* throttling.c already clamped state between 0 and 7 */
+       if (state) 
+               state = 8 - state;
+
+       return omnibook_acpi_execute(priv_data->ec_handle, SET_THROTTLE_METHOD, &state, NULL);
+}
+
+/*
+ * Fn+foo hotkeys handling
+ */
+static int omnibook_hci_get_hotkeys(const struct omnibook_operation *io_op, unsigned int *state)
+{
+       u32 in[HCI_WORDS] = { HCI_GET, HCI_HOTKEY_EVENT, 0, 0, 0, 0 };
+       u32 out[HCI_WORDS];
+       acpi_status status = hci_raw(in, out);
+
+       if (status != AE_OK)
+               return HCI_FAILURE;
+
+       dprintk("get_hotkeys raw_state: %x\n", out[2]);
+
+       *state = (out[2] & ACPI_FN_MASK) ? HKEY_FN : 0;
+
+       return 0;
+}
+
+static int omnibook_hci_set_hotkeys(const struct omnibook_operation *io_op, unsigned int state)
+{
+       u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
+       u32 out[HCI_WORDS];
+       acpi_status status;
+       in[0] = HCI_SET;
+       in[1] = HCI_HOTKEY_EVENT;
+       in[2] = (state & HKEY_FN) ? 1 : 0;
+
+       status = hci_raw(in, out);
+
+       dprintk("set_hotkeys (Fn interface) raw_state: %x\n", in[2]);
+
+       return (status == AE_OK) ? out[0] : HCI_FAILURE;
+}
+
+static int omnibook_acpi_get_events(unsigned int *state)
+{
+       acpi_status status;
+       struct acpi_backend_data *priv_data = acpi_backend.data;
+  
+       /* We need to call the NTFY method first so it can activate the TECF variable */
+       status = omnibook_acpi_execute(priv_data->ec_handle, TSX205_NOTIFY_METHOD, NULL, NULL);
+       if (status != AE_OK) {
+               dprintk(O_ERR "Failed to activate NTFY method.\n");
+               return -EIO;
+       }
+
+       /* Now we can poll the INFO method to get last pressed hotkey */
+       status = omnibook_acpi_execute(priv_data->hci_handle, TSX205_EVENTS_METHOD, NULL, state);
+       if (status != AE_OK) {
+               dprintk(O_ERR "Failed to get Hotkey event.\n");
+               return -EIO;
+       }
+
+       /* We only care about a key press, so just report the Fn key Press/Release */
+       if ( ((*state & ~0x80) == 0x100) || ((*state & ~0x80) == 0x17f) )
+               *state &= ~0x80;
+
+       return status;
+}
+
+/*
+ * Adjust the lcd backlight level by delta.
+ * Used for Fn+F6/F7 keypress
+ */
+static int adjust_brighness(int delta)
+{
+       struct omnibook_feature *lcd_feature = omnibook_find_feature("lcd");
+       struct omnibook_operation *io_op;
+       int retval = 0;
+       u8 brgt;
+
+       if(!lcd_feature)
+               return -ENODEV;
+
+       io_op = lcd_feature->io_op;
+
+       mutex_lock(&io_op->backend->mutex);
+
+       if(( retval = __backend_byte_read(io_op, &brgt)))
+               goto out;       
+
+       dprintk("Fn-F6/F7 pressed: adjusting brightness.\n");
+
+       if (((int) brgt + delta) < 0)
+               brgt = 0;
+       else if ((brgt + delta) > omnibook_max_brightness)
+               brgt = omnibook_max_brightness;
+       else
+               brgt += delta;
+
+       retval = __backend_byte_write(io_op, brgt);
+
+       out:
+       mutex_unlock(&io_op->backend->mutex);
+       return retval;
+}
+
+/*
+ * Workqueue handler for Fn hotkeys
+ */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
+static void omnibook_handle_fnkey(struct work_struct *work)
+#else
+static void omnibook_handle_fnkey(void* data)
+#endif
+{
+       int i;
+       u32 gen_scan;
+       struct input_dev *input_dev;
+       acpi_status status;
+
+       status = omnibook_acpi_get_events(&gen_scan);
+       if (status != AE_OK)
+               return;
+
+       dprintk("detected scancode 0x%x.\n", gen_scan);
+       switch(gen_scan) {
+       case HCI_BRIGHTNESSDOWN:
+               adjust_brighness(-1);
+               break;
+       case HCI_BRIGHTNESSUP:
+               adjust_brighness(+1);
+               break;
+       }
+
+       for (i = 0 ; i < ARRAY_SIZE(acpi_scan_table); i++) {
+               if (gen_scan == acpi_scan_table[i].scancode) {
+                       dprintk("generating keycode %i.\n", acpi_scan_table[i].keycode);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
+                       input_dev = container_of(work, struct acpi_backend_data, fnkey_work)->acpi_input_dev;
+#else
+                       input_dev = ((struct acpi_backend_data *) data)->acpi_input_dev;
+#endif
+                       omnibook_report_key(input_dev, acpi_scan_table[i].keycode);
+                       break;
+               }
+       }
+}
+
+struct omnibook_backend acpi_backend = {
+       .name = "acpi",
+       .hotkeys_read_cap = HKEY_FN,
+       .hotkeys_write_cap = HKEY_FN,
+       .init = omnibook_acpi_init,
+       .exit = omnibook_acpi_exit,
+       .aerial_get = omnibook_acpi_get_wireless,
+       .aerial_set = omnibook_acpi_set_wireless,
+       .display_get = omnibook_acpi_get_display,
+       .display_set = omnibook_acpi_set_display,
+       .throttle_get = omnibook_acpi_get_throttle,
+       .throttle_set = omnibook_acpi_set_throttle,
+       .hotkeys_get = omnibook_hci_get_hotkeys,
+       .hotkeys_set = omnibook_hci_set_hotkeys,
+};
+
+#else                          /* CONFIG_ACPI */
+
+/* dummy backend for non-ACPI systems */
+static int _fail_probe(const struct omnibook_operation *io_op)
+{
+       return -ENODEV;
+}
+
+struct omnibook_backend acpi_backend = {
+       .name = "acpi",
+       .init = _fail_probe,
+};
+
+#endif                         /* CONFIG_ACPI */
diff --git a/battery.c b/battery.c
new file mode 100644 (file)
index 0000000..c9191fc
--- /dev/null
+++ b/battery.c
@@ -0,0 +1,557 @@
+/*
+ * battery.c -- battery related functions
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+struct omnibook_battery_info {
+       u8 type;                /* 1 - Li-Ion, 2 NiMH */
+       u16 sn;                 /* Serial number */
+       u16 dv;                 /* Design Voltage */
+       u16 dc;                 /* Design Capacity */
+};
+
+struct omnibook_battery_state {
+       u16 pv;                 /* Present Voltage */
+       u16 rc;                 /* Remaining Capacity */
+       u16 lc;                 /* Last Full Capacity */
+       u8 gauge;               /* Gauge in % */
+       u8 status;              /* 0 - unknown, 1 - charged, 2 - discharging, 3 - charging, 4 - critical) */
+};
+
+enum {
+       OMNIBOOK_BATTSTAT_UNKNOWN,
+       OMNIBOOK_BATTSTAT_CHARGED,
+       OMNIBOOK_BATTSTAT_DISCHARGING,
+       OMNIBOOK_BATTSTAT_CHARGING,
+       OMNIBOOK_BATTSTAT_CRITICAL
+};
+
+#define BAT_OFFSET 0x10
+
+static int __backend_u16_read(struct omnibook_operation *io_op, u16 *data)
+{
+       int retval;
+       u8 byte;
+
+       retval = __backend_byte_read(io_op, &byte);
+       if (retval)
+               return retval;
+       *data = byte;
+       io_op->read_addr += 1;
+       retval = __backend_byte_read(io_op, &byte);
+       *data += (byte << 8);
+       return retval;
+}
+
+static int omnibook_battery_present(struct omnibook_operation *io_op, int num)
+{
+       int retval;
+       u8 bat;
+       int i;
+
+       /*
+        * XE3GF
+        * TSP10
+        * TSM30X
+        * TSM70
+        */
+       if (omnibook_ectype & (XE3GF | TSP10 | TSM70 | TSM30X)) {
+               io_op->read_addr = XE3GF_BAL;
+               io_op->read_mask = XE3GF_BAL0_MASK;
+               for (i = 0; i < num; i++)
+                       io_op->read_mask = io_op->read_mask << 1;
+               retval = __backend_byte_read(io_op, &bat);
+       /*
+        * XE3GC
+        * AMILOD
+        */
+       } else if (omnibook_ectype & (XE3GC | AMILOD)) {
+               io_op->read_addr = XE3GC_BAT;
+               io_op->read_mask = XE3GC_BAT0_MASK;
+               for (i = 0; i < num; i++)
+                       io_op->read_mask = io_op->read_mask << 1;
+               retval = __backend_byte_read(io_op, &bat);
+       } else
+               retval = -ENODEV;
+
+       /* restore default read_mask */
+       io_op->read_mask = 0;
+
+       return !!bat;
+}
+
+/*
+ * Get static battery information
+ * All info have to be reread every time because battery sould be cahnged
+ * when laptop is on AC power 
+ * return values:
+ *  < 0 - ERROR
+ *    0 - OK
+ *    1 - Battery is not present
+ *    2 - Not supported
+ */
+static int omnibook_get_battery_info(struct omnibook_operation *io_op,
+                                    int num,
+                                    struct omnibook_battery_info *battinfo)
+{
+       int retval;
+       /*
+        * XE3GF
+        * TSP10
+        * TSM70
+         * TSM30X
+        */
+       if (omnibook_ectype & (XE3GF | TSP10 | TSM70 | TSM30X)) {
+               retval = omnibook_battery_present(io_op, num);
+               if (retval < 0)
+                       return retval;
+               if (retval) {
+                       io_op->read_addr = XE3GF_BTY0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_byte_read(io_op, &(*battinfo).type)))
+                               return retval;
+                       io_op->read_addr = XE3GF_BSN0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_u16_read(io_op, &(*battinfo).sn)))
+                               return retval;
+                       io_op->read_addr = XE3GF_BDV0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_u16_read(io_op, &(*battinfo).dv)))
+                               return retval;
+                       io_op->read_addr = XE3GF_BDC0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_u16_read(io_op, &(*battinfo).dc)))
+                               return retval;
+
+                       (*battinfo).type = ((*battinfo).type & XE3GF_BTY_MASK) ? 1 : 0;
+               } else
+                       return 1;
+       /*
+        * XE3GC
+        */
+       } else if (omnibook_ectype & (XE3GC)) {
+               retval = omnibook_battery_present(io_op, num);
+               if (retval < 0)
+                       return retval;
+               if (retval) {
+                       io_op->read_addr = XE3GC_BDV0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_u16_read(io_op, &(*battinfo).dv)))
+                               return retval;
+                       io_op->read_addr = XE3GC_BDC0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_u16_read(io_op, &(*battinfo).dc)))
+                               return retval;
+                       io_op->read_addr = XE3GC_BTY0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_byte_read(io_op, &(*battinfo).type)))
+                               return retval;
+
+                       (*battinfo).type = ((*battinfo).type & XE3GC_BTY_MASK) ? 1 : 0;
+                       (*battinfo).sn = 0;     /* Unknown */
+               } else
+                       return 1;
+               /*
+                * AMILOD
+                */
+       } else if (omnibook_ectype & (AMILOD)) {
+               retval = omnibook_battery_present(io_op, num);
+               if (retval < 0)
+                       return retval;
+               if (retval) {
+                       io_op->read_addr = AMILOD_BDV0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_u16_read(io_op, &(*battinfo).dv)))
+                               return retval;
+                       io_op->read_addr = AMILOD_BDC0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_u16_read(io_op, &(*battinfo).dc)))
+                               return retval;
+                       io_op->read_addr = AMILOD_BTY0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_byte_read(io_op, &(*battinfo).type)))
+                               return retval;
+
+                       (*battinfo).type = ((*battinfo).type & AMILOD_BTY_MASK) ? 1 : 0;
+                       (*battinfo).sn = 0;     /* Unknown */
+               } else
+                       return 1;
+               /*
+                * FIXME
+                * OB500
+                * OB510
+                */
+       } else if (omnibook_ectype & (OB500 | OB510)) {
+               switch (num) {
+               case 0:
+               case 1:
+               case 2:
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               /*
+                * OB6000
+                * OB6100
+                * XE4500
+                */
+       } else if (omnibook_ectype & (OB6000 | OB6100 | XE4500)) {
+               switch (num) {
+               case 0:
+               case 1:
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       } else
+               return 2;
+
+       return 0;
+}
+
+/*
+ * Get battery status
+ * return values:
+ *  < 0 - ERROR
+ *    0 - OK
+ *    1 - Battery is not present
+ *    2 - Not supported
+ */
+static int omnibook_get_battery_status(struct omnibook_operation *io_op, 
+                                      int num,
+                                      struct omnibook_battery_state *battstat)
+{
+       int retval;
+       u8 status;
+       u16 dc;
+       int gauge;
+
+       /*
+        * XE3GF
+        * TSP10
+        * TSM70
+        */
+       if (omnibook_ectype & (XE3GF | TSP10 | TSM70 | TSM30X)) {
+               retval = omnibook_battery_present(io_op, num);
+               if (retval < 0)
+                       return retval;
+               if (retval) {
+                       io_op->read_addr = XE3GF_BST0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_byte_read(io_op, &status)))
+                               return retval;
+                       io_op->read_addr = XE3GF_BRC0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_u16_read(io_op, &(*battstat).rc)))
+                               return retval;
+                       io_op->read_addr = XE3GF_BPV0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_u16_read(io_op, &(*battstat).pv)))
+                               return retval;
+                       io_op->read_addr = XE3GF_BFC0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_u16_read(io_op, &(*battstat).lc)))
+                               return retval;
+                       io_op->read_addr = XE3GF_GAU0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_byte_read(io_op, &(*battstat).gauge)))
+                               return retval;
+
+                       if (status & XE3GF_BST_MASK_CRT)
+                               (*battstat).status = OMNIBOOK_BATTSTAT_CRITICAL;
+                       else if (status & XE3GF_BST_MASK_CHR)
+                               (*battstat).status = OMNIBOOK_BATTSTAT_CHARGING;
+                       else if (status & XE3GF_BST_MASK_DSC)
+                               (*battstat).status = OMNIBOOK_BATTSTAT_DISCHARGING;
+                       else if (status & (XE3GF_BST_MASK_CHR | XE3GF_BST_MASK_DSC))
+                               (*battstat).status = OMNIBOOK_BATTSTAT_UNKNOWN;
+                       else {
+                               (*battstat).status = OMNIBOOK_BATTSTAT_CHARGED;
+                       }
+               } else
+                       return 1;
+       /*
+        * XE3GC
+        */
+       } else if (omnibook_ectype & (XE3GC)) {
+               retval = omnibook_battery_present(io_op, num);
+               if (retval < 0)
+                       return retval;
+               if (retval) {
+                       io_op->read_addr = XE3GC_BST0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_byte_read(io_op, &status)))
+                               return retval;
+                       io_op->read_addr = XE3GC_BRC0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_u16_read(io_op, &(*battstat).rc)))
+                               return retval;
+                       io_op->read_addr = XE3GC_BPV0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_u16_read(io_op, &(*battstat).pv)))
+                               return retval;
+                       io_op->read_addr = XE3GC_BDC0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_u16_read(io_op, &dc)))
+                               return retval;
+
+                       if (status & XE3GC_BST_MASK_CRT)
+                               (*battstat).status = OMNIBOOK_BATTSTAT_CRITICAL;
+                       else if (status & XE3GC_BST_MASK_CHR)
+                               (*battstat).status = OMNIBOOK_BATTSTAT_CHARGING;
+                       else if (status & XE3GC_BST_MASK_DSC)
+                               (*battstat).status = OMNIBOOK_BATTSTAT_DISCHARGING;
+                       else if (status & (XE3GC_BST_MASK_CHR | XE3GC_BST_MASK_DSC))
+                               (*battstat).status = OMNIBOOK_BATTSTAT_UNKNOWN;
+                       else {
+                               (*battstat).status = OMNIBOOK_BATTSTAT_CHARGED;
+                       }
+                       gauge = ((*battstat).rc * 100) / dc;
+                       (*battstat).gauge = gauge;
+                       (*battstat).lc = 0;     /* Unknown */
+               } else
+                       return 1;
+       /*
+        * AMILOD
+        */
+       } else if (omnibook_ectype & (AMILOD)) {
+               retval = omnibook_battery_present(io_op, num);
+               if (retval < 0)
+                       return retval;
+               if (retval) {
+                       io_op->read_addr = AMILOD_BST0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_byte_read(io_op, &status)))
+                               return retval;
+                       io_op->read_addr = AMILOD_BRC0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_u16_read(io_op, &(*battstat).rc)))
+                               return retval;
+                       io_op->read_addr = AMILOD_BPV0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_u16_read(io_op, &(*battstat).pv)))
+                               return retval;
+                       io_op->read_addr = AMILOD_BDC0 + (BAT_OFFSET * num);
+                       if ((retval = __backend_u16_read(io_op, &dc)))
+                               return retval;
+
+                       if (status & AMILOD_BST_MASK_CRT)
+                               (*battstat).status = OMNIBOOK_BATTSTAT_CRITICAL;
+                       else if (status & AMILOD_BST_MASK_CHR)
+                               (*battstat).status = OMNIBOOK_BATTSTAT_CHARGING;
+                       else if (status & AMILOD_BST_MASK_DSC)
+                               (*battstat).status = OMNIBOOK_BATTSTAT_DISCHARGING;
+                       else if (status & (AMILOD_BST_MASK_CHR | AMILOD_BST_MASK_DSC))
+                               (*battstat).status = OMNIBOOK_BATTSTAT_UNKNOWN;
+                       else {
+                               (*battstat).status = OMNIBOOK_BATTSTAT_CHARGED;
+                       }
+                       gauge = ((*battstat).rc * 100) / dc;
+                       (*battstat).gauge = gauge;
+                       (*battstat).lc = 0;     /* Unknown */
+               } else
+                       return 1;
+               /*
+                * OB500
+                * OB510
+                */
+       } else if (omnibook_ectype & (OB500 | OB510)) {
+               switch (num) {
+               case 0:
+                       io_op->read_addr = OB500_BT1S;
+                       if ((retval = __backend_byte_read(io_op, &status)))
+                               return retval;
+                       io_op->read_addr = OB500_BT1C;
+                       if ((retval = __backend_u16_read(io_op, &(*battstat).rc)))
+                               return retval;
+                       io_op->read_addr = OB500_BT1V;
+                       if ((retval = __backend_u16_read(io_op, &(*battstat).pv)))
+                               return retval;
+                       break;
+               case 1:
+                       io_op->read_addr = OB500_BT2S;
+                       if ((retval = __backend_byte_read(io_op, &status)))
+                               return retval;
+                       io_op->read_addr = OB500_BT2C;
+                       if ((retval = __backend_u16_read(io_op, &(*battstat).rc)))
+                               return retval;
+                       io_op->read_addr = OB500_BT2V;
+                       if ((retval = __backend_u16_read(io_op, &(*battstat).pv)))
+                               return retval;
+                       break;
+               case 2:
+                       io_op->read_addr = OB500_BT3S;
+                       if ((retval = __backend_byte_read(io_op, &status)))
+                               return retval;
+                       io_op->read_addr = OB500_BT3C;
+                       if ((retval = __backend_u16_read(io_op, &(*battstat).rc)))
+                               return retval;
+                       io_op->read_addr = OB500_BT3V;
+                       if ((retval = __backend_u16_read(io_op, &(*battstat).pv)))
+                               return retval;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               if (status & OB500_BST_MASK_CRT)
+                       (*battstat).status = OMNIBOOK_BATTSTAT_CRITICAL;
+               else if (status & OB500_BST_MASK_CHR)
+                       (*battstat).status = OMNIBOOK_BATTSTAT_CHARGING;
+               else if (status & OB500_BST_MASK_DSC)
+                       (*battstat).status = OMNIBOOK_BATTSTAT_DISCHARGING;
+               else if (status & (OB500_BST_MASK_CHR | OB500_BST_MASK_DSC))
+                       (*battstat).status = OMNIBOOK_BATTSTAT_UNKNOWN;
+               else {
+                       (*battstat).status = OMNIBOOK_BATTSTAT_CHARGED;
+               }
+               /*
+                * OB6000
+                * OB6100
+                * XE4500
+                */
+       } else if (omnibook_ectype & (OB6000 | OB6100 | XE4500)) {
+               switch (num) {
+               case 0:
+                       io_op->read_addr = OB500_BT1S;
+                       if ((retval = __backend_byte_read(io_op, &status)))
+                               return retval;
+                       io_op->read_addr = OB500_BT1C;
+                       if ((retval = __backend_u16_read(io_op, &(*battstat).rc)))
+                               return retval;
+                       io_op->read_addr = OB500_BT1V;
+                       if ((retval = __backend_u16_read(io_op, &(*battstat).pv)))
+                               return retval;
+                       break;
+               case 1:
+                       io_op->read_addr = OB500_BT3S;
+                       if ((retval = __backend_byte_read(io_op, &status)))
+                               return retval;
+                       io_op->read_addr = OB500_BT3C;
+                       if ((retval = __backend_u16_read(io_op, &(*battstat).rc)))
+                               return retval;
+                       io_op->read_addr = OB500_BT3V;
+                       if ((retval = __backend_u16_read(io_op, &(*battstat).pv)))
+                               return retval;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               if (status & OB500_BST_MASK_CRT)
+                       (*battstat).status = OMNIBOOK_BATTSTAT_CRITICAL;
+               else if (status & OB500_BST_MASK_CHR)
+                       (*battstat).status = OMNIBOOK_BATTSTAT_CHARGING;
+               else if (status & OB500_BST_MASK_DSC)
+                       (*battstat).status = OMNIBOOK_BATTSTAT_DISCHARGING;
+               else if (status & (OB500_BST_MASK_CHR | OB500_BST_MASK_DSC))
+                       (*battstat).status = OMNIBOOK_BATTSTAT_UNKNOWN;
+               else {
+                       (*battstat).status = OMNIBOOK_BATTSTAT_CHARGED;
+               }
+       } else {
+               return 2;
+       }
+       return 0;
+}
+
+static int omnibook_battery_read(char *buffer, struct omnibook_operation *io_op)
+{
+       char *statustr;
+       char *typestr;
+       int max = 0;
+       int num = 0;
+       int len = 0;
+       int retval;
+       int i;
+       struct omnibook_battery_info battinfo;
+       struct omnibook_battery_state battstat;
+       /*
+        * XE3GF
+        * XE3GC
+        * 0B6000
+        * 0B6100
+        * XE4500
+        * AMILOD
+        * TSP10
+        */
+       if (omnibook_ectype & (XE3GF | XE3GC | OB6000 | OB6100 | XE4500 | AMILOD | TSP10))
+               max = 2;
+       /*
+        * OB500
+        * 0B510
+        */
+       else if (omnibook_ectype & (OB500 | OB510))
+               max = 3;
+       /*
+        * TSM30X
+        * TSM70
+        */
+       else if (omnibook_ectype & (TSM70 | TSM30X))
+               max = 1;
+
+       if(mutex_lock_interruptible(&io_op->backend->mutex))
+                       return -ERESTARTSYS;
+
+       for (i = 0; i < max; i++) {
+               retval = omnibook_get_battery_info(io_op, i, &battinfo);
+               if (retval == 0) {
+                       num++;
+                       omnibook_get_battery_status(io_op, i, &battstat);
+                       typestr = (battinfo.type) ? "Li-Ion" : "NiMH";
+                       switch (battstat.status) {
+                       case OMNIBOOK_BATTSTAT_CHARGED:
+                               statustr = "charged";
+                               break;
+                       case OMNIBOOK_BATTSTAT_DISCHARGING:
+                               statustr = "discharging";
+                               break;
+                       case OMNIBOOK_BATTSTAT_CHARGING:
+                               statustr = "charging";
+                               break;
+                       case OMNIBOOK_BATTSTAT_CRITICAL:
+                               statustr = "critical";
+                               break;
+                       default:
+                               statustr = "unknown";
+                       }
+
+                       len += sprintf(buffer + len, "Battery:            %11d\n", i);
+                       len += sprintf(buffer + len, "Type:               %11s\n", typestr);
+                       if (battinfo.sn)
+                               len +=
+                                   sprintf(buffer + len, "Serial Number:      %11d\n",
+                                           battinfo.sn);
+                       len += sprintf(buffer + len, "Present Voltage:    %11d mV\n", battstat.pv);
+                       len += sprintf(buffer + len, "Design Voltage:     %11d mV\n", battinfo.dv);
+                       len += sprintf(buffer + len, "Remaining Capacity: %11d mAh\n", battstat.rc);
+                       if (battstat.lc)
+                               len +=
+                                   sprintf(buffer + len, "Last Full Capacity: %11d mAh\n",
+                                           battstat.lc);
+                       len += sprintf(buffer + len, "Design Capacity:    %11d mAh\n", battinfo.dc);
+                       len +=
+                           sprintf(buffer + len, "Gauge:              %11d %%\n", battstat.gauge);
+                       len += sprintf(buffer + len, "Status:             %11s\n", statustr);
+                       len += sprintf(buffer + len, "\n");
+               }
+       }
+       if (num == 0)
+               len += sprintf(buffer + len, "No battery present\n");
+
+       mutex_unlock(&io_op->backend->mutex);
+
+       return len;
+}
+
+static struct omnibook_tbl battery_table[] __initdata = {
+       {XE3GF | XE3GC | AMILOD | TSP10 | TSM70 | TSM30X, {EC,}},
+       {0,}
+};
+
+static struct omnibook_feature __declared_feature battery_driver = {
+       .name = "battery",
+#ifdef CONFIG_OMNIBOOK_LEGACY
+       .enabled = 1,
+#else
+       .enabled = 0,
+#endif
+       .read = omnibook_battery_read,
+       .ectypes = XE3GF | XE3GC | AMILOD | TSP10 | TSM70 | TSM30X,     /* FIXME: OB500|OB6000|OB6100|XE4500 */
+       .tbl = battery_table,
+};
+
+module_param_named(battery, battery_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(battery, "Use 0 to disable, 1 to enable battery status monitoring");
+/* End of file */
diff --git a/blank.c b/blank.c
new file mode 100644 (file)
index 0000000..1bad34c
--- /dev/null
+++ b/blank.c
@@ -0,0 +1,138 @@
+/*
+ * blank.c -- blanking lcd console
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+
+#include <asm/io.h>
+#include "hardware.h"
+
+static struct omnibook_feature blank_driver;
+
+/* 
+ * console_blank_hook pointer manipulation is lock protected
+ */
+extern int (*console_blank_hook) (int);
+static DEFINE_SPINLOCK(blank_spinlock);
+
+
+int omnibook_lcd_blank(int blank)
+{
+       struct omnibook_feature *blank_feature = omnibook_find_feature("blank");
+
+       if(!blank_feature)
+               return -ENODEV;
+
+       return omnibook_apply_write_mask(blank_feature->io_op, blank);
+}
+
+static int console_blank_register_hook(void)
+{
+       spin_lock(&blank_spinlock);
+       if (console_blank_hook != omnibook_lcd_blank) {
+               if (console_blank_hook == NULL) {
+                       console_blank_hook = omnibook_lcd_blank;
+                       printk(O_INFO "LCD backlight turn off at console blanking is enabled.\n");
+               } else 
+                       printk(O_INFO "There is a console blanking solution already registered.\n");
+       }
+       spin_unlock(&blank_spinlock);
+       return 0;
+}
+
+static int console_blank_unregister_hook(void)
+{
+       int retval;
+       spin_lock(&blank_spinlock);
+       if (console_blank_hook == omnibook_lcd_blank) {
+               console_blank_hook = NULL;
+               printk(O_INFO "LCD backlight turn off at console blanking is disabled.\n");
+       } else if (console_blank_hook) {
+               printk(O_WARN "You can not disable another console blanking solution.\n");
+               retval = -EBUSY;
+       } else {
+               printk(O_INFO "Console blanking already disabled.\n");
+       }
+       spin_unlock(&blank_spinlock);
+       return retval;
+}
+
+static int omnibook_console_blank_read(char *buffer, struct omnibook_operation *io_op)
+{
+       int len = 0;
+
+       spin_lock(&blank_spinlock);
+
+       len +=
+           sprintf(buffer + len, "LCD console blanking hook is %s\n",
+                   (console_blank_hook == omnibook_lcd_blank) ? "enabled" : "disabled");
+
+       spin_unlock(&blank_spinlock);
+
+       return len;
+}
+
+static int omnibook_console_blank_write(char *buffer, struct omnibook_operation *io_op)
+{
+       int retval;
+
+       switch (*buffer) {
+       case '0':
+               retval = console_blank_unregister_hook();
+               break;
+       case '1':
+               retval = console_blank_register_hook();
+               break;
+       default:
+               retval = -EINVAL;
+       }
+       return retval;
+}
+
+static int __init omnibook_console_blank_init(struct omnibook_operation *io_op)
+{      
+       return console_blank_register_hook();
+}
+
+static void __exit omnibook_console_blank_cleanup(struct omnibook_operation *io_op)
+{
+       console_blank_unregister_hook();
+}
+
+static struct omnibook_tbl blank_table[] __initdata = {
+       {TSM70 | TSX205, {CDI, 0, TSM100_BLANK_INDEX, 0, TSM100_LCD_OFF, TSM100_LCD_ON}},
+       {XE3GF | XE3GC | AMILOD | TSP10 | TSM70 | TSM30X,
+        COMMAND(KBC, OMNIBOOK_KBC_CMD_LCD_OFF, OMNIBOOK_KBC_CMD_LCD_ON)},
+       {OB500 | OB6000 | XE2, {PIO, OB500_GPO1, OB500_GPO1, 0, -OB500_BKLT_MASK, OB500_BKLT_MASK}},
+       {OB510 | OB6100, {PIO, OB510_GPO2, OB510_GPO2, 0, -OB510_BKLT_MASK, OB510_BKLT_MASK}},
+       {0,}
+};
+
+static struct omnibook_feature __declared_feature blank_driver = {
+       .name = "blank",
+       .enabled = 1,
+       .read = omnibook_console_blank_read,
+       .write = omnibook_console_blank_write,
+       .init = omnibook_console_blank_init,
+       .exit = omnibook_console_blank_cleanup,
+       .ectypes =
+           XE3GF | XE3GC | OB500 | OB510 | OB6000 | OB6100 | XE2 | AMILOD | TSP10 | TSM70 | TSM30X | TSX205,
+       .tbl = blank_table,
+};
+
+module_param_named(blank, blank_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(blank, "Use 0 to disable, 1 to enable lcd console blanking");
+/* End of file */
diff --git a/bluetooth.c b/bluetooth.c
new file mode 100644 (file)
index 0000000..1095eec
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * wireless.c Bluetooth feature
+ * 
+ * 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, 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.
+ *
+ * Written by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ *
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+static int omnibook_bt_read(char *buffer, struct omnibook_operation *io_op)
+{
+       int len = 0;
+       int retval;
+       unsigned int state;
+
+       if ((retval = backend_aerial_get(io_op, &state)))
+               return retval;
+
+       len +=
+           sprintf(buffer + len, "Bluetooth adapter is %s",
+                   (state & BT_EX) ? "present" : "absent");
+       if (state & BT_EX)
+               len += sprintf(buffer + len, " and %s", (state & BT_STA) ? "enabled" : "disabled");
+       len += sprintf(buffer + len, ".\n");
+       return len;
+
+}
+
+static int omnibook_bt_write(char *buffer, struct omnibook_operation *io_op)
+{
+       int retval = 0;
+       unsigned int state;
+
+       if(mutex_lock_interruptible(&io_op->backend->mutex))
+               return -ERESTARTSYS;    
+
+       if ((retval = __backend_aerial_get(io_op, &state)))
+               goto out;
+
+       if (*buffer == '0')
+               state &= ~BT_STA;
+       else if (*buffer == '1')
+               state |= BT_STA;
+       else {
+               retval = -EINVAL;
+               goto out;
+       }
+
+       retval = __backend_aerial_set(io_op, state);
+
+       out:            
+       mutex_unlock(&io_op->backend->mutex);
+       return retval;
+}
+
+static struct omnibook_feature bt_driver;
+
+static int __init omnibook_bt_init(struct omnibook_operation *io_op)
+{
+       int retval = 0;
+       unsigned int state;
+
+/*
+ *  Refuse enabling/disabling a non-existent device
+ */
+
+       if ((retval = backend_aerial_get(io_op, &state)))
+               return retval;
+
+       if (!(state & BT_EX))
+               bt_driver.write = NULL;
+
+       return retval;
+}
+
+static struct omnibook_tbl wireless_table[] __initdata = {
+       {TSM70 | TSA105 | TSX205, {ACPI,}},     /* stubs to select backend */
+       {TSM40, {SMI,}},                        /* stubs to select backend */
+       {0,}
+};
+
+static struct omnibook_feature __declared_feature bt_driver = {
+       .name = "bluetooth",
+       .enabled = 1,
+       .read = omnibook_bt_read,
+       .write = omnibook_bt_write,
+       .init = omnibook_bt_init,
+       .ectypes = TSM70 | TSM40 | TSA105 | TSX205,
+       .tbl = wireless_table,
+};
+
+module_param_named(bluetooth, bt_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(bluetooth, "Use 0 to disable, 1 to enable bluetooth adapter control");
diff --git a/compal.c b/compal.c
new file mode 100644 (file)
index 0000000..766aec5
--- /dev/null
+++ b/compal.c
@@ -0,0 +1,526 @@
+/*
+ * compal.c -- EC PIO Command/Data/Index mode low-level access code
+ * 
+ * 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, 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.
+ *
+ * Written by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ *
+ */
+
+#include "omnibook.h"
+
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/kref.h>
+
+#include <asm/io.h>
+#include "hardware.h"
+
+/*
+ * ATI's IXP PCI-LPC bridge
+ */
+#define PCI_DEVICE_ID_ATI_SB400 0x4377
+
+/* 
+ * PCI Config space regiser
+ * Laptop with Intel ICH Chipset
+ * See ICH6M and ICH7M spec
+ */
+#define INTEL_LPC_GEN1_DEC     0x84
+#define INTEL_LPC_GEN4_DEC     0x90
+#define INTEL_IOPORT_BASE      0xff2c
+
+/* 
+ * PCI Config space regiser
+ * Laptop with ATI Chipset
+ * FIXME Untested, name unknown
+ */
+#define ATI_LPC_REG            0x4a
+#define ATI_IOPORT_BASE        0xfd60
+
+/* 
+ *This interface uses 2 ports for command and 1 port for data
+ *These are relative to the ioport_base address
+ */
+
+#define PIO_PORT_COMMAND1      0x1
+#define PIO_PORT_COMMAND2      0x2
+#define PIO_PORT_DATA          0x3
+
+/*
+ * Private data of this backend
+ */
+static struct pci_dev *lpc_bridge;     /* Southbridge chip ISA bridge/LPC interface PCI device */
+static u32 ioport_base;                /* PIO base adress */
+static union {
+       u16 word;
+       u32 dword;
+} pci_reg_state;               /* Saved state of register in PCI config spave */
+
+/*
+ * Possible list of supported southbridges
+ * Here mostly to implement a more or less clean PCI probing
+ * Works only because of previous DMI probing.
+ * Shared with nbsmi backend
+ */
+const struct pci_device_id lpc_bridge_table[] = {
+       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_30, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+        {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_4, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+       {PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SB400, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+       {0,},                   /* End of list */
+};
+
+/*
+ * Low-level Read function:
+ * Write a 2-bytes wide command to the COMMAND ports
+ * Read the result in the DATA port
+ */
+static unsigned char lowlevel_read(u16 command)
+{
+       unsigned char data;
+       outb((command & 0xff00) >> 8, ioport_base + PIO_PORT_COMMAND1);
+       outb(command & 0x00ff, ioport_base + PIO_PORT_COMMAND2);
+       data = inb(ioport_base + PIO_PORT_DATA);
+       return data;
+}
+
+/*
+ * Low-level Write function:
+ * Write a 2-bytes wide command to the COMMAND ports
+ * Write the result in the DATA port
+ */
+static void lowlevel_write(u16 command, u8 data)
+{
+       outb((command & 0xff00) >> 8, ioport_base + PIO_PORT_COMMAND1);
+       outb(command & 0x00ff, ioport_base + PIO_PORT_COMMAND2);
+       outb(data, ioport_base + PIO_PORT_DATA);
+}
+
+/*
+ * Probe for a state of the PIO Command/Data/Index interface
+ * Give some time for the controler to settle in the desired state
+ * mode significance:
+ * 0: Waiting for command
+ * 1,2,3: I am confused FIXME
+ */
+static int check_cdimode_flag(unsigned int mode)
+{
+       int i;
+       int retval;
+
+       /*dprintk("Index mode:");*/
+       for (i = 1; i <= 250; i++) {
+               retval = lowlevel_read(0xfbfc);
+               /*dprintk_simple(" [%i]", retval);*/
+               if (retval == mode) {
+                       /*dprintk_simple(".\n");
+                       dprintk("Index Mode Ok (%i) after %i iter\n", mode, i);*/
+                       return 0;
+               }
+               udelay(100);
+       }
+       printk(O_ERR "check_cdimode_flag timeout.\n");
+       return -ETIME;
+}
+
+/*
+ * Check for conventional default (0xf432) state in Commad ports
+ */
+static int check_default_state(void)
+{
+       int i;
+
+       for (i = 1; i <= 250; i++) {
+               if ((inb(ioport_base + PIO_PORT_COMMAND1) == 0xf4)
+                   && (inb(ioport_base + PIO_PORT_COMMAND2) == 0x32))
+                       return 0;
+               udelay(100);
+       }
+       printk(O_ERR "check_default_state timeout.\n");
+       return -ETIME;
+}
+
+/*
+ * Enable EC Command/Data/Index PIO Access and then check EC state.
+ * Enabling is done in PCI config space of the LPC bridge.
+ *
+ * Just after Enabling, the EC should be in a precisly defined state:
+ * - PIO should be in a conventional default state (0xf432 in the Command ports)
+ * - Command/Data/Index interface waiting for command
+ * The EC is expected to be in that state prior to any attempt to use the interface.
+ *
+ */
+static int enable_cdimode(void)
+{
+       union {
+               u16 word;
+               u32 dword;
+       } value;
+
+       switch (lpc_bridge->vendor) {
+       case PCI_VENDOR_ID_INTEL:
+               switch (lpc_bridge->device) {
+               case PCI_DEVICE_ID_INTEL_ICH7_0:        /* ICH7 */
+               case PCI_DEVICE_ID_INTEL_ICH7_1:
+               case PCI_DEVICE_ID_INTEL_ICH7_30:
+               case PCI_DEVICE_ID_INTEL_ICH7_31:
+               case PCI_DEVICE_ID_INTEL_ICH8_4:        /* ICH8 */
+                       pci_read_config_dword(lpc_bridge, INTEL_LPC_GEN4_DEC, &(value.dword));
+                       pci_reg_state.dword = value.dword;
+                       value.dword = 0x3CFF21;
+                       pci_write_config_dword(lpc_bridge, INTEL_LPC_GEN4_DEC, value.dword);
+                       break;
+               default:        /* All other Intel chipset */
+                       pci_read_config_word(lpc_bridge, INTEL_LPC_GEN1_DEC, &(value.word));
+                       pci_reg_state.word = value.word;
+                       value.word = (INTEL_IOPORT_BASE & 0xfff1) | 0x1;
+                       pci_write_config_word(lpc_bridge, INTEL_LPC_GEN1_DEC, value.word);
+               }
+               break;
+       case PCI_VENDOR_ID_ATI:
+               pci_read_config_dword(lpc_bridge, ATI_LPC_REG, &(value.dword));
+               pci_reg_state.dword = value.dword;
+               value.dword = ((pci_reg_state.dword & 0x7f) | 0x80) << 0x10;
+               pci_write_config_dword(lpc_bridge, ATI_LPC_REG, value.dword);
+               break;
+       default:
+               BUG();
+       }
+       dprintk("Saved state of PCI register: [%x].\n", pci_reg_state.dword);
+
+       if (check_default_state() || check_cdimode_flag(0)) {
+               printk(O_ERR "EC state check failure, please report.\n");
+               return -EIO;
+       }
+
+       return 0;
+
+}
+
+/*
+ * Send a write command and associated data code to be written
+ * Known commands an associated code significance:
+ * 0xfbfd: Select Index with 'code' ordinal
+ * 0xfbfe: Set to 'code' a previously selected Index
+ * 0xfbfc: Set CDI mode flag
+ */
+static int send_ec_cmd(unsigned int command, u8 code)
+{
+       lowlevel_write(0xfbfc, 0x2);
+       lowlevel_write(command, code);
+       lowlevel_write(0xfbfc, 0x1);
+       if (check_cdimode_flag(2))
+               return -ETIME;
+       return 0;
+}
+
+/*
+ * Send a read command
+ * Known commands an associated code significance:
+ * 0xfbfe: Read a previously selected Index
+ * 0xfbfc: Set CDI mode flag
+ */
+static int read_ec_cmd(unsigned int command, u8 * value)
+{
+       *value = lowlevel_read(command);
+       lowlevel_write(0xfbfc, 0x1);
+       if (check_cdimode_flag(2))
+               return -ETIME;
+       return 0;
+}
+
+/*
+ * Disable EC Command/Data/Index PIO Access 
+ * Step 1: clear_cdimode
+ * Send Disable command
+ * Revert PIO interface to conventional default state (0xf432 in the Command ports)
+ * Step 2: clear_cdimode_pci
+ * Disable the interface in the PCI config space of the Southbridge
+ * These steps are separated due to constrains in error path treatement
+ */
+static void clear_cdimode(void)
+{
+       lowlevel_write(0xfbfc, 0x0);
+       outb(0xf4, ioport_base + PIO_PORT_COMMAND1);
+       outb(0x32, ioport_base + PIO_PORT_COMMAND2);
+}
+
+static void clear_cdimode_pci(void)
+{
+       switch (lpc_bridge->vendor) {
+       case PCI_VENDOR_ID_INTEL:
+               switch (lpc_bridge->device) {
+               case PCI_DEVICE_ID_INTEL_ICH7_0:        /* ICH7 */
+               case PCI_DEVICE_ID_INTEL_ICH7_1:
+               case PCI_DEVICE_ID_INTEL_ICH7_30:
+               case PCI_DEVICE_ID_INTEL_ICH7_31:
+               case PCI_DEVICE_ID_INTEL_ICH8_4:        /* ICH8 */
+                       pci_write_config_dword(lpc_bridge, INTEL_LPC_GEN4_DEC, pci_reg_state.dword);
+                       break;
+               default:        /* All other Intel chipset */
+                       pci_write_config_word(lpc_bridge, INTEL_LPC_GEN1_DEC, pci_reg_state.word);
+               }
+               break;
+       case PCI_VENDOR_ID_ATI:
+               pci_write_config_dword(lpc_bridge, ATI_LPC_REG, pci_reg_state.dword);
+               break;
+       default:
+               BUG();
+       }
+}
+
+/*
+ * Try to init the backend
+ * This function can be called blindly as it use a kref
+ * to check if the init sequence was already done.
+ */
+static int omnibook_cdimode_init(const struct omnibook_operation *io_op)
+{
+       int retval = 0;
+       int i;
+
+       /* ectypes other than TSM70 have no business with this backend */
+       if (!(omnibook_ectype & (TSM70 | TSX205)))
+               return -ENODEV;
+
+       if (io_op->backend->already_failed) {
+               dprintk("CDI backend init already failed, skipping.\n");
+               return -ENODEV;
+       }
+
+       if (!lpc_bridge) {
+               /* Fist use of the backend */
+               dprintk("Try to init cdimode\n");
+               mutex_init(&io_op->backend->mutex);
+               mutex_lock(&io_op->backend->mutex);
+               kref_init(&io_op->backend->kref);
+
+               /* PCI probing: find the LPC Super I/O bridge PCI device */
+               for (i = 0; !lpc_bridge && lpc_bridge_table[i].vendor; ++i)
+                       lpc_bridge =
+                           pci_get_device(lpc_bridge_table[i].vendor, lpc_bridge_table[i].device,
+                                          NULL);
+
+               if (!lpc_bridge) {
+                       printk(O_ERR "Fail to find a supported LPC I/O bridge, please report\n");
+                       retval = -ENODEV;
+                       goto error1;
+               }
+
+               if ((retval = pci_enable_device(lpc_bridge))) {
+                       printk(O_ERR "Unable to enable PCI device.\n");
+                       goto error2;
+               }
+
+               switch (lpc_bridge->vendor) {
+               case PCI_VENDOR_ID_INTEL:
+                       ioport_base = INTEL_IOPORT_BASE;
+                       break;
+               case PCI_VENDOR_ID_ATI:
+                       ioport_base = ATI_IOPORT_BASE;
+                       break;
+               default:
+                       BUG();
+               }
+
+               if (!request_region(ioport_base, 4, OMNIBOOK_MODULE_NAME)) {
+                       printk(O_ERR "Request I/O region error\n");
+                       retval = -ENODEV;
+                       goto error2;
+               }
+
+               /*
+                * Make an enable-check disable cycle for testing purpose
+                */
+
+               retval = enable_cdimode();
+               if (retval)
+                       goto error3;
+
+               clear_cdimode();
+               clear_cdimode_pci();
+
+               dprintk("Cdimode init ok\n");
+               mutex_unlock(&io_op->backend->mutex);
+               return 0;
+       } else {
+               dprintk("Cdimode has already been initialized\n");
+               kref_get(&io_op->backend->kref);
+               return 0;
+       }
+
+      error3:
+       clear_cdimode_pci();
+       release_region(ioport_base, 4);
+      error2:
+       pci_dev_put(lpc_bridge);
+       lpc_bridge = NULL;
+      error1:
+       io_op->backend->already_failed = 1;
+       mutex_unlock(&io_op->backend->mutex);
+       mutex_destroy(&io_op->backend->mutex);
+       return retval;
+}
+
+static void cdimode_free(struct kref *ref)
+{
+       struct omnibook_backend *backend;
+       
+       dprintk("Cdimode not used anymore: disposing\n");
+
+       backend = container_of(ref, struct omnibook_backend, kref);
+
+       mutex_lock(&backend->mutex);
+       pci_dev_put(lpc_bridge);
+       release_region(ioport_base, 4);
+       lpc_bridge = NULL;
+       mutex_unlock(&backend->mutex);
+       mutex_destroy(&backend->mutex);
+}
+
+static void omnibook_cdimode_exit(const struct omnibook_operation *io_op)
+{
+       /* ectypes other than TSM70 have no business with this backend */
+       BUG_ON(!(omnibook_ectype & (TSM70 | TSX205)));
+       dprintk("Trying to dispose cdimode\n");
+       kref_put(&io_op->backend->kref, cdimode_free);
+}
+
+/* 
+ * Read EC index and write result to value 
+ * 'EC index' here is unrelated to an index in the EC registers
+ */
+static int omnibook_cdimode_read(const struct omnibook_operation *io_op, u8 * value)
+{
+       int retval = 0;
+
+       if (!lpc_bridge)
+               return -ENODEV;
+
+       retval = enable_cdimode();
+       if (retval)
+               goto out;
+       retval = send_ec_cmd(0xfbfd, (unsigned int)io_op->read_addr);
+       if (retval)
+               goto error;
+       retval = read_ec_cmd(0xfbfe, value);
+
+       if (io_op->read_mask)
+               *value &= io_op->read_mask;
+
+      error:
+       clear_cdimode();
+      out:
+       clear_cdimode_pci();
+       return retval;
+}
+
+/* 
+ * Write value 
+ * 'EC index' here is unrelated to an index in the EC registers
+ */
+static int omnibook_cdimode_write(const struct omnibook_operation *io_op, u8 value)
+{
+       int retval = 0;
+
+       if (!lpc_bridge)
+               return -ENODEV;
+
+       retval = enable_cdimode();
+       if (retval)
+               goto out;
+       retval = send_ec_cmd(0xfbfd, (unsigned int)io_op->write_addr);
+       if (retval)
+               goto error;
+       retval = send_ec_cmd(0xfbfe, value);
+      error:
+       clear_cdimode();
+      out:
+       clear_cdimode_pci();
+       return retval;
+
+}
+
+/*
+ * Fn+foo and multimedia hotkeys handling
+ */
+static int omnibook_cdimode_hotkeys(const struct omnibook_operation *io_op, unsigned int state)
+{
+       int retval;
+
+       struct omnibook_operation hotkeys_op = 
+               { CDI, 0, TSM70_FN_INDEX, 0, TSM70_FN_ENABLE, TSM70_FN_DISABLE};
+
+       /* Fn+foo handling */
+       retval = __omnibook_toggle(&hotkeys_op, !!(state & HKEY_FN));
+       if (retval < 0)
+               return retval;
+
+       /* Multimedia keys handling */
+       hotkeys_op.write_addr = TSM70_HOTKEYS_INDEX;
+       hotkeys_op.on_mask = TSM70_HOTKEYS_ENABLE;
+       hotkeys_op.off_mask = TSM70_HOTKEYS_DISABLE;
+       retval = __omnibook_toggle(&hotkeys_op, !!(state & HKEY_MULTIMEDIA));
+
+       return retval;
+}
+
+/* Scan index space, this hard locks my machine */
+#if 0
+static int compal_scan(char *buffer)
+{
+       int len = 0;
+       int i, j;
+       u8 v;
+
+       for (i = 0; i < 255; i += 16) {
+               for (j = 0; j < 16; j++) {
+                       omnibook_compal_read(i + j, &v);
+                       len += sprintf(buffer + len, "Read index %02x: %02x\n", i + j, v);
+                       mdelay(500);
+               }
+               if (j != 16)
+                       break;
+       }
+
+       return len;
+}
+#endif
+
+struct omnibook_backend compal_backend = {
+       .name = "compal",
+       .hotkeys_write_cap = HKEY_MULTIMEDIA | HKEY_FN,
+       .init = omnibook_cdimode_init,
+       .exit = omnibook_cdimode_exit,
+       .byte_read = omnibook_cdimode_read,
+       .byte_write = omnibook_cdimode_write,
+       .hotkeys_set = omnibook_cdimode_hotkeys,
+};
+
+/* End of file */
diff --git a/compat.h b/compat.h
new file mode 100644 (file)
index 0000000..d456053
--- /dev/null
+++ b/compat.h
@@ -0,0 +1,71 @@
+/*
+ * compat.h -- Older kernel (=> 2.6.11) support 
+ * 
+ * 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, 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.
+ *
+ * Written by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include <linux/version.h>
+
+/*
+ * For compatibility with kernel older than 2.6.16
+ * Mutex to Semaphore fallback
+ */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16))
+#include <asm/semaphore.h>
+#define DEFINE_MUTEX(lock)             DECLARE_MUTEX(lock)
+#define        mutex_init(lock)                init_MUTEX(lock)
+#define mutex_lock(lock)               down(lock)
+#define mutex_lock_interruptible(lock) down_interruptible(lock)
+#define mutex_unlock(lock)             up(lock)
+#define mutex_destroy(lock)            do { } while(0)
+#else
+#include <linux/mutex.h>
+#endif
+
+/*
+ * For compatibility with kernel older than 2.6.14
+ */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14))
+static void inline *kzalloc(size_t size, int flags)
+{
+       void *ret = kmalloc(size, flags);
+       if (ret)
+               memset(ret, 0, size);
+       return ret;
+}
+#endif
+
+/*
+ * For compatibility with kernel older than 2.6.11
+ */
+
+#ifndef DEFINE_SPINLOCK
+#define DEFINE_SPINLOCK(s)              spinlock_t s = SPIN_LOCK_UNLOCKED
+#endif
+
+/*
+ * Those kernel don't have ICH7 southbridge pcids
+ */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11))
+#define PCI_DEVICE_ID_INTEL_ICH7_0      0x27b8
+#define PCI_DEVICE_ID_INTEL_ICH7_1      0x27b9
+#define PCI_DEVICE_ID_INTEL_ICH7_30    0x27b0
+#define PCI_DEVICE_ID_INTEL_ICH7_31     0x27bd
+#endif
+
+
+
+/* End of file */
diff --git a/cooling.c b/cooling.c
new file mode 100644 (file)
index 0000000..3f507bd
--- /dev/null
+++ b/cooling.c
@@ -0,0 +1,97 @@
+/*
+ * colling.c -- cooling methods feature
+ * 
+ * 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, 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.
+ *
+ * Written by Mathieu Bérard <mathieu.berard@crans.org>, 2007
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+static int omnibook_cooling_read(char *buffer, struct omnibook_operation *io_op)
+{
+       int len = 0;
+
+       if(mutex_lock_interruptible(&io_op->backend->mutex))
+               return -ERESTARTSYS;
+
+       len += sprintf(buffer + len, "Cooling method : %s\n", 
+                       io_op->backend->cooling_state ? "Performance"  : "Powersave" );
+
+       mutex_unlock(&io_op->backend->mutex);
+       return len;
+}
+
+static int omnibook_cooling_write(char *buffer, struct omnibook_operation *io_op)
+{
+       int retval = 0;
+
+       if(mutex_lock_interruptible(&io_op->backend->mutex))
+               return -ERESTARTSYS;
+
+
+       if (*buffer == '0') {
+               retval = __backend_byte_write(io_op, 
+                               TSM70_COOLING_OFFSET + TSM70_COOLING_POWERSAVE);
+       } else if (*buffer == '1') {
+               retval = __backend_byte_write(io_op,
+                               TSM70_COOLING_OFFSET + TSM70_COOLING_PERF);
+       } else {
+               retval = -EINVAL;
+               goto out;
+       }
+
+       /* *buffer is either '0' or '1' here */
+       if (!retval)
+               io_op->backend->cooling_state = *buffer - '0' ;
+
+       mutex_unlock(&io_op->backend->mutex);
+
+       out:
+       return retval;
+}
+
+static int __init omnibook_cooling_init(struct omnibook_operation *io_op)
+{
+       mutex_lock(&io_op->backend->mutex);
+       /* XXX: Assumed default cooling method: performance */
+       io_op->backend->cooling_state = TSM70_COOLING_PERF;
+       mutex_unlock(&io_op->backend->mutex);
+       return 0;
+}
+
+static void __exit omnibook_cooling_exit(struct omnibook_operation *io_op)
+{
+       /* Set back cooling method to performance */    
+       backend_byte_write(io_op, TSM70_COOLING_OFFSET + TSM70_COOLING_PERF);
+}
+
+static struct omnibook_tbl cooling_table[] __initdata = {
+       {TSM70 | TSX205, {CDI, 0, TSM70_FN_INDEX, 0, 0, 0 }},
+       {0,}
+};
+
+static struct omnibook_feature __declared_feature cooling_driver = {
+       .name = "cooling",
+       .enabled = 1,
+       .read = omnibook_cooling_read,
+       .write = omnibook_cooling_write,
+       .init = omnibook_cooling_init,
+       .exit = omnibook_cooling_exit,
+       .ectypes = TSM70 | TSX205,
+       .tbl = cooling_table,
+};
+
+module_param_named(cooling, cooling_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(cooling, "Use 0 to disable, 1 to enable CPU cooling method control");
+
+/* End of file */
diff --git a/display.c b/display.c
new file mode 100644 (file)
index 0000000..1c5d4d7
--- /dev/null
+++ b/display.c
@@ -0,0 +1,114 @@
+/*
+ * display.c -- External display (LCD,VGA,TV-OUT) feature
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+static const char display_name[][16] = {
+       "Internal LCD",
+       "External VGA",
+       "External TV-OUT",
+       "External DVI",
+};
+
+static int omnibook_display_read(char *buffer, struct omnibook_operation *io_op)
+{
+       int len = 0;
+       int retval;
+       unsigned int sta, en_mask, det_mask;
+
+       retval = backend_display_get(io_op, &sta);
+       if (retval < 0)
+               return retval;
+
+       for (en_mask = DISPLAY_LCD_ON; en_mask <= DISPLAY_DVI_ON; en_mask = en_mask << 1) {
+               det_mask = en_mask << 4;        /* see display masks in omnibook.h */
+               if (!(retval & en_mask) && !(retval & det_mask))
+                       continue;       /* not supported */
+               len += sprintf(buffer + len, "%s:", display_name[ffs(en_mask) - 1]);
+               if (retval & det_mask)
+                       len +=
+                           sprintf(buffer + len, " display %s",
+                                   (sta & det_mask) ? "present" : "absent");
+               if (retval & en_mask)
+                       len +=
+                           sprintf(buffer + len, " port %s",
+                                   (sta & en_mask) ? "enabled" : "disabled");
+               len += sprintf(buffer + len, "\n");
+       }
+
+       return len;
+}
+
+static int omnibook_display_write(char *buffer, struct omnibook_operation *io_op)
+{
+       int retval;
+       unsigned int state;
+       char *endp;
+
+       state = simple_strtoul(buffer, &endp, 16);
+       if (endp == buffer)
+               return -EINVAL;
+       else
+               retval = backend_display_set(io_op, state);
+
+       return retval;
+}
+
+static struct omnibook_feature display_driver;
+
+static int __init omnibook_display_init(struct omnibook_operation *io_op)
+{
+       int retval;
+       unsigned int state;
+       
+       /* Disable file writing if unsuported by backend */
+       if (!io_op->backend->display_set)
+               display_driver.write = NULL;
+               
+       retval = backend_display_get(io_op, &state);
+       if (retval < 0)
+               return retval;
+       else
+               return 0;
+}
+
+static struct omnibook_tbl display_table[] __initdata = {
+       {TSM70 | TSX205, {ACPI,}},
+       {TSM40, {SMI, SMI_GET_DISPLAY_STATE, SMI_SET_DISPLAY_STATE, 0, 0, 0}},
+       {XE3GF | TSP10 | TSM70 | TSM30X | TSM40, SIMPLE_BYTE(EC, XE3GF_STA1, XE3GF_SHDD_MASK)},
+       {XE3GC, SIMPLE_BYTE(EC, XE3GC_STA1, XE3GC_CRTI_MASK)},
+       {OB500 | OB510 | OB6000 | OB6100 | XE4500, SIMPLE_BYTE(EC, OB500_STA1, OB500_CRTS_MASK)},
+       {OB4150, SIMPLE_BYTE(EC, OB4150_STA2, OB4150_CRST_MASK)},
+       {0,}
+};
+
+static struct omnibook_feature __declared_feature display_driver = {
+       .name = "display",
+       .enabled = 1,
+       .init = omnibook_display_init,
+       .read = omnibook_display_read,
+       .write = omnibook_display_write,
+       .ectypes =
+           XE3GF | XE3GC | OB500 | OB510 | OB6000 | OB6100 | XE4500 | OB4150 | TSP10 | TSM70 | TSM30X |
+           TSM40 | TSX205,
+       .tbl = display_table,
+};
+
+module_param_named(display, display_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(display, "Use 0 to disable, 1 to enable display status handling");
+/* End of file */
diff --git a/doc/BUGS b/doc/BUGS
new file mode 100644 (file)
index 0000000..c629259
--- /dev/null
+++ b/doc/BUGS
@@ -0,0 +1,17 @@
+Bugs and problems in omnibook module code
+=========================================
+
+* Volume Control buttons on machine (not on docking station) do not generate
+  scancodes on OB500 style models. It is unhandled yet.
+* Setting the LCD brightness on HP OmniBook XE3 GF via /proc/omnibook/lcd
+  is working if you press one of the brightness control keys once after
+  writing the value into /proc/omnibook/lcd.
+* I'm not a native English speaker so text corrections are welcome.
+* obtest can BADLY confuse the in-kernel ACPI code due to its racy 
+  implementation.
+* Reenabling wifi adapter after previous disabling is broken on 
+  Toshiba Satellite M100 (ipw3945)
+* Real support of ectype 14 is still missing 
+* See http://sourceforge.net/tracker/?atid=868542&group_id=174260&func=browse
+  for sf.net bug tracking system.
+
diff --git a/doc/COPYING b/doc/COPYING
new file mode 100644 (file)
index 0000000..d60c31a
--- /dev/null
@@ -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.
+\f
+                   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.)
+\f
+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.
+\f
+  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.
+\f
+  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
+\f
+           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) <year>  <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) year  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 --git a/doc/CREDITS b/doc/CREDITS
new file mode 100644 (file)
index 0000000..c525a4b
--- /dev/null
@@ -0,0 +1,39 @@
+The module was originally written by
+
+* Soós Péter <sp@osb.hu>
+
+Special thanks to the following persons and/or organisations (without
+particular order):
+
+* Al Stone <ahs3@fc.hp.com> and Linux Systems Operation at HP for lending
+  an HP OmniBook 500 for the project purposes.
+* Pavel Mihaylov <bin@bash.info> for his omke project discovering a lot of
+  OmniBook features, providing some code for XE3 GC machines and testing.
+* Ducrot Bruno <ducrot@poupinou.org> sharing lots of information about
+  embedded controller and related code, added lots of Toshiba support,
+  writing tosh3k code, sending patches etc.
+
+Thanks to the following people (without particular order):
+
+* Al Stone <ahs3@fc.hp.com> for sharing some programming information.
+* Guido Guenther <agx@sigxcpu.org> for initial OneTouch enabling code.
+* Jens Thoms Toerring <Jens.Toerring@physik.fu-berlin.de> for initial
+  OneTouch power management code.
+* Maciek Gorniak <mago@acn.waw.pl> for initial HP Pavilion N5415 detecting
+  code and initial lcd brighness code.
+* Rick Richardson <rickr@mn.rr.com> for some bugfixes and useful patches.
+* Bob McElrath <mcelrath@draal.physics.wisc.edu> for initial Compal ACL00
+  code.
+* Luisimi Moya <luismimoya@eresmas.net> for Acer Aspire 1400 support.
+* Bernhard Kaindl <bernhard.kaindl@gmx.de> for bugfixes and patches
+* Gabriele Vivinetto <gabriele.mailing@rvmgroup.it> for documentation
+  enhancements and testing.
+* Mark Chappell <nslm@nslm.fsnet.co.uk> for building on kernel 2.6.
+* Massimo Dal Zotto <dz@debian.org> for his i8k code.
+* Jonathan A. Buzzard <jonathan@buzzard.org.uk> for his toshiba code.
+* Some others on OmniBook mailing list at
+  http://zurich.ai.mit.edu/mailman/listinfo/omnibook
+  for providing information and testing.
+
+Last but not least thanks to Linus Torvald and more for creating and
+maintaining the Linux kernel.
diff --git a/doc/ChangeLog b/doc/ChangeLog
new file mode 100644 (file)
index 0000000..91adea6
--- /dev/null
@@ -0,0 +1,523 @@
+Changelog file for omnibook package:
+------------------------------------
+
+2.XXXXXXXX Mathieu Bérard <math_b@users.sourceforge.net>
+* DMI signature added:
+       Toshiba Satellite P25 (ectype 11)
+       Toshiba Satellite M60 (ectype 12)
+* Applied patch from Danny Kukawka <dkukawka@suse.de> to
+  fix compiler warning about use uninitialized variable
+* Applied patch from Danny Kukawka <dkukawka@suse.de> to
+  fix build the driver on older kernel versions
+* Applied patches from Azael Avalos <coproscefalo@gmail.com>
+  to add support to Satellite X205 and other laptops based on
+  ICH8
+* Fix build with kernel >= 2.6.30
+* Apply patch from Tiago Batista <a19944@gmail.com> to fix
+  backlight compilation issue with kernel >= 2.6.34
+
+2.20070211 Mathieu Bérard <math_b@users.sourceforge.net>
+* Disable Acer support, acerhk module should provided better
+  support with a far more complete autodetection database
+  (see http://www2.informatik.hu-berlin.de/~tauber/acerhk/)
+* Fix and improve bluetooth handling for TSM30X class laptops
+  bluetooth now also works for TSA105
+* Implement Volume down,up and Mute buttons polling for ectype 2
+   It was the last missing part from the "omke" module which never
+   got ported to linux 2.6
+* Implement ectype 13 Fn hotkeys handling.
+* DMI signature added:
+       HP Pavilion ze4500 (ectype 7)
+       Toshiba Satellite 1130 (ectype 1)
+       Toshiba Satellite A75 (ectype 12)
+       Toshiba Tecra A4 (ectype 13)
+       Toshiba Satellite A80 (ectype 12)
+       Toshiba Satellite P100 (ectype 14)
+* Split TSM30X (ectype 12) : this ectype was reimplemented and if the
+  new implementation works with Toshiba M40X, M70, M100... it does not
+  (and will never, due to hardware) with Toshiba M30X, the only way
+  to fix this is to split TSM30X (ectype 12) in :
+  -TSM70 (ectype 12) => new implementation (compal.c & acpi.c backends)
+  -TSM30X (ectype 15) => old implementation (legacy backends)
+  This is done by renaming TSM30X to TSM40 and restore old TSM30X
+  The state of the Toshiba M35X is unknown and is assigned to TSM70, one
+  should send a bug report if that fail.
+  Fix bugs 1617818 and 1605278
+* New features for TSM70 class laptops:
+  -Cooling method control (can tune fan behaviour to 'Save power' or
+   to 'Maximize performance') provided in /proc/omnibook/cooling 
+  -CPU Throttling status&control (also known as ACPI T-States) should
+   be supported out of the box via /proc/acpi/processor/CPU0/throttling
+   but at least Toshiba Satellite M70 as a deficient ACPI FADT table
+   which prevent than, thus a custom access to ACPI Throttling is 
+   provided in /proc/omnibook/throttling
+
+2.20060921 Mathieu Bérard <math_b@users.sourceforge.net>
+* The minimal required kernel version is now 2.6.9 (kref API)
+* Convert semaphore to mutex with fallback for pre 2.6.16 kernel
+* Kill CONFIG_OMNIBOOK_APMEMU and introduce OMNIBOOK_LEGACY:
+  pre-ACPI features now depends on it.
+  Default enabling of ac and battery features also
+  depends on it. It is _disabled_ by default.
+* Introduce ACPI methods execution backend: TSM70 needs it
+  for Display and Wifi/Bluetooth features
+* Expand display and hotkeys features
+* Introduce experimental NbSmi backend for TSM40. It is
+  based on technical documentation provided by Toshiba.
+  Thanks Toshiba !
+* Kill unused omnibook_mem_read/write function for mmio
+  access
+* Cleanup in blank.c fan.c temperature.c
+* Unbreak Pio backend: use request/release_region
+* Introduce bluetooth and wifi frontend features : they allow
+  adapter state querry and control (existence probing, wifi
+  kill switch probing and adapter enabling/disabling).
+  Supported by TSM30X and TSM40
+* Introduce omnibook_backend struct as a uniform way of 
+  communication between backend and frontend, this
+  kill omnibook_io_{read/write} and friends.
+* Modify ombibook_feature struct to incorporate pointers
+  to an omnibook_table table and to a omnibook_operation
+  struct which is picked-up from the ectype matching
+  omnibook_table entry upon feature initialization
+* Add muteled resume handler
+* Add touchpad handling for TSM30X
+* Add proper display handling for TSM30X
+* Change all features struct name from foo_feature to
+  foo_driver to kept modpost section mismatch detection
+  silent. Put tbl, init and exit entries to their relevant
+  sections.
+* Many bugfix and dock support for TSM40 by Holger Nelson.
+* Add DMI Signature for Toshiba Satellite 1700-Series, with ectype 10.
+  LCD does not work.
+* Add DMI Signature for Toshiba Equium A110, added with
+  ectype 1, until implementation of a better backend
+* Add DMI Signature for Toshiba _Satellite_ M100, Satellite A70 
+  and Tecra S2. added with ectype 12
+* Add DMI Signature for Toshiba Tecra S1, added with
+  ectype 13
+
+2.200608017 Mathieu Bérard <math_b@users.sourceforge.net>
+* Fix bug un omnibook_io_match
+* Fix DMI handling behaviour: we stop on the FIRST matched
+  DMI entry. This is restoring pre-20060806 behaviour.
+  Invert M40 vs. M40X entry position.
+
+2.20060816 Mathieu Bérard <math_b@users.sourceforge.net>
+* Merge from the new-backend branch: Add new backend code 
+  (in compal.c) used with TSM30X class laptops:
+  Used for lcd access
+  Used for hotkeys support: now most Fn+key generate a scancode,
+  as well as the wifi kill switch.
+  Warning: tested only on TSM40X an TSM70 laptops.
+* Create omnibook_io_operation struct and omnibook_io_{read/write}
+  funtions to simplify implementation of some simple features.
+  Used with ac display dock and led features.
+* Rename onetouch feature to "hotkeys" which is a vendor neutral name.
+* The minimal required kernel version is now 2.6.9 (kref API)
+* Convert semaphore to mutex with fallback for pre 2.6.16 kernel
+* Kill CONFIG_OMNIBOOK_APMEMU and introduce OMNIBOOK_LEGACY:
+  pre-ACPI features now depends on it.
+  Default enabling of ac and battery features also
+  depends on it. It is _disabled_ by default.
+* Introduce ACPI methods execution backend: TSM70 needs it
+  for Display and Wifi/Bluetooth features
+* Expand display and hotkeys features
+* Introduce experimental NbSmi backend for TSM40. It is
+  based on technical documentation provided by Toshiba.
+  Thanks Toshiba !
+* Kill unused omnibook_mem_read/write function for mmio
+  access
+* Cleanup in blank.c fan.c temperature.c
+* Unbreak Pio backend: use request/release_region
+* Introduce bluetooth and wifi frontend features : they allow
+  adapter state querry and control (existence probing, wifi 
+  kill switch probing and adapter enabling/disabling).
+  Supported by TSM30X and TSM40
+* Introduce omnibook_backend struct as a uniform way of 
+  communication between backend and frontend, this
+  kill omnibook_io_{read/write} and friends.
+* Modify ombibook_feature struct to incorporate pointers
+  to an omnibook_table table and to a omnibook_operation
+  struct which is picked-up from the ectype matching
+  omnibook_table entry upon feature initialization
+* Add muteled resume handler
+* Add touchpad handling for TSM30X
+* Add proper display handling for TSM30X
+* Change all features struct name from foo_feature to
+  foo_driver to kept modpost section mismatch detection
+  silent. Put tbl, init and exit entries to their relevant
+  sections.
+
+2.20060809 Mathieu Bérard <math_b@users.sourceforge.net>
+* Add dmi info for Toshiba Satellite M40X (Thanks Julien Valroff) 
+* Fix two brown paper bag bugs in Debian/Ubuntu support 
+
+2.20060806 Mathieu Bérard <math_b@users.sourceforge.net>
+* Make the module linux 2.6 only
+  Kernel versions from 2.6.8 to a least 2.6.17 are supported
+  Code for compatibility with kernels older than 2.6.17 is 
+  mostly implemented in compat.h
+* Integrate with Driver Model:
+  register as a platform device and optional
+  registration as a backlight device (2.6.17+ required here)
+* Get rid of deprecated pm_legacy functions
+* Use kernel-provided DMI information:
+  Use kernel-provided dmi_check_system for system identification
+  omnibook_tc_t and omnibook_models_t are merged and converted into a
+  dmi_system_id struct and moved from init.c to laptop.h
+* MODULE_PARAM -> 2.6-style module_parm_*
+* Move some code from "feature".c files back to init.c
+  Interface is provided by the new omnibook_feature struct
+  Enabled features are now in placed in a linked list
+  This eliminate util.c
+  Rationale: Reduce code duplication and create a standard template for features
+* Move dmi and version display into their own file: info.c
+* Remove all (as unneeded) EXPORT_SYMBOL
+* Misc fixes in Makefile
+  Also make more use of Kbuild
+* Use sscanf and simple_stro{u}l for strings parsing instead of custom code
+* Run lindent for better conformance with kernel coding style
+* Add very limited support for some Toshiba M40 (more info needed)
+* Use bitmasks for EC types matching, this change is transparent for the user
+  (e.g. one can still use ectype=num module parameter)
+  Rationale: Reduce the size of the omnibook_feature struct
+* Polish Debian support: Use module-assistant and fix all Lintian warning
+  Fix building against non-running kernel (Thanks to Daniel Gimpelevich)
+* Update documentation and omnibook-integration.patch
+* Fix spinlock usage: they can be used unconditionally as they are automatically
+  optimized out at build-time on UP. This should improve PREEMPT safety
+* Spinlock protect omnibook_mem_* and use ioread8 and iowrite8
+* Fix: Custom EC access function are also used if ACPI is compiled but disabled
+* Cleanup: remove lots of unneeded #ifdef
+* Add a new feature for testers: dump
+  Dump was stolen from the ibm_acpi driver
+  It is disabled by default
+* Bump version to 2.YYYYMMDD
+
+2006-05-15 Thomas Perl <thp@perli.net>
+* Added support for xe4500's "audio mute" led
+
+2006-01-26 Soós Péter <sp@osb.hu>
+* Added support for kernels >= 2.6.15 (pm_legacy.h)
+* Added Toshiba Satellite M30X
+* Added support for Toshiba Satellite M70
+* Added support for HP Pavilion ze4300 series
+* Fixed module unloading on 2.6 series kernels (thanks to
+  math_b@users.sourceforge.net)
+* Changed version number to +%Y%m%d format
+* Added Debian support
+
+2005-02-17 Soós Péter <sp@osb.hu> 
+* Fixed Makefile
+* Updated Toshiba 1115 information
+
+2004-12-15 Scott Barnes <reeve@users.sourceforge.net>
+* Added Toshiba Satellite M35X
+
+2004-09-16 Soós Péter <sp@osb.hu>
+* Added INSTALL-2.6 file
+* Little spelling fixes in documentation
+* Little bugfixes
+* Added Compal ACL10
+
+2004-07-01 Soós Péter <sp@osb.hu>
+* Added new technology codes
+* Added some new HP nx9000 detection string
+* Added Toshiba Satellite P20
+
+2004-06-07 Chris Green <cmg@dok.org>
+* Added Toshiba Satellite P15
+
+2004-06-01 Soós Péter <sp@osb.hu>
+* Added Toshiba Satellite 1955
+* Added Toshiba Satellite 2435
+* Added Toshiba Satellite P10 (new ectype)
+* Acer Aspire 1350
+
+2004-01-23 Soós Péter <sp@osb.hu>
+* Added HP Pavilion ze8500 (HP nx9010)
+* fixed PM handler for OneTouch keys and touchpad
+
+2004-01-20 Soós Péter <sp@osb.hu>
+* Only fan status supported on HP OmniBook 4150, XE2 and
+  Fujitsu-Siemens Amilo D, fan control is unsupported
+* #include fixes in ec.c
+
+2004-01-16 Soós Péter <sp@osb.hu>
+* Added fan support for Fujitsu-Siemens Amilo D series laptops
+
+2004-01-14 Soós Péter <sp@osb.hu>
+* Fixed Makefile for kernels 2.6
+* Added Fujitsu-Siemens Amilo D series laptops (new ectype)
+
+2003-12-08 Soós Péter <sp@osb.hu>
+
+* Fixed tecnology code detection
+* Added HP/Compaq nx9005
+* Fixed Makefile for kernel 2.4
+
+2003-11-12 Soós Péter <sp@osb.hu>
+
+* Fixed KERNEL_WARNING in init.c
+
+2003-11-10 Soós Péter <sp@osb.hu>
+
+* Fixed timeout bugs in ec.c
+* Fixed touchpad dependency code for kernel 2.6
+* Added Compaq nx9000
+
+2003-11-10 Mark Chappell <mark@nslm.fsnet.co.uk>
+
+* Added kernel 2.6 support to Makefile
+
+2003-10-23 Soós Péter <sp@osb.hu>
+
+* Totally removed key polling code for kernels >= 2.5.0 but 2.5/2.6 kernels
+  is unsuported yet
+* proc_battery is static
+* Added HP OmniBook 900 B support
+* Added HP OmniBook XE2 support (added new ectype value for it)
+* Added Compaq nx9010
+* Reversed ChangeLog
+* Some documentation changes
+
+2003-08-28 Soós Péter <sp@osb.hu>
+
+* Added Toshiba Satellite 2430
+* Documentation enhancements
+
+2003-04-03 Soós Péter <sp@osb.hu>
+
+* Really fixed __init bug in user parameter code
+* Fixed omnibook_dmi_ident (it was static)
+
+2003-03-31 Soós Péter <sp@osb.hu>
+
+* Fixed HP technology code detection
+* Key polling is disabled by default on XE3GC style machines
+* Fixed PM code in polling.c
+* Added util.c
+* Fixed __init bug in user parameter code
+* Cleaned up ec.h
+* Added Toshiba Satellite 1950 detection
+* Documentation enhancements
+
+2003-03-13 Soós Péter <sp@osb.hu>
+
+* Added HP Pavilion ZU1155 and ZU1175 detection
+
+2003-03-11 Soós Péter <sp@osb.hu>
+
+* Fixed bogus version information
+
+2003-03-06 Ducrot Bruno <ducrot@poupinou.org>
+
+* Fan off hack for XE3GF style machines
+
+2003-03-04 Ducrot Bruno <ducrot@poupinou.org>
+
+* Fixed spinlock problem
+
+2003-02-28 Soós Péter <sp@osb.hu>
+
+* Added /proc/omnibook/version
+* Added OMNIBOOK_ prefix to MODULE_NAME and MODULE_VERSION definitions
+* Fixed bugs in lcd.c (thanks to Bernhard Kaindl <bernhard.kaindl@gmx.de>)
+* Some code tuning and cosmetic changes
+* Fixed OmniBook 4150 support
+
+2003-02-26 Soós Péter <sp@osb.hu>
+
+* Fixed kernel Oops in technology code identification
+* Some minor changes in logging
+
+2003-02-25 Soós Péter <sp@osb.hu>
+
+* Try to identify HP laptops by technology code if machine is unsupported
+* Fixed dmi identification code
+
+2003-02-14 Soós Péter <sp@osb.hu>
+
+* Added HP Pavilion ze4100 support
+* Added HP Pavilion ze4200 support
+* Fixed HP Pavilion xt155 detection
+* Added Acer Aspire 1400 series laptop support
+* Fixed APM status detection bug
+* Cleaned up dmi identification code
+* Removed "Asset Tag:" field from dmi string structure
+
+2003-01-27 Soós Péter <sp@osb.hu>
+
+* Added HP Pavilion N5430 support
+* EC functions are work even if boot parameter acpi=off is given
+* Improved error handling in externally callable functions
+* Fixed kernel integration patch
+* Removed unreliable undocking feature for OB500
+* Fixed HP Pavilion N5415 support
+* Added new format hotkeys sample files
+
+2003-01-09 Ducrot Bruno <ducrot@poupinou.org>
+
+* Added to use ACPI_EC if available
+
+2003-01-09 Soós Péter <sp@osb.hu>
+
+* Fixed reverse console blanking bug on OB5xx and OB6xxx
+* Disabled unreliable undocking feature on OB500
+
+2003-01-08 Ducrot Bruno <ducrot@poupinou.org>
+
+* Added Toshiba Satellite 3000, 3005, 1000, 1005, 1110, 1115, 1900, 1905
+  support
+
+2003-01-08 Soós Péter <sp@osb.hu>
+
+* The ectype values changed again! See the README!
+* Fixed new ectypes detection bug
+* Added OmniBook xe4400 support
+* Added LCD display turn off at console blanking on OB5xx and OB6xxx
+* Documentation fixes
+
+2003-01-07 Soós Péter <sp@osb.hu>
+
+* Fixed bit level negation bug in fan.c
+* Added turn fan on for Toshiba 3000
+* Corrected OmniBook 4150 support code
+
+2003-01-06 Soós Péter <sp@osb.hu>
+
+* Changed ectype values! See the README!
+* Fixed some bugs in obtest utility
+* Fixed second battery status bug in battery.c
+* Added textual descriptions to some functions in /proc/omnibook
+* Fix APM emulation to work when APM support is present but APM power
+  status reporting flagged broken
+* Added docking station support
+* Added fan support
+* Added module parameter: user
+* Added OmniBook xe155, xe4100 and ze4125 support
+* Fan policy moved to /proc/omnibook/fan_policy
+* Reorganized scancode emulation code for XE3 GC
+* Polling of volume buttons on XE3CG style models can be enabled/disabled
+  via /proc/omnibook/key_polling
+* Finished abstraction layer
+* Some minor changes in Rick's model detection code
+* New kernel integration code
+
+2002-12-22 Rick Richardson <rickr@mn.rr.com>
+
+* Added on and off as valid input to /proc/omnibook/lcd, to turn
+  the LCD backlight on and off.
+
+2002-12-15 Rick Richardson <rickr@mn.rr.com>
+
+* Reimplemented model detection so you only have to modify one file
+  to add a new model. features.h is now deprecated.
+* Added the Toshiba Satellite 1115/S103 to the supported models
+* Fixed bug in apmemu.c which caused /proc/apm to report the battery
+  status as critical when the battery was charging.
+
+2002-10-16 Soós Péter <sp@osb.hu>
+
+* Added HP Pavilion N5415 support
+* Corrected HP Pavilion N5441 support
+* Fix values of OB500 type machines in ec.h
+* LCD brightness support added for XE3GC and XE3GF style machines
+* Added HP OmniBook 510 FB support
+* AC adapter status monitoring is working on all machines
+* External display status monitoring is working on all machines
+* CPU temperature monitoring is working on all machines
+* __init functions gone to init.h
+* Added an abstraction layer between the low level, hardware dependent
+  functions and the applications (not yet finished). See omnibook.h for
+  details.
+
+2002-09-20 Soós Péter <sp@osb.hu>
+
+* Using save_flags()/cli() instead spinlocks in ec.c because of laptops do
+  not have more than one CPU (yet ;)). This improves performance and
+  eliminates packet loss in ppp stack
+* The previous version of XE3 GC scancode emulation was buggy: it worked only
+  when ACPI enabled. Current version is working ACPI independent way
+
+2002-09-05 Soós Péter <sp@osb.hu>
+
+* Added secondary battery support (untested, please report!)
+* Added ectype module parameter to specify the type of embedded
+  controller firmware
+* Added some OmniBook XE3 GC support code
+* Added some OmniBook 500 style embedded controller firmware support code
+  (OmniBook 5xx, 6xxx and some Pavilions)
+* Reorganized features matrix (again): the features depends on the embedded
+  controller firmware, not the model
+* Added external display status monitoring on some machine
+* Added scancode emulation on OmniBook XE3 GC
+
+2002-08-14 Soós Péter <sp@osb.hu>
+
+* Added HP OmniBook 6000 EA support (OneTouch only)
+* Added HP OmniBook 6100 EB support (OneTouch only)
+* Fixed Toshiba Satellite 3000-100 detection
+* Fixed timeout and locking bugs in ec.c
+* Added HP Pavilion Notebook ZT1141
+* Reorganized the feature matrix and parameter detection code to make easy
+  to add new features differents machine by machine
+
+2002-08-11 Soós Péter <sp@osb.hu>
+
+* Fixed removing of procfs entries
+* Fixed APM detection
+* Added kernel source integration
+* Fixed __initdata bugs
+* Handling difference between untesed and unsupported features
+
+2002-08-09 Soós Péter <sp@osb.hu>
+
+* Added Compal ACL00 laptop support
+* Updated documentation
+* Added touchpad support
+* Some bugfixes
+* /proc/apm emulation added
+
+2002-08-06 Soós Péter <sp@osb.hu>
+
+* Corrected full charged battery info
+* Added OneTouch handling via procfs
+* Added console blank handling via procfs
+* Added temperature policy handling via procfs
+* Corrected the bug in DMI code to report the serial number
+* Added module parameter support
+* Added HP Pavilion Notebook N5490, ZT1195 (and probably other Pavilions)
+
+2002-07-17 Soós Péter <sp@osb.hu>
+
+* Improved error handling
+* Some text corrections
+* Added Toshiba Satellite 3000-100 support
+* Some code tuning
+* Added omnibook prefix for variables and functions to prevent conflicts
+  with another code
+* Added /proc filesystem support
+* Added battery status monitoring
+* Added CPU temperature monitoring
+
+2002-06-03 Soós Péter <sp@osb.hu>
+
+* Some code tuning
+
+2002-05-07 Soós Péter <sp@osb.hu>
+
+* Added missing #include <linux/sched.h> to main.c
+* Some text corrections
+* Added HP OmniBook 500 FA support (OneTouch only)
+
+2002-05-06 Soós Péter <sp@osb.hu>
+
+* LCD display turn off at console blanking added
+* Code cleanup
+
+2002-05-02 Soós Péter <sp@osb.hu>
+
+* The first release of omnibook module
+* OneTouch button support
diff --git a/doc/INSTALL b/doc/INSTALL
new file mode 100644 (file)
index 0000000..6e373cc
--- /dev/null
@@ -0,0 +1,21 @@
+Basic installation instructions
+==================================
+
+1/ Install GNU make and C compiler (gcc), as well as the configured
+source of the running kernels (ie. either the kernel headers or the
+sources from which you have compiled your own kernel)
+
+2/ get the up-to-date sources:
+$ git clone git://omnibook.git.sourceforge.net/gitroot/omnibook/omnibook
+
+3/ compile, install and load the module against your kernel sources:
+$ cd omnibook/
+# make load
+
+4/ (Optional) Add necessary module options to your /etc/modprobe.conf or in
+a file in /etc/modprobe.d/. e.g.: "options omnibook apmemu=1 dock=1
+user=1"
+
+5/ (Optional) Edit your startup scripts (eg. /etc/rc.local, /etc/rc.modules
+or /etc/modules) to load this module at boot time.
+
diff --git a/doc/README b/doc/README
new file mode 100644 (file)
index 0000000..4260195
--- /dev/null
@@ -0,0 +1,39 @@
+===============================================================
+Kernel Support for HP OmniBooks, Pavilions and Compal laptops
+===============================================================
+
+This package is intended to provide Linux kernel support for many laptops such as:
+- HP OmniBook and Pavilion
+- Toshiba Satellite and Tecra which are not supported by the toshiba_acpi module
+- Compal ACL00
+- Many laptops manufactured by Compal Electronics, Inc as ODM
+
+Supported features depends on the exact laptop model but may include:
+- Enabling hotkey buttons
+- Console (LCD display) blanking
+- Battery status monitoring.
+- Fan and fan policy support
+- Touchpad control
+- AC Adapter status monitoring
+- External display monitors status monitoring and control
+- LCD brightness (backlight) monitoring and control
+- Docking station/port replicator status
+- CPU temperature monitoring
+- Mute LED monitoring and control
+- Wifi and Bluetooth adapters monitoring and control
+- Cooling method control
+- CPU Throttling control
+
+Useful links:
+
+Sourceforge project page:
+http://sourceforge.net/projects/omnibook
+
+Other links not related to the project:
+
+For HP Omnibook specific issues ou can see the OmniBook mailing list:
+http://zurich.ai.mit.edu/mailman/listinfo/omnibook
+
+or the Toshiba linux mailing list:
+http://linux.toshiba-dme.co.jp/linux/
+
diff --git a/dock.c b/dock.c
new file mode 100644 (file)
index 0000000..3264f70
--- /dev/null
+++ b/dock.c
@@ -0,0 +1,84 @@
+/*
+ * dock.c -- docking station/port replicator support
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+static int omnibook_dock_read(char *buffer, struct omnibook_operation *io_op)
+{
+       int len = 0;
+       u8 dock;
+       int retval;
+
+       if ((retval = backend_byte_read(io_op, &dock)))
+               return retval;
+
+       len += sprintf(buffer + len, "Laptop is %s\n", (dock) ? "docked" : "undocked");
+
+       return len;
+}
+
+static int omnibook_dock_write(char *buffer, struct omnibook_operation *io_op)
+{
+       int retval;
+
+       switch (*buffer) {
+       case '0':
+               retval = backend_byte_write(io_op, 0);
+               break;
+       case '1':
+               retval = backend_byte_write(io_op, 1);
+               break;
+       default:
+               retval = -EINVAL;
+       }
+
+       return retval;
+}
+
+static struct omnibook_feature dock_driver;
+
+static int __init omnibook_dock_init(struct omnibook_operation *io_op)
+{
+       /* writing is only supported on ectype 13 */
+       if(!(omnibook_ectype & TSM40))
+               dock_driver.write = NULL;
+       
+       return 0;
+}
+
+static struct omnibook_tbl dock_table[] __initdata = {
+       {XE3GF, SIMPLE_BYTE(EC, XE3GF_CSPR, XE3GF_CSPR_MASK)},
+       {OB500 | OB510 | OB6000 | OB6100, SIMPLE_BYTE(EC, OB500_STA1, OB500_DCKS_MASK)},
+       {OB4150, SIMPLE_BYTE(EC, OB4150_DCID, 0)},
+       {TSM40, {SMI, SMI_GET_DOCK, SMI_SET_DOCK, 0, 0, 0}},
+       {0,}
+};
+
+static struct omnibook_feature __declared_feature dock_driver = {
+       .name = "dock",
+       .enabled = 0,
+       .init = omnibook_dock_init,
+       .read = omnibook_dock_read,
+       .write = omnibook_dock_write,
+       .ectypes = XE3GF | OB500 | OB510 | OB6000 | OB6100 | OB4150 | TSM40,
+       .tbl = dock_table,
+};
+
+module_param_named(dock, dock_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(dock, "Use 0 to disable, 1 to enable docking station support");
+/* End of file */
diff --git a/dump.c b/dump.c
new file mode 100644 (file)
index 0000000..ff959e9
--- /dev/null
+++ b/dump.c
@@ -0,0 +1,107 @@
+/*
+ *  dump.c - Raw dump of EC register, stolen from ibm_acpi.c
+ *
+ *
+ *  Copyright (C) 2004-2005 Borislav Deianov <borislav@users.sf.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
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+static u8 ecdump_regs[256];
+
+static int ecdump_read(char *buffer, struct omnibook_operation *io_op)
+{
+       int len = 0;
+       int i, j;
+       u8 v;
+
+       len +=
+           sprintf(buffer + len,
+                   "EC      " " +00 +01 +02 +03 +04 +05 +06 +07"
+                   " +08 +09 +0a +0b +0c +0d +0e +0f\n");
+
+       if(mutex_lock_interruptible(&io_op->backend->mutex))
+                       return -ERESTARTSYS;
+
+       for (i = 0; i < 255; i += 16) {
+               len += sprintf(buffer + len, "EC 0x%02x:", i);
+               for (j = 0; j < 16; j++) {
+                       io_op->read_addr = i +j;
+                       if (__backend_byte_read(io_op, &v))
+                               break;
+                       if (v != ecdump_regs[i + j])
+                               len += sprintf(buffer + len, " *%02x", v);
+                       else
+                               len += sprintf(buffer + len, "  %02x", v);
+                       ecdump_regs[i + j] = v;
+               }
+               len += sprintf(buffer + len, "\n");
+               if (j != 16)
+                       break;
+       }
+
+       mutex_unlock(&io_op->backend->mutex);
+
+       /* These are way too dangerous to advertise openly... */
+#if 0
+       len +=
+           sprintf(buffer + len,
+                   "commands:\t0x<offset> 0x<value>" " (<offset> is 00-ff, <value> is 00-ff)\n");
+       len +=
+           sprintf(buffer + len,
+                   "commands:\t0x<offset> <value>  " " (<offset> is 00-ff, <value> is 0-255)\n");
+#endif
+       return len;
+}
+
+static int ecdump_write(char *buffer, struct omnibook_operation *io_op)
+{
+
+       int i, v;
+
+       if (sscanf(buffer, "0x%x 0x%x", &i, &v) == 2) {
+               /* i and v set */
+       } else if (sscanf(buffer, "0x%x %u", &i, &v) == 2) {
+               /* i and v set */
+       } else
+               return -EINVAL;
+       if (i >= 0 && i < 256 && v >= 0 && v < 256) {
+               io_op->write_addr = i;
+               return backend_byte_write(io_op, v);
+       } else
+               return -EINVAL;
+
+       return 0;
+}
+
+static struct omnibook_tbl dump_table[] __initdata = {
+       {ALL_ECTYPES, {EC,}},
+       {0,}
+};
+
+static struct omnibook_feature __declared_feature dump_driver = {
+       .name = "dump",
+       .enabled = 0,
+       .read = ecdump_read,
+       .write = ecdump_write,
+       .tbl = dump_table,
+};
+
+module_param_named(dump, dump_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(dump, "Use 0 to disable, 1 to enable embedded controller register dump support");
+/* End of file */
diff --git a/ec.c b/ec.c
new file mode 100644 (file)
index 0000000..47e24c6
--- /dev/null
+++ b/ec.c
@@ -0,0 +1,188 @@
+/*
+ * ec.c -- low level functions to access Embedded Controller,
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/ioport.h>
+
+#include <asm/io.h>
+#include "hardware.h"
+
+/*
+ * Interrupt control
+ */
+
+static DEFINE_SPINLOCK(omnibook_ec_lock);
+
+/*
+ * Registers of the embedded controller
+ */
+
+#define OMNIBOOK_EC_DATA               0x62
+#define OMNIBOOK_EC_SC                 0x66
+
+/*
+ * Embedded controller status register bits
+ */
+
+#define OMNIBOOK_EC_STAT_OBF           0x01    /* Output buffer full */
+#define OMNIBOOK_EC_STAT_IBF           0x02    /* Input buffer full */
+
+
+/*
+ * Embedded controller commands
+ */
+
+#define OMNIBOOK_EC_CMD_READ           0x80
+#define OMNIBOOK_EC_CMD_WRITE          0x81
+
+/*
+ * Wait for embedded controller buffer
+ */
+
+static int omnibook_ec_wait(u8 event)
+{
+       int timeout = OMNIBOOK_TIMEOUT;
+
+       switch (event) {
+       case OMNIBOOK_EC_STAT_OBF:
+               while (!(inb(OMNIBOOK_EC_SC) & event) && timeout--)
+                       mdelay(1);
+               break;
+       case OMNIBOOK_EC_STAT_IBF:
+               while ((inb(OMNIBOOK_EC_SC) & event) && timeout--)
+                       mdelay(1);
+               break;
+       default:
+               return -EINVAL;
+       }
+       if (timeout > 0)
+               return 0;
+       return -ETIME;
+}
+
+/*
+ * Read from the embedded controller
+ * Decide at run-time if we can use the much cleaner ACPI EC driver instead of
+ * this implementation, this is the case if ACPI has been compiled and is not
+ * disabled.
+ */
+
+static int omnibook_ec_read(const struct omnibook_operation *io_op, u8 * data)
+{
+       int retval;
+
+#ifdef CONFIG_ACPI_EC
+       if (likely(!acpi_disabled)) {
+               retval = ec_read((u8) io_op->read_addr, data);
+               if (io_op->read_mask)
+                       *data &= io_op->read_mask;
+//             dprintk("ACPI EC read at %lx success %i.\n", io_op->read_addr, retval);
+               return retval;
+       }
+#endif
+       spin_lock_irq(&omnibook_ec_lock);
+       retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF);
+       if (retval)
+               goto end;
+       outb(OMNIBOOK_EC_CMD_READ, OMNIBOOK_EC_SC);
+       retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF);
+       if (retval)
+               goto end;
+       outb((u8) io_op->read_addr, OMNIBOOK_EC_DATA);
+       retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_OBF);
+       if (retval)
+               goto end;
+       *data = inb(OMNIBOOK_EC_DATA);
+       if (io_op->read_mask)
+               *data &= io_op->read_mask;
+      end:
+       spin_unlock_irq(&omnibook_ec_lock);
+//     dprintk("Custom EC read at %lx success %i.\n", io_op->read_addr, retval);
+       return retval;
+}
+
+/*
+ * Write to the embedded controller:
+ * If OMNIBOOK_LEGACY is set, decide at run-time if we can use the much cleaner 
+ * ACPI EC driver instead of this legacy implementation. 
+ * This is the case if ACPI has been compiled and is not
+ * disabled.
+ * If OMNIBOOK_LEGACY is unset, we drop our custoim implementation
+ */
+
+static int omnibook_ec_write(const struct omnibook_operation *io_op, u8 data)
+{
+       int retval;
+
+#ifdef CONFIG_ACPI_EC
+       if (likely(!acpi_disabled)) {
+               retval = ec_write((u8) io_op->write_addr, data);
+//             dprintk("ACPI EC write at %lx success %i.\n", io_op->write_addr, retval);
+               return retval;
+       }
+#endif
+
+       spin_lock_irq(&omnibook_ec_lock);
+       retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF);
+       if (retval)
+               goto end;
+       outb(OMNIBOOK_EC_CMD_WRITE, OMNIBOOK_EC_SC);
+       retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF);
+       if (retval)
+               goto end;
+       outb((u8) io_op->write_addr, OMNIBOOK_EC_DATA);
+       retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF);
+       if (retval)
+               goto end;
+       outb(data, OMNIBOOK_EC_DATA);
+      end:
+       spin_unlock_irq(&omnibook_ec_lock);
+//     dprintk("Custom EC write at %lx success %i.\n", io_op->write_addr, retval);
+       return retval;
+}
+
+static int omnibook_ec_display(const struct omnibook_operation *io_op, unsigned int *state)
+{
+       int retval;
+       u8 raw_state;
+
+       retval = __backend_byte_read(io_op, &raw_state);
+       if (retval < 0)
+               return retval;
+
+       *state = !!(raw_state & DISPLAY_CRT_DET);
+
+       return DISPLAY_CRT_DET;
+}
+
+/*
+ * Backend interface declarations
+ */
+
+struct omnibook_backend ec_backend = {
+       .name = "ec",
+       .byte_read = omnibook_ec_read,
+       .byte_write = omnibook_ec_write,
+       .display_get = omnibook_ec_display,
+};
+
+/* End of file */
diff --git a/fan.c b/fan.c
new file mode 100644 (file)
index 0000000..d812993
--- /dev/null
+++ b/fan.c
@@ -0,0 +1,183 @@
+/*
+ * fan.c -- fan status/control
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+
+#include <linux/delay.h>
+#include <asm/io.h>
+#include "hardware.h"
+
+static const struct omnibook_operation ctmp_io_op = { EC, XE3GF_CTMP, 0, 0, 0, 0 };
+static const struct omnibook_operation fot_io_op = { EC, XE3GF_FOT, XE3GF_FOT, 0, 0, 0 };
+
+static int omnibook_get_fan(struct omnibook_operation *io_op)
+{
+       u8 fan;
+       int retval;
+
+       if ((retval = backend_byte_read(io_op, &fan)))
+               return retval;
+
+       /*
+        * For most models the reading is a bool
+        * It as to be inverted on all but OB6000|OB6100|OB4150|AMILOD
+        * TSP10|XE3GF|TSX205 return an integer
+        */
+
+       if (omnibook_ectype & (TSP10 | XE3GF | TSX205))
+               retval = fan;
+       else if (omnibook_ectype & (OB6000 | OB6100 | OB4150 | AMILOD))
+               retval = !!fan;
+       else
+               retval = !fan;
+
+       return retval;
+}
+
+static int omnibook_fan_on(struct omnibook_operation *io_op)
+{
+       return omnibook_apply_write_mask(io_op, 1);
+}
+
+static int omnibook_fan_off(struct omnibook_operation *io_op)
+{
+       int i, retval = 0;
+
+       if (!(omnibook_ectype & (XE3GF | TSP10 | TSX205))) {
+               retval = omnibook_apply_write_mask(io_op, 0);
+               return retval;
+       } else {
+       /*
+        * Special handling for XE3GF & TSP10
+        */
+               u8 fot, temp, fan;
+
+               if(mutex_lock_interruptible(&io_op->backend->mutex))
+                       return -ERESTARTSYS;    
+
+               retval = __backend_byte_read(io_op, &fan);
+
+               /* error or fan is already off */
+               if (retval || !fan)
+                       goto out;
+
+               /* now we set FOT to current temp, then reset to initial value */
+               if ((retval = __backend_byte_read(&fot_io_op, &fot)))
+                       goto out;
+               if ((retval = __backend_byte_read(&ctmp_io_op, &temp)))
+                       goto out;
+
+               /* Wait for no longer than 250ms (this is arbitrary). */
+               for (i = 0; i < 250; i++) {
+                       __backend_byte_write(&fot_io_op, temp);
+                       mdelay(1);
+                       __backend_byte_read(io_op, &fan);
+                       if (!fan) /* Fan is off */
+                               break;
+               }
+               __backend_byte_write(&fot_io_op, fot);
+
+               if(i == 250 ) {
+                       printk(O_ERR "Attempt to switch off the fan failed.\n");
+                       retval = -EIO;
+               }
+
+               out:            
+               mutex_unlock(&io_op->backend->mutex);
+       }
+               
+
+       return retval;
+}
+
+static int omnibook_fan_read(char *buffer, struct omnibook_operation *io_op)
+{
+       int fan;
+       int len = 0;
+       char *str;
+
+       fan = omnibook_get_fan(io_op);
+       if (fan < 0)
+               return fan;
+       str = (fan) ? "on" : "off";
+
+       if (fan > 1)
+               len += sprintf(buffer + len, "Fan is %s (level %d)\n", str, fan);
+       else
+               len += sprintf(buffer + len, "Fan is %s\n", str);
+
+       return len;
+}
+
+static int omnibook_fan_write(char *buffer, struct omnibook_operation *io_op)
+{
+       int retval;
+
+       switch (*buffer) {
+       case '0':
+               retval = omnibook_fan_off(io_op);
+               break;
+       case '1':
+               retval = omnibook_fan_on(io_op);
+               break;
+       default:
+               retval = -EINVAL;
+       }
+       return retval;
+}
+
+static struct omnibook_feature fan_driver;
+
+static int __init omnibook_fan_init(struct omnibook_operation *io_op)
+{
+       /*
+        * OB4150
+        * XE2
+        * AMILOD
+        * They only support fan reading 
+        */
+       if (omnibook_ectype & (OB4150 | XE2 | AMILOD))
+               fan_driver.write = NULL;
+       return 0;
+}
+
+static struct omnibook_tbl fan_table[] __initdata = {
+       {XE3GF | TSP10 | TSM70 | TSX205, {EC, XE3GF_FSRD, XE3GF_FSRD, 0, XE3GF_FAN_ON_MASK, 0}},
+       {OB500,
+        {PIO, OB500_GPO1, OB500_GPO1, OB500_FAN_OFF_MASK, -OB500_FAN_ON_MASK, OB500_FAN_OFF_MASK}},
+       {OB510,
+        {PIO, OB510_GPIO, OB510_GPIO, OB510_FAN_OFF_MASK, -OB510_FAN_ON_MASK, OB510_FAN_OFF_MASK}},
+       {OB6000 | OB6100,
+        {EC, OB6000_STA1, OB6000_STA1, OB6000_FAN_MASK, OB6000_FAN_MASK, -OB6000_FAN_MASK}},
+       {OB4150 | AMILOD, {EC, OB4150_STA1, 0, OB4150_FAN_MASK, 0, 0}},
+       {XE2, {PIO, OB500_GPO1, 0, XE2_FAN_MASK, 0, 0}},
+       {0,}
+};
+
+static struct omnibook_feature __declared_feature fan_driver = {
+       .name = "fan",
+       .enabled = 1,
+       .read = omnibook_fan_read,
+       .write = omnibook_fan_write,
+       .init = omnibook_fan_init,
+       .ectypes = XE3GF | OB500 | OB510 | OB6000 | OB6100 | OB4150 | XE2 | AMILOD | TSP10 | TSX205,
+       .tbl = fan_table,
+};
+
+module_param_named(fan, fan_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(fan, "Use 0 to disable, 1 to enable fan status monitor and control");
+/* End of file */
diff --git a/fan_policy.c b/fan_policy.c
new file mode 100644 (file)
index 0000000..67915ff
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * fan_policy.c -- fan policy support
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+
+#include <linux/ctype.h>
+#include "hardware.h"
+
+/*
+ * Default temperature limits.
+ * Danger! You may overheat your CPU!
+ * Do not change these values unless you exactly know what you do.
+ */
+
+#define OMNIBOOK_FAN_LEVELS                    8
+#define OMNIBOOK_FAN_MIN                       25      /* Minimal value of fan off temperature */
+#define OMNIBOOK_FOT_MAX                       75      /* Maximal value of fan off temperature */
+#define OMNIBOOK_FAN_MAX                       95      /* Maximal value of fan on temperature */
+#define OMNIBOOK_FOT_DEFAULT                   60      /* Default value of fan off temperature */
+#define OMNIBOOK_FAN1_DEFAULT                  75      /* Default value of fan on temperature */
+#define OMNIBOOK_FAN2_DEFAULT                  85      /* Default value of fan level 2 temperature */
+#define OMNIBOOK_FAN3_DEFAULT                  90      /* Default value of fan level 3 temperature */
+#define OMNIBOOK_FAN4_DEFAULT                  95      /* Default value of fan level 4 temperature */
+#define OMNIBOOK_FAN5_DEFAULT                  95      /* Default value of fan level 5 temperature */
+#define OMNIBOOK_FAN6_DEFAULT                  95      /* Default value of fan level 6 temperature */
+#define OMNIBOOK_FAN7_DEFAULT                  95      /* Default value of fan level 7 temperature */
+
+static const u8 fan_defaults[] = {
+               OMNIBOOK_FOT_DEFAULT,
+               OMNIBOOK_FAN1_DEFAULT,
+               OMNIBOOK_FAN2_DEFAULT,
+               OMNIBOOK_FAN3_DEFAULT,
+               OMNIBOOK_FAN4_DEFAULT,
+               OMNIBOOK_FAN5_DEFAULT,
+               OMNIBOOK_FAN6_DEFAULT,
+               OMNIBOOK_FAN7_DEFAULT,
+};
+
+static int omnibook_get_fan_policy(struct omnibook_operation *io_op, u8 *fan_policy)
+{
+       int retval ;
+       int i;
+
+       for (i = 0; i < OMNIBOOK_FAN_LEVELS; i++) {
+               io_op->read_addr = XE3GF_FOT + i;
+               if ((retval = __backend_byte_read(io_op, &fan_policy[i])))
+                       return retval;
+       }
+
+       return 0;
+}
+
+static int omnibook_set_fan_policy(struct omnibook_operation *io_op, const u8 *fan_policy)
+{
+       int retval;
+       int i;
+
+       if (fan_policy[0] > OMNIBOOK_FOT_MAX)
+               return -EINVAL;
+
+       for (i = 0; i < OMNIBOOK_FAN_LEVELS; i++) {
+               if ((fan_policy[i] > fan_policy[i + 1])
+                   || (fan_policy[i] < OMNIBOOK_FAN_MIN)
+                   || (fan_policy[i] > OMNIBOOK_FAN_MAX))
+                       return -EINVAL;
+       }
+       for (i = 0; i < OMNIBOOK_FAN_LEVELS; i++) {
+               io_op->write_addr = XE3GF_FOT + i;
+               if ((retval = __backend_byte_write(io_op, fan_policy[i])))
+                       return retval;
+       }
+
+       return 0;
+}
+
+static int omnibook_fan_policy_read(char *buffer, struct omnibook_operation *io_op)
+{
+       int retval;
+       int len = 0;
+       u8 i;
+       u8 fan_policy[OMNIBOOK_FAN_LEVELS];
+
+       if(mutex_lock_interruptible(&io_op->backend->mutex))
+               return -ERESTARTSYS;
+
+       retval = omnibook_get_fan_policy(io_op, &fan_policy[0]);
+
+       mutex_unlock(&io_op->backend->mutex);
+
+       if(retval)
+               return retval;
+
+       len += sprintf(buffer + len, "Fan off temperature:        %2d C\n", fan_policy[0]);
+       len += sprintf(buffer + len, "Fan on temperature:         %2d C\n", fan_policy[1]);
+       for (i = 2; i < OMNIBOOK_FAN_LEVELS; i++) {
+               len +=
+                   sprintf(buffer + len, "Fan level %1d temperature:    %2d C\n", i,
+                           fan_policy[i]);
+       }
+       len += sprintf(buffer + len, "Minimal temperature to set: %2d C\n", OMNIBOOK_FAN_MIN);
+       len += sprintf(buffer + len, "Maximal temperature to set: %2d C\n", OMNIBOOK_FAN_MAX);
+
+       return len;
+}
+
+static int omnibook_fan_policy_write(char *buffer, struct omnibook_operation *io_op)
+{
+       int n = 0;
+       char *b;
+       char *endp;
+       int retval;
+       int temp;
+       u8 fan_policy[OMNIBOOK_FAN_LEVELS];
+
+       if(mutex_lock_interruptible(&io_op->backend->mutex))
+               return -ERESTARTSYS;
+
+       if ((retval = omnibook_get_fan_policy(io_op, &fan_policy[0])))
+               goto out;
+
+       /* 
+        * Could also be done much simpler using sscanf(,"%u %u ... 
+        * but this would hardcode OMNIBOOK_FAN_LEVELS.
+        * The parsed format is "%u " repeated OMNIBOOK_FAN_LEVELS+1 times
+        */
+
+       b = buffer;
+       do {
+               dprintk("n=[%i] b=[%s]\n", n, b);
+               if (n > OMNIBOOK_FAN_LEVELS) {
+                       retval = -EINVAL;
+                       goto out;
+               }
+               if (!isspace(*b)) {
+                       temp = simple_strtoul(b, &endp, 10);
+                       if (endp != b) {        /* there was a match */
+                               fan_policy[n++] = temp;
+                               b = endp;
+                       } else {
+                               retval = -EINVAL;
+                               goto out;
+                       }
+               } else
+                       b++;
+       } while ((*b != '\0') && (*b != '\n'));
+
+       /* A zero value set the defaults */
+       if ((fan_policy[0] == 0) && (n == 1))
+               retval = omnibook_set_fan_policy(io_op, &fan_defaults[0]);
+       else
+               retval = omnibook_set_fan_policy(io_op, &fan_policy[0]);
+
+       out:
+       mutex_unlock(&io_op->backend->mutex);
+       return retval;
+}
+
+static struct omnibook_tbl fan_policy_table[] __initdata = {
+       {XE3GF, {EC,}},
+       {0,}
+};
+
+static struct omnibook_feature __declared_feature fan_policy_driver = {
+       .name = "fan_policy",
+       .enabled = 1,
+       .read = omnibook_fan_policy_read,
+       .write = omnibook_fan_policy_write,
+       .ectypes = XE3GF,
+       .tbl = fan_policy_table,
+};
+
+module_param_named(fan_policy, fan_policy_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(fan_policy, "Use 0 to disable, 1 to enable fan control policy support");
+/* End of file */
diff --git a/hardware.h b/hardware.h
new file mode 100644 (file)
index 0000000..aa12a43
--- /dev/null
@@ -0,0 +1,582 @@
+/*
+ * hardware.h -- low level definitions to access Embedded Controller and co.
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006-2007
+ */
+
+#include <linux/acpi.h>
+#include "compat.h"
+
+/*
+ * Quite ugly:
+ * on_mask and off_maks are also used to store the i8042 data for kbc backend.
+ * an union seemed overkilled
+ */
+
+struct omnibook_backend;
+
+struct omnibook_operation {
+               struct omnibook_backend *backend;
+               unsigned long read_addr; /* address for data reading */
+               unsigned long write_addr; /* address for data writing */
+               u8 read_mask; /* read mask */
+               int on_mask; /* mask to set (pos value) or unset (neg value) to put feature in on state */
+               int off_mask; /* mask to set (pos value) or unset (neg value) to put feature in off state */
+};
+
+#define COMMAND(backend,data_on,data_off) { backend, 0, 0, 0, data_on, data_off }
+#define SIMPLE_BYTE(backend,addr,mask) { backend, addr, addr, mask, 0, 0 }
+
+struct omnibook_tbl {
+       enum omnibook_ectype_t ectypes;
+       struct omnibook_operation io_op;
+};
+
+/*
+ * Backend interface definition
+ */
+
+struct omnibook_backend {
+       const char *name;       /* backend name */
+       struct mutex mutex;     /* serializes all access to backend functions */
+       const unsigned int hotkeys_read_cap; /* hotkey probing mask */
+       const unsigned int hotkeys_write_cap; /* hotkey setting mask */
+
+       /* Public data fields, access with mutex held */
+       unsigned int hotkeys_state;     /* saved hotkeys state */
+       unsigned int touchpad_state;    /* saved touchpad state */
+       unsigned int muteled_state;     /* saved muteled state */
+       unsigned int cooling_state;     /* saved cooling method state */
+
+       /* Public function pointers */
+       int (*init) (const struct omnibook_operation *); 
+       void (*exit) (const struct omnibook_operation *);
+       int (*byte_read) (const struct omnibook_operation *, u8 *); 
+       int (*byte_write) (const struct omnibook_operation *, u8);
+       int (*aerial_get) (const struct omnibook_operation *, unsigned int *);
+       int (*aerial_set) (const struct omnibook_operation *, unsigned int);
+       int (*hotkeys_get) (const struct omnibook_operation *, unsigned int *);
+       int (*hotkeys_set) (const struct omnibook_operation *, unsigned int);
+       int (*display_get) (const struct omnibook_operation *, unsigned int *);
+       int (*display_set) (const struct omnibook_operation *, unsigned int);
+       int (*throttle_get) (const struct omnibook_operation *, unsigned int *);
+       int (*throttle_set) (const struct omnibook_operation *, unsigned int);
+
+       /* Private fields, never to be accessed outside backend code */
+       struct kref kref;       /* Reference counter of this backend */
+       void *data;             /* private data pointer */
+       int already_failed;     /* Backend init already failed at least once */
+};
+
+extern struct omnibook_backend kbc_backend;
+extern struct omnibook_backend pio_backend;
+extern struct omnibook_backend ec_backend;
+extern struct omnibook_backend acpi_backend;
+extern struct omnibook_backend nbsmi_backend;
+extern struct omnibook_backend compal_backend;
+
+#define KBC   &kbc_backend
+#define PIO   &pio_backend
+#define EC    &ec_backend
+#define ACPI  &acpi_backend
+#define SMI   &nbsmi_backend
+#define CDI   &compal_backend
+
+int __omnibook_apply_write_mask(const struct omnibook_operation *io_op, int toggle);
+int __omnibook_toggle(const struct omnibook_operation *io_op, int toggle);
+
+/*
+ * Lock helper functions. Defines locking and __prefixed non locking variants.
+ */
+
+#define helper_func(func) \
+static inline int backend_##func##_get(const struct omnibook_operation *io_op, unsigned int *data) \
+{ \
+       int retval; \
+       if(mutex_lock_interruptible(&io_op->backend->mutex)) \
+               return -ERESTARTSYS; \
+       retval = io_op->backend->func##_get(io_op, data); \
+       mutex_unlock(&io_op->backend->mutex); \
+       return retval; \
+} \
+static inline int backend_##func##_set(const struct omnibook_operation *io_op, unsigned int data) \
+{ \
+       int retval; \
+       if(mutex_lock_interruptible(&io_op->backend->mutex)) \
+               return -ERESTARTSYS; \
+       retval = io_op->backend->func##_set(io_op, data); \
+       mutex_unlock(&io_op->backend->mutex); \
+       return retval; \
+}\
+static inline int __backend_##func##_get(const struct omnibook_operation *io_op, unsigned int *data) \
+{ \
+       int retval; \
+       WARN_ON(!mutex_is_locked(&io_op->backend->mutex)); \
+       retval = io_op->backend->func##_get(io_op, data); \
+       return retval; \
+} \
+static inline int __backend_##func##_set(const struct omnibook_operation *io_op, unsigned int data) \
+{ \
+       int retval; \
+       WARN_ON(!mutex_is_locked(&io_op->backend->mutex)); \
+       retval = io_op->backend->func##_set(io_op, data); \
+       return retval; \
+}
+
+helper_func(aerial)
+helper_func(hotkeys)
+helper_func(display)
+helper_func(throttle)
+
+static inline int backend_byte_read(const struct omnibook_operation *io_op, u8 *data)
+{
+       int retval;
+       if(mutex_lock_interruptible(&io_op->backend->mutex))
+               return -ERESTARTSYS;
+       retval = io_op->backend->byte_read(io_op, data);
+       mutex_unlock(&io_op->backend->mutex);
+       return retval;
+}
+
+static inline int backend_byte_write(const struct omnibook_operation *io_op, u8 data)
+{
+       int retval;
+       if(mutex_lock_interruptible(&io_op->backend->mutex))
+               return -ERESTARTSYS;
+       retval = io_op->backend->byte_write(io_op, data);
+       mutex_unlock(&io_op->backend->mutex);
+       return retval;
+}
+
+static inline int __backend_byte_read(const struct omnibook_operation *io_op, u8 *data)
+{
+       int retval;
+       WARN_ON(!mutex_is_locked(&io_op->backend->mutex));
+       retval = io_op->backend->byte_read(io_op, data);
+       return retval;
+}
+
+static inline int __backend_byte_write(const struct omnibook_operation *io_op, u8 data)
+{
+       int retval;
+       WARN_ON(!mutex_is_locked(&io_op->backend->mutex));
+       retval = io_op->backend->byte_write(io_op, data);
+       return retval;
+}
+
+static inline int omnibook_apply_write_mask(const struct omnibook_operation *io_op, int toggle)
+{
+       int retval;
+       if(mutex_lock_interruptible(&io_op->backend->mutex))
+               return -ERESTARTSYS;
+       retval = __omnibook_apply_write_mask(io_op, toggle);
+       mutex_unlock(&io_op->backend->mutex);
+       return retval;
+}
+
+static inline int omnibook_toggle(const struct omnibook_operation *io_op, int toggle)
+{
+       int retval;
+       if(mutex_lock_interruptible(&io_op->backend->mutex))
+               return -ERESTARTSYS;
+       retval = __omnibook_toggle(io_op, toggle);
+       mutex_unlock(&io_op->backend->mutex);
+       return retval;
+}
+
+/*
+ * Timeout in ms for sending to controller
+ */
+
+#define OMNIBOOK_TIMEOUT                250
+
+
+/*
+ *     Embedded controller adresses
+ */
+
+#define XE3GF_CHGM     0x90    /* , 16 bit */
+#define XE3GF_CHGS     0x92    /* , 16 bit */
+#define XE3GF_CHGC     0x94    /* Current charge of board, 16 bit */
+#define XE3GF_CHGV     0x96    /* Current voltage, 16 bit */
+#define XE3GF_CHGA     0x98    /* Current intensity, 16 bit */
+#define XE3GF_BAL      0x9A    /* Battery present status */
+#define XE3GF_STA1     0x9C    /* Various status bits */
+#define XE3GF_CSPR     0xA1    /* Port replicator status, 1 bit */
+#define XE3GF_ADP      0xA3    /* AC acapter status, 1 bit */
+#define XE3GF_FOT      0xA5    /* Fan off temperature, 8 bit */
+#define XE3GF_FSD1     0xA6    /* Fan on temperature, 8 bit */
+#define XE3GF_FSD2     0xA7    /* Fan level 2 temperature, 8 bit */
+#define XE3GF_FSD3     0xA8    /* Fan level 3 temperature, 8 bit */
+#define XE3GF_FSD4     0xA9    /* Fan level 4 temperature, 8 bit */
+#define XE3GF_FSD5     0xAA    /* Fan level 5 temperature, 8 bit */
+#define XE3GF_FSD6     0xAB    /* Fan level 6 temperature, 8 bit */
+#define XE3GF_FSD7     0xAC    /* Fan level 7 temperature, 8 bit */
+#define XE3GF_FSRD     0xAD    /* Fan status, 8 bit */
+#define XE3GF_CTMP     0xB0    /* CPU tempetature, 8 bit */
+#define XE3GF_BRTS     0xB9    /* LCD brightness, 4 bit */
+#define XE3GF_BTY0     0xC0    /* Battery 0 type, 1 bit */
+#define XE3GF_BST0     0xC1    /* Battery 0 status, 3 bit */
+#define XE3GF_BRC0     0xC2    /* Battery 0 remaining capacity, 16 bit */
+#define XE3GF_BSN0     0xC4    /* Battery 0 serial number 16 bit */
+#define XE3GF_BPV0     0xC6    /* Battery 0 present voltage, 16 bit */
+#define XE3GF_BDV0     0xC8    /* Battery 0 design voltage 16 bit */
+#define XE3GF_BDC0     0xCA    /* Battery 0 design capacity 16 bit */
+#define XE3GF_BFC0     0xCC    /* Battery 0 last full capacity 16 bit */
+#define XE3GF_GAU0     0xCE    /* Battery 0 gauge, 8 bit */
+#define XE3GF_BTY1     0xD0    /* Battery 1 type, 1 bit */
+#define XE3GF_BST1     0xD1    /* Battery 1 status, 3 bit */
+#define XE3GF_BRC1     0xD2    /* Battery 1 remaining capacity, 16 bit */
+#define XE3GF_BSN1     0xD4    /* Battery 1 serial number, 16 bit */
+#define XE3GF_BPV1     0xD6    /* Battery 1 present voltage, 16 bit */
+#define XE3GF_BDV1     0xD8    /* Battery 1 design voltage 16 bit */
+#define XE3GF_BDC1     0xDA    /* Battery 1 design capacity 16 bit */
+#define XE3GF_BFC1     0xDC    /* Battery 1 last full capacity 16 bit */
+#define XE3GF_GAU1     0xDE    /* Battery 1 gauge, 8 bit */
+
+/*
+ * Bitmasks for sub byte values
+ */
+
+#define XE3GF_SHDD_MASK                0x40    /* External display status */
+#define XE3GF_CSPR_MASK                0x01    /* Port replicator status */
+#define XE3GF_ADP_MASK         0x20    /* AC acapter status */
+#define XE3GF_BAL0_MASK                0x01    /* Battery 0 present */
+#define XE3GF_BAL1_MASK                0x02    /* Battery 1 present */
+#define XE3GF_BMF_MASK         0x70    /* Model code */
+#define XE3GF_BTY_MASK         0x80    /* Type: Ni-MH or Li-Ion */
+#define XE3GF_BST_MASK_DSC     0x01    /* Discarging */
+#define XE3GF_BST_MASK_CHR     0x02    /* Charging */
+#define XE3GF_BST_MASK_CRT     0x04    /* Critical */
+#define XE3GF_FSRD_MASK_S1     0x01    /* Fan level 1 */
+#define XE3GF_FSRD_MASK_S2     0x02    /* Fan level 2 */
+#define XE3GF_FSRD_MASK_S3     0x04    /* Fan level 3 */
+#define XE3GF_FSRD_MASK_S4     0x08    /* Fan level 4 */
+#define XE3GF_FSRD_MASK_S5     0x10    /* Fan level 5 */
+#define XE3GF_FSRD_MASK_S6     0x20    /* Fan level 6 */
+#define XE3GF_FSRD_MASK_S7     0x40    /* Fan level 7 */
+#define XE3GF_BRTS_MASK                0x0F    /* LCD brightness */
+#define XE3GF_FAN_ON_MASK      0x02    /* Fan on */
+
+/*
+ * OmniBook XE3 GC values
+ */
+
+#define XE3GC_CTMP     0x28    /* CPU tempetature, 8 bit */
+#define XE3GC_STA1     0x30    /* Various status bits */
+#define XE3GC_Q0A      0x31    /* Various status bits */
+#define XE3GC_CCUR     0x38    /* Current charge of board, 16 bit ? */
+#define XE3GC_CVOL     0x3A    /* Current voltage, 16 bit ? */
+#define XE3GC_CARM     0x3C    /* Current intensity, 16 bit ? */
+#define XE3GC_BAT      0x3E    /* Battery present status */
+#define XE3GC_BST0     0x40    /* Battery 0 status, 3 bit */
+#define XE3GC_BPR0     0x41    /* Battery 0 present rate, 16 bit ? */
+#define XE3GC_BRC0     0x43    /* Battery 0 remaining capacity, 16 bit */
+#define XE3GC_BPV0     0x45    /* Battery 0 present voltage, 16 bit */
+#define XE3GC_BDV0     0x47    /* Battery 0 design voltage 16 bit */
+#define XE3GC_BDC0     0x49    /* Battery 0 design capacity 16 bit */
+#define XE3GC_BTY0     0x4A    /* Battery 0 type, 1 bit ? */
+#define XE3GC_BTP0     0x4B    /* Battery 0 ?, 1 bit */
+#define XE3GC_BSN0     0x4C    /* Battery 0 serial number, 8 bit ? */
+#define XE3GC_BMF0     0x4D    /* Battery 0 ?,8 bit */
+#define XE3GC_BST1     0x50    /* Battery 1 status, 3 bit */
+#define XE3GC_BPR1     0x51    /* Battery 1 present rate, 16 bit ? */
+#define XE3GC_BRC1     0x53    /* Battery 1 remaining capacity, 16 bit */
+#define XE3GC_BPV1     0x55    /* Battery 1 present voltage, 16 bit */
+#define XE3GC_BDV1     0x57    /* Battery 1 design voltage 16 bit */
+#define XE3GC_BDC1     0x59    /* Battery 1 design capacity 16 bit */
+#define XE3GC_BTY1     0x5A    /* Battery 1 type, 1 bit ? */
+#define XE3GC_BTP1     0x5B    /* Battery 1 ?, 1 bit */
+#define XE3GC_BSN1     0x5C    /* Battery 1 serial number, 8 bit ? */
+#define XE3GC_BMF1     0x5D    /* Battery 1 ?,8 bit */
+#define XE3GC_STA2     0x61    /* Various status bits */
+#define XE3GC_BTVL     0x6A    /* LCD brightness, 4 bit */
+
+/*
+ * Bitmasks for sub byte values
+ */
+
+#define XE3GC_ADP_MASK         0x40    /* AC acapter status */
+#define XE3GC_BAT0_MASK                0x01    /* Battery 0 present */
+#define XE3GC_BAT1_MASK                0x02    /* Battery 1 present */
+#define XE3GC_BTY_MASK         0x01    /* Type: Ni-MH or Li-Ion */
+#define XE3GC_BST_MASK_DSC     0x01    /* Discarging */
+#define XE3GC_BST_MASK_CHR     0x02    /* Charging */
+#define XE3GC_BST_MASK_CRT     0x04    /* Critical */
+#define XE3GC_CRTI_MASK                0x04    /* External display status */
+#define XE3GC_SLPB_MASK                0x01    /* Sleep button pressed */
+#define XE3GC_F5_MASK          0x02    /* Fn-F5 - LCD/CRT switch pressed */
+#define XE3GC_VOLD_MASK                0x04    /* Fn-down arrow or Volume down pressed */
+#define XE3GC_VOLU_MASK                0x08    /* Fn-up arrow or Volume up pressed */
+#define XE3GC_MUTE_MASK                0x10    /* Fn+F7 - Volume mute pressed */
+#define XE3GC_CNTR_MASK                0x20    /* Fn+F3/Fn+F4 - Contrast up or down pressed */
+#define XE3GC_BRGT_MASK                0x40    /* Fn+F1/Fn+F2 - Brightness up or down pressed */
+#define XE3GC_BTVL_MASK                0x0F    /* LCD brightness */
+
+/*
+ * Toshiba Satellite A105 values and mask
+ */
+
+#define A105_BNDT                              0xA3    /* LCD brightness */
+#define A105_BNDT_MASK                         0x0F
+
+/*
+ * Fujitsu Amilo D values
+ */
+
+#define AMILOD_TMP     0x28    /* CPU tempetature, 8 bit */
+#define AMILOD_STA1    0x30    /* Various status bits */
+#define AMILOD_BAT     0x3E    /* Battery present status */
+#define AMILOD_BDC0    0x40    /* Battery 0 design capacity 16 bit */
+#define AMILOD_BDV0    0x42    /* Battery 0 design voltage 16 bit */
+#define AMILOD_BTY0    0x44    /* Battery 0 type, 1 bit ? */
+#define AMILOD_BST0    0x45    /* Battery 0 status, 3 bit */
+#define AMILOD_BPR0    0x46    /* Battery 0 present rate, 16 bit ? */
+#define AMILOD_BRC0    0x48    /* Battery 0 remaining capacity, 16 bit */
+#define AMILOD_BPV0    0x4A    /* Battery 0 present voltage, 16 bit */
+#define AMILOD_BTP0    0x4C    /* Battery 0 ?, 1 bit */
+#define AMILOD_BDC1    0x50    /* Battery 1 design capacity 16 bit */
+#define AMILOD_BDV1    0x52    /* Battery 1 design voltage 16 bit */
+#define AMILOD_BTY1    0x54    /* Battery 1 type, 1 bit ? */
+#define AMILOD_BST1    0x55    /* Battery 1 status, 3 bit */
+#define AMILOD_BPR1    0x56    /* Battery 1 present rate, 16 bit ? */
+#define AMILOD_BRC1    0x58    /* Battery 1 remaining capacity, 16 bit */
+#define AMILOD_BPV1    0x5A    /* Battery 1 present voltage, 16 bit */
+#define AMILOD_BTP1    0x5C    /* Battery 1 ?, 1 bit */
+#define AMILOD_CBRG    0x6F    /* LCD brightness, 4 bit */
+
+/*
+ * Bitmasks for sub byte values
+ */
+
+#define AMILOD_ADP_MASK                0x40    /* AC acapter status */
+#define AMILOD_BAT0_MASK       0x01    /* Battery 0 present */
+#define AMILOD_BAT1_MASK       0x02    /* Battery 1 present */
+#define AMILOD_BTY_MASK                0x01    /* Type: Ni-MH or Li-Ion */
+#define AMILOD_BST_MASK_DSC    0x01    /* Discarging */
+#define AMILOD_BST_MASK_CHR    0x02    /* Charging */
+#define AMILOD_BST_MASK_CRT    0x04    /* Critical */
+#define AMILOD_CBRG_MASK       0x0F    /* LCD brightness */
+
+/*
+ * OmniBook 500, 510, 6000, 6100, XE2 values
+ */
+
+#define OB500_STA1     0x44    /* Various status bits */
+#define OB500_STA2     0x50    /* Various status bits */
+#define OB500_CTMP     0x55    /* CPU tempetature, 8 bit */
+#define OB500_BT1I     0x58    /* Battery 1 ? 16 bit */
+#define OB500_BT1C     0x5A    /* Battery 1 remaining capacity 16 bit ? */
+#define OB500_BT1V     0x5C    /* Battery 1 present voltage 16 bit ? */
+#define OB500_BT1S     0x5E    /* Battery 1 status 3 bit ? */
+#define OB500_BT2I     0x6A    /* Battery 2 ? 16 bit */
+#define OB500_BT2C     0x6C    /* Battery 2 remaining capacity 16 bit ? */
+#define OB500_BT2V     0x6E    /* Battery 2 present voltage 16 bit ? */
+#define OB500_BT2S     0x70    /* Battery 2 status 3 bit ? */
+#define OB500_BT3I     0x5F    /* Battery 3 ? 16 bit */
+#define OB500_BT3C     0x61    /* Battery 3 remaining capacity 16 bit ? */
+#define OB500_BT3V     0x63    /* Battery 3 present voltage 16 bit ? */
+#define OB500_BT3S     0x65    /* Battery 3 status 3 bit ? */
+
+#define OB6000_STA1    0x77    /* Various status bits */
+
+#define XE2_STA1       0x50    /* Various status bits */
+
+/*
+ * Bitmasks for sub byte values
+ */
+
+#define OB500_LIDS_MASK                0x01    /* LID status */
+#define OB500_CRTS_MASK                0x20    /* External display status */
+#define OB500_SLPS_MASK                0x40    /* Sleep button status */
+#define OB500_DCKS_MASK                0x80    /* Docking status */
+#define OB500_ADP_MASK         0x02    /* AC acapter status */
+#define OB500_BST_MASK_DSC     0x01    /* Discarging */
+#define OB500_BST_MASK_CHR     0x02    /* Charging */
+#define OB500_BST_MASK_CRT     0x04    /* Critical */
+
+#define OB6000_FAN_MASK                0x10    /* Fan status */
+
+#define XE2_ADP_MASK           0x02    /* AC acapter status */
+
+/*
+ * OmniBook 4150
+ */
+
+#define OB4150_TMP             0x28    /* CPU tempetature, 8 bit */
+#define OB4150_STA1            0x2E    /* Various status bits */
+#define OB4150_STA2            0x2F    /* Various status bits */
+#define OB4150_ADP             0x30    /* AC acapter status, 1 bit */
+#define OB4150_DCID            0x2C    /* Port replicator */
+
+/*
+ * Bitmasks for sub byte values
+ */
+
+#define OB4150_FAN_MASK                0x01    /* Fan status */
+#define OB4150_ADP_MASK                0x40    /* AC acapter status */
+#define OB4150_CRST_MASK       0x20    /* External display status */
+
+/*
+ *     Keyboard controller command for some laptop functions
+ */
+
+#define OMNIBOOK_KBC_CONTROL_CMD               0x59
+
+/*
+ *     Keyboard controller command parameters for functions available via kbc
+ */
+
+#define OMNIBOOK_KBC_CMD_ONETOUCH_ENABLE       0x90    /* Enables OneTouch buttons */
+#define OMNIBOOK_KBC_CMD_ONETOUCH_DISABLE      0x91    /* Disables OneTouch buttons */
+#define OMNIBOOK_KBC_CMD_TOUCHPAD_ENABLE       0xAA    /* Enables touchpad */
+#define OMNIBOOK_KBC_CMD_TOUCHPAD_DISABLE      0xA9    /* Disables touchpad */
+#define OMNIBOOK_KBC_CMD_LCD_ON                        0xE1    /* Turns LCD display on */
+#define OMNIBOOK_KBC_CMD_LCD_OFF               0xE2    /* Turns LCD display off */
+#define OMNIBOOK_KBC_CMD_MUTELED_ON            0x94    /* Turns (xe4500) Mute LED on */
+#define OMNIBOOK_KBC_CMD_MUTELED_OFF           0x95    /* Turns (xe4500) Mute LED off */
+#define OMNIBOOK_KBC_CMD_AC_POWER_ENABLE       0xC2    /* Enable AC power */
+#define OMNIBOOK_KBC_CMD_AC_POWER_DISABLE      0xC1    /* Disable AC power */
+
+/*
+ * Other I/O ports
+ */
+
+#define ACL00_AC_STAT          0x11B9  /* AC adapter status on ACL00 */
+#define ACL00_AC_MASK          0x04    /* Bitmask for AC adapter status on ACL00 */
+#define TOSH3K_AC_STAT         0x102D  /* AC adapter status on Toshiba 3000 */
+#define TOSH3K_AC_MASK         0x08    /* Bitmask for AC adapter status on Toshiba 3000 */
+#define XE3GF_AC_STAT          0x11B9  /* AC adapter status on XE3 GF */
+#define XE3GF_AC_MASK          0x04    /* Bitmask for AC adapter status on XE3 GF */
+#define XE3GF_LID_STAT         0x11AD  /* LID switch status on XE3 GF */
+#define XE3GF_LID_MASK         0x20    /* Bitmask for LID switch status on XE3 GF */
+#define XE3GC_SMIC             0xFE00
+
+#define OB500_GPO1             0x8034  /* Fan control */
+#define OB510_GPO2             0x11B9  /* LCD backlight */
+#define OB510_GPIO             0x118F  /* Fan control */
+
+#define OB500_FAN_ON_MASK      0x0A    /* Turn fan on with zero bits */
+#define OB500_FAN_OFF_MASK     0x08    /* Fan status/off */
+#define OB500_BKLT_MASK                0x40    /* LCD backlight */
+#define OB510_FAN_ON_MASK      0x18    /* Turn fan on with zero bits */
+#define OB510_FAN_OFF_MASK     0x10    /* Turn fan on */
+#define OB510_BKLT_MASK                0x01    /* LCD backlight */
+
+#define XE2_FAN_MASK           0x02    /* Turn fan on with zero bit */
+
+/*
+ * Memory adresses
+ */
+
+#define XE3GC_BCMD             0xFFFFEBC
+
+/*
+ * Toshiba Satellite A105 values and mask
+ */
+
+#define A105_BNDT              0xA3    /* LCD brightness */
+#define A105_BNDT_MASK         0x0F
+
+/*
+ * Index and values for Command/Data/Index interface
+ * Notice similitudes with commands code for kbc
+ */
+
+#define TSM70_FN_INDEX         0x45
+#define TSM70_FN_ENABLE                0x75
+#define TSM70_FN_DISABLE       0x74
+#define TSM70_HOTKEYS_INDEX    0x59
+#define TSM70_HOTKEYS_ENABLE   0x90
+#define TSM70_HOTKEYS_DISABLE  0x91
+#define TSM70_LCD_READ         0x5C
+#define TSM70_LCD_WRITE                0x5D
+#define TSM70_TOUCHPAD_ON      0x80
+#define TSM70_TOUCHPAD_OFF     0x81
+#define TSM100_BLANK_INDEX     0x59
+#define        TSM100_LCD_ON           0xe1
+#define        TSM100_LCD_OFF          0xe2
+#define TSM70_COOLING_OFFSET   0xb0
+#define TSM70_COOLING_POWERSAVE        0x0
+#define TSM70_COOLING_PERF     0x2
+
+/* Toshiba SMI funtions and constants*/
+#define SMI_FN_PRESSED         0x8f
+#define SMI_SET_LCD_BRIGHTNESS 0xa2
+#define SMI_GET_LCD_BRIGHTNESS 0xa3
+#define SMI_GET_KILL_SWITCH    0xa4
+#define SMI_SET_AERIAL         0xa5
+#define SMI_GET_AERIAL         0xa6
+#define SMI_SET_DISPLAY_STATE  0xa7
+#define SMI_GET_DISPLAY_STATE  0xa8
+#define SMI_SET_FN_INTERFACE   0xa9
+#define SMI_GET_FN_INTERFACE   0xaa
+#define SMI_GET_FN_LAST_SCAN   0xab
+#define SMI_SET_DOCK           0xac    /* Undocumented */
+#define SMI_GET_DOCK           0xad    /* Undocumented */
+#define SMI_SET_FN_F5_INTERFACE        0xc2
+
+#define SMI_FN_KEYS_MASK       0x01
+#define SMI_STICK_KEYS_MASK    0x02
+#define SMI_FN_TWICE_LOCK_MASK 0x04
+#define SMI_FN_DOCK_MASK       0x08
+
+#define SMI_FN_SCAN            0x6d    /* Fn key scancode */
+#define        SMI_DOCK_SCAN           0x6e    /* Dock scancode */
+
+/* Toshiba HCI method and constants */
+#define HCI_METHOD             "SPFC"
+#define HCI_WORDS              6
+
+#define HCI_GET                        0xfe00
+#define HCI_SET                        0xff00
+
+#define HCI_HOTKEY_EVENT       0x001e
+#define HCI_RF_CONTROL         0x0056
+
+#define HCI_ENABLE             0x0001
+#define HCI_DISABLE            0x0000
+
+#define HCI_WIRELESS_CHECK     0x0001
+#define HCI_WIRELESS_POWER     0x0200
+
+#define HCI_SUCCESS            0x0000
+#define HCI_FAILURE            0x1000
+#define HCI_NOT_SUPPORTED      0x8000
+
+/* Toshiba Satellite X205 methods */
+#define TSX205_EVENTS_METHOD   "INFO"
+#define TSX205_NOTIFY_METHOD   "NTFY"
+#define TSX205_KILLSW_METHOD   "KLSW"
+#define TSX205_SLIVDO_METHOD   "CSLI"
+
+#define ACPI_FN_MASK           0x01
+#define ACPI_FN_SCAN           0x6e    /* Fn key scancode */
+
+/* HCI key definitions */
+#define HCI_FN_RELEASED                0x100
+#define HCI_MUTE               0x101
+#define HCI_1                  0x102
+#define HCI_2                  0x103
+#define HCI_SPACE              0x139
+#define HCI_BREAK              0x13b
+#define HCI_BSM                        0x13c
+#define HCI_SUSPEND            0x13d
+#define HCI_HIBERNATE          0x13e
+#define HCI_VIDEOOUT           0x13f
+#define HCI_BRIGHTNESSDOWN     0x140
+#define HCI_BRIGHTNESSUP       0x141
+#define HCI_WLAN               0x142
+#define HCI_TOUCHPAD           0x143
+#define HCI_FN_PRESSED         0x17f
diff --git a/hotkeys.c b/hotkeys.c
new file mode 100644 (file)
index 0000000..7d541e1
--- /dev/null
+++ b/hotkeys.c
@@ -0,0 +1,193 @@
+/*
+ * hotkeys.c -- code to handling Hotkey/E-Key/EasyAccess buttons
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+/* Predefined convinient on/off states */
+#define HKEY_ON  HKEY_ONETOUCH|HKEY_MULTIMEDIA|HKEY_FN|HKEY_DOCK|HKEY_FNF5
+#define HKEY_OFF 0
+
+/*
+ * Set hotkeys status and update recorded saved state
+ */
+static int hotkeys_set_save(struct omnibook_operation *io_op, unsigned int state)
+{
+       int retval;
+
+       if(mutex_lock_interruptible(&io_op->backend->mutex))
+               return -ERESTARTSYS;
+
+       retval = __backend_hotkeys_set(io_op, state);
+       if (retval < 0)
+               goto out;
+
+       /* Update saved state */
+       io_op->backend->hotkeys_state = state & io_op->backend->hotkeys_write_cap;
+
+       out:
+       mutex_unlock(&io_op->backend->mutex);
+       return retval;
+}
+
+/*
+ * Read hotkeys status, fallback to reading saved state if real probing is not
+ * supported.
+ */
+static int hotkeys_get_save(struct omnibook_operation *io_op, unsigned int *state)
+{
+       unsigned int read_state = 0;
+       int retval = 0;
+
+       if(mutex_lock_interruptible(&io_op->backend->mutex))
+               return -ERESTARTSYS;
+
+       if (io_op->backend->hotkeys_get)
+               retval = __backend_hotkeys_get(io_op, &read_state);
+       if (retval < 0)
+               goto out;
+
+       /* Return previously set state for the fields that are write only */
+       *state = (read_state & io_op->backend->hotkeys_read_cap) + 
+                (io_op->backend->hotkeys_state & ~io_op->backend->hotkeys_read_cap);
+
+       out:
+       mutex_unlock(&io_op->backend->mutex);
+       return 0;
+}
+
+/*
+ * Power management handlers
+ */
+
+/*
+ * Restore previously saved state
+ */
+static int omnibook_hotkeys_resume(struct omnibook_operation *io_op)
+{
+       int retval;
+       mutex_lock(&io_op->backend->mutex);
+       retval = __backend_hotkeys_set(io_op, io_op->backend->hotkeys_state);
+       mutex_unlock(&io_op->backend->mutex);
+       return retval;
+}
+
+/*
+ * Disable hotkeys upon suspend (FIXME is the disabling required ?)
+ */
+static int omnibook_hotkeys_suspend(struct omnibook_operation *io_op)
+{
+       int retval = 0;
+       retval = backend_hotkeys_set(io_op, HKEY_OFF);
+       return retval;
+}
+
+static const char pretty_name[][27] = {
+       "Onetouch buttons are",
+       "Multimedia hotkeys are",
+       "Fn hotkeys are",
+       "Stick key is",
+       "Press Fn twice to lock is",
+       "Dock events are",
+       "Fn + F5 hotkey is",
+};
+
+static int omnibook_hotkeys_read(char *buffer, struct omnibook_operation *io_op)
+{
+       int len = 0;
+       int retval;
+       unsigned int read_state = 0; /* buggy gcc 4.1 warning fix */
+       unsigned int shift, mask;
+
+       retval = hotkeys_get_save(io_op, &read_state);
+
+       if (retval < 0)
+               return retval;
+
+       for (shift = 0; shift <= HKEY_LAST_SHIFT ; shift++) {
+               mask = 1 << shift;
+               /* we assume write capability or read capability imply support */
+               if ((io_op->backend->hotkeys_read_cap | io_op->backend->hotkeys_write_cap) & mask)
+                       len +=
+                           sprintf(buffer + len, "%s %s.\n", pretty_name[shift],
+                                   (read_state & mask) ? "enabled" : "disabled");
+       }
+
+       return len;
+}
+
+static int omnibook_hotkeys_write(char *buffer, struct omnibook_operation *io_op)
+{
+       unsigned int state;
+       char *endp;
+
+       if (strncmp(buffer, "off", 3) == 0)
+               hotkeys_set_save(io_op, HKEY_OFF);
+       else if (strncmp(buffer, "on", 2) == 0)
+               hotkeys_set_save(io_op, HKEY_ON);
+       else {
+               state = simple_strtoul(buffer, &endp, 16);
+               if (endp == buffer)
+                       return -EINVAL;
+               else
+                       hotkeys_set_save(io_op, state);
+       }
+       return 0;
+}
+
+static int __init omnibook_hotkeys_init(struct omnibook_operation *io_op)
+{
+       int retval;
+
+       printk(O_INFO "Enabling all hotkeys.\n");
+       retval = hotkeys_set_save(io_op, HKEY_ON);
+       return retval < 0 ? retval : 0;
+}
+
+static void __exit omnibook_hotkeys_cleanup(struct omnibook_operation *io_op)
+{
+       printk(O_INFO "Disabling all hotkeys.\n");
+       hotkeys_set_save(io_op, HKEY_OFF);
+}
+
+static struct omnibook_tbl hotkeys_table[] __initdata = {
+       {XE3GF | XE3GC | OB500 | OB510 | OB6000 | OB6100 | XE4500 | AMILOD | TSP10 | TSM30X, 
+       COMMAND(KBC,OMNIBOOK_KBC_CMD_ONETOUCH_ENABLE,OMNIBOOK_KBC_CMD_ONETOUCH_DISABLE)},
+       {TSM70, {CDI,}},
+       {TSM40, {SMI,}},
+       {TSX205, {ACPI,}},
+       {0,}
+};
+
+static struct omnibook_feature __declared_feature hotkeys_driver = {
+       .name = "hotkeys",
+       .enabled = 1,
+       .read = omnibook_hotkeys_read,
+       .write = omnibook_hotkeys_write,
+       .init = omnibook_hotkeys_init,
+       .exit = omnibook_hotkeys_cleanup,
+       .suspend = omnibook_hotkeys_suspend,
+       .resume = omnibook_hotkeys_resume,
+       .ectypes =
+           XE3GF | XE3GC | OB500 | OB510 | OB6000 | OB6100 | XE4500 | AMILOD | TSP10 | TSM70 | TSM30X |
+           TSM40 | TSX205,
+       .tbl = hotkeys_table,
+};
+
+module_param_named(hotkeys, hotkeys_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(hotkeys, "Use 0 to disable, 1 to enable hotkeys handling");
+/* End of file */
diff --git a/info.c b/info.c
new file mode 100644 (file)
index 0000000..8e25e7a
--- /dev/null
+++ b/info.c
@@ -0,0 +1,68 @@
+/*
+ * info.c -- trivial informational features
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+
+#include <linux/dmi.h>
+#include <linux/version.h>
+
+static int omnibook_version_read(char *buffer, struct omnibook_operation *io_op)
+{
+       int len = 0;
+
+       len += sprintf(buffer + len, "%s\n", OMNIBOOK_MODULE_VERSION);
+
+       return len;
+}
+
+static int omnibook_dmi_read(char *buffer, struct omnibook_operation *io_op)
+{
+       int len = 0;
+
+       len += sprintf(buffer + len, "BIOS Vendor:   %s\n", dmi_get_system_info(DMI_BIOS_VENDOR));
+       len += sprintf(buffer + len, "BIOS Version:  %s\n", dmi_get_system_info(DMI_BIOS_VERSION));
+       len += sprintf(buffer + len, "BIOS Release:  %s\n", dmi_get_system_info(DMI_BIOS_DATE));
+       len += sprintf(buffer + len, "System Vendor: %s\n", dmi_get_system_info(DMI_SYS_VENDOR));
+       len += sprintf(buffer + len, "Product Name:  %s\n", dmi_get_system_info(DMI_PRODUCT_NAME));
+       len +=
+           sprintf(buffer + len, "Version:       %s\n", dmi_get_system_info(DMI_PRODUCT_VERSION));
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+       len +=
+           sprintf(buffer + len, "Serial Number: %s\n", dmi_get_system_info(DMI_PRODUCT_SERIAL));
+#endif
+       len += sprintf(buffer + len, "Board Vendor:  %s\n", dmi_get_system_info(DMI_BOARD_VENDOR));
+       len += sprintf(buffer + len, "Board Name:    %s\n", dmi_get_system_info(DMI_BOARD_VERSION));
+
+       return len;
+}
+
+static struct omnibook_feature __declared_feature version_driver = {
+       .name = "version",
+       .enabled = 1,
+       .read = omnibook_version_read,
+};
+
+static struct omnibook_feature __declared_feature dmi_driver = {
+       .name = "dmi",
+       .enabled = 1,
+       .read = omnibook_dmi_read,
+};
+
+module_param_named(dmi, dmi_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(dmi, "Use 0 to disable, 1 to enable DMI informations display support");
+
+/* End of file */
diff --git a/init.c b/init.c
new file mode 100644 (file)
index 0000000..70d5415
--- /dev/null
+++ b/init.c
@@ -0,0 +1,542 @@
+/*
+ * init.c -- module initialization code
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+
+#include <linux/proc_fs.h>
+#include <linux/dmi.h>
+#include <linux/version.h>
+#include <asm/uaccess.h>
+
+#include "hardware.h"
+#include "laptop.h"
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#include <linux/platform_device.h>
+#else
+#include <linux/device.h>
+#endif
+
+/*
+ * For compatibility with kernel older than 2.6.11
+ */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11))
+typedef u32 pm_message_t;
+#endif
+
+static int __init omnibook_probe(struct platform_device *dev);
+static int __exit omnibook_remove(struct platform_device *dev);
+static int omnibook_suspend(struct platform_device *dev, pm_message_t state);
+static int omnibook_resume(struct platform_device *dev);
+
+/*
+ * For compatibility with kernel older than 2.6.15
+ */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+
+#define to_platform_device(x) container_of((x), struct platform_device, dev)
+
+static int __init compat_omnibook_probe(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       return omnibook_probe(pdev);
+}
+
+static int __exit compat_omnibook_remove(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       return omnibook_remove(pdev);
+}
+
+static int compat_omnibook_suspend(struct device *dev, pm_message_t state, u32 level)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       return omnibook_suspend(pdev, state);
+}
+
+static int compat_omnibook_resume(struct device *dev, u32 level)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       return omnibook_resume(pdev);
+}
+
+#endif
+
+static struct proc_dir_entry *omnibook_proc_root = NULL;
+
+enum omnibook_ectype_t omnibook_ectype = NONE;
+
+static const char *laptop_model __initdata;
+
+static int omnibook_userset = 0;
+
+/*
+ * The platform_driver interface was added in linux 2.6.15
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+
+static struct platform_device *omnibook_device;
+
+static struct platform_driver omnibook_driver = {
+       .probe = omnibook_probe,
+       .remove = omnibook_remove,
+#ifdef CONFIG_PM
+       .suspend = omnibook_suspend,
+       .resume = omnibook_resume,
+#endif
+       .driver = {
+                  .name = OMNIBOOK_MODULE_NAME,
+                  .owner = THIS_MODULE,
+                  },
+};
+
+#else                          /* 2.6.15 */
+
+static struct device_driver omnibook_driver = {
+       .name = OMNIBOOK_MODULE_NAME,
+       .bus = &platform_bus_type,
+       .probe = compat_omnibook_probe,
+       .remove = compat_omnibook_remove,
+#ifdef CONFIG_PM
+       .suspend = compat_omnibook_suspend,
+       .resume = compat_omnibook_resume,
+#endif
+};
+
+static struct platform_device omnibook_device = {
+       .name = OMNIBOOK_MODULE_NAME,
+};
+
+#endif                         /* 2.6.15 */
+
+/* Linked list of all enabled features */
+static struct omnibook_feature *omnibook_available_feature;
+
+/* Delimiters of the .features section wich holds all the omnibook_feature structs */
+extern struct omnibook_feature _start_features_driver[];
+extern struct omnibook_feature _end_features_driver[];
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+static int __init dmi_matched(struct dmi_system_id *dmi)
+#else
+static int __init dmi_matched(const struct dmi_system_id *dmi)
+#endif
+{
+       omnibook_ectype = (enum omnibook_ectype_t)dmi->driver_data;
+       if (dmi->ident)
+               laptop_model = (char *)dmi->ident;
+       else
+               laptop_model = dmi_get_system_info(DMI_PRODUCT_VERSION);
+       return 1;               /* return non zero means we stop the parsing selecting this entry */
+}
+
+/* 
+ * Callback function for procfs file reading: the name of the file read was stored in *data 
+ */
+static int procfile_read_dispatch(char *page, char **start, off_t off, int count, int *eof,
+                                 void *data)
+{
+       struct omnibook_feature *feature = (struct omnibook_feature *)data;
+       int len = 0;
+
+       if (!feature || !feature->read)
+               return -EINVAL;
+
+       if(off)
+               goto out;
+
+       len = feature->read(page, feature->io_op);
+       if (len < 0)
+               return len;
+
+       out:
+       *eof = 1;
+       return len;
+}
+
+/* 
+ * Callback function for procfs file writing: the name of the file written was stored in *data 
+ */
+static int procfile_write_dispatch(struct file *file, const char __user * userbuf,
+                                  unsigned long count, void *data)
+{
+       struct omnibook_feature *feature = (struct omnibook_feature *)data;
+       char *kernbuf;
+       int retval;
+
+       if (!feature || !feature->write)
+               return -EINVAL;
+
+       kernbuf = kmalloc(count + 1, GFP_KERNEL);
+       if (!kernbuf)
+               return -ENOMEM;
+
+       if (copy_from_user(kernbuf, userbuf, count)) {
+               kfree(kernbuf);
+               return -EFAULT;
+       }
+
+       /* Make sure the string is \0 terminated */
+       kernbuf[count] = '\0';
+
+       retval = feature->write(kernbuf, feature->io_op);
+       if (retval == 0)
+               retval = count;
+
+       kfree(kernbuf);
+
+       return retval;
+}
+
+/*
+ * Match an ectype and return pointer to corresponding omnibook_operation.
+ * Also make corresponding backend initialisation if necessary, and skip
+ * to the next entry if it fails.
+ */
+static struct omnibook_operation *omnibook_backend_match(struct omnibook_tbl *tbl)
+{
+       int i;
+       struct omnibook_operation *matched = NULL;
+
+       for (i = 0; tbl[i].ectypes; i++) {
+               if (omnibook_ectype & tbl[i].ectypes) {
+                    dprintk("Attempting backend %s init.\n",
+                            tbl[i].io_op.backend->name);
+                       if (tbl[i].io_op.backend->init && tbl[i].io_op.backend->init(&tbl[i].io_op)) {
+                               dprintk("Backend %s init failed, skipping entry.\n",
+                                       tbl[i].io_op.backend->name);
+                               continue;
+                       }
+                       matched = &tbl[i].io_op;
+                       dprintk("Returning table entry nr %i.\n", i);
+                       break;
+               }
+       }
+       return matched;
+}
+
+/* 
+ * Initialise a feature and add it to the linked list of active features
+ */
+static int __init omnibook_init(struct omnibook_feature *feature)
+{
+       int retval = 0;
+       mode_t pmode;
+       struct proc_dir_entry *proc_entry;
+       struct omnibook_operation *op;
+
+       if (!feature)
+               return -EINVAL;
+
+/*
+ * Select appropriate backend for feature operations
+ * We copy the io_op field so the tbl can be initdata
+ */
+       if (feature->tbl) {
+               dprintk("Begin table match of %s feature.\n", feature->name);
+               op = omnibook_backend_match(feature->tbl);
+               if (!op) {
+                       dprintk("Match failed: disabling %s.\n", feature->name);
+                       return -ENODEV;
+               }
+                dprintk("Match succeeded: continuing with %s.\n", feature->name);
+               feature->io_op = kmalloc(sizeof(struct omnibook_operation), GFP_KERNEL);
+               if (!feature->io_op)
+                       return -ENOMEM;
+               memcpy(feature->io_op, op, sizeof(struct omnibook_operation));
+       } else
+               dprintk("%s feature has no backend table, io_op not initialized.\n", feature->name);
+
+/*
+ * Specific feature init code
+ */
+       if (feature->init && (retval = feature->init(feature->io_op))) {
+               printk(O_ERR "Init function of %s failed with error %i.\n", feature->name, retval);
+               goto err;
+       }
+/*
+ * procfs file setup
+ */
+       if (feature->name && feature->read) {
+               pmode = S_IFREG | S_IRUGO;
+               if (feature->write) {
+                       pmode |= S_IWUSR;
+                       if (omnibook_userset)
+                               pmode |= S_IWUGO;
+               }
+
+               proc_entry = create_proc_entry(feature->name, pmode, omnibook_proc_root);
+
+               if (!proc_entry) {
+                       printk(O_ERR "Unable to create proc entry %s\n", feature->name);
+                       if (feature->exit)
+                               feature->exit(feature->io_op);
+                       retval = -ENOENT;
+                       goto err;
+               }
+               proc_entry->data = feature;
+               proc_entry->read_proc = &procfile_read_dispatch;
+               if (feature->write)
+                       proc_entry->write_proc = &procfile_write_dispatch;
+               #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
+                       proc_entry->owner = THIS_MODULE;
+               #endif
+       }
+       list_add_tail(&feature->list, &omnibook_available_feature->list);
+       return 0;
+      err:
+       if (feature->io_op && feature->io_op->backend->exit)
+               feature->io_op->backend->exit(feature->io_op);
+       kfree(feature->io_op);
+       return retval;
+}
+
+/* 
+ * Callback function for driver registering :
+ * Initialize the linked list of enabled features and call omnibook_init to populate it
+ */
+static int __init omnibook_probe(struct platform_device *dev)
+{
+       int i;
+       struct omnibook_feature *feature;
+
+       /* temporary hack */
+       mutex_init(&kbc_backend.mutex);
+       mutex_init(&pio_backend.mutex);
+       mutex_init(&ec_backend.mutex);
+
+       omnibook_available_feature = kzalloc(sizeof(struct omnibook_feature), GFP_KERNEL);
+       if (!omnibook_available_feature)
+               return -ENOMEM;
+       INIT_LIST_HEAD(&omnibook_available_feature->list);
+
+        dprintk("Feature range %p - %p\n", _start_features_driver, _end_features_driver);
+
+       for (i = 0; i < _end_features_driver - _start_features_driver; i++) {
+
+               feature = &_start_features_driver[i];
+                dprintk("Testing feature %s at address %p\n", feature->name, feature);
+               if (!feature->name)
+                       continue;
+               if (!feature->enabled)
+                       continue;
+
+               if ((omnibook_ectype & feature->ectypes) || (!feature->ectypes))
+                       omnibook_init(feature);
+       }
+
+       printk(O_INFO "Enabled features:");
+       list_for_each_entry(feature, &omnibook_available_feature->list, list) {
+               if (feature->name)
+                       printk(" %s", feature->name);
+       }
+       printk(".\n");
+
+       return 0;
+}
+
+/* 
+ * Callback function for driver removal
+ */
+static int __exit omnibook_remove(struct platform_device *dev)
+{
+       struct omnibook_feature *feature, *temp;
+
+       list_for_each_entry_safe(feature, temp, &omnibook_available_feature->list, list) {
+               list_del(&feature->list);
+               /* Feature specific cleanup */
+               if (feature->exit)
+                       feature->exit(feature->io_op);
+               /* Generic backend cleanup */
+               if (feature->io_op && feature->io_op->backend->exit)
+                       feature->io_op->backend->exit(feature->io_op);
+               if (feature->name)
+                       remove_proc_entry(feature->name, omnibook_proc_root);
+               kfree(feature->io_op);
+       }
+       kfree(omnibook_available_feature);
+
+       return 0;
+}
+
+/* 
+ * Callback function for system suspend 
+ */
+static int omnibook_suspend(struct platform_device *dev, pm_message_t state)
+{
+       int retval;
+       struct omnibook_feature *feature;
+
+       list_for_each_entry(feature, &omnibook_available_feature->list, list) {
+               if (feature->suspend) {
+                       retval = feature->suspend(feature->io_op);
+                       if (retval)
+                               printk(O_ERR "Unable to suspend the %s feature (error %i).\n", feature->name, retval);
+               }
+       }
+       return 0;
+}
+
+/* 
+ * Callback function for system resume
+ */
+static int omnibook_resume(struct platform_device *dev)
+{
+       int retval;
+       struct omnibook_feature *feature;
+
+       list_for_each_entry(feature, &omnibook_available_feature->list, list) {
+               if (feature->resume) {
+                       retval = feature->resume(feature->io_op);
+                       if (retval)
+                               printk(O_ERR "Unable to resume the %s feature (error %i).\n", feature->name, retval);
+               }
+       }
+       return 0;
+}
+
+/* 
+ * Find a given available feature by its name
+ */
+struct omnibook_feature *omnibook_find_feature(char *name)
+{
+       struct omnibook_feature *feature;
+
+       list_for_each_entry(feature, &omnibook_available_feature->list, list) {
+               if (!strcmp(feature->name, name))
+                       return feature;
+       }
+       return NULL;
+}
+
+/*
+ * Maintain compatibility with the old ectype numbers:
+ * ex: The user set/get ectype=12 for TSM70=2^(12-1)
+ */
+static int __init set_ectype_param(const char *val, struct kernel_param *kp)
+{
+       char *endp;
+       int value;
+
+       if (!val)
+               return -EINVAL;
+
+       value = simple_strtol(val, &endp, 10);
+       if (endp == val)        /* No match */
+               return -EINVAL;
+       omnibook_ectype = 1 << (value - 1);
+       return 0;
+}
+
+static int get_ectype_param(char *buffer, struct kernel_param *kp)
+{
+       return sprintf(buffer, "%i", ffs(omnibook_ectype));
+}
+
+static int __init omnibook_module_init(void)
+{
+       int retval;
+
+       printk(O_INFO "Driver version %s.\n", OMNIBOOK_MODULE_VERSION);
+
+       if (omnibook_ectype != NONE)
+               printk(O_WARN "Forced load with EC type %i.\n", ffs(omnibook_ectype));
+       else if (dmi_check_system(omnibook_ids))
+               printk(O_INFO "%s detected.\n", laptop_model);
+       else
+               printk(O_INFO "Unknown model.\n");
+
+       omnibook_proc_root = proc_mkdir(OMNIBOOK_MODULE_NAME, NULL);
+       if (!omnibook_proc_root) {
+               printk(O_ERR "Unable to create /proc/%s.\n", OMNIBOOK_MODULE_NAME);
+               return -ENOENT;
+       }
+
+/*
+ * The platform_driver interface was added in linux 2.6.15
+ */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+
+       retval = platform_driver_register(&omnibook_driver);
+       if (retval < 0)
+               return retval;
+
+       omnibook_device = platform_device_alloc(OMNIBOOK_MODULE_NAME, -1);
+       if (!omnibook_device) {
+               platform_driver_unregister(&omnibook_driver);
+               return -ENOMEM;
+       }
+
+       retval = platform_device_add(omnibook_device);
+       if (retval) {
+               platform_device_put(omnibook_device);
+               platform_driver_unregister(&omnibook_driver);
+               return retval;
+       }
+#else                          /* 2.6.15 */
+
+       retval = driver_register(&omnibook_driver);
+       if (retval < 0)
+               return retval;
+
+       retval = platform_device_register(&omnibook_device);
+
+       if (retval) {
+               driver_unregister(&omnibook_driver);
+               return retval;
+       }
+#endif
+       return 0;
+}
+
+static void __exit omnibook_module_cleanup(void)
+{
+
+/*
+ * The platform_driver interface was added in linux 2.6.15
+ */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+       platform_device_unregister(omnibook_device);
+       platform_driver_unregister(&omnibook_driver);
+#else
+       platform_device_unregister(&omnibook_device);
+       driver_unregister(&omnibook_driver);
+#endif
+
+       if (omnibook_proc_root)
+               remove_proc_entry("omnibook", NULL);
+       printk(O_INFO "Module is unloaded.\n");
+}
+
+module_init(omnibook_module_init);
+module_exit(omnibook_module_cleanup);
+
+MODULE_AUTHOR("Soós Péter, Mathieu Bérard");
+MODULE_VERSION(OMNIBOOK_MODULE_VERSION);
+MODULE_DESCRIPTION
+    ("Kernel interface for HP OmniBook, HP Pavilion, Toshiba Satellite and Compal ACL00 laptops");
+MODULE_LICENSE("GPL");
+module_param_call(ectype, set_ectype_param, get_ectype_param, NULL, S_IRUGO);
+module_param_named(userset, omnibook_userset, int, S_IRUGO);
+MODULE_PARM_DESC(ectype, "Type of embedded controller firmware");
+MODULE_PARM_DESC(userset, "Use 0 to disable, 1 to enable users to set parameters");
+
+/* End of file */
diff --git a/kbc.c b/kbc.c
new file mode 100644 (file)
index 0000000..5634b40
--- /dev/null
+++ b/kbc.c
@@ -0,0 +1,152 @@
+/*
+ * kbc.c -- low level functions to access Keyboard Controller
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/ioport.h>
+
+#include <asm/io.h>
+#include "hardware.h"
+
+extern int omnibook_key_polling_enable(void);
+extern int omnibook_key_polling_disable(void);
+
+/*
+ * Registers of the keyboard controller
+ */
+
+#define OMNIBOOK_KBC_DATA              0x60
+#define OMNIBOOK_KBC_SC                        0x64
+
+/*
+ * Keyboard controller status register bits
+ */
+
+#define OMNIBOOK_KBC_STAT_OBF          0x01    /* Output buffer full */
+#define OMNIBOOK_KBC_STAT_IBF          0x02    /* Input buffer full */
+
+
+/*
+ * Interrupt control
+ */
+
+static DEFINE_SPINLOCK(omnibook_kbc_lock);
+
+/*
+ * Wait for keyboard buffer
+ */
+
+static int omnibook_kbc_wait(u8 event)
+{
+       int timeout = OMNIBOOK_TIMEOUT;
+
+       switch (event) {
+       case OMNIBOOK_KBC_STAT_OBF:
+               while (!(inb(OMNIBOOK_KBC_SC) & event) && timeout--)
+                       mdelay(1);
+               break;
+       case OMNIBOOK_KBC_STAT_IBF:
+               while ((inb(OMNIBOOK_KBC_SC) & event) && timeout--)
+                       mdelay(1);
+               break;
+       default:
+               return -EINVAL;
+       }
+       if (timeout > 0)
+               return 0;
+       return -ETIME;
+}
+
+/*
+ * Write to the keyboard command register
+ */
+
+static int omnibook_kbc_write_command(u8 cmd)
+{
+       int retval;
+
+       spin_lock_irq(&omnibook_kbc_lock);
+       retval = omnibook_kbc_wait(OMNIBOOK_KBC_STAT_IBF);
+       if (retval)
+               goto end;
+       outb(cmd, OMNIBOOK_KBC_SC);
+       retval = omnibook_kbc_wait(OMNIBOOK_KBC_STAT_IBF);
+      end:
+       spin_unlock_irq(&omnibook_kbc_lock);
+       return retval;
+}
+
+/*
+ * Write to the keyboard data register
+ */
+
+static int omnibook_kbc_write_data(u8 data)
+{
+       int retval;
+
+       spin_lock_irq(&omnibook_kbc_lock);
+       retval = omnibook_kbc_wait(OMNIBOOK_KBC_STAT_IBF);
+       if (retval)
+               goto end;
+       outb(data, OMNIBOOK_KBC_DATA);
+       retval = omnibook_kbc_wait(OMNIBOOK_KBC_STAT_IBF);
+      end:
+       spin_unlock_irq(&omnibook_kbc_lock);
+       return retval;
+}
+
+/*
+ * Send a command to keyboard controller
+ */
+
+static int omnibook_kbc_command(const struct omnibook_operation *io_op, u8 data)
+{
+       int retval;
+
+       if ((retval = omnibook_kbc_write_command(OMNIBOOK_KBC_CONTROL_CMD)))
+               return retval;
+
+       retval = omnibook_kbc_write_data(data);
+       return retval;
+}
+
+/*
+ * Onetouch button hotkey handler
+ */
+static int omnibook_kbc_hotkeys(const struct omnibook_operation *io_op, unsigned int state)
+{
+       int retval;
+
+       retval = __omnibook_toggle(io_op, !!(state & HKEY_ONETOUCH));
+       return retval;
+}
+
+/*
+ * Backend interface declarations
+ */
+struct omnibook_backend kbc_backend = {
+       .name = "i8042",
+       .hotkeys_write_cap = HKEY_ONETOUCH,
+       .byte_write = omnibook_kbc_command,
+       .hotkeys_set = omnibook_kbc_hotkeys,
+};
+
+/* End of file */
diff --git a/laptop.h b/laptop.h
new file mode 100644 (file)
index 0000000..dd0a198
--- /dev/null
+++ b/laptop.h
@@ -0,0 +1,1077 @@
+/*
+ * laptop.h -- Various structures about supported hardware
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Written by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+
+#define HP_SIGNATURE   "Hewlett-Packard"
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+static int __init dmi_matched(struct dmi_system_id *dmi);
+#else
+static int __init dmi_matched(const struct dmi_system_id *dmi);
+#endif
+
+static struct  dmi_system_id omnibook_ids[] __initdata = {
+       {
+               .callback = dmi_matched,
+               .ident = "HP OmniBook XE3 GF",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook XE3 GF"),
+               },
+               .driver_data = (void *) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP OmniBook XT1000",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook XT1000"),
+               },
+               .driver_data = (void *) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP OmniBook XE2 DC",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook XE2 DC"),
+               },
+               .driver_data = (void *) XE2
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP OmniBook XE3 GC",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook XE3 GC"),
+               },
+               .driver_data = (void*) XE3GC
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP OmniBook XE3 GD / Pavilion N5430",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook XE3 GD"),
+               },
+               .driver_data = (void*) XE3GC
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP OmniBook XE3 GE / Pavilion N5415",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook XE3 GE"),
+               },
+               .driver_data = (void*) XE3GC
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP OmniBook 500 FA",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 500 FA"),
+               },
+               .driver_data = (void*) OB500
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP OmniBook 510 FB",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 510 FB"),
+               },
+               .driver_data = (void*) OB510
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP OmniBook 4150",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 4150"),
+               },
+               .driver_data = (void*) OB4150
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP OmniBook 900 B",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 900 B"),
+               },
+               .driver_data = (void*) OB4150
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP OmniBook 6000 EA",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 6000 EA"),
+               },
+               .driver_data = (void*) OB6000
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP OmniBook 6100 EB",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 6100 EB"),
+               },
+               .driver_data = (void*) OB6100
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP OmniBook xe4000/xe4100",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook xe4000"),
+               },
+               .driver_data = (void*) XE4500
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP OmniBook xe4400",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook xe4400"),
+               },
+               .driver_data = (void*) XE4500
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP OmniBook xe4500",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook xe4500"),
+               },
+               .driver_data = (void*) XE4500
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP OmniBook 6200 EG / vt6200 / xt 6200",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 6200 EG"),
+               },
+               .driver_data = (void*) XE4500
+       },
+       /* There are no model specific strings of some HP OmniBook XT1500 */
+       {
+               .callback = dmi_matched,
+               .ident = "HP OmniBook XT1500",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP Pavilion ze4000 / ze4125",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP NoteBook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP NoteBook ze4000"),
+               },
+               .driver_data = (void*) XE4500
+       },
+       /* There are no model specific strings of some HP Pavilion xt155 and some HP Pavilion ze4100 
+        * There are no model specific strings of some HP nx9000 */
+       {
+               .callback = dmi_matched,
+               .ident = "HP Pavilion xt155 / ze4100 / nx9000",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP NoteBook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP NoteBook PC"),
+               },
+               .driver_data = (void*) XE4500
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP Pavilion ZU1000 FA / ZU1000 FA / ZU1175",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion ZU1000 FA"),
+               },
+               .driver_data = (void*) OB500
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP Pavilion Notebook XE3 GC / N5290",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook XE3 GC"),
+               },
+               .driver_data = (void*) XE3GC
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP Pavilion Notebook GD / N5441",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GD"),
+               },
+               .driver_data = (void*) XE3GC
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP Pavilion Notebook GE / XH545",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"),
+               },
+               .driver_data = (void*) XE3GC
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP Pavilion Notebook ZT1000 / ZT1141",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook ZT1000"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       /* There are no model specific strings of some HP Pavilion ZT1175 and ZT1195 notebooks */
+       {
+               .callback = dmi_matched,
+               .ident = "HP Pavilion ZT1175 / ZT1195",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP Pavilion ze4200 series",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ze4200"),
+               },
+               .driver_data = (void*) XE4500
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP Pavilion ze4300 series",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ze4300"),
+               },
+               .driver_data = (void*) XE4500
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP Pavilion ze4500 series",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ze4500"),
+               },
+               .driver_data = (void*) XE4500
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP Pavilion ze8500 series",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ze8500"),
+               },
+               .driver_data = (void*) XE4500
+       },
+       /* Compaq nx9000 */
+       {
+               .callback = dmi_matched,
+               .ident = "HP Compaq nx9000",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP nx9000"),
+               },
+               .driver_data = (void*) XE4500
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP Compaq nx9005",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP nx9005"),
+               },
+               .driver_data = (void*) XE4500
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP Compaq nx9010",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP nx9010"),
+               },
+               .driver_data = (void*) XE4500
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1000",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S1000"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1005",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S1005"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1110",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S1110"),
+               },
+               .driver_data = (void*) XE3GF
+       },      
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1115",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S1115"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1130",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1130"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1700-100",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S1700-100"),
+               },
+               .driver_data = (void*) AMILOD
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1700-200",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S1700-200"),
+               },
+               .driver_data = (void*) AMILOD
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1700-300",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S1700-300"),
+               },
+               .driver_data = (void*) AMILOD
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1700-400",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S1700-400"),
+               },
+               .driver_data = (void*) AMILOD
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1700-500",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S1700-500"),
+               },
+               .driver_data = (void*) AMILOD
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1900",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S1900"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1905",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S1905"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1950",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S1950"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1955",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S1955"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 2430",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S2430"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 2435",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S2435"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 3000",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S3000"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 3005",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S3005"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1000",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1000"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1005",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1005"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1110",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1110"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1115",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1115"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1115",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Toshiba 1115"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1900",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1900"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1905",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1905"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1950",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1950"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 1955",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1955"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 2430",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 2430"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 2435",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 2435"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 3000",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 3000"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite 3005",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 3005"),
+               },
+               .driver_data = (void*) XE3GF,
+       },
+       {
+                .callback = dmi_matched,
+                .ident = "Toshiba Satellite A70",
+                .matches = {
+                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                        DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A70"),
+                },
+                .driver_data = (void*) TSM70
+        },
+       {
+                .callback = dmi_matched,
+                .ident = "Toshiba Satellite A75",
+                .matches = {
+                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                        DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A75"),
+                },
+                .driver_data = (void*) TSM70
+        },
+       {
+                .callback = dmi_matched,
+                .ident = "Toshiba Satellite A80",
+                .matches = {
+                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                        DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A80"),
+                },
+                .driver_data = (void*) TSM70
+        },
+        {
+                .callback = dmi_matched,
+                .ident = "Toshiba Satellite A105",
+                .matches = {
+                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                        DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A105"),
+                },
+                .driver_data = (void*) TSA105
+        },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite A100",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A100"),
+               },
+               .driver_data = (void*) TSA105
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite P100",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P100"),
+               },
+               .driver_data = (void*) TSA105
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite P10",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P10"),
+               },
+               .driver_data = (void*) TSP10
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite P15",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P15"),
+               },
+               .driver_data = (void*) TSP10
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite P20",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P20"),
+               },
+               .driver_data = (void*) TSP10
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite P25",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P25"),
+               },
+               .driver_data = (void*) TSM70
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite M30X",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M30X"),
+               },
+               .driver_data = (void*) TSM30X
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite M35X",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M35X"),
+               },
+               .driver_data = (void*) TSM70
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite M50",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M50"),
+               },
+               .driver_data = (void*) TSM70
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite M60",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M60"),
+               },
+               .driver_data = (void*) TSM70
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite M70",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M70"),
+               },
+               .driver_data = (void*) TSM70
+       },
+        {
+                .callback = dmi_matched,
+                .ident = "Toshiba Satellite M100",
+                .matches = {
+                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                        DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE M100"),
+                },
+                .driver_data = (void*) TSM70
+        },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite M100",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M100"),
+               },
+               .driver_data = (void*) TSM70
+       },
+               {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite M115",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M115"),
+               },
+               .driver_data = (void*) TSA105
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite M40X",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M40X"),
+               },
+               .driver_data = (void*) TSM70
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite M40",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M40"),
+               },
+               .driver_data = (void*) TSM40
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite M45",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M45"),
+               },
+               .driver_data = (void*) TSM40
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Satellite X205-S9800",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite X205"),
+               },
+               .driver_data = (void*) TSX205
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Tecra S1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TECRA S1"),
+               },
+               .driver_data = (void*) TSM40
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Tecra S1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Tecra S1"),
+               },
+               .driver_data = (void*) TSM40
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Tecra S2",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Tecra S2"),
+               },
+               .driver_data = (void*) TSM70
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Tecra A4",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Tecra A4"),
+               },
+               .driver_data = (void*) TSM40
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Toshiba Tecra A6",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A6"),
+               },
+               .driver_data = (void*) TSM70
+       },
+       {
+                .callback = dmi_matched,
+                .ident = "Toshiba Equium A110",
+                .matches = {
+                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                        DMI_MATCH(DMI_PRODUCT_NAME, "EQUIUM A110"),
+                },
+                .driver_data = (void*) TSM30X /* FIXME: provisional */
+        },
+       {
+               .callback = dmi_matched,
+               .ident = "Compal ACL00",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "COMPAL"),
+                       DMI_MATCH(DMI_BOARD_NAME, "ACL00"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Compal ACL10",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "COMPAL"),
+                       DMI_MATCH(DMI_BOARD_NAME, "ACL10"),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Fujitsu-Siemens Amilo D series",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Amilo D-Series"),
+               },
+               .driver_data = (void*) AMILOD
+       },
+/* HP Technology code Matching:
+ * Technology code appears in the first two chracters of BIOS version string
+ * ended by a dot, but it prefixed a space character on some models and BIOS
+ * versions.
+ * New HP/Compaq models use more characters (eg. KF_KH.).
+ */
+       {
+               .callback = dmi_matched,
+               .ident = "HP model with technology code CI",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+                       DMI_MATCH(DMI_BIOS_VERSION, "CI."),
+               },
+               .driver_data = (void*) OB4150
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP model with technology code CL",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+                       DMI_MATCH(DMI_BIOS_VERSION, "CL."),
+               },
+               .driver_data = (void*) OB4150
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP model with technology code DC",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+                       DMI_MATCH(DMI_BIOS_VERSION, "DC."),
+               },
+               .driver_data = (void*) XE2
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP model with technology code EA",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+                       DMI_MATCH(DMI_BIOS_VERSION, "EA."),
+               },
+               .driver_data = (void*) OB6000
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP model with technology code EB",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+                       DMI_MATCH(DMI_BIOS_VERSION, "EB."),
+               },
+               .driver_data = (void*) OB6100
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP model with technology code EG",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+                       DMI_MATCH(DMI_BIOS_VERSION, "EG."),
+               },
+               .driver_data = (void*) XE4500
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP model with technology code FA",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+                       DMI_MATCH(DMI_BIOS_VERSION, "FA."),
+               },
+               .driver_data = (void*) OB500
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP model with technology code FB",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+                       DMI_MATCH(DMI_BIOS_VERSION, "FB."),
+               },
+               .driver_data = (void*) OB510
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP model with technology code GC",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+                       DMI_MATCH(DMI_BIOS_VERSION, "GC."),
+               },
+               .driver_data = (void*) XE3GC
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP model with technology code GD",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+                       DMI_MATCH(DMI_BIOS_VERSION, "GD."),
+               },
+               .driver_data = (void*) XE3GC
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP model with technology code GE",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+                       DMI_MATCH(DMI_BIOS_VERSION, "GE."),
+               },
+               .driver_data = (void*) XE3GC
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP model with technology code GF",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+                       DMI_MATCH(DMI_BIOS_VERSION, "GF."),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP model with technology code IB",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+                       DMI_MATCH(DMI_BIOS_VERSION, "IB."),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP model with technology code IC",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+                       DMI_MATCH(DMI_BIOS_VERSION, "IC."),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP model with technology code ID",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+                       DMI_MATCH(DMI_BIOS_VERSION, "ID."),
+               },
+               .driver_data = (void*) XE3GF
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP model with technology code KA",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+                       DMI_MATCH(DMI_BIOS_VERSION, "KA."),
+               },
+               .driver_data = (void*) XE4500
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP model with technology code KB",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+                       DMI_MATCH(DMI_BIOS_VERSION, "KB."),
+               },
+               .driver_data = (void*) XE4500
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP model with technology code KC",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+                       DMI_MATCH(DMI_BIOS_VERSION, "KC."),
+               },
+               .driver_data = (void*) XE4500
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP model with technology code KD",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+                       DMI_MATCH(DMI_BIOS_VERSION, "KD."),
+               },
+               .driver_data = (void*) XE4500
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP model with technology code KE",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+                       DMI_MATCH(DMI_BIOS_VERSION, "KE."),
+               },
+               .driver_data = (void*) XE4500
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP model with technology code KE_KG",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+                       DMI_MATCH(DMI_BIOS_VERSION, "KE_KG."),
+               },
+               .driver_data = (void*) XE4500
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "HP model with technology code KF_KH",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+                       DMI_MATCH(DMI_BIOS_VERSION, "KF_KH."),
+               },
+               .driver_data = (void*) XE4500
+       },
+       { NULL, }
+};
diff --git a/lcd.c b/lcd.c
new file mode 100644 (file)
index 0000000..85fe17c
--- /dev/null
+++ b/lcd.c
@@ -0,0 +1,216 @@
+/*
+ * lcd.c -- LCD brightness and on/off
+ * 
+ * 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, 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.
+ *
+ * Written by Maciek Górniak <mago@acn.waw.pl>, 2002
+ * Modified by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+#include <linux/err.h>
+
+#ifdef CONFIG_OMNIBOOK_BACKLIGHT
+#include <linux/backlight.h>
+#endif
+
+#include "hardware.h"
+
+unsigned int omnibook_max_brightness;
+
+#ifdef CONFIG_OMNIBOOK_BACKLIGHT
+static struct backlight_device *omnibook_backlight_device;
+
+static int omnibook_get_backlight(struct backlight_device *bd);
+static int omnibook_set_backlight(struct backlight_device *bd);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34)
+static struct backlight_properties props;
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
+static struct backlight_ops omnibookbl_ops = {
+#else /* 2.6.21 */
+static struct backlight_properties omnibookbl_data = {
+       .owner = THIS_MODULE,
+#endif /* 2.6.21 */
+       .get_brightness = omnibook_get_backlight,
+       .update_status = omnibook_set_backlight,
+};
+
+static int omnibook_get_backlight(struct backlight_device *bd)
+{
+       int retval = 0;
+       struct omnibook_operation *io_op;
+       u8 brgt;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
+       io_op = bl_get_data(bd);
+#else /* 2.6.23 */     
+       io_op = class_get_devdata(&bd->class_dev);
+#endif /* 2.6.23 */
+       retval = backend_byte_read(io_op, &brgt);
+       if (!retval)
+               retval = brgt;
+
+       return retval;
+}
+
+static int omnibook_set_backlight(struct backlight_device *bd)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
+       u8 intensity = bd->props.brightness;
+#else /* 2.6.21 */
+       u8 intensity = bd->props->brightness;
+#endif /* 2.6.21 */    
+       struct omnibook_operation *io_op;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
+       io_op = bl_get_data(bd);
+#else /* 2.6.23 */     
+       io_op = class_get_devdata(&bd->class_dev);
+#endif /* 2.6.23 */
+       return backend_byte_write(io_op, intensity);
+}
+#endif /* CONFIG_OMNIBOOK_BACKLIGHT */
+
+static int omnibook_brightness_read(char *buffer, struct omnibook_operation *io_op)
+{
+       int len = 0;
+       u8 brgt;
+
+       backend_byte_read(io_op, &brgt);
+
+       len +=
+           sprintf(buffer + len, "LCD brightness: %2d (max value: %d)\n", brgt,
+                   omnibook_max_brightness);
+
+       return len;
+}
+
+static int omnibook_brightness_write(char *buffer, struct omnibook_operation *io_op)
+{
+       unsigned int brgt = 0;
+       char *endp;
+
+       if (strncmp(buffer, "off", 3) == 0)
+               omnibook_lcd_blank(1);
+       else if (strncmp(buffer, "on", 2) == 0)
+               omnibook_lcd_blank(0);
+       else {
+               brgt = simple_strtoul(buffer, &endp, 10);
+               if ((endp == buffer) || (brgt > omnibook_max_brightness))
+                       return -EINVAL;
+               else {
+                       backend_byte_write(io_op, brgt);
+#ifdef CONFIG_OMNIBOOK_BACKLIGHT
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
+                       omnibook_backlight_device->props.brightness = brgt;
+#else /* 2.6.21 */
+                       omnibookbl_data.brightness = brgt;
+#endif
+#endif 
+               }
+       }
+       return 0;
+}
+
+static int __init omnibook_brightness_init(struct omnibook_operation *io_op)
+{
+       /*
+        * FIXME: What is exactly the max value for each model ?
+        * I know that it's 7 for the TSM30X, TSM70, TSM40 and TSA105
+        * and previous versions of this driver (wrongly) assumed it was 10 for
+        * all models.
+        * 
+        * XE3GF
+        * TSM30X
+        * TSM70
+        * TSM40
+        * TSA105
+        * TSX205
+        */
+       if (omnibook_ectype & (XE3GF | TSM70 | TSM30X | TSM40 | TSA105 | TSX205))
+               omnibook_max_brightness = 7;
+       else {
+               omnibook_max_brightness = 10;
+               printk(O_WARN "Assuming that LCD brightness is between 0 and %i,\n",
+                      omnibook_max_brightness);
+               printk(O_WARN
+                      "please contact http://sourceforge.net/projects/omnibook to confirm.\n");
+       }
+
+#ifdef CONFIG_OMNIBOOK_BACKLIGHT
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34)
+       memset (&props, 0, sizeof(struct backlight_properties));
+       props.max_brightness = omnibook_max_brightness;
+       omnibook_backlight_device =
+           backlight_device_register(OMNIBOOK_MODULE_NAME, NULL, (void *)io_op, 
+                                     &omnibookbl_ops, &props);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
+       omnibook_backlight_device =
+           backlight_device_register(OMNIBOOK_MODULE_NAME, NULL, (void *)io_op, &omnibookbl_ops);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+       omnibook_backlight_device =
+           backlight_device_register(OMNIBOOK_MODULE_NAME, NULL, (void *)io_op, &omnibookbl_data);
+#else /*  < 2.6.20 */
+       omnibook_backlight_device =
+           backlight_device_register(OMNIBOOK_MODULE_NAME, (void *)io_op, &omnibookbl_data);
+#endif
+       if (IS_ERR(omnibook_backlight_device)) {
+               printk(O_ERR "Unable to register as backlight device.\n");
+               return -ENODEV;
+       }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34)
+       backend_byte_read(io_op, (u8*) &omnibook_backlight_device->props.brightness);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
+       omnibook_backlight_device->props.max_brightness = omnibook_max_brightness;
+       backend_byte_read(io_op, (u8*) &omnibook_backlight_device->props.brightness);
+#else /* < 2.6.21 */
+       omnibookbl_data.max_brightness = omnibook_max_brightness;
+       backend_byte_read(io_op, (u8*) &omnibookbl_data.brightness);
+#endif
+#endif /* CONFIG_OMNIBOOK_BACKLIGHT */
+       return 0;
+}
+static void __exit omnibook_brightness_cleanup(struct omnibook_operation *io_op)
+{
+#ifdef CONFIG_OMNIBOOK_BACKLIGHT
+       backlight_device_unregister(omnibook_backlight_device);
+#endif
+}
+
+static struct omnibook_tbl lcd_table[] __initdata = {
+       {TSM70 | TSX205, {CDI, TSM70_LCD_READ, TSM70_LCD_WRITE, 0, 0, 0}},
+       {TSM40, {SMI, SMI_GET_LCD_BRIGHTNESS, SMI_SET_LCD_BRIGHTNESS, 0, 0, 0}},
+       {XE3GF | TSP10 | TSM70 | TSM30X, SIMPLE_BYTE(EC, XE3GF_BRTS, XE3GF_BRTS_MASK)},
+       {XE3GC, SIMPLE_BYTE(EC, XE3GC_BTVL, XE3GC_BTVL_MASK)},
+       {AMILOD, SIMPLE_BYTE(EC, AMILOD_CBRG, XE3GC_BTVL_MASK)},
+       {TSA105, SIMPLE_BYTE(EC, A105_BNDT, A105_BNDT_MASK)},
+       {0,}
+};
+
+static struct omnibook_feature __declared_feature lcd_driver = {
+       .name = "lcd",
+       .enabled = 1,
+       .read = omnibook_brightness_read,
+       .write = omnibook_brightness_write,
+       .init = omnibook_brightness_init,
+       .exit = omnibook_brightness_cleanup,
+       .ectypes = XE3GF | XE3GC | AMILOD | TSP10 | TSM70 | TSM30X | TSM40 | TSA105 | TSX205,
+       .tbl = lcd_table,
+};
+
+module_param_named(lcd, lcd_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(lcd, "Use 0 to disable, 1 to enable to LCD brightness support");
+
+/* End of file */
diff --git a/lib.c b/lib.c
new file mode 100644 (file)
index 0000000..728e70f
--- /dev/null
+++ b/lib.c
@@ -0,0 +1,81 @@
+/*
+ * lib.c -- Generic helpers functions
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+
+#include "hardware.h"
+#include "compat.h"
+#include <linux/input.h>
+
+/*
+ * Generic funtion for applying a mask on a value
+ * Hack: degenerate to omnibook_toggle if there is no read method 
+ * of if the read address is 0, this is used in blank.c 
+ */
+int __omnibook_apply_write_mask(const struct omnibook_operation *io_op, int toggle)
+{
+       int retval = 0;
+       int mask;
+       u8 data;
+
+       if(!(io_op->backend->byte_read  && io_op->read_addr))
+               return __omnibook_toggle(io_op,toggle);
+
+       if ((retval = __backend_byte_read(io_op, &data)))
+               return retval;
+
+       if (toggle == 1)
+               mask = io_op->on_mask;
+       else if (toggle == 0)
+               mask = io_op->off_mask;
+       else
+               return -EINVAL;
+
+       if (mask > 0)
+               data |= (u8) mask;
+       else if (mask < 0)
+               data &= ~((u8) (-mask));
+       else
+               return -EINVAL;
+
+       retval = __backend_byte_write(io_op, data);
+
+       return retval;
+}
+
+/*
+ * Helper for toggle like operations
+ */
+int __omnibook_toggle(const struct omnibook_operation *io_op, int toggle)
+{
+       int retval;
+       u8 data;
+
+       data = toggle ? io_op->on_mask : io_op->off_mask;
+       retval = __backend_byte_write(io_op, data);
+       return retval;
+}
+
+void omnibook_report_key( struct input_dev *dev, unsigned int keycode)
+{
+       input_report_key(dev, keycode, 1);
+       input_sync(dev);
+       input_report_key(dev, keycode, 0);
+       input_sync(dev);
+}
+
+/* End of file */
diff --git a/misc/README.mmkeys b/misc/README.mmkeys
new file mode 100644 (file)
index 0000000..9a9fc04
--- /dev/null
@@ -0,0 +1,9 @@
+This patch maps some extra Fn+key combinations to keycodes for multimedia
+keyboards and only works for the nbsmi-backend. It might be useful if you
+want to control some mediaplayer while working with other applications.
+
+Following combinations are mapped:
+Fn+Y => Previous song
+Fn+X => Play/pause
+Fn+V => Stop CD
+Fn+B => Next song
\ No newline at end of file
diff --git a/misc/dmi_strings.txt b/misc/dmi_strings.txt
new file mode 100644 (file)
index 0000000..4eef0c0
--- /dev/null
@@ -0,0 +1,857 @@
+HP OmniBook XT1000 -------------------------
+
+BIOS Vendor:   Insyde Software
+BIOS Version:  IB.M1.05
+BIOS Release:  02/28/2002
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook XT1000
+Board Vendor:  Hewlett-Packard
+Board Name:    HP OmniBook PC
+Board Version: HP OmniBook XT1000
+
+---------------------------------------------
+HP OmniBook XT1500 --------------------------
+
+BIOS Vendor:   Insyde Software
+BIOS Version:  IC.M1.05
+BIOS Release:  08/13/2002
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook
+Board Vendor:  Hewlett-Packard
+Board Name:    HP OmniBook PC
+Board Version: HP OmniBook
+
+---------------------------------------------
+HP OmniBook XT1500 -------------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  ID.M1.04
+BIOS Release:  08/14/2002
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook XE3 GF
+Board Vendor:  Hewlett-Packard
+Board Name:    N/A
+Board Version: OmniBook Zinfandel 4.5
+
+---------------------------------------------
+HP OmniBook XE3 GC --------------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  GC.M1.63
+BIOS Release:  01/01/1992
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook XE3 GC
+Board Vendor:  Hewlett-Packard
+Board Name:    N/A
+Board Version: OmniBook N32N-733
+
+---------------------------------------------
+HP OmniBook XE3 GF --------------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  GF.M1.07
+BIOS Release:  03/05/2002
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook XE3 GF
+Board Vendor:  Hewlett-Packard
+Board Name:    N/A
+Board Version: OmniBook N32N-101
+
+---------------------------------------------
+HP OmniBook 500 FA --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd
+BIOS Version:  FA.M2.62
+BIOS Release:  11/30/1999
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook 500 FA
+Board Vendor:  Hewlett-Packard
+Board Name:    HP OmniBook PC
+Board Version: 500 FA
+
+---------------------------------------------
+HP OmniBook 510 FB --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  FB.M1.20
+BIOS Release:  04/12/02
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook 510 FB
+Board Vendor:  Hewlett-Packard
+Board Name:    HP OmniBook PC
+Board Version: 510FB
+
+---------------------------------------------
+Toshiba Satellite 3000-100 ------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V2.20
+BIOS Release:  10/12/01
+System Vendor: TOSHIBA
+Product Name:  S3000-100
+Version:       PS300E-03EKL-FR
+Board Vendor:  Null
+Board Name:    888M1
+Board Version: Null
+
+---------------------------------------------
+Toshiba Satellite 1115-s103------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.20
+BIOS Release:  09/11/2002
+System Vendor: TOSHIBA
+Product Name:  Satellite 1115
+Version:       PS111U-001FUV
+Board Vendor:  TOSHIBA
+Board Name:    BTK20
+Board Version: Null
+
+---------------------------------------------
+Toshiba Satellite 1110 ----------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.20
+BIOS Release:  09/11/2002
+System Vendor: TOSHIBA
+Product Name:  S1110
+Version:       PS111E-003DN-GR
+Board Vendor:  TOSHIBA
+Board Name:    BTK20
+Board Version: Null
+
+---------------------------------------------
+Toshiba Satellite 1130 ----------------------
+
+BIOS Vendor: TOSHIBA
+BIOS Version: V1.70A
+BIOS Release: 09/02/2003
+System Vendor: TOSHIBA
+Product Name: Satellite 1130
+Version: PS113E-05ZYF-GR
+Board Vendor: TOSHIBA
+Board Name: BTW30
+Board Version: Null
+
+---------------------------------------------
+Toshiba Satellite 1900-704 ------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.50
+BIOS Release:  11/25/2002
+System Vendor: TOSHIBA
+Product Name:  Satellite 1950
+Version:       PS195E-008QY-DU
+Board Vendor:  TOSHIBA
+Board Name:    ATR60
+
+---------------------------------------------
+Toshiba Satellite 1955-s805 -----------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.00
+BIOS Release:  01/17/2003
+System Vendor: TOSHIBA
+Product Name:  Satellite 1955
+Version:       PS197U-000LEV
+Board Vendor:  TOSHIBA
+Board Name:    BTR80
+Board Version: Null
+
+---------------------------------------------
+Toshiba Satellite A70 -----------------------
+
+BIOS Vendor: TOSHIBA 
+BIOS Version: V1.50 
+BIOS Release: 11/16/2004 
+System Vendor: TOSHIBA 
+Product Name: Satellite A70 
+Version: PSA70C-KL100E 
+Serial Number: X4451615K 
+Board Vendor: TOSHIBA 
+Board Name: EDW10 
+Board Version: Null 
+
+---------------------------------------------
+Toshiba Satellite A80 -----------------------
+
+BIOS Vendor: TOSHIBA
+BIOS Version: V2.50
+BIOS Release: 01/11/2006
+System Vendor: TOSHIBA
+Product Name: Satellite A80
+Version: PSA80E-03T00JSP
+Board Vendor: TOSHIBA
+Board Name: Null
+
+---------------------------------------------
+Toshiba Satellite A105 ----------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  1.30
+BIOS Release:  02/09/2006
+System Vendor: TOSHIBA
+Product Name:  Satellite A105
+Version:       PSAA8U-02000U
+Board Vendor:  Intel Corporation
+Board Name:    Not Applicable
+
+---------------------------------------------
+Toshiba Satellite P10 -----------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.20
+BIOS Release:  09/12/2003
+System Vendor: TOSHIBA
+Product Name:  Satellite P10
+Version:       PSP10E-34FJR
+Board Vendor:  TOSHIBA
+Board Name:    DAL00
+Board Version: Null
+
+---------------------------------------------
+Toshiba Satellite P15 -----------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.20
+BIOS Release:  09/12/2003
+System Vendor: TOSHIBA
+Product Name:  Satellite P15
+Version:       PSP10U-0DUJPV
+Board Vendor:  TOSHIBA
+Board Name:    DAL00
+Board Version: Null
+
+---------------------------------------------
+Toshiba Satellite P25 -----------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V2.10
+BIOS Release:  12/27/2004
+System Vendor: TOSHIBA
+Product Name:  Satellite P25
+Version:       PSP20U-19PS8R
+Board Vendor:  TOSHIBA
+Board Name:    Null
+
+---------------------------------------------
+Toshiba Satellite P100 ----------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V3.30  
+BIOS Release:  12/22/2006
+System Vendor: TOSHIBA
+Product Name:  Satellite P100
+Version:       PSPA3E-02E013G3                   
+Board Vendor:  TOSHIBA
+Board Name:    Not Applicable                 
+
+---------------------------------------------
+Toshiba Satellite M40 -----------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  1.10
+BIOS Release:  08/24/05
+System Vendor: TOSHIBA
+Product Name:  Satellite M40
+Version:       PSM44E-00U00EFR
+Board Vendor:  ATI
+Board Name:    SB400
+Board Version: Rev0.4b
+
+---------------------------------------------
+Toshiba Satellite M45 (S355) ----------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  Version 2.00
+BIOS Release:  02/07/2006
+System Vendor: TOSHIBA
+Product Name:  Satellite M45
+Version:       PSM40U-073001
+Board Vendor:  TOSHIBA
+Board Name:    Version A0
+
+---------------------------------------------
+Toshiba Satellite M40X (-131)----------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.60
+BIOS Release:  06/09/2005
+System Vendor: TOSHIBA
+Product Name:  Satellite M40X
+Version:       PSM4XE-01400GFR
+Board Vendor:  TOSHIBA
+Board Name:    EAL30
+Board Version: Null
+
+---------------------------------------------
+Toshiba Satellite M50------------------------
+
+BIOS Vendor: TOSHIBA
+BIOS Version: V2.10
+BIOS Release: 05/08/2006
+System Vendor: TOSHIBA
+Product Name: Satellite M50
+Version: PSM51E-01C011IT
+Board Vendor: TOSHIBA
+Board Name: Null
+
+---------------------------------------------
+Toshiba Satellite M60 -----------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.60
+BIOS Release:  03/16/2006
+System Vendor: TOSHIBA
+Product Name:  Satellite M60
+Version:       PSM60E-0CD01FIT
+Board Vendor:  TOSHIBA
+Board Name:    Null
+
+---------------------------------------------
+Toshiba Satellite M70 -----------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.10
+BIOS Release:  09/15/2005
+System Vendor: TOSHIBA
+Product Name:  Satellite M70
+Version:       PSM71E-01100KFR
+Board Vendor:  TOSHIBA
+Board Name:    HTW00
+Board Version: Null
+
+---------------------------------------------
+Toshiba Satellite A75 -----------------------
+
+IOS Vendor:    TOSHIBA
+BIOS Version:  V1.50
+BIOS Release:  11/16/2004
+System Vendor: TOSHIBA
+Product Name:  Satellite A75
+Version:       PSA70U-004004B
+Board Vendor:  TOSHIBA
+Board Name:    Null
+
+---------------------------------------------
+Toshiba Satellite M100 ----------------------
+
+BIOS Vendor:    TOSHIBA
+BIOS Version:   V1.90
+BIOS Release:   07/20/2006
+System Vendor:  TOSHIBA
+Product Name:   SATELLITE M100
+Version:        PSMA0E-030019TE
+Board Vendor:   TOSHIBA
+Board Name:     HAQAA
+Board Version:  Null
+
+---------------------------------------------
+Toshiba Satellite M100 ----------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.00
+BIOS Release:  03/30/2006
+System Vendor: TOSHIBA
+Product Name:  Satellite M100
+Version:       PSMA2U-00T00G
+Board Vendor:  TOSHIBA
+Board Name:    HAWAA
+Board Version: None
+
+---------------------------------------------
+Toshiba Satellite M115 ----------------------
+
+Bios vender: Phoenix Tech. LTD
+Bios version: 1.00
+Bios release: 08/31/2006
+System Vendor: Toshiba
+Product Name: Satellite M115
+Version: PSMBOU-015007
+Board vendor Intel
+Board name: N/a
+
+---------------------------------------------
+Toshiba Equium A110 -------------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.30
+BIOS Release:  07/20/2006
+System Vendor: TOSHIBA
+Product Name:  EQUIUM A110
+Version:       PSAB2E-002006AV
+Board Vendor:  TOSHIBA
+Board Name:    Null
+
+---------------------------------------------
+Toshiba Tecra A4 ----------------------------
+
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  Version 1.70
+BIOS Release:  10/14/2005
+System Vendor: TOSHIBA
+Product Name:  Tecra A4
+Version:       PTA40E-0UN00FSP
+Board Vendor:  TOSHIBA
+Board Name:    Version A0
+
+---------------------------------------------
+Toshiba Tecra A6 ----------------------------
+
+BIOS Vendor: TOSHIBA
+BIOS Version: V2.70
+BIOS Release: 04/26/2007
+System Vendor: TOSHIBA
+Product Name: TECRA A6
+Version: PTA60U-0FK00D
+Board Vendor: TOSHIBA
+Board Name: Null
+
+---------------------------------------------
+Toshiba Tecra S2 ----------------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V2.50
+BIOS Release:  01/11/2006
+System Vendor: TOSHIBA
+Product Name:  Tecra S2
+Version:       PTS20E-1FE04Q8M
+Board Vendor:  TOSHIBA
+Board Name:    Null
+
+---------------------------------------------
+Compal ACL00 --------------------------------
+
+BIOS Vendor:   COMPAL
+BIOS Version:  V2.10C
+BIOS Release:  03/25/02
+System Vendor: COMPAL
+Product Name:  *
+Version:       *
+Board Vendor:  Null
+Board Name:    ACL00
+Board Version: Null
+
+---------------------------------------------
+Compal ACL10 --------------------------------
+
+BIOS Vendor:   COMPAL
+BIOS Version:  V1.10
+BIOS Release:  04/12/2001
+System Vendor: *
+Product Name:  *
+Version:       *
+Board Vendor:  COMPAL
+Board Name:    ACL10
+Board Version: Null
+
+---------------------------------------------
+HP Pavilion ZT1195 --------------------------
+
+BIOS Vendor:   Insyde Software
+BIOS Version:  IC.M1.00
+BIOS Release:  03/20/2002
+System Vendor: Hewlett-Packard
+Product Name:  HP Pavilion Notebook PC
+Version:       HP Pavilion Notebook
+Board Vendor:  Hewlett-Packard
+Board Name:    HP Pavilion Notebook PC
+Board Version: HP Pavilion Notebook
+
+---------------------------------------------
+HP Pavilion ZT1141 --------------------------
+
+BIOS Vendor:   Insyde Software
+BIOS Version:  IB.M1.05
+BIOS Release:  02/28/2002
+System Vendor: Hewlett-Packard
+Product Name:  HP Pavilion Notebook PC
+Version:       HP Pavilion Notebook ZT1000
+Board Vendor:  Hewlett-Packard
+Board Name:    HP Pavilion Notebook PC
+Board Version: HP Pavilion Notebook ZT1000
+
+---------------------------------------------
+HP OmniBook 6100 EB -------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  EB.M2.20
+BIOS Release:  02/27/02
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook 6100 EB
+Board Vendor:  Hewlett-Packard
+Board Name:    HP OmniBook PC
+Board Version: 6100EB
+
+---------------------------------------------
+HP OmniBook 6000 EA -------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  EA.M1.81
+BIOS Release:  02/22/2002
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook 6000 EA
+Board Vendor:  Hewlett-Packard
+Board Name:    HP OmniBook PC
+Board Version: 6000EA
+
+---------------------------------------------
+HP OmniBook xe4500 --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KB.M1.30
+BIOS Release:  08/05/20022
+System Vendor: Hewlett-Packard.
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook xe4500
+Board Vendor:  Hewlett-Packard
+Board Name:    HP OmniBook PC
+Board Version: xe4500
+
+---------------------------------------------
+HP Pavilion N5441 ---------------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  GD.M1.08
+BIOS Release:  09/27/2001
+System Vendor: Hewlett-Packard
+Product Name:  HP Pavilion Notebook PC
+Version:       HP Pavilion Notebook Model GD
+Board Vendor:  Hewlett-Packard
+Board Name:    N/A
+Board Version: OmniBook N32N-736
+
+---------------------------------------------
+HP Pavilion N5430 ---------------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  GD.M1.08
+BIOS Release:  09/27/2001
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook XE3 GD
+Board Vendor:  Hewlett-Packard
+Board Name:    N/A
+Board Version: OmniBook N32N-736
+
+---------------------------------------------
+HP Pavilion N5415 ---------------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  GE.M1.04
+BIOS Release:  07/30/2002
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook XE3 GE
+Board Vendor:  Hewlett-Packard
+Board Name:    N/A
+Board Version: OmniBook N32N-736
+
+---------------------------------------------
+HP Pavilion N5290 ---------------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  GC.M1.63
+BIOS Release:  01/01/1992
+System Vendor: Hewlett-Packard
+Product Name:  HP Pavilion Notebook PC
+Version:       HP Pavilion Notebook XE3 GC
+Board Vendor:  Hewlett-Packard
+Board Name:    N/A
+Board Version: OmniBook N32N-733
+
+---------------------------------------------
+HP OmniBook vt6200 -------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  EG.M2.10
+BIOS Release:  09/19/02
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook 6200 EG
+Board Vendor:  Hewlett-Packard
+Board Name:    HP OmniBook PC
+Board Version: 6200EG
+
+---------------------------------------------
+HP OmniBook 4150 ----------------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  CI.M2.250
+BIOS Release:  06/10/99
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook 4150
+Board Vendor:  Hewlett-Packard
+Board Name:    N/A
+Board Version: OmniBook TS32T2
+
+---------------------------------------------
+HP OmniBook xt6200 --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd
+BIOS Version:  EG.M2.10
+BIOS Release:  09/19/02
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook 6200 EG
+Board Vendor:  Hewlett-Packard
+Board Name:    HP OmniBook PC
+Board Version: 6200EG
+
+---------------------------------------------
+HP Pavilion ze4125 --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd
+BIOS Version:  KA.M1.20
+BIOS Release:  09/13/2002
+System Vendor: Hewlett-Packard
+Product Name:  HP NoteBook PC
+Version:       HP NoteBook ze4000
+Board Vendor:  Hewlett-Packard
+Board Name:    HP NoteBook PC
+Board Version: HP NoteBook ze4000
+
+---------------------------------------------
+HP OmniBook xt155 ---------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KE.M1.40
+BIOS Release:  10/11/20022
+System Vendor: Hewlett-Packard
+Product Name:  HP NoteBook PC
+Version:       HP Notebook PC
+Board Vendor:  Hewlett-Packard
+Board Name:    HP NoteBook PC
+Board Version: HP Notebook PC
+
+---------------------------------------------
+HP OmniBook xe4100 --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KC.M1.10
+BIOS Release:  07/11/2002
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook xe4000
+Board Vendor:  Hewlett-Packard
+Board Name:    HP OmniBook PC
+Board Version: 4000KC
+
+---------------------------------------------
+HP Omnibook xe4400 --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KD.M1.60
+BIOS Release:  09/19/20022
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP Omnibook xe4400
+Board Vendor:  Hewlett-Packard
+Board Name:    HP OmniBook PC
+Board Version: xe4400
+
+---------------------------------------------
+HP Pavilion ze4100 --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KE.M1.40
+BIOS Release:  10/11/20022
+System Vendor: Hewlett-Packard
+Product Name:  HP NoteBook PC         
+Version:       HP Notebook PC
+Board Vendor:  Hewlett-Packard
+Board Name:    HP NoteBook PC         
+Board Version: HP Notebook PC
+
+---------------------------------------------
+Acer Aspire 1350 ----------------------------
+BIOS Vendor:   Acer   
+BIOS Version:  3A24
+BIOS Release:  12/01/2003
+System Vendor: Acer,Inc.
+Product Name:  Aspire 1350
+Version:       3A24
+Board Vendor:  Acer,Inc.
+Board Name:    Aspire 1350
+Board Version: Rev.A
+
+---------------------------------------------
+Acer Aspire 1406 LC -------------------------
+
+BIOS Vendor:   Acer
+BIOS Version:  V2.30
+BIOS Release:  10/04/02
+System Vendor: Acer
+Product Name:  Aspire 1400 series
+Version:       *
+Board Vendor:  Null
+Board Name:    BR20
+Board Version: Null
+
+---------------------------------------------
+HP Pavilion ze4200 --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KE.M1.53
+BIOS Release:  12/10/20022
+System Vendor: Hewlett-Packard
+Product Name:  Pavilion ze4200
+Version:       KE.M1.53
+Board Vendor:  Hewlett-Packard
+Board Name:    002A
+Board Version: NS570 Version PQ1A74
+
+---------------------------------------------
+HP Pavilion ze4500 --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KAM1.57  
+BIOS Release:  02/19/2004
+System Vendor: Hewlett-Packard          
+Product Name:  Pavilion ze4500 (DP793E) 
+Version:       KAM1.57  
+Board Vendor:  Hewlett-Packard          
+Board Name:    PQ1A83
+
+---------------------------------------------
+HP Pavilion ZU1175 --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  FA.M2.60
+BIOS Release:  11/30/1999
+System Vendor: Hewlett-Packard
+Product Name:  HP Pavilion Notebook PC
+Version:       HP Pavilion ZU1000 FA
+Board Vendor:  Hewlett-Packard
+Board Name:    HP Pavilion Notebook PC
+Board Version: 1000FA
+
+---------------------------------------------
+HP Pavilion XH545 ---------------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  GE.M1.03
+BIOS Release:  11/08/2001
+System Vendor: Hewlett-Packard
+Product Name:  HP Pavilion Notebook PC
+Version:       HP Pavilion Notebook Model GE
+Board Vendor:  Hewlett-Packard
+Board Name:    N/A
+Board Version: OmniBook N32N-736
+
+---------------------------------------------
+Toshiba Satellite 2430-402 ------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.30
+BIOS Release:  01/16/2003
+System Vendor: TOSHIBA
+Product Name:  Satellite 2430
+Version:       PS243E-06P4S-4V
+Board Vendor:  TOSHIBA
+Board Name:    BTS88
+Board Version: Null
+
+---------------------------------------------
+HP OmniBook 900 B ---------------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  CL.M3.13
+BIOS Release:  11/11/99
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook 900 B
+Board Vendor:  Hewlett-Packard
+Board Name:    N/A
+Board Version: OmniBook TS32U2
+
+---------------------------------------------
+HP Compaq nx9000 ----------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KE_KG.M1.06
+BIOS Release:  05/16/2003
+System Vendor: Hewlett-Packard        
+Product Name:  HP nx9000 (DG223T)       
+Version:       KG.M1.06
+Board Vendor:  Hewlett-Packard        
+Board Name:    002A                   
+Board Version: NS570 Version PQ1A78   
+
+---------------------------------------------
+HP Compaq nx9000 ----------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KE_KG.M1.15
+BIOS Release:  12/19/2003
+System Vendor: Hewlett-Packard
+Product Name:  HP Notebook PC
+Version:       HP Notebook PC
+Board Vendor:  <NULL>
+Board Name:    <NULL>
+Board Version: <NULL>
+
+---------------------------------------------
+HP Compaq nx9005 ----------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KAM1.46
+BIOS Release:  07/21/200392
+System Vendor: Hewlett-Packard
+Product Name:  HP nx9005 (DJ163A)
+Version:       KAM1.46
+Board Vendor:  Hewlett-Packard
+Board Name:    0024
+Board Version: PQ1A78
+
+----------------------------------------------
+HP Compaq nx9010 -----------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KF_KH.F.08
+BIOS Release:  06/06/2003
+System Vendor: Hewlett-Packard
+Product Name:  HP nx9010 (DJ123A)
+Version:       KH.F.08
+Board Vendor:  Hewlett-Packard
+Board Name:    0850
+Board Version: NS570 Version PQ1B56
+
+----------------------------------------------
+HP Pavilion ze8500 --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KF_KH.F.18
+BIOS Release:  11/13/2003
+System Vendor: Hewlett-Packard
+Product Name:  Pavilion ze8500 (DJ317A)
+Version:       KH.F.18
+Board Vendor:  Hewlett-Packard
+Board Name:    0850
+Board Version: NS570 Version PQ1B60
+
+---------------------------------------------
+Fujitsu-Siemens Amilo D ---------------------
+
+BIOS Vendor:   Phoenix
+BIOS Version:  V1.20
+BIOS Release:  11/14/2001
+System Vendor: FUJITSU SIEMENS
+Product Name:  Amilo D-Series
+Version:       DESKTOP CPU ONLY
+Board Vendor:  CY23
+Board Name:    8606-686B
+Board Version: None
+
+---------------------------------------------
diff --git a/misc/hotkeys/README.hotkeys b/misc/hotkeys/README.hotkeys
new file mode 100644 (file)
index 0000000..3522bdf
--- /dev/null
@@ -0,0 +1,22 @@
+HotKeys is a program to use the special keys on internet/multimedia
+keyboards.
+
+The HotKeys daemon listens for the "special" hotkeys that you won't
+normally use on your Internet/Multimedia keyboards. The buttons
+perform their intended behaviors, such as volume up and down, mute the
+speaker, or launch applications.  It has On-screen display (OSD) to
+show the volume, program that's being started, etc.  It features an
+XML-based keycode configuration file format, which makes it possible
+to define the hotkeys to launch any programs you want.
+
+You may reach it at http://ypwong.org/hotkeys/
+
+Files in this directory provide examles for hotkeys definition files
+for certain laptop models supported by omnibook module:
+
+ob5xx.def:     HP OmniBook 5xx
+xe3gc.def:     HP OmniBook XE3 GC, GD, GE and HP Pavilion N5xxx
+xe3gf.def:     HP OmniBook XE3 GF
+xe4xxx.def:    HP OmniBook xe4xxx and ze4xxx
+xt155.def:     HP OmniBook xt155
+nx9xxx.def:    HP/Compaq nx9xxx
diff --git a/misc/hotkeys/nx9xxx.def b/misc/hotkeys/nx9xxx.def
new file mode 100644 (file)
index 0000000..9d3f531
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<definition>
+       <config model="HP/Compaq nx9xxx laptops">
+
+       <!--
+               Multimedia keys are disabled by default on HP laptops.
+               For enabling them see the project at URL
+               http://sourceforge.net/projects/omke
+       -->
+
+               <Email          keycode="236"/>
+               <WebBrowser     keycode="178"/>
+               <Shell          keycode="243"/>
+               <ScreenSaver    keycode="241"/>
+               <Help           keycode="240"/>
+
+               <VolUp          keycode="176" adj="1"/>
+               <VolDown        keycode="174" adj="1"/>
+
+               <userdef keycode="160" command="aumix -vM">Sound muted</userdef>
+
+       </config>
+
+       <contributor>
+               <name>Soos, Peter</name>
+               <email>sp@osb.hu</email>
+       </contributor>
+</definition>
diff --git a/misc/hotkeys/ob5xx.def b/misc/hotkeys/ob5xx.def
new file mode 100644 (file)
index 0000000..807b8d1
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<definition>
+       <config model="HP OmniBook 5xx">
+
+       <!--
+               Multimedia keys are disabled by default on HP OmniBook
+               laptops. For enabling them see the project at URL
+               http://sourceforge.net/projects/omke
+       -->
+
+               <Shell          keycode="244"/>
+               <Help           keycode="243"/>
+
+               <!-- Keys below available on the docking station only -->
+
+               <PrevTrack      keycode="144"/>
+               <Play           keycode="162"/>
+               <Stop           keycode="164"/>
+               <NextTrack      keycode="153"/>
+
+               <VolUp          keycode="176" adj="1"/>
+               <VolDown        keycode="174" adj="1"/>
+
+       </config>
+
+       <contributor>
+               <name>Soos, Peter</name>
+               <email>sp@osb.hu</email>
+       </contributor>
+</definition>
diff --git a/misc/hotkeys/xe3gc.def b/misc/hotkeys/xe3gc.def
new file mode 100644 (file)
index 0000000..5e418f2
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<definition>
+       <config model="HP OmniBook XE3 GC, GD, GE and HP Pavilion N5xxx">
+
+       <!--
+               Multimedia keys are disabled by default on HP OmniBook
+               laptops. For enabling them see the project at URL
+               http://sourceforge.net/projects/omke
+       -->
+
+               <PrevTrack      keycode="144"/>
+               <Play           keycode="162"/>
+               <Stop           keycode="164"/>
+               <NextTrack      keycode="153"/>
+
+               <VolUp          keycode="176" adj="1"/>
+               <VolDown        keycode="174" adj="1"/>
+
+               <WebBrowser     keycode="243"/>
+               <Email          keycode="244"/>
+               <Shell          keycode="242"/>
+               <Help           keycode="241"/>
+
+               <userdef keycode="160" command="aumix -vM">Sound muted</userdef>
+
+       </config>
+
+       <contributor>
+               <name>Soos, Peter</name>
+               <email>sp@osb.hu</email>
+       </contributor>
+</definition>
diff --git a/misc/hotkeys/xe3gf.def b/misc/hotkeys/xe3gf.def
new file mode 100644 (file)
index 0000000..8f8b40e
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<definition>
+       <config model="HP OmniBook XE3 GF">
+
+       <!--
+               Multimedia keys are disabled by default on HP OmniBook
+               laptops. For enabling them see the project at URL
+               http://sourceforge.net/projects/omke
+       -->
+
+               <PrevTrack      keycode="144"/>
+               <Play           keycode="162"/>
+               <Stop           keycode="164"/>
+               <NextTrack      keycode="153"/>
+
+               <VolUp          keycode="176" adj="1"/>
+               <VolDown        keycode="174" adj="1"/>
+
+               <Email          keycode="236"/>
+               <WebBrowser     keycode="178"/>
+               <Shell          keycode="244"/>
+               <Help           keycode="243"/>
+
+               <userdef keycode="160" command="aumix -vM">Sound muted</userdef>
+
+       </config>
+
+       <contributor>
+               <name>Soos, Peter</name>
+               <email>sp@osb.hu</email>
+       </contributor>
+</definition>
diff --git a/misc/hotkeys/xe4xxx.def b/misc/hotkeys/xe4xxx.def
new file mode 100644 (file)
index 0000000..6b14cde
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<definition>
+       <config model="HP OmniBook xe4xxx and ze4xxx">
+
+       <!--
+               Multimedia keys are disabled by default on HP OmniBook
+               laptops. For enabling them see the project at URL
+               http://sourceforge.net/projects/omke
+       -->
+
+               <Email          keycode="236"/>
+               <WebBrowser     keycode="178"/>
+               <Shell          keycode="243"/>
+               <ScreenSaver    keycode="241"/>
+               <Help           keycode="240"/>
+
+               <VolUp          keycode="176" adj="1"/>
+               <VolDown        keycode="174" adj="1"/>
+
+               <userdef keycode="160" command="aumix -vM">Sound muted</userdef>
+
+       </config>
+
+       <contributor>
+               <name>Soos, Peter</name>
+               <email>sp@osb.hu</email>
+       </contributor>
+</definition>
diff --git a/misc/hotkeys/xt155.def b/misc/hotkeys/xt155.def
new file mode 100644 (file)
index 0000000..d200bf0
--- /dev/null
+++ b/