FIND   = find
 endif
 
-DEBUG  =  # -D OMNIBOOK_DEBUG  -g -O0
-# Used by 2.6 stuff, so let's be consistant.
+DEBUG  =  #-D DEBUG  -g -O0
 EXTRA_CFLAGS += -D OMNIBOOK_STANDALONE $(DEBUG)
+EXTRA_LDFLAGS += $(src)/sections.lds
+
 
 OBJS   = ac.o battery.o blank.o display.o dock.o \
          ec.o fan.o fan_policy.o init.o lcd.o onetouch.o \
-         temperature.o touchpad.o dump.o info.o watch.o \
-         apmemu.o
+         temperature.o touchpad.o dump.o info.o \
+         apmemu.o muteled.o
 
 # All extra flags delt with automagically
+
 obj-m         += $(MODULE_NAME).o
 omnibook-objs := $(OBJS)
 
 all:            $(MODULE_NAME).ko
 
 clean:
-               $(RM) .*.cmd *.map *.mod.c *.o *.ko *~ "#*#"
-               $(RM) -r .tmp_versions
+               make -C $(KSRC) M=$(PWD) clean
+               $(RM) *~ "#*#" .swp
                $(RM) -r debian/omnibook-source *-stamp
                $(RM) -r Modules.symvers
                (cd misc/obtest; $(RM) obtest *.o)
 
+
 install:       all
                # Removing module from old location
-               $(RM) $(MODDIR)/char/$(MODULE_NAME).ko
-               $(RM) $(MODDIR)/misc/$(MODULE_NAME).ko
-               $(MKDIR) $(INSTDIR)
-               $(INSTALL) $(MODULE_NAME).ko $(INSTDIR)
-               $(DEPMOD)
+               $(RM) $(VMODDIR)/kernel/drivers/char/$(MODULE_NAME).ko
+               make -C $(KSRC) M=$(PWD) modules_install                
 
 unload:
                $(RMMOD) $(MODULE_NAME) || :
 
        return len;
 }
 
-struct omnibook_feature ac_feature = {
+static struct omnibook_feature __declared_feature ac_feature = {
         .name = "ac",
         .enabled = 1,
         .read = omnibook_ac_read,
 
        return 0;
 }
 
-struct omnibook_feature apmemu_feature = {
+static struct omnibook_feature __declared_feature apmemu_feature = {
         .name = "apmemu",
         .proc_entry = "apm", /* create /proc/apm */
 #ifdef CONFIG_OMNIBOOK_APMEMU
 
        return len;
 }
 
-struct omnibook_feature battery_feature  = {
+static struct omnibook_feature __declared_feature battery_feature  = {
         .name = "battery",
         .enabled = 1,
         .read = omnibook_battery_read,
 
        omnibook_console_blank_disable();
 }
 
-struct omnibook_feature blank_feature = {
+static struct omnibook_feature __declared_feature blank_feature = {
         .name = "blank",
         .enabled = 1,
         .read = omnibook_console_blank_read,
 
 /*
- * init.h -- Interfaces functions with omnibook features
+ * compat.h -- Older kernel (=> 2.6.8) 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
  * 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
  */
 
 /*
 }
 #endif
 
-struct omnibook_feature;
-
-static int __init omnibook_init(struct omnibook_feature *feature);
-
-extern struct omnibook_feature ac_feature;
-extern struct omnibook_feature apmemu_feature;
-extern struct omnibook_feature battery_feature;
-extern struct omnibook_feature blank_feature;
-extern struct omnibook_feature display_feature;
-extern struct omnibook_feature dock_feature;
-extern struct omnibook_feature dump_feature;
-extern struct omnibook_feature fan_feature;
-extern struct omnibook_feature fan_policy_feature;
-extern struct omnibook_feature dmi_feature;
-extern struct omnibook_feature lcd_feature;
-extern struct omnibook_feature onetouch_feature;
-extern struct omnibook_feature temperature_feature;
-extern struct omnibook_feature touchpad_feature;
-extern struct omnibook_feature version_feature;
-extern struct omnibook_feature watch_feature;
-
 /* End of file */
 
        return len;
 }
 
-struct omnibook_feature display_feature = {
+static struct omnibook_feature __declared_feature display_feature = {
         .name = "display",
         .enabled = 1,
         .read = omnibook_display_read,
 
 Changelog file for omnibook package:
 ------------------------------------
 
+
+
 2006-XX-XX 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-rc1 are supported
   conditions
   They are both disabled by default
 
+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
 
--- /dev/null
+hp's onetouch windows utility
+-----------------------------
+
+When installing hp's onetouch utility in Windows, you can find a ONETOUCH.CFG 
+file in the installation folder which seems to contain EC Controller commands 
+for some special features of the embedded controller (like mute led, etc..).
+
+It looks like the Windows DLL that sends commands to the EC controller is 
+LgKCUtl.DLL, also found in the onetouch installation folder. Maybe this is 
+useful to somebody someday :)
 
 * Adding more features of embedded controller
 * Support more machines
 * See if/how key polling can be ported to 2.6
+* LED API support
 
        return len;
 }
 
-struct omnibook_feature dock_feature = {
+static struct omnibook_feature __declared_feature dock_feature = {
         .name = "dock",
         .enabled = 0,
         .read = omnibook_dock_read,
 
        return 0;
 }
 
-struct omnibook_feature dump_feature = {
+static struct omnibook_feature __declared_feature dump_feature = {
         .name = "dump",
         .enabled = 0,
         .read = ecdump_read,
 
  * Read a value from a system I/O address
  */
 
-int omnibook_io_read(u32 addr, u8 * data)
+int inline omnibook_io_read(u32 addr, u8 * data)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(&omnibook_ec_lock, flags);
        *data = inb(addr);
-       spin_unlock_irqrestore(&omnibook_ec_lock, flags);
        return 0;
 }
 
  * Write a value to a system I/O address
  */
 
-int omnibook_io_write(u32 addr, u8 data)
+int inline omnibook_io_write(u32 addr, u8 data)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(&omnibook_ec_lock, flags);
        outb(data, addr);
-       spin_unlock_irqrestore(&omnibook_ec_lock, flags);
        return 0;
 }
 
 
 #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 */
 
 
        return 0;
 }
 
-struct omnibook_feature fan_feature;
+static struct omnibook_feature fan_feature;
 
 static int omnibook_fan_init(void)
 {
        return 0;
 }
 
-struct omnibook_feature fan_feature = {
+static struct omnibook_feature __declared_feature fan_feature = {
         .name = "fan",
         .enabled = 1,
         .read = omnibook_fan_read,
 
 
        b = buffer;
        do {
-#ifdef OMNIBOOK_DEBUG
-               printk("n=[%i] b=[%s]\n", n, b);
-#endif
+
+               pr_debug("n=[%i] b=[%s]\n", n, b);
+
                if (n > OMNIBOOK_FAN_LEVELS)
                        return -EINVAL;
                if (!isspace(*b)) {
        return 0;
 }
 
-struct omnibook_feature fan_policy_feature = {
+static struct omnibook_feature __declared_feature fan_policy_feature = {
         .name = "fan_policy",
         .enabled = 1,
         .read = omnibook_fan_policy_read,
 
        return len;
 }
 
-struct omnibook_feature version_feature = {
+static struct omnibook_feature __declared_feature version_feature = {
         .name = "version",
         .enabled = 1,
         .read = omnibook_version_read,
 };
 
-struct omnibook_feature dmi_feature = {
+static struct omnibook_feature __declared_feature dmi_feature = {
         .name = "dmi",
         .enabled = 1,
         .read = omnibook_dmi_read,
 
 #include <linux/device.h>
 #endif
 
-
 #include "ec.h"
-#include "init.h"
+#include "laptop.h"
+#include "compat.h"
 
 static struct proc_dir_entry *omnibook_proc_root = NULL;
 
 /* Linked list of all enabled features */
 static struct omnibook_feature *omnibook_available_feature;
 
-/* 
- * Array of all the features provided by this module 
- */
-static struct omnibook_feature *omnibook_features[] __initdata = {
-       &ac_feature,
-       &apmemu_feature,
-       &battery_feature,
-       &blank_feature,
-       &display_feature,
-       &dock_feature,
-       &dump_feature,
-       &fan_feature,
-       &fan_policy_feature,
-       &dmi_feature,
-       &lcd_feature,
-       &onetouch_feature,
-       &temperature_feature,
-       &touchpad_feature,
-       &version_feature,
-       &watch_feature
-};
-
-#define HP_SIGNATURE   "Hewlett-Packard"
-
-struct omnibook_models_t {
-       /* DMI field matchers (table inputs) */
-       char *sys_vendor;
-       char *product_name;
-       char *product_version;
-       char *board_name;
-       /* Table outputs */
-       char *syslog_name;      /* Name which will appear in the syslog */
-       int ectype;     /* Type of the embedded controller firmware, see omnibook.h and README */
-};
 
-static struct omnibook_models_t omnibook_models[] __initdata = {
-  /* sys_vendor product_name                 product_version                   board_name syslog_name                  ectype */
-  { NULL,       "HP OmniBook PC*",           "HP OmniBook XE3 GF*",            NULL,    NULL,                          XE3GF },
-  { NULL,       "HP OmniBook PC*",           "HP OmniBook XT1000*",            NULL,    NULL,                          XE3GF },
-  { NULL,       "HP OmniBook PC*",           "HP OmniBook XE2 DC*",            NULL,    NULL,                          XE2 },
-  { NULL,       "HP OmniBook PC*",           "HP OmniBook XE3 GC*",            NULL,    NULL,                          XE3GC },
-  /* HP Pavilion N5430 */
-  { NULL,       "HP OmniBook PC*",           "HP OmniBook XE3 GD*",            NULL,    NULL,                          XE3GC },
-  /* HP Pavilion N5415 */
-  { NULL,       "HP OmniBook PC*",           "HP OmniBook XE3 GE*",            NULL,    NULL,                          XE3GC },
-  { NULL,       "HP OmniBook PC*",           "HP OmniBook 500 FA*",            NULL,    NULL,                          OB500 },
-  { NULL,       "HP OmniBook PC*",           "HP OmniBook 510 FB*",            NULL,    NULL,                          OB510 },
-  { NULL,       "HP OmniBook PC*",           "HP OmniBook 4150*",              NULL,    NULL,                          OB4150 },
-  { NULL,       "HP OmniBook PC*",           "HP OmniBook 900 B*",             NULL,    NULL,                          OB4150 },
-  { NULL,       "HP OmniBook PC*",           "HP OmniBook 6000 EA*",           NULL,    NULL,                          OB6000 },
-  { NULL,       "HP OmniBook PC*",           "HP OmniBook 6100 EB*",           NULL,    NULL,                          OB6100 },
-  /* HP OmniBook xe4100 */
-  { NULL,       "HP OmniBook PC*",           "HP OmniBook xe4000*",            NULL,    NULL,                          XE4500 },
-  { NULL,       "HP OmniBook PC*",           "HP OmniBook xe4400*",            NULL,    NULL,                          XE4500 },
-  { NULL,       "HP OmniBook PC*",           "HP OmniBook xe4500*",            NULL,    NULL,                          XE4500 },
-  /* HP OmniBook vt6200 and xt6200 */
-  { NULL,       "HP OmniBook PC*",           "HP OmniBook 6200 EG*",           NULL,    NULL,                          XE4500 },
-  /* There are no model specific strings of some HP OmniBook XT1500 */
-  { NULL,       "HP OmniBook PC*",           "HP OmniBook*",                   NULL,    NULL,                          XE3GF },
-  /* HP Pavilion ze4125 */
-  { NULL,       "HP NoteBook PC*",           "HP NoteBook ze4000*",            NULL,    NULL,                          XE4500 },
-  /* There are no model specific strings of some HP Pavilion xt155 and some HP Pavilion ze4100 */
-  { NULL,       "HP NoteBook PC*",           "HP NoteBook PC*",                NULL,    NULL,                          XE4500 },
-  /* There are no model specific strings of some HP nx9000 */
-  { NULL,       "HP Notebook PC*",           "HP Notebook PC*",                NULL,    NULL,                          XE4500 },
-  /* HP Pavilion ZU1155 and ZU1175 */
-  { NULL,       "HP Pavilion Notebook PC*",  "HP Pavilion ZU1000 FA*",         NULL,    NULL,                          OB500 },
-  /* HP Pavilion N5290 */
-  { NULL,       "HP Pavilion Notebook PC*",  "HP Pavilion Notebook XE3 GC*",   NULL,    NULL,                          XE3GC },
-  /* HP Pavilion N5441 */
-  { NULL,       "HP Pavilion Notebook PC*",  "HP Pavilion Notebook Model GD*", NULL,    NULL,                          XE3GC },
-  /* HP Pavilion XH545 */
-  { NULL,       "HP Pavilion Notebook PC*",  "HP Pavilion Notebook Model GE*", NULL,    NULL,                          XE3GC },
-  /* HP Pavilion ZT1141 */
-  { NULL,       "HP Pavilion Notebook PC*",  "HP Pavilion Notebook ZT1000*",   NULL,    NULL,                          XE3GF },
-  /* There are no model specific strings of some HP Pavilion ZT1175 and ZT1195 notebooks */
-  { NULL,       "HP Pavilion Notebook PC*",  "HP Pavilion Notebook*",          NULL,    NULL,                          XE3GF },
-  { NULL,       "Pavilion ze4200*",          NULL,                             NULL,    "HP Pavilion ze4200 series",   XE4500 },
-  { NULL,       "Pavilion ze4300*",          NULL,                             NULL,    "HP Pavilion ze4300 series",   XE4500 },
-  { NULL,       "Pavilion ze8500*",          NULL,                             NULL,    "HP Pavilion ze8500 series",   XE4500 },
-  /* Compaq nx9000 */
-  { NULL,       "HP nx9000*",                NULL,                             NULL,    "HP Compaq nx9000",            XE4500 },
-  /* Compaq nx9005 */
-  { NULL,       "HP nx9005*",                NULL,                             NULL,    "HP Compaq nx9005",            XE4500 },
-  /* Compaq nx9010 */
-  { NULL,       "HP nx9010*",                NULL,                             NULL,    "HP Compaq nx9010",            XE4500 },
-  { "TOSHIBA",  "S1000*",                    NULL,                             NULL,    "Toshiba Satellite 1000",      XE3GF },
-  { "TOSHIBA",  "S1005*",                    NULL,                             NULL,    "Toshiba Satellite 1005",      XE3GF },
-  { "TOSHIBA",  "S1110*",                    NULL,                             NULL,    "Toshiba Satellite 1110",      XE3GF },
-  { "TOSHIBA",  "S1115*",                    NULL,                             NULL,    "Toshiba Satellite 1115",      XE3GF },
-  { "TOSHIBA",  "S1900*",                    NULL,                             NULL,    "Toshiba Satellite 1900",      XE3GF },
-  { "TOSHIBA",  "S1905*",                    NULL,                             NULL,    "Toshiba Satellite 1905",      XE3GF },
-  { "TOSHIBA",  "S1950*",                    NULL,                             NULL,    "Toshiba Satellite 1950",      XE3GF },
-  { "TOSHIBA",  "S1955*",                    NULL,                             NULL,    "Toshiba Satellite 1955",      XE3GF },
-  { "TOSHIBA",  "S2430*",                    NULL,                             NULL,    "Toshiba Satellite 2430",      XE3GF },
-  { "TOSHIBA",  "S2435*",                    NULL,                             NULL,    "Toshiba Satellite 2435",      XE3GF },
-  { "TOSHIBA",  "S3000*",                    NULL,                             NULL,    "Toshiba Satellite 3000",      XE3GF },
-  { "TOSHIBA",  "S3005*",                    NULL,                             NULL,    "Toshiba Satellite 3005",      XE3GF },
-  { "TOSHIBA",  "Satellite 1000*",           NULL,                             NULL,    "Toshiba Satellite 1000",      XE3GF },
-  { "TOSHIBA",  "Satellite 1005*",           NULL,                             NULL,    "Toshiba Satellite 1005",      XE3GF },
-  { "TOSHIBA",  "Satellite 1110*",           NULL,                             NULL,    "Toshiba Satellite 1110",      XE3GF },
-  { "TOSHIBA",  "Satellite 1115*",           NULL,                             NULL,    "Toshiba Satellite 1115",      XE3GF },
-  { "TOSHIBA",  "Toshiba 1115*",             NULL,                             NULL,    "Toshiba Satellite 1115",      XE3GF },
-  { "TOSHIBA",  "Satellite 1900*",           NULL,                             NULL,    "Toshiba Satellite 1900",      XE3GF },
-  { "TOSHIBA",  "Satellite 1905*",           NULL,                             NULL,    "Toshiba Satellite 1905",      XE3GF },
-  { "TOSHIBA",  "Satellite 1950*",           NULL,                             NULL,    "Toshiba Satellite 1950",      XE3GF },
-  { "TOSHIBA",  "Satellite 1955*",           NULL,                             NULL,    "Toshiba Satellite 1955",      XE3GF },
-  { "TOSHIBA",  "Satellite 2430*",           NULL,                             NULL,    "Toshiba Satellite 2430",      XE3GF },
-  { "TOSHIBA",  "Satellite 2435*",           NULL,                             NULL,    "Toshiba Satellite 2435",      XE3GF },
-  { "TOSHIBA",  "Satellite 3000*",           NULL,                             NULL,    "Toshiba Satellite 3000",      XE3GF },
-  { "TOSHIBA",  "Satellite 3005*",           NULL,                             NULL,    "Toshiba Satellite 3005",      XE3GF },
-  { "TOSHIBA",  "Satellite P10*",            NULL,                             NULL,    "Toshiba Satellite P10",       TSP10 },
-  { "TOSHIBA",  "Satellite P15*",            NULL,                             NULL,    "Toshiba Satellite P15",       TSP10 },
-  { "TOSHIBA",  "Satellite P20*",            NULL,                             NULL,    "Toshiba Satellite P20",       TSP10 },
-  { "TOSHIBA",  "Satellite M30X*",           NULL,                             NULL,    "Toshiba Satellite M30X",      TSM30X },
-  { "TOSHIBA",  "Satellite M35X*",           NULL,                             NULL,    "Toshiba Satellite M35X",      TSM30X },
-  { "TOSHIBA",  "Satellite M70*",            NULL,                             NULL,    "Toshiba Satellite M70",       TSM30X },
-  { "TOSHIBA",  "Satellite M40*",            NULL,                             NULL,    "Toshiba Satellite M40",       TSM40 },
-  { "COMPAL",   NULL,                        NULL,                             "ACL00", "Compal ACL00",                XE3GF },
-  { "COMPAL",   NULL,                        NULL,                             "ACL10", "Compal ACL10",                XE3GF },
-  { "Acer",     "Aspire 1400 series*",       NULL,                             NULL,    "Acer Aspire 1400 series",     XE3GF },
-  { "Acer",     "Aspire 1350*",              NULL,                             NULL,    "Acer Aspire 1350",            XE4500 },
-  { "FUJITSU SIEMENS", "Amilo D-Series*",    NULL,                             NULL,    "Fujitsu-Siemens Amilo D series", AMILOD },
-  /* This sentinel at the end catches all unsupported models */
-  { NULL, NULL, NULL, NULL, NULL, NONE }
-};
+/* Delimiters of the .features section wich holds all the omnibook_feature structs */
+extern struct omnibook_feature _features_start[];
+extern struct omnibook_feature _features_end[];
 
-struct omnibook_tc_t {
-       char *tc;
-       int ectype;
-};
-
-/* HP technology codes */
-static struct omnibook_tc_t omnibook_tc[] __initdata = {
-       /* technology code      ectype */
-       {"CI.", OB4150},
-       {"CL.", OB4150},
-       {"DC.", XE2},
-       {"EA.", OB6000},
-       {"EB.", OB6100},
-       {"EG.", XE4500},
-       {"FA.", OB500},
-       {"FB.", OB510},
-       {"GC.", XE3GC},
-       {"GD.", XE3GC},
-       {"GE.", XE3GC},
-       {"GF.", XE3GF},
-       {"IB.", XE3GF},
-       {"IC.", XE3GF},
-       {"ID.", XE3GF},
-       {"KA.", XE4500},
-       {"KB.", XE4500},
-       {"KC.", XE4500},
-       {"KD.", XE4500},
-       {"KE.", XE4500},
-       {"KE_KG.", XE4500},
-       {"KF_KH.", XE4500},
-       {NULL, NONE}
-};
 
 /*
  * Compare the saved DMI info at "index" with a string.
 
        /* Make sure the string is \0 terminated */
        kernbuf[count] = '\0';
-#ifdef OMNIBOOK_DEBUG
-       printk("Input string length is %u and is: [%s]\n", (unsigned int)count,
-              kernbuf);
-#endif
+
        retval = feature->write(kernbuf);
        if (retval == 0)
                retval = count;
        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 list_head *p;
-       struct omnibook_feature *feature;
-
-       omnibook_available_feature =
-           kzalloc(sizeof(struct omnibook_feature), GFP_KERNEL);
-       if (!omnibook_available_feature)
-               return -ENOMEM;
-       INIT_LIST_HEAD(&omnibook_available_feature->list);
-
-       for (i = 0; i < ARRAY_SIZE(omnibook_features); i++) {
-               if (!omnibook_features[i]->enabled)
-                       continue;
-               if ((omnibook_ectype & omnibook_features[i]->ectypes) || (!omnibook_features[i]->ectypes))
-                       omnibook_init(omnibook_features[i]);
-       }
-       
-       printk(KERN_INFO "%s: Enabled features:",OMNIBOOK_MODULE_NAME);
-       list_for_each(p, &omnibook_available_feature->list) {
-               feature = list_entry(p, struct omnibook_feature, list);
-               if (feature->name)
-                       printk(" %s", feature->name);
-       }
-       printk(".\n");
-       
-       return 0;
-}
-
 /* 
  * Initialise a feature and add it to the linked list of active features
  */
                        if (feature->write)
                                proc_entry->write_proc =
                                    &procfile_write_dispatch;
+                       proc_entry->owner = THIS_MODULE;
                }
        }
        list_add_tail(&feature->list, &omnibook_available_feature->list);
        return 0;
 }
 
+
+/* 
+ * 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 list_head *p;
+       struct omnibook_feature *feature;
+
+       
+       omnibook_available_feature =
+           kzalloc(sizeof(struct omnibook_feature), GFP_KERNEL);
+       if (!omnibook_available_feature)
+               return -ENOMEM;
+       INIT_LIST_HEAD(&omnibook_available_feature->list);
+       
+       for (i=0; i < _features_end - _features_start; i++ ) {
+               
+               feature = &_features_start[i];
+
+               if (!feature->enabled)  
+                       continue;
+               
+               if ((omnibook_ectype & feature->ectypes) || (!feature->ectypes)) {
+/*                     printk("cursor is at: %p\n", (void*) feature);
+                       if(feature->name)
+                               printk("trying to init:%s\n",feature->name);
+                       else
+                               printk("trying to init nameless feature\n"); */
+
+                       omnibook_init(feature);
+               }
+       }
+       
+       printk(KERN_INFO "%s: Enabled features:",OMNIBOOK_MODULE_NAME);
+       list_for_each(p, &omnibook_available_feature->list) {
+               feature = list_entry(p, struct omnibook_feature, list);
+               if (feature->name)
+                       printk(" %s", feature->name);
+       }
+       printk(".\n");
+       
+       return 0;
+}
+
 /* 
  * Callback function for driver removal
  */
 
--- /dev/null
+/*
+ * 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"
+
+struct omnibook_models_t {
+       /* DMI field matchers (table inputs) */
+       char *sys_vendor;
+       char *product_name;
+       char *product_version;
+       char *board_name;
+       /* Table outputs */
+       char *syslog_name;      /* Name which will appear in the syslog */
+       int ectype;     /* Type of the embedded controller firmware, see omnibook.h and README */
+};
+
+static struct omnibook_models_t omnibook_models[] __initdata = {
+  /* sys_vendor product_name                 product_version                   board_name syslog_name                  ectype */
+  { NULL,       "HP OmniBook PC*",           "HP OmniBook XE3 GF*",            NULL,    NULL,                          XE3GF },
+  { NULL,       "HP OmniBook PC*",           "HP OmniBook XT1000*",            NULL,    NULL,                          XE3GF },
+  { NULL,       "HP OmniBook PC*",           "HP OmniBook XE2 DC*",            NULL,    NULL,                          XE2 },
+  { NULL,       "HP OmniBook PC*",           "HP OmniBook XE3 GC*",            NULL,    NULL,                          XE3GC },
+  /* HP Pavilion N5430 */
+  { NULL,       "HP OmniBook PC*",           "HP OmniBook XE3 GD*",            NULL,    NULL,                          XE3GC },
+  /* HP Pavilion N5415 */
+  { NULL,       "HP OmniBook PC*",           "HP OmniBook XE3 GE*",            NULL,    NULL,                          XE3GC },
+  { NULL,       "HP OmniBook PC*",           "HP OmniBook 500 FA*",            NULL,    NULL,                          OB500 },
+  { NULL,       "HP OmniBook PC*",           "HP OmniBook 510 FB*",            NULL,    NULL,                          OB510 },
+  { NULL,       "HP OmniBook PC*",           "HP OmniBook 4150*",              NULL,    NULL,                          OB4150 },
+  { NULL,       "HP OmniBook PC*",           "HP OmniBook 900 B*",             NULL,    NULL,                          OB4150 },
+  { NULL,       "HP OmniBook PC*",           "HP OmniBook 6000 EA*",           NULL,    NULL,                          OB6000 },
+  { NULL,       "HP OmniBook PC*",           "HP OmniBook 6100 EB*",           NULL,    NULL,                          OB6100 },
+  /* HP OmniBook xe4100 */
+  { NULL,       "HP OmniBook PC*",           "HP OmniBook xe4000*",            NULL,    NULL,                          XE4500 },
+  { NULL,       "HP OmniBook PC*",           "HP OmniBook xe4400*",            NULL,    NULL,                          XE4500 },
+  { NULL,       "HP OmniBook PC*",           "HP OmniBook xe4500*",            NULL,    NULL,                          XE4500 },
+  /* HP OmniBook vt6200 and xt6200 */
+  { NULL,       "HP OmniBook PC*",           "HP OmniBook 6200 EG*",           NULL,    NULL,                          XE4500 },
+  /* There are no model specific strings of some HP OmniBook XT1500 */
+  { NULL,       "HP OmniBook PC*",           "HP OmniBook*",                   NULL,    NULL,                          XE3GF },
+  /* HP Pavilion ze4125 */
+  { NULL,       "HP NoteBook PC*",           "HP NoteBook ze4000*",            NULL,    NULL,                          XE4500 },
+  /* There are no model specific strings of some HP Pavilion xt155 and some HP Pavilion ze4100 */
+  { NULL,       "HP NoteBook PC*",           "HP NoteBook PC*",                NULL,    NULL,                          XE4500 },
+  /* There are no model specific strings of some HP nx9000 */
+  { NULL,       "HP Notebook PC*",           "HP Notebook PC*",                NULL,    NULL,                          XE4500 },
+  /* HP Pavilion ZU1155 and ZU1175 */
+  { NULL,       "HP Pavilion Notebook PC*",  "HP Pavilion ZU1000 FA*",         NULL,    NULL,                          OB500 },
+  /* HP Pavilion N5290 */
+  { NULL,       "HP Pavilion Notebook PC*",  "HP Pavilion Notebook XE3 GC*",   NULL,    NULL,                          XE3GC },
+  /* HP Pavilion N5441 */
+  { NULL,       "HP Pavilion Notebook PC*",  "HP Pavilion Notebook Model GD*", NULL,    NULL,                          XE3GC },
+  /* HP Pavilion XH545 */
+  { NULL,       "HP Pavilion Notebook PC*",  "HP Pavilion Notebook Model GE*", NULL,    NULL,                          XE3GC },
+  /* HP Pavilion ZT1141 */
+  { NULL,       "HP Pavilion Notebook PC*",  "HP Pavilion Notebook ZT1000*",   NULL,    NULL,                          XE3GF },
+  /* There are no model specific strings of some HP Pavilion ZT1175 and ZT1195 notebooks */
+  { NULL,       "HP Pavilion Notebook PC*",  "HP Pavilion Notebook*",          NULL,    NULL,                          XE3GF },
+  { NULL,       "Pavilion ze4200*",          NULL,                             NULL,    "HP Pavilion ze4200 series",   XE4500 },
+  { NULL,       "Pavilion ze4300*",          NULL,                             NULL,    "HP Pavilion ze4300 series",   XE4500 },
+  { NULL,       "Pavilion ze8500*",          NULL,                             NULL,    "HP Pavilion ze8500 series",   XE4500 },
+  /* Compaq nx9000 */
+  { NULL,       "HP nx9000*",                NULL,                             NULL,    "HP Compaq nx9000",            XE4500 },
+  /* Compaq nx9005 */
+  { NULL,       "HP nx9005*",                NULL,                             NULL,    "HP Compaq nx9005",            XE4500 },
+  /* Compaq nx9010 */
+  { NULL,       "HP nx9010*",                NULL,                             NULL,    "HP Compaq nx9010",            XE4500 },
+  { "TOSHIBA",  "S1000*",                    NULL,                             NULL,    "Toshiba Satellite 1000",      XE3GF },
+  { "TOSHIBA",  "S1005*",                    NULL,                             NULL,    "Toshiba Satellite 1005",      XE3GF },
+  { "TOSHIBA",  "S1110*",                    NULL,                             NULL,    "Toshiba Satellite 1110",      XE3GF },
+  { "TOSHIBA",  "S1115*",                    NULL,                             NULL,    "Toshiba Satellite 1115",      XE3GF },
+  { "TOSHIBA",  "S1900*",                    NULL,                             NULL,    "Toshiba Satellite 1900",      XE3GF },
+  { "TOSHIBA",  "S1905*",                    NULL,                             NULL,    "Toshiba Satellite 1905",      XE3GF },
+  { "TOSHIBA",  "S1950*",                    NULL,                             NULL,    "Toshiba Satellite 1950",      XE3GF },
+  { "TOSHIBA",  "S1955*",                    NULL,                             NULL,    "Toshiba Satellite 1955",      XE3GF },
+  { "TOSHIBA",  "S2430*",                    NULL,                             NULL,    "Toshiba Satellite 2430",      XE3GF },
+  { "TOSHIBA",  "S2435*",                    NULL,                             NULL,    "Toshiba Satellite 2435",      XE3GF },
+  { "TOSHIBA",  "S3000*",                    NULL,                             NULL,    "Toshiba Satellite 3000",      XE3GF },
+  { "TOSHIBA",  "S3005*",                    NULL,                             NULL,    "Toshiba Satellite 3005",      XE3GF },
+  { "TOSHIBA",  "Satellite 1000*",           NULL,                             NULL,    "Toshiba Satellite 1000",      XE3GF },
+  { "TOSHIBA",  "Satellite 1005*",           NULL,                             NULL,    "Toshiba Satellite 1005",      XE3GF },
+  { "TOSHIBA",  "Satellite 1110*",           NULL,                             NULL,    "Toshiba Satellite 1110",      XE3GF },
+  { "TOSHIBA",  "Satellite 1115*",           NULL,                             NULL,    "Toshiba Satellite 1115",      XE3GF },
+  { "TOSHIBA",  "Toshiba 1115*",             NULL,                             NULL,    "Toshiba Satellite 1115",      XE3GF },
+  { "TOSHIBA",  "Satellite 1900*",           NULL,                             NULL,    "Toshiba Satellite 1900",      XE3GF },
+  { "TOSHIBA",  "Satellite 1905*",           NULL,                             NULL,    "Toshiba Satellite 1905",      XE3GF },
+  { "TOSHIBA",  "Satellite 1950*",           NULL,                             NULL,    "Toshiba Satellite 1950",      XE3GF },
+  { "TOSHIBA",  "Satellite 1955*",           NULL,                             NULL,    "Toshiba Satellite 1955",      XE3GF },
+  { "TOSHIBA",  "Satellite 2430*",           NULL,                             NULL,    "Toshiba Satellite 2430",      XE3GF },
+  { "TOSHIBA",  "Satellite 2435*",           NULL,                             NULL,    "Toshiba Satellite 2435",      XE3GF },
+  { "TOSHIBA",  "Satellite 3000*",           NULL,                             NULL,    "Toshiba Satellite 3000",      XE3GF },
+  { "TOSHIBA",  "Satellite 3005*",           NULL,                             NULL,    "Toshiba Satellite 3005",      XE3GF },
+  { "TOSHIBA",  "Satellite P10*",            NULL,                             NULL,    "Toshiba Satellite P10",       TSP10 },
+  { "TOSHIBA",  "Satellite P15*",            NULL,                             NULL,    "Toshiba Satellite P15",       TSP10 },
+  { "TOSHIBA",  "Satellite P20*",            NULL,                             NULL,    "Toshiba Satellite P20",       TSP10 },
+  { "TOSHIBA",  "Satellite M30X*",           NULL,                             NULL,    "Toshiba Satellite M30X",      TSM30X },
+  { "TOSHIBA",  "Satellite M35X*",           NULL,                             NULL,    "Toshiba Satellite M35X",      TSM30X },
+  { "TOSHIBA",  "Satellite M70*",            NULL,                             NULL,    "Toshiba Satellite M70",       TSM30X },
+  { "TOSHIBA",  "Satellite M40*",            NULL,                             NULL,    "Toshiba Satellite M40",       TSM40 },
+  { "COMPAL",   NULL,                        NULL,                             "ACL00", "Compal ACL00",                XE3GF },
+  { "COMPAL",   NULL,                        NULL,                             "ACL10", "Compal ACL10",                XE3GF },
+  { "Acer",     "Aspire 1400 series*",       NULL,                             NULL,    "Acer Aspire 1400 series",     XE3GF },
+  { "Acer",     "Aspire 1350*",              NULL,                             NULL,    "Acer Aspire 1350",            XE4500 },
+  { "FUJITSU SIEMENS", "Amilo D-Series*",    NULL,                             NULL,    "Fujitsu-Siemens Amilo D series", AMILOD },
+  /* This sentinel at the end catches all unsupported models */
+  { NULL, NULL, NULL, NULL, NULL, NONE }
+};
+
+struct omnibook_tc_t {
+       char *tc;
+       int ectype;
+};
+
+/* HP technology codes */
+static struct omnibook_tc_t omnibook_tc[] __initdata = {
+       /* technology code      ectype */
+       {"CI.", OB4150},
+       {"CL.", OB4150},
+       {"DC.", XE2},
+       {"EA.", OB6000},
+       {"EB.", OB6100},
+       {"EG.", XE4500},
+       {"FA.", OB500},
+       {"FB.", OB510},
+       {"GC.", XE3GC},
+       {"GD.", XE3GC},
+       {"GE.", XE3GC},
+       {"GF.", XE3GF},
+       {"IB.", XE3GF},
+       {"IC.", XE3GF},
+       {"ID.", XE3GF},
+       {"KA.", XE4500},
+       {"KB.", XE4500},
+       {"KC.", XE4500},
+       {"KD.", XE4500},
+       {"KE.", XE4500},
+       {"KE_KG.", XE4500},
+       {"KF_KH.", XE4500},
+       {NULL, NONE}
+};
 
 static struct backlight_device *omnibook_backlight_device;
 
 int omnibook_get_backlight(struct backlight_device *bd);
-int omnibook_set_backlight(struct backlight_device *bd, int brgt);
+int omnibook_set_backlight(struct backlight_device *bd);
 
 static struct backlight_properties omnibookbl_data = {
        .owner = THIS_MODULE,
        .get_brightness = omnibook_get_backlight,
-       .set_brightness = omnibook_set_backlight,
+       .update_status = omnibook_set_backlight,
 };
 
 #endif
        return omnibook_get_lcd_brightness();
 }
 
-int omnibook_set_backlight(struct backlight_device *bd, int brgt)
+int omnibook_set_backlight(struct backlight_device *bd)
 {
-       return omnibook_set_lcd_brightness(brgt);
+       int intensity = bd->props->brightness;
+       return omnibook_set_lcd_brightness(intensity);
 }
 #endif
 
 #endif
 }
 
-struct omnibook_feature lcd_feature = {
+static struct omnibook_feature __declared_feature lcd_feature = {
         .name = "lcd",
         .enabled = 1,
         .read = omnibook_brightness_read,
 
--- /dev/null
+/*
+ * mutled.c -- MUTE LED 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 Thomas Perl <thp@perli.net>, 2006
+ */
+
+#ifdef OMNIBOOK_STANDALONE
+#include "omnibook.h"
+#else
+#include <linux/omnibook.h>
+#endif
+
+#include "ec.h"
+
+/* There is no information about reading MUTE LED status */
+static int omnibook_muteled_enabled = 0;
+
+static int omnibook_muteled_on(void)
+{
+       if (omnibook_kbc_command(OMNIBOOK_KBC_CONTROL_CMD, OMNIBOOK_KBC_CMD_MUTELED_ON)) {
+               printk(KERN_ERR "%s: failed muteled on command.\n", OMNIBOOK_MODULE_NAME);
+               return -EIO;
+       }
+        omnibook_muteled_enabled = 1;
+       return 0;
+}
+
+static int omnibook_muteled_off(void)
+{
+       if (omnibook_kbc_command(OMNIBOOK_KBC_CONTROL_CMD, OMNIBOOK_KBC_CMD_MUTELED_OFF)) {
+               printk(KERN_ERR "%s: failed muteled off command.\n", OMNIBOOK_MODULE_NAME);
+               return -EIO;
+       }
+        omnibook_muteled_enabled = 0;
+       return 0;
+}
+
+
+static int omnibook_muteled_disable(void)
+{
+        omnibook_muteled_off();
+        return 0;
+}
+
+static int omnibook_muteled_enable(void)
+{
+        omnibook_muteled_on();
+        return 0;
+}
+
+static int omnibook_muteled_read(char *buffer)
+{
+       int len = 0;
+
+       len += sprintf(buffer+len, "The mute LED is %s\n", (omnibook_muteled_enabled) ? "on" : "off");
+
+       return len;
+}
+
+static int omnibook_muteled_write(char *buffer)
+{
+       int retval;     
+       
+       switch (*buffer) {
+       case '0':
+               if ((retval = omnibook_muteled_disable()));
+                       return retval;
+               break;
+       case '1':
+               if ((retval = omnibook_muteled_enable()));
+                       return retval;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+
+static struct omnibook_feature __declared_feature muteled_feature = {
+        .name = "muteled",
+        .enabled = 1,
+        .read = omnibook_muteled_read,
+        .write = omnibook_muteled_write,
+        .ectypes = XE4500,
+};
+
+module_param_named(muteled, muteled_feature.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(muteled, "Use 0 to disable, 1 to enable 'Audo Mute' LED control");
+
 
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/config.h>
+#include <linux/version.h>
 
 /*
  * Module informations
  */
 
 struct omnibook_feature {
-       struct list_head list;
        char *name;             /* Name */
        char *proc_entry;       /* Specify proc entry relative to /proc (will be omnibook/name otherwise) */
        int enabled;            /* Set from module parameter */
        int (*suspend) (void);  /* PM Suspend function */
        int (*resume) (void);   /* PM Resume function */
        int ectypes;            /* Type(s) of EC we support for this feature (bitmask) */
+       struct list_head list;
 };
 
 struct omnibook_battery_info {
 extern int omnibook_get_battery_status(int num, struct omnibook_battery_state *battstat);
 extern int set_omnibook_param(const char *val, struct kernel_param *kp);
 
+
+#define __declared_feature __attribute__ (( __section__(".features"),  __aligned__(__alignof__ (struct omnibook_feature)))) __attribute_used__
+
+
 /* 
  * Configuration for standalone compilation: 
- * -Register as backlight depends on kernel config
+ * -Register as backlight depends on kernel config (requires 2.6.17+ interface)
  * -APM emulation is disabled by default
  */
 
 #ifdef  OMNIBOOK_STANDALONE
-#ifdef  CONFIG_BACKLIGHT_CLASS_DEVICE
+#if     defined(CONFIG_BACKLIGHT_DEVICE) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16))
 #define CONFIG_OMNIBOOK_BACKLIGHT
 #else
 #undef  CONFIG_OMNIBOOK_BACKLIGHT
 
 #include "ec.h"
 
 /* There is no information about reading OneTouch status */
-int omnibook_onetouch_enabled = 0;
+static int omnibook_onetouch_enabled = 0;
 
 static int omnibook_onetouch_on(void)
 {
        omnibook_onetouch_disable();
 }
 
-struct omnibook_feature onetouch_feature = {
+static struct omnibook_feature __declared_feature onetouch_feature = {
         .name = "onetouch",
         .enabled = 1,
         .read = omnibook_onetouch_read,
 
--- /dev/null
+SECTIONS{
+  .features :
+    {
+      _features_start = .;
+      *(.features)
+      _features_end = .;
+    } 
+}
 
        return len;
 }
 
-struct omnibook_feature temperature_feature = {
+static struct omnibook_feature __declared_feature temperature_feature = {
         .name = "temperature",
         .enabled = 1,
         .read = omnibook_temperature_read,
 
        omnibook_touchpad_enable();
 }
 
-struct omnibook_feature touchpad_feature = {
+static struct omnibook_feature __declared_feature touchpad_feature = {
         .name = "touchpad",
         .enabled = 1,
         .read = omnibook_touchpad_read,
 
+++ /dev/null
-/*
- *  watch.c - Watch a specific ioport/iomem/ec register
- *
- *
- * 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
- */
-
-#ifdef OMNIBOOK_STANDALONE
-#include "omnibook.h"
-#else
-#include <linux/omnibook.h>
-#endif
-
-#include "ec.h"
-
-enum {
-       BAD,
-       EC,
-       PIO,
-       MMIO,
-};
-
-static u32 addr = 0;
-static int addr_type = BAD;
-
-static int watch_read(char *buffer)
-{
-       int len = 0;
-       u8 v;
-       
-       switch (addr_type) {
-       case BAD:
-               len += sprintf(buffer + len, "Please first write to this file and address to watch\n");
-               len += sprintf(buffer + len, "ex: 'TYPE 0x2f' where TYPE={EC,PIO,MMIO}\n");
-               return len;
-       case EC:
-               omnibook_ec_read((u8) addr, &v);
-               break;
-       case PIO:
-               omnibook_io_read(addr, &v);
-               break;
-       case MMIO:
-               omnibook_mem_read(addr, &v);
-               break;
-       }
-       len += sprintf(buffer + len, "%02x\n",v );
-       
-       return len;
-}
-
-static int watch_write(char *buffer)
-{
-       int retval;
-       u32 value;
-       char type[5];
-
-       retval = sscanf(buffer, "%4s%x", type, &value);
-       
-       if (retval != 2)
-               return -EINVAL; 
-
-       if (strncmp(type,"EC",2) == 0)
-               addr_type = EC;
-       else if (strncmp(type,"PIO",3) == 0)
-               addr_type = PIO;
-       else if (strncmp(type,"MMIO",4) == 0)
-               addr_type = MMIO;
-       else
-               return -EINVAL;
-       
-       if  ((value > 0xff) && (addr_type == EC))
-               return -EINVAL;
-       else if ((value > 0xffff) && (addr_type == PIO))
-               return -EINVAL;
-       else
-               addr = value;
-
-       return 0;
-}
-
-struct omnibook_feature watch_feature = {
-        .name = "watch",
-        .enabled = 0,
-        .read = watch_read,
-        .write = watch_write,
-};
-
-
-module_param_named(watch, watch_feature.enabled, int, S_IRUGO);
-MODULE_PARM_DESC(watch, "Use 0 to disable, 1 to enable register watching (DANGEROUS)");
-
-/* End of file */