2007-10-19 18:56:07

by Németh Márton

[permalink] [raw]
Subject: [PATCH 3/3] leds-clevo-mail: driver for Clevo mail LED

From: M?rton N?meth <[email protected]>

The driver supports the mail LED commonly found on different Clevo notebooks.
The driver access the LED through the i8042 hardware and implements the support for
hardware accelerated blink function.

Signed-off-by: M?rton N?meth <[email protected]>
---
diff -uprN linux-2.6.23.orig/drivers/leds/Kconfig linux-2.6.23/drivers/leds/Kconfig
--- linux-2.6.23.orig/drivers/leds/Kconfig 2007-10-09 22:31:38.000000000 +0200
+++ linux-2.6.23/drivers/leds/Kconfig 2007-10-18 07:20:12.000000000 +0200
@@ -101,6 +101,26 @@ config LEDS_GPIO
outputs. To be useful the particular board must have LEDs
and they must be connected to the GPIO lines.

+config LEDS_CLEVO_MAIL
+ tristate "Mail LED on Clevo notebook (EXPERIMENTAL)"
+ depends on LEDS_CLASS && X86 && SERIO_I8042 && DMI && EXPERIMENTAL
+ help
+ This driver makes the mail LED accessible from userspace
+ programs through the leds subsystem. This LED can blink at
+ about 0.5Hz and 1Hz.
+
+ This module can drive the mail LED for the following notebooks:
+
+ Clevo D410J
+ Clevo D410V
+ Clevo D400V/D470V (not tested, but might work)
+ Clevo M540N
+ Clevo M5x0N (not tested, but might work)
+ Positivo Mobile (Clevo M5x0V)
+
+ To compile this driver as a module, choose M here: the
+ module will be called leds-clevo-mail.
+
comment "LED Triggers"

config LEDS_TRIGGERS
diff -uprN linux-2.6.23.orig/drivers/leds/leds-clevo-mail.c linux-2.6.23/drivers/leds/leds-clevo-mail.c
--- linux-2.6.23.orig/drivers/leds/leds-clevo-mail.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.23/drivers/leds/leds-clevo-mail.c 2007-10-18 07:17:56.000000000 +0200
@@ -0,0 +1,226 @@
+
+#include <linux/module.h>
+
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/leds.h>
+
+#include <linux/io.h>
+#include <linux/dmi.h>
+
+#include <linux/i8042.h>
+
+
+#define TRUE 1
+#define FALSE 0
+
+#define HANDLED 0
+
+#define CLEVO_MAIL_LED_OFF 0x0084
+#define CLEVO_MAIL_LED_BLINK_1HZ 0x008A
+#define CLEVO_MAIL_LED_BLINK_0_5HZ 0x0083
+
+#define MODULE_FNAME "leds-clevo-mail.c"
+#define DRVNAME "clevo-mail-led"
+#define NO_RESOURCES NULL
+
+MODULE_AUTHOR("M?rton N?meth <[email protected]>");
+MODULE_DESCRIPTION("Clevo mail LED driver");
+MODULE_LICENSE("GPL");
+
+static unsigned int __initdata nodetect;
+module_param_named(nodetect, nodetect, bool, 0);
+MODULE_PARM_DESC(nodetect, "Skip DMI hardware detection");
+
+
+static struct platform_device *pdev;
+
+
+static int __init clevo_mail_led_dmi_callback(struct dmi_system_id *id)
+{
+ printk(KERN_INFO MODULE_FNAME ": '%s' found\n", id->ident);
+ return 1;
+}
+
+/**
+ * struct mail_led_whitelist - List of known good models
+ *
+ * Contains the known good models this driver is compatible with.
+ * When adding a new model try to be as strict as possible. This
+ * makes it possible to keep the false positives (the model is
+ * detected as working, but in reality it is not) as low as
+ * possible.
+ */
+static struct dmi_system_id __initdata mail_led_whitelist[] = {
+ {
+ .callback = clevo_mail_led_dmi_callback,
+ .ident = "Clevo D410J",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "VIA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "K8N800"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "VT8204B")
+ }
+ },
+ {
+ .callback = clevo_mail_led_dmi_callback,
+ .ident = "Clevo M5x0N",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "CLEVO Co."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "M5x0N")
+ }
+ },
+ {
+ .callback = clevo_mail_led_dmi_callback,
+ .ident = "Positivo Mobile",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "CLEVO Co. "),
+ DMI_MATCH(DMI_BOARD_NAME, "M5X0V "),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Positivo Mobile"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "VT6198")
+ }
+ },
+ {
+ .callback = clevo_mail_led_dmi_callback,
+ .ident = "Clevo D410V",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Clevo, Co."),
+ DMI_MATCH(DMI_BOARD_NAME, "D400V/D470V"),
+ DMI_MATCH(DMI_BOARD_VERSION, "SS78B"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Rev. A1")
+ }
+ },
+ { }
+};
+
+
+static void clevo_mail_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ if (value == LED_OFF)
+ i8042_command(NULL, CLEVO_MAIL_LED_OFF);
+ else if (value <= LED_HALF)
+ i8042_command(NULL, CLEVO_MAIL_LED_BLINK_0_5HZ);
+ else
+ i8042_command(NULL, CLEVO_MAIL_LED_BLINK_1HZ);
+
+}
+
+static int clevo_mail_led_blink(struct led_classdev *led_cdev,
+ int delay_on, int delay_off)
+{
+ int status = -EINVAL;
+
+ if (delay_on == 500 /* ms */ && delay_off == 500 /* ms */) {
+ /* blink the led with 1Hz */
+ i8042_command(NULL, CLEVO_MAIL_LED_BLINK_1HZ);
+ status = HANDLED;
+
+ } else if (delay_on == 1000 /* ms */ && delay_off == 1000 /* ms */) {
+ /* blink the led with 0.5Hz */
+ i8042_command(NULL, CLEVO_MAIL_LED_BLINK_0_5HZ);
+ status = HANDLED;
+
+ } else {
+ printk(KERN_DEBUG MODULE_FNAME
+ ": clevo_mail_led_blink(..., %u, %u),"
+ " returning -EINVAL (unsupported)\n",
+ delay_on, delay_off);
+ }
+
+ return status;
+}
+
+
+static struct led_classdev clevo_mail_led = {
+ .name = "clevo::mail",
+ .brightness_set = clevo_mail_led_set,
+ .blink_set = clevo_mail_led_blink,
+};
+
+static int __init clevo_mail_led_probe(struct platform_device *pdev)
+{
+ return led_classdev_register(&pdev->dev, &clevo_mail_led);
+}
+
+static int clevo_mail_led_remove(struct platform_device *pdev)
+{
+ led_classdev_unregister(&clevo_mail_led);
+ return 0;
+}
+
+
+
+#ifdef CONFIG_PM
+static int clevo_mail_led_suspend(struct platform_device *dev,
+ pm_message_t state)
+{
+ led_classdev_suspend(&clevo_mail_led);
+ return 0;
+}
+
+static int clevo_mail_led_resume(struct platform_device *dev)
+{
+ led_classdev_resume(&clevo_mail_led);
+ return 0;
+}
+#endif
+
+static struct platform_driver clevo_mail_led_driver = {
+ .probe = clevo_mail_led_probe,
+ .remove = clevo_mail_led_remove,
+#ifdef CONFIG_PM
+ .suspend = clevo_mail_led_suspend,
+ .resume = clevo_mail_led_resume,
+#endif
+ .driver = {
+ .name = DRVNAME,
+ },
+};
+
+
+static int __init clevo_mail_led_init(void)
+{
+ int error = 0;
+ int count = 0;
+
+ /* Check with the help of DMI if we are running on supported hardware */
+ if (!nodetect) {
+ count = dmi_check_system(mail_led_whitelist);
+ } else {
+ count = 1;
+ printk(KERN_ERR MODULE_FNAME ": Skipping DMI detection. "
+ "If the driver works on your hardware please "
+ "report model and the output of dmidecode in tracker "
+ "at http://sourceforge.net/projects/clevo-mailled/\n");
+ }
+
+ if (!count) {
+ return -ENODEV;
+ }
+
+ pdev = platform_device_register_simple(DRVNAME, -1, NO_RESOURCES, 0);
+ if (!IS_ERR(pdev)) {
+ error = platform_driver_probe(&clevo_mail_led_driver,
+ clevo_mail_led_probe);
+ if (error) {
+ printk(KERN_ERR MODULE_FNAME
+ ": Can't probe platform driver\n");
+ platform_device_unregister(pdev);
+ }
+ } else {
+ error = PTR_ERR(pdev);
+ }
+
+ return error;
+}
+
+static void __exit clevo_mail_led_exit(void)
+{
+ platform_device_unregister(pdev);
+ platform_driver_unregister(&clevo_mail_led_driver);
+
+ clevo_mail_led_set(NULL, LED_OFF);
+}
+
+module_init(clevo_mail_led_init);
+module_exit(clevo_mail_led_exit);
diff -uprN linux-2.6.23.orig/drivers/leds/Makefile linux-2.6.23/drivers/leds/Makefile
--- linux-2.6.23.orig/drivers/leds/Makefile 2007-10-09 22:31:38.000000000 +0200
+++ linux-2.6.23/drivers/leds/Makefile 2007-10-18 07:18:49.000000000 +0200
@@ -17,6 +17,7 @@ obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o
obj-$(CONFIG_LEDS_H1940) += leds-h1940.o
obj-$(CONFIG_LEDS_COBALT) += leds-cobalt.o
obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
+obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o

# LED Triggers
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o


2007-10-19 20:36:46

by Randy Dunlap

[permalink] [raw]
Subject: Re: [PATCH 3/3] leds-clevo-mail: driver for Clevo mail LED

On Fri, 19 Oct 2007 20:52:52 +0200 N?meth M?rton wrote:

> From: M?rton N?meth <[email protected]>
>
> The driver supports the mail LED commonly found on different Clevo notebooks.
> The driver access the LED through the i8042 hardware and implements the support for
> hardware accelerated blink function.
>
> Signed-off-by: M?rton N?meth <[email protected]>
> ---
> diff -uprN linux-2.6.23.orig/drivers/leds/Kconfig linux-2.6.23/drivers/leds/Kconfig
> --- linux-2.6.23.orig/drivers/leds/Kconfig 2007-10-09 22:31:38.000000000 +0200
> +++ linux-2.6.23/drivers/leds/Kconfig 2007-10-18 07:20:12.000000000 +0200
> @@ -101,6 +101,26 @@ config LEDS_GPIO
> outputs. To be useful the particular board must have LEDs
> and they must be connected to the GPIO lines.
>
> +config LEDS_CLEVO_MAIL
> + tristate "Mail LED on Clevo notebook (EXPERIMENTAL)"
> + depends on LEDS_CLASS && X86 && SERIO_I8042 && DMI && EXPERIMENTAL
> + help
> + This driver makes the mail LED accessible from userspace
> + programs through the leds subsystem. This LED can blink at
> + about 0.5Hz and 1Hz.

?:
can blink 1 time every 1 or 2 seconds.

> + This module can drive the mail LED for the following notebooks:
> +
> + Clevo D410J
> + Clevo D410V
> + Clevo D400V/D470V (not tested, but might work)
> + Clevo M540N
> + Clevo M5x0N (not tested, but might work)
> + Positivo Mobile (Clevo M5x0V)
> +
> + To compile this driver as a module, choose M here: the
> + module will be called leds-clevo-mail.
> +
> comment "LED Triggers"
>
> config LEDS_TRIGGERS
> diff -uprN linux-2.6.23.orig/drivers/leds/leds-clevo-mail.c linux-2.6.23/drivers/leds/leds-clevo-mail.c
> --- linux-2.6.23.orig/drivers/leds/leds-clevo-mail.c 1970-01-01 01:00:00.000000000 +0100
> +++ linux-2.6.23/drivers/leds/leds-clevo-mail.c 2007-10-18 07:17:56.000000000 +0200
> @@ -0,0 +1,226 @@
> +
> +#include <linux/module.h>
> +
> +#include <linux/platform_device.h>
> +#include <linux/err.h>
> +#include <linux/leds.h>
> +
> +#include <linux/io.h>
> +#include <linux/dmi.h>
> +
> +#include <linux/i8042.h>
> +
> +
> +#define TRUE 1
> +#define FALSE 0

Just use true / false.

> +#define HANDLED 0
> +
> +#define CLEVO_MAIL_LED_OFF 0x0084
> +#define CLEVO_MAIL_LED_BLINK_1HZ 0x008A
> +#define CLEVO_MAIL_LED_BLINK_0_5HZ 0x0083
> +
> +#define MODULE_FNAME "leds-clevo-mail.c"
> +#define DRVNAME "clevo-mail-led"

Kbuild provides KBUILD_BASENAME and KBUILD_MODNAME. Can you use
one of those?

> +#define NO_RESOURCES NULL

Just use NULL.

> +MODULE_AUTHOR("M?rton N?meth <[email protected]>");
> +MODULE_DESCRIPTION("Clevo mail LED driver");
> +MODULE_LICENSE("GPL");
> +
> +
> +static int __init clevo_mail_led_dmi_callback(struct dmi_system_id *id)
> +{
> + printk(KERN_INFO MODULE_FNAME ": '%s' found\n", id->ident);

MODULE_FNAME string looks too long and out of place here.

> + return 1;
> +}
> +
> +/**

/** introduces kernel-doc, but there is no following kernel-doc....,
so just use /*, please.

> + * struct mail_led_whitelist - List of known good models
> + *
> + * Contains the known good models this driver is compatible with.
> + * When adding a new model try to be as strict as possible. This
> + * makes it possible to keep the false positives (the model is
> + * detected as working, but in reality it is not) as low as
> + * possible.
> + */
> +static struct dmi_system_id __initdata mail_led_whitelist[] = {
> + {
...
> + { }
> +};
> +
> +
> +
> +static struct led_classdev clevo_mail_led = {
> + .name = "clevo::mail",

What's the purpose of the "::"?

> + .brightness_set = clevo_mail_led_set,
> + .blink_set = clevo_mail_led_blink,
> +};
> +
> +
> +static struct platform_driver clevo_mail_led_driver = {
> + .probe = clevo_mail_led_probe,
> + .remove = clevo_mail_led_remove,
> +#ifdef CONFIG_PM
> + .suspend = clevo_mail_led_suspend,
> + .resume = clevo_mail_led_resume,
> +#endif
> + .driver = {
> + .name = DRVNAME,
> + },
> +};

We prefer to have clevo_mail_led_susped() and _resume() defined
all the time, so that the above ifdef & endif can go away, so
do more like:

#ifdef CONFIG_PM
/* those functions as you have them */
#else
#define clevo_mail_led_suspend NULL
#define clevo_mail_led_resume NULL
#endif



> +static int __init clevo_mail_led_init(void)
> +{
> + int error = 0;
> + int count = 0;
> +
> + /* Check with the help of DMI if we are running on supported hardware */
> + if (!nodetect) {
> + count = dmi_check_system(mail_led_whitelist);
> + } else {
> + count = 1;
> + printk(KERN_ERR MODULE_FNAME ": Skipping DMI detection. "
> + "If the driver works on your hardware please "
> + "report model and the output of dmidecode in tracker "
> + "at http://sourceforge.net/projects/clevo-mailled/\n");
> + }
> +
> + if (!count) {
> + return -ENODEV;
> + }

Don't use braces on one-statement/one-line "blocks."

> + pdev = platform_device_register_simple(DRVNAME, -1, NO_RESOURCES, 0);
> + if (!IS_ERR(pdev)) {
> + error = platform_driver_probe(&clevo_mail_led_driver,
> + clevo_mail_led_probe);
> + if (error) {
> + printk(KERN_ERR MODULE_FNAME

Use the module logical name, not source file name.

> + ": Can't probe platform driver\n");
> + platform_device_unregister(pdev);
> + }
> + } else {
> + error = PTR_ERR(pdev);
> + }
> +
> + return error;
> +}


---
~Randy

2007-10-21 12:55:39

by Németh Márton

[permalink] [raw]
Subject: Re: [PATCH 3/3] leds-clevo-mail: driver for Clevo mail LED

Randy Dunlap wrote:
> On Fri, 19 Oct 2007 20:52:52 +0200 N?meth M?rton wrote:
>
>> From: M?rton N?meth <[email protected]>
>>
>> The driver supports the mail LED commonly found on different Clevo notebooks.
>> The driver access the LED through the i8042 hardware and implements the support for
>> hardware accelerated blink function.
>>
>> Signed-off-by: M?rton N?meth <[email protected]>
>> ---
>> diff -uprN linux-2.6.23.orig/drivers/leds/Kconfig linux-2.6.23/drivers/leds/Kconfig
>> --- linux-2.6.23.orig/drivers/leds/Kconfig 2007-10-09 22:31:38.000000000 +0200
>> +++ linux-2.6.23/drivers/leds/Kconfig 2007-10-18 07:20:12.000000000 +0200
>> @@ -101,6 +101,26 @@ config LEDS_GPIO
>> outputs. To be useful the particular board must have LEDs
>> and they must be connected to the GPIO lines.
>>
>> +config LEDS_CLEVO_MAIL
>> + tristate "Mail LED on Clevo notebook (EXPERIMENTAL)"
>> + depends on LEDS_CLASS && X86 && SERIO_I8042 && DMI && EXPERIMENTAL
>> + help
>> + This driver makes the mail LED accessible from userspace
>> + programs through the leds subsystem. This LED can blink at
>> + about 0.5Hz and 1Hz.
>
> ?:
> can blink 1 time every 1 or 2 seconds.

It has three modes, I'll try to explain this in more detail in my next patch version.

>
>> + This module can drive the mail LED for the following notebooks:
>> +
>> + Clevo D410J
>> + Clevo D410V
>> + Clevo D400V/D470V (not tested, but might work)
>> + Clevo M540N
>> + Clevo M5x0N (not tested, but might work)
>> + Positivo Mobile (Clevo M5x0V)
>> +
>> + To compile this driver as a module, choose M here: the
>> + module will be called leds-clevo-mail.
>> +
> comment "LED Triggers"
>
> config LEDS_TRIGGERS

I'll document the led trigger extension in more detail in the next
version of the "[PATCH 2/3] leds-clevo-mail: hw accelerated LED blink extension",
in drivers/leds/Kconfig.

>> +#define TRUE 1
>> +#define FALSE 0
>
> Just use true / false.

I'll delete these #defines.

>> +#define HANDLED 0
>> +
>> +#define CLEVO_MAIL_LED_OFF 0x0084
>> +#define CLEVO_MAIL_LED_BLINK_1HZ 0x008A
>> +#define CLEVO_MAIL_LED_BLINK_0_5HZ 0x0083
>> +
>> +#define MODULE_FNAME "leds-clevo-mail.c"
>> +#define DRVNAME "clevo-mail-led"
>
> Kbuild provides KBUILD_BASENAME and KBUILD_MODNAME. Can you use
> one of those?

I'll use KBUILD_MODNAME instead.

>> +#define NO_RESOURCES NULL
>
> Just use NULL.

I'll delete NO_RESOURCES.

>> +static int __init clevo_mail_led_dmi_callback(struct dmi_system_id *id)
>> +{
>> + printk(KERN_INFO MODULE_FNAME ": '%s' found\n", id->ident);
>
> MODULE_FNAME string looks too long and out of place here.

I'll replace MODULE_FNAME with KBUILD_MODNAME. Is this what you mean?

>> +/**
>
> /** introduces kernel-doc, but there is no following kernel-doc....,
> so just use /*, please.

OK, I'll replace.

>> +static struct led_classdev clevo_mail_led = {
>> + .name = "clevo::mail",
>
> What's the purpose of the "::"?

Here I have the problem that the different laptop models have
different colors of mail LED. So I left out the color and
introduced the type of the LED which is "mail". I'll try to
document this in Documents/leds-class.txt

>> +static struct platform_driver clevo_mail_led_driver = {
>> + .probe = clevo_mail_led_probe,
>> + .remove = clevo_mail_led_remove,
>> +#ifdef CONFIG_PM
>> + .suspend = clevo_mail_led_suspend,
>> + .resume = clevo_mail_led_resume,
>> +#endif
>> + .driver = {
>> + .name = DRVNAME,
>> + },
>> +};
>
> We prefer to have clevo_mail_led_susped() and _resume() defined
> all the time, so that the above ifdef & endif can go away, so
> do more like:
>
> #ifdef CONFIG_PM
> /* those functions as you have them */
> #else
> #define clevo_mail_led_suspend NULL
> #define clevo_mail_led_resume NULL
> #endif

I'll change this to what you proposed.

>> + if (!count) {
>> + return -ENODEV;
>> + }
>
> Don't use braces on one-statement/one-line "blocks."

I'll remove the braces for the on-line expression.

>> + pdev = platform_device_register_simple(DRVNAME, -1, NO_RESOURCES, 0);
>> + if (!IS_ERR(pdev)) {
>> + error = platform_driver_probe(&clevo_mail_led_driver,
>> + clevo_mail_led_probe);
>> + if (error) {
>> + printk(KERN_ERR MODULE_FNAME
>
> Use the module logical name, not source file name.

I'll use KBUILD_MODNAME instead.

> ---
> ~Randy

M?rton N?meth

2007-10-21 12:58:23

by Németh Márton

[permalink] [raw]
Subject: Re: [PATCH 3/3] leds-clevo-mail: driver for Clevo mail LED

From: M?rton N?meth <[email protected]>

The driver supports the mail LED commonly found on different Clevo notebooks.
The driver access the LED through the i8042 hardware and implements the support for
hardware accelerated blink function.

Signed-off-by: M?rton N?meth <[email protected]>
---
diff -uprN linux-2.6.23.orig/Documentation/leds-class.txt linux-2.6.23/Documentation/leds-class.txt
--- linux-2.6.23.orig/Documentation/leds-class.txt 2007-10-09 22:31:38.000000000 +0200
+++ linux-2.6.23/Documentation/leds-class.txt 2007-10-21 10:45:35.000000000 +0200
@@ -39,7 +39,9 @@ LED Device Naming

Is currently of the form:

-"devicename:colour"
+"devicename:colour" or
+"devicename:colour:type" or
+"devicename::type"

There have been calls for LED properties such as colour to be exported as
individual led class attributes. As a solution which doesn't incur as much
diff -uprN linux-2.6.23.orig/drivers/leds/Kconfig linux-2.6.23/drivers/leds/Kconfig
--- linux-2.6.23.orig/drivers/leds/Kconfig 2007-10-09 22:31:38.000000000 +0200
+++ linux-2.6.23/drivers/leds/Kconfig 2007-10-21 12:04:50.000000000 +0200
@@ -101,6 +101,39 @@ config LEDS_GPIO
outputs. To be useful the particular board must have LEDs
and they must be connected to the GPIO lines.

+config LEDS_CLEVO_MAIL
+ tristate "Mail LED on Clevo notebook (EXPERIMENTAL)"
+ depends on LEDS_CLASS && X86 && SERIO_I8042 && DMI && EXPERIMENTAL
+ help
+ This driver makes the mail LED accessible from userspace
+ programs through the leds subsystem. This LED have three
+ known mode: off, blink at 0.5Hz and blink at 1Hz.
+
+ The driver supports two kinds of interface: using ledtrig-timer
+ or through /sys/class/leds/clevo::mail/brightness. As this LED
+ cannot change it's brightness it blinks instead. The brightness
+ value 0 means off, 1..127 means blink at 0.5Hz and 128..255 means
+ blink at 1Hz.
+
+ Example to start blink at 0.5Hz:
+ echo 1 >/sys/class/leds/clevo::mail/brightness
+ - or -
+ echo timer >/sys/class/leds/clevo::mail/trigger
+ echo 1000 >/sys/class/leds/clevo::mail/delay_on
+ echo 1000 >/sys/class/leds/clevo::mail/delay_off
+
+ This module can drive the mail LED for the following notebooks:
+
+ Clevo D410J
+ Clevo D410V
+ Clevo D400V/D470V (not tested, but might work)
+ Clevo M540N
+ Clevo M5x0N (not tested, but might work)
+ Positivo Mobile (Clevo M5x0V)
+
+ To compile this driver as a module, choose M here: the
+ module will be called leds-clevo-mail.
+
comment "LED Triggers"

config LEDS_TRIGGERS
diff -uprN linux-2.6.23.orig/drivers/leds/leds-clevo-mail.c linux-2.6.23/drivers/leds/leds-clevo-mail.c
--- linux-2.6.23.orig/drivers/leds/leds-clevo-mail.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.23/drivers/leds/leds-clevo-mail.c 2007-10-21 10:49:32.000000000 +0200
@@ -0,0 +1,210 @@
+
+#include <linux/module.h>
+
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/leds.h>
+
+#include <linux/io.h>
+#include <linux/dmi.h>
+
+#include <linux/i8042.h>
+
+#define HANDLED 0
+
+#define CLEVO_MAIL_LED_OFF 0x0084
+#define CLEVO_MAIL_LED_BLINK_1HZ 0x008A
+#define CLEVO_MAIL_LED_BLINK_0_5HZ 0x0083
+
+MODULE_AUTHOR("M?rton N?meth <[email protected]>");
+MODULE_DESCRIPTION("Clevo mail LED driver");
+MODULE_LICENSE("GPL");
+
+static unsigned int __initdata nodetect;
+module_param_named(nodetect, nodetect, bool, 0);
+MODULE_PARM_DESC(nodetect, "Skip DMI hardware detection");
+
+static struct platform_device *pdev;
+
+static int __init clevo_mail_led_dmi_callback(struct dmi_system_id *id)
+{
+ printk(KERN_INFO KBUILD_MODNAME ": '%s' found\n", id->ident);
+ return 1;
+}
+
+/*
+ * struct mail_led_whitelist - List of known good models
+ *
+ * Contains the known good models this driver is compatible with.
+ * When adding a new model try to be as strict as possible. This
+ * makes it possible to keep the false positives (the model is
+ * detected as working, but in reality it is not) as low as
+ * possible.
+ */
+static struct dmi_system_id __initdata mail_led_whitelist[] = {
+ {
+ .callback = clevo_mail_led_dmi_callback,
+ .ident = "Clevo D410J",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "VIA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "K8N800"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "VT8204B")
+ }
+ },
+ {
+ .callback = clevo_mail_led_dmi_callback,
+ .ident = "Clevo M5x0N",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "CLEVO Co."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "M5x0N")
+ }
+ },
+ {
+ .callback = clevo_mail_led_dmi_callback,
+ .ident = "Positivo Mobile",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "CLEVO Co. "),
+ DMI_MATCH(DMI_BOARD_NAME, "M5X0V "),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Positivo Mobile"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "VT6198")
+ }
+ },
+ {
+ .callback = clevo_mail_led_dmi_callback,
+ .ident = "Clevo D410V",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Clevo, Co."),
+ DMI_MATCH(DMI_BOARD_NAME, "D400V/D470V"),
+ DMI_MATCH(DMI_BOARD_VERSION, "SS78B"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Rev. A1")
+ }
+ },
+ { }
+};
+
+static void clevo_mail_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ if (value == LED_OFF)
+ i8042_command(NULL, CLEVO_MAIL_LED_OFF);
+ else if (value <= LED_HALF)
+ i8042_command(NULL, CLEVO_MAIL_LED_BLINK_0_5HZ);
+ else
+ i8042_command(NULL, CLEVO_MAIL_LED_BLINK_1HZ);
+
+}
+
+static int clevo_mail_led_blink(struct led_classdev *led_cdev,
+ int delay_on, int delay_off)
+{
+ int status = -EINVAL;
+
+ if (delay_on == 500 /* ms */ && delay_off == 500 /* ms */) {
+ /* blink the led with 1Hz */
+ i8042_command(NULL, CLEVO_MAIL_LED_BLINK_1HZ);
+ status = HANDLED;
+
+ } else if (delay_on == 1000 /* ms */ && delay_off == 1000 /* ms */) {
+ /* blink the led with 0.5Hz */
+ i8042_command(NULL, CLEVO_MAIL_LED_BLINK_0_5HZ);
+ status = HANDLED;
+
+ } else {
+ printk(KERN_DEBUG KBUILD_MODNAME
+ ": clevo_mail_led_blink(..., %u, %u),"
+ " returning -EINVAL (unsupported)\n",
+ delay_on, delay_off);
+ }
+
+ return status;
+}
+
+static struct led_classdev clevo_mail_led = {
+ .name = "clevo::mail",
+ .brightness_set = clevo_mail_led_set,
+ .blink_set = clevo_mail_led_blink,
+};
+
+static int __init clevo_mail_led_probe(struct platform_device *pdev)
+{
+ return led_classdev_register(&pdev->dev, &clevo_mail_led);
+}
+
+static int clevo_mail_led_remove(struct platform_device *pdev)
+{
+ led_classdev_unregister(&clevo_mail_led);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int clevo_mail_led_suspend(struct platform_device *dev,
+ pm_message_t state)
+{
+ led_classdev_suspend(&clevo_mail_led);
+ return 0;
+}
+
+static int clevo_mail_led_resume(struct platform_device *dev)
+{
+ led_classdev_resume(&clevo_mail_led);
+ return 0;
+}
+#else
+#define clevo_mail_led_suspend NULL
+#define clevo_mail_led_resume NULL
+#endif
+
+static struct platform_driver clevo_mail_led_driver = {
+ .probe = clevo_mail_led_probe,
+ .remove = clevo_mail_led_remove,
+ .suspend = clevo_mail_led_suspend,
+ .resume = clevo_mail_led_resume,
+ .driver = {
+ .name = KBUILD_MODNAME,
+ },
+};
+
+static int __init clevo_mail_led_init(void)
+{
+ int error = 0;
+ int count = 0;
+
+ /* Check with the help of DMI if we are running on supported hardware */
+ if (!nodetect) {
+ count = dmi_check_system(mail_led_whitelist);
+ } else {
+ count = 1;
+ printk(KERN_ERR KBUILD_MODNAME ": Skipping DMI detection. "
+ "If the driver works on your hardware please "
+ "report model and the output of dmidecode in tracker "
+ "at http://sourceforge.net/projects/clevo-mailled/\n");
+ }
+
+ if (!count)
+ return -ENODEV;
+
+ pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0);
+ if (!IS_ERR(pdev)) {
+ error = platform_driver_probe(&clevo_mail_led_driver,
+ clevo_mail_led_probe);
+ if (error) {
+ printk(KERN_ERR KBUILD_MODNAME
+ ": Can't probe platform driver\n");
+ platform_device_unregister(pdev);
+ }
+ } else
+ error = PTR_ERR(pdev);
+
+ return error;
+}
+
+static void __exit clevo_mail_led_exit(void)
+{
+ platform_device_unregister(pdev);
+ platform_driver_unregister(&clevo_mail_led_driver);
+
+ clevo_mail_led_set(NULL, LED_OFF);
+}
+
+module_init(clevo_mail_led_init);
+module_exit(clevo_mail_led_exit);
diff -uprN linux-2.6.23.orig/drivers/leds/Makefile linux-2.6.23/drivers/leds/Makefile
--- linux-2.6.23.orig/drivers/leds/Makefile 2007-10-09 22:31:38.000000000 +0200
+++ linux-2.6.23/drivers/leds/Makefile 2007-10-18 18:21:37.000000000 +0200
@@ -17,6 +17,7 @@ obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o
obj-$(CONFIG_LEDS_H1940) += leds-h1940.o
obj-$(CONFIG_LEDS_COBALT) += leds-cobalt.o
obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
+obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o

# LED Triggers
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o

2007-10-23 21:50:21

by Richard Purdie

[permalink] [raw]
Subject: Re: [PATCH 3/3] leds-clevo-mail: driver for Clevo mail LED

On Sun, 2007-10-21 at 14:55 +0200, N?meth M?rton wrote:
> diff -uprN linux-2.6.23.orig/Documentation/leds-class.txt linux-2.6.23/Documentation/leds-class.txt
> --- linux-2.6.23.orig/Documentation/leds-class.txt 2007-10-09 22:31:38.000000000 +0200
> +++ linux-2.6.23/Documentation/leds-class.txt 2007-10-21 10:45:35.000000000 +0200
> @@ -39,7 +39,9 @@ LED Device Naming
>
> Is currently of the form:
>
> -"devicename:colour"
> +"devicename:colour" or
> +"devicename:colour:type" or
> +"devicename::type"

Adding a the idea of function here was proposed a while back and we
probably should do that but it needs to be a separate patch and some of
the other drivers probably need tweaking for consistency. I will take
care of this for the next merge window.

> diff -uprN linux-2.6.23.orig/drivers/leds/Kconfig linux-2.6.23/drivers/leds/Kconfig
> --- linux-2.6.23.orig/drivers/leds/Kconfig 2007-10-09 22:31:38.000000000 +0200
> +++ linux-2.6.23/drivers/leds/Kconfig 2007-10-21 12:04:50.000000000 +0200
> @@ -101,6 +101,39 @@ config LEDS_GPIO
> outputs. To be useful the particular board must have LEDs
> and they must be connected to the GPIO lines.
>
> +config LEDS_CLEVO_MAIL
> + tristate "Mail LED on Clevo notebook (EXPERIMENTAL)"
> + depends on LEDS_CLASS && X86 && SERIO_I8042 && DMI && EXPERIMENTAL
> + help
> + This driver makes the mail LED accessible from userspace
> + programs through the leds subsystem. This LED have three
> + known mode: off, blink at 0.5Hz and blink at 1Hz.
> +
> + The driver supports two kinds of interface: using ledtrig-timer
> + or through /sys/class/leds/clevo::mail/brightness. As this LED
> + cannot change it's brightness it blinks instead. The brightness
> + value 0 means off, 1..127 means blink at 0.5Hz and 128..255 means
> + blink at 1Hz.

Hmm, there really is no way to just turn the LED on? :(

> + Example to start blink at 0.5Hz:
> + echo 1 >/sys/class/leds/clevo::mail/brightness
> + - or -
> + echo timer >/sys/class/leds/clevo::mail/trigger
> + echo 1000 >/sys/class/leds/clevo::mail/delay_on
> + echo 1000 >/sys/class/leds/clevo::mail/delay_off

The Kconfig option shouldn't need to go into this much detail. If we
need this much detail, we should probably enhance the LED documentation
in Documentation/ instead.

> diff -uprN linux-2.6.23.orig/drivers/leds/leds-clevo-mail.c linux-2.6.23/drivers/leds/leds-clevo-mail.c
> --- linux-2.6.23.orig/drivers/leds/leds-clevo-mail.c 1970-01-01 01:00:00.000000000 +0100
> +++ linux-2.6.23/drivers/leds/leds-clevo-mail.c 2007-10-21 10:49:32.000000000 +0200
> @@ -0,0 +1,210 @@
> +
> +#include <linux/module.h>
> +
> +#include <linux/platform_device.h>
> +#include <linux/err.h>
> +#include <linux/leds.h>
> +
> +#include <linux/io.h>
> +#include <linux/dmi.h>
> +
> +#include <linux/i8042.h>
> +
> +#define HANDLED 0

Probably easiest to turn the two references to this into "return 0"

Other than that the driver looks ok and I'm happy to add a version with
the above minor tweaks to the LED tree.

Cheers,

Richard

2007-10-28 10:26:17

by Németh Márton

[permalink] [raw]
Subject: Re: [PATCH 3/3] leds-clevo-mail: driver for Clevo mail LED

Richard Purdie wrote:
> On Sun, 2007-10-21 at 14:55 +0200, N?meth M?rton wrote:
>> diff -uprN linux-2.6.23.orig/drivers/leds/Kconfig linux-2.6.23/drivers/leds/Kconfig
>> --- linux-2.6.23.orig/drivers/leds/Kconfig 2007-10-09 22:31:38.000000000 +0200
>> +++ linux-2.6.23/drivers/leds/Kconfig 2007-10-21 12:04:50.000000000 +0200
>> @@ -101,6 +101,39 @@ config LEDS_GPIO
>> outputs. To be useful the particular board must have LEDs
>> and they must be connected to the GPIO lines.
>>
>> +config LEDS_CLEVO_MAIL
>> + tristate "Mail LED on Clevo notebook (EXPERIMENTAL)"
>> + depends on LEDS_CLASS && X86 && SERIO_I8042 && DMI && EXPERIMENTAL
>> + help
>> + This driver makes the mail LED accessible from userspace
>> + programs through the leds subsystem. This LED have three
>> + known mode: off, blink at 0.5Hz and blink at 1Hz.
>> +
>> + The driver supports two kinds of interface: using ledtrig-timer
>> + or through /sys/class/leds/clevo::mail/brightness. As this LED
>> + cannot change it's brightness it blinks instead. The brightness
>> + value 0 means off, 1..127 means blink at 0.5Hz and 128..255 means
>> + blink at 1Hz.
>
> Hmm, there really is no way to just turn the LED on? :(

I looked up the printed manual (which can be also found at
ftp://ftp.clevo.com.tw/USRMANUAL/D4x0J/D4x0J_CUG.zip ), page 9 contains
the following information:

LED Power & Communication Indicators:

Icon | Color | Description
-----+------------------+-----------------------------------------------
Mail | Blinking Green & | New mail has arrived
LED | Orange |
+------------------+-----------------------------------------------
| Fast Blinking | New mail has arrived from users defined
| Green & Orange | in the Special Group in the Auto Mail Checker
+------------------+-----------------------------------------------
| Green | The (optional) Wireless LAN module is On
+------------------+-----------------------------------------------
| Orange | The (optional) Bluetooth module is On
+------------------+-----------------------------------------------
| Half Orange/ | Both the (optional) Wireless LAN and Bluetooth
| Half Green | modules are On (see sidebar)
-----+------------------+-----------------------------------------------

Unfortunately I do not have these optional modules so I never saw the LED
just on without blinking. I don't know if there is any hardware limitation
turning on the LED without the optional modules.

I will send a new patch collection which addresses the other mentioned topics.

M?rton N?meth

2007-10-31 20:24:59

by Richard Purdie

[permalink] [raw]
Subject: Re: [PATCH 3/3] leds-clevo-mail: driver for Clevo mail LED

On Sun, 2007-10-28 at 12:22 +0100, Németh Márton wrote:
> Richard Purdie wrote:
> > Hmm, there really is no way to just turn the LED on? :(
>
> Unfortunately I do not have these optional modules so I never saw the LED
> just on without blinking. I don't know if there is any hardware limitation
> turning on the LED without the optional modules.

Ok, if we don't know how to do it or even if its possible, so be it. If
you ever do find out please do update the driver.

> I will send a new patch collection which addresses the other mentioned topics.

Thanks, I've applied the patches although I've rewritten the second one
to update the drivers with LED names that don't match the naming
convention. They'll appear in the led git tree and hence -mm.

Thanks,

Richard