parent
9e62a7668c
commit
577f873daf
@ -1,366 +0,0 @@ |
||||
/*
|
||||
* LED Morse Trigger |
||||
* |
||||
* Copyright (C) 2007 Gabor Juhos <juhosg at openwrt.org> |
||||
* |
||||
* This file was based on: drivers/led/ledtrig-timer.c |
||||
* Copyright 2005-2006 Openedhand Ltd. |
||||
* Author: Richard Purdie <rpurdie@openedhand.com> |
||||
* |
||||
* also based on the patch '[PATCH] 2.5.59 morse code panics' posted |
||||
* in the LKML by Tomas Szepe at Thu, 30 Jan 2003 |
||||
* Copyright (C) 2002 Andrew Rodland <arodland@noln.com> |
||||
* Copyright (C) 2003 Tomas Szepe <szepe@pinerecords.com> |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify it |
||||
* under the terms of the GNU General Public License version 2 as published |
||||
* by the Free Software Foundation. |
||||
* |
||||
*/ |
||||
|
||||
#include <linux/kernel.h> |
||||
#include <linux/version.h> |
||||
#include <linux/module.h> |
||||
#include <linux/jiffies.h> |
||||
#include <linux/init.h> |
||||
#include <linux/list.h> |
||||
#include <linux/spinlock.h> |
||||
#include <linux/device.h> |
||||
#include <linux/sysdev.h> |
||||
#include <linux/timer.h> |
||||
#include <linux/ctype.h> |
||||
#include <linux/leds.h> |
||||
#include <linux/slab.h> |
||||
|
||||
#include "leds.h" |
||||
|
||||
#define MORSE_DELAY_BASE (HZ/2) |
||||
|
||||
#define MORSE_STATE_BLINK_START 0 |
||||
#define MORSE_STATE_BLINK_STOP 1 |
||||
|
||||
#define MORSE_DIT_LEN 1 |
||||
#define MORSE_DAH_LEN 3 |
||||
#define MORSE_SPACE_LEN 7 |
||||
|
||||
struct morse_trig_data { |
||||
unsigned long delay; |
||||
char *msg; |
||||
|
||||
unsigned char morse; |
||||
unsigned char state; |
||||
char *msgpos; |
||||
struct timer_list timer; |
||||
}; |
||||
|
||||
const unsigned char morsetable[] = { |
||||
0122, 0, 0310, 0, 0, 0163, /* "#$%&' */ |
||||
055, 0155, 0, 0, 0163, 0141, 0152, 0051, /* ()*+,-./ */ |
||||
077, 076, 074, 070, 060, 040, 041, 043, 047, 057, /* 0-9 */ |
||||
0107, 0125, 0, 0061, 0, 0114, 0, /* :;<=>?@ */ |
||||
006, 021, 025, 011, 002, 024, 013, 020, 004, /* A-I */ |
||||
036, 015, 022, 007, 005, 017, 026, 033, 012, /* J-R */ |
||||
010, 003, 014, 030, 016, 031, 035, 023, /* S-Z */ |
||||
0, 0, 0, 0, 0154 /* [\]^_ */ |
||||
}; |
||||
|
||||
static inline unsigned char tomorse(char c) { |
||||
if (c >= 'a' && c <= 'z') |
||||
c = c - 'a' + 'A'; |
||||
if (c >= '"' && c <= '_') { |
||||
return morsetable[c - '"']; |
||||
} else |
||||
return 0; |
||||
} |
||||
|
||||
static inline unsigned long dit_len(struct morse_trig_data *morse_data) |
||||
{ |
||||
return MORSE_DIT_LEN*morse_data->delay; |
||||
} |
||||
|
||||
static inline unsigned long dah_len(struct morse_trig_data *morse_data) |
||||
{ |
||||
return MORSE_DAH_LEN*morse_data->delay; |
||||
} |
||||
|
||||
static inline unsigned long space_len(struct morse_trig_data *morse_data) |
||||
{ |
||||
return MORSE_SPACE_LEN*morse_data->delay; |
||||
} |
||||
|
||||
static void morse_timer_function(unsigned long data) |
||||
{ |
||||
struct led_classdev *led_cdev = (struct led_classdev *)data; |
||||
struct morse_trig_data *morse_data = led_cdev->trigger_data; |
||||
unsigned long brightness = LED_OFF; |
||||
unsigned long delay = 0; |
||||
|
||||
if (!morse_data->msg) |
||||
goto set_led; |
||||
|
||||
switch (morse_data->state) { |
||||
case MORSE_STATE_BLINK_START: |
||||
/* Starting a new blink. We have a valid code in morse. */ |
||||
delay = (morse_data->morse & 001) ? dah_len(morse_data): |
||||
dit_len(morse_data); |
||||
brightness = LED_FULL; |
||||
morse_data->state = MORSE_STATE_BLINK_STOP; |
||||
morse_data->morse >>= 1; |
||||
break; |
||||
case MORSE_STATE_BLINK_STOP: |
||||
/* Coming off of a blink. */ |
||||
morse_data->state = MORSE_STATE_BLINK_START; |
||||
|
||||
if (morse_data->morse > 1) { |
||||
/* Not done yet, just a one-dit pause. */ |
||||
delay = dit_len(morse_data); |
||||
break; |
||||
} |
||||
|
||||
/* Get a new char, figure out how much space. */ |
||||
/* First time through */ |
||||
if (!morse_data->msgpos) |
||||
morse_data->msgpos = (char *)morse_data->msg; |
||||
|
||||
if (!*morse_data->msgpos) { |
||||
/* Repeating */ |
||||
morse_data->msgpos = (char *)morse_data->msg; |
||||
delay = space_len(morse_data); |
||||
} else { |
||||
/* Inter-letter space */ |
||||
delay = dah_len(morse_data); |
||||
} |
||||
|
||||
if (!(morse_data->morse = tomorse(*morse_data->msgpos))) { |
||||
delay = space_len(morse_data); |
||||
/* And get us back here */ |
||||
morse_data->state = MORSE_STATE_BLINK_STOP; |
||||
} |
||||
morse_data->msgpos++; |
||||
break; |
||||
} |
||||
|
||||
mod_timer(&morse_data->timer, jiffies + msecs_to_jiffies(delay)); |
||||
|
||||
set_led: |
||||
led_set_brightness(led_cdev, brightness); |
||||
} |
||||
|
||||
static ssize_t _morse_delay_show(struct led_classdev *led_cdev, char *buf) |
||||
{ |
||||
struct morse_trig_data *morse_data = led_cdev->trigger_data; |
||||
|
||||
sprintf(buf, "%lu\n", morse_data->delay); |
||||
|
||||
return strlen(buf) + 1; |
||||
} |
||||
|
||||
static ssize_t _morse_delay_store(struct led_classdev *led_cdev, |
||||
const char *buf, size_t size) |
||||
{ |
||||
struct morse_trig_data *morse_data = led_cdev->trigger_data; |
||||
char *after; |
||||
unsigned long state = simple_strtoul(buf, &after, 10); |
||||
size_t count = after - buf; |
||||
int ret = -EINVAL; |
||||
|
||||
if (*after && isspace(*after)) |
||||
count++; |
||||
|
||||
if (count == size) { |
||||
morse_data->delay = state; |
||||
mod_timer(&morse_data->timer, jiffies + 1); |
||||
ret = count; |
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
static ssize_t _morse_msg_show(struct led_classdev *led_cdev, char *buf) |
||||
{ |
||||
struct morse_trig_data *morse_data = led_cdev->trigger_data; |
||||
|
||||
if (!morse_data->msg) |
||||
sprintf(buf, "<none>\n"); |
||||
else |
||||
sprintf(buf, "%s\n", morse_data->msg); |
||||
|
||||
return strlen(buf) + 1; |
||||
} |
||||
|
||||
static ssize_t _morse_msg_store(struct led_classdev *led_cdev, |
||||
const char *buf, size_t size) |
||||
{ |
||||
struct morse_trig_data *morse_data = led_cdev->trigger_data; |
||||
char *m; |
||||
|
||||
m = kmalloc(size, GFP_KERNEL); |
||||
if (!m) |
||||
return -ENOMEM; |
||||
|
||||
memcpy(m,buf,size); |
||||
m[size]='\0'; |
||||
|
||||
if (morse_data->msg) |
||||
kfree(morse_data->msg); |
||||
|
||||
morse_data->msg = m; |
||||
morse_data->msgpos = NULL; |
||||
morse_data->state = MORSE_STATE_BLINK_STOP; |
||||
|
||||
mod_timer(&morse_data->timer, jiffies + 1); |
||||
|
||||
return size; |
||||
} |
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) |
||||
static ssize_t morse_delay_show(struct device *dev, |
||||
struct device_attribute *attr, char *buf) |
||||
{ |
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev); |
||||
|
||||
return _morse_delay_show(led_cdev, buf); |
||||
} |
||||
|
||||
static ssize_t morse_delay_store(struct device *dev, |
||||
struct device_attribute *attr, const char *buf, size_t size) |
||||
{ |
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev); |
||||
|
||||
return _morse_delay_store(led_cdev, buf, size); |
||||
} |
||||
|
||||
static ssize_t morse_msg_show(struct device *dev, |
||||
struct device_attribute *attr, char *buf) |
||||
{ |
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev); |
||||
|
||||
return _morse_msg_show(led_cdev, buf); |
||||
} |
||||
|
||||
static ssize_t morse_msg_store(struct device *dev, |
||||
struct device_attribute *attr, const char *buf, size_t size) |
||||
{ |
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev); |
||||
|
||||
return _morse_msg_store(led_cdev, buf, size); |
||||
} |
||||
|
||||
static DEVICE_ATTR(delay, 0644, morse_delay_show, morse_delay_store); |
||||
static DEVICE_ATTR(message, 0644, morse_msg_show, morse_msg_store); |
||||
|
||||
#define led_device_create_file(leddev, attr) \ |
||||
device_create_file(leddev->dev, &dev_attr_ ## attr) |
||||
#define led_device_remove_file(leddev, attr) \ |
||||
device_remove_file(leddev->dev, &dev_attr_ ## attr) |
||||
|
||||
#else |
||||
static ssize_t morse_delay_show(struct class_device *dev, char *buf) |
||||
{ |
||||
struct led_classdev *led_cdev = class_get_devdata(dev); |
||||
|
||||
return _morse_delay_show(led_cdev, buf); |
||||
} |
||||
|
||||
static ssize_t morse_delay_store(struct class_device *dev, const char *buf, |
||||
size_t size) |
||||
{ |
||||
struct led_classdev *led_cdev = class_get_devdata(dev); |
||||
|
||||
return _morse_delay_store(led_cdev, buf, size); |
||||
} |
||||
|
||||
static ssize_t morse_msg_show(struct class_device *dev, char *buf) |
||||
{ |
||||
struct led_classdev *led_cdev = class_get_devdata(dev); |
||||
|
||||
return _morse_msg_show(led_cdev, buf); |
||||
} |
||||
|
||||
static ssize_t morse_msg_store(struct class_device *dev, const char *buf, |
||||
size_t size) |
||||
{ |
||||
struct led_classdev *led_cdev = class_get_devdata(dev); |
||||
|
||||
return _morse_msg_store(led_cdev, buf, size); |
||||
} |
||||
|
||||
static CLASS_DEVICE_ATTR(delay, 0644, morse_delay_show, morse_delay_store); |
||||
static CLASS_DEVICE_ATTR(message, 0644, morse_msg_show, morse_msg_store); |
||||
|
||||
#define led_device_create_file(leddev, attr) \ |
||||
class_device_create_file(leddev->class_dev, &class_device_attr_ ## attr) |
||||
#define led_device_remove_file(leddev, attr) \ |
||||
class_device_remove_file(leddev->class_dev, &class_device_attr_ ## attr) |
||||
|
||||
#endif |
||||
|
||||
static void morse_trig_activate(struct led_classdev *led_cdev) |
||||
{ |
||||
struct morse_trig_data *morse_data; |
||||
int rc; |
||||
|
||||
morse_data = kzalloc(sizeof(*morse_data), GFP_KERNEL); |
||||
if (!morse_data) |
||||
return; |
||||
|
||||
morse_data->delay = MORSE_DELAY_BASE; |
||||
init_timer(&morse_data->timer); |
||||
morse_data->timer.function = morse_timer_function; |
||||
morse_data->timer.data = (unsigned long)led_cdev; |
||||
|
||||
rc = led_device_create_file(led_cdev, delay); |
||||
if (rc) goto err; |
||||
|
||||
rc = led_device_create_file(led_cdev, message); |
||||
if (rc) goto err_delay; |
||||
|
||||
led_cdev->trigger_data = morse_data; |
||||
|
||||
return; |
||||
|
||||
err_delay: |
||||
led_device_remove_file(led_cdev, delay); |
||||
err: |
||||
kfree(morse_data); |
||||
} |
||||
|
||||
static void morse_trig_deactivate(struct led_classdev *led_cdev) |
||||
{ |
||||
struct morse_trig_data *morse_data = led_cdev->trigger_data; |
||||
|
||||
if (!morse_data) |
||||
return; |
||||
|
||||
led_device_remove_file(led_cdev, message); |
||||
led_device_remove_file(led_cdev, delay); |
||||
|
||||
del_timer_sync(&morse_data->timer); |
||||
if (morse_data->msg) |
||||
kfree(morse_data->msg); |
||||
|
||||
kfree(morse_data); |
||||
} |
||||
|
||||
static struct led_trigger morse_led_trigger = { |
||||
.name = "morse", |
||||
.activate = morse_trig_activate, |
||||
.deactivate = morse_trig_deactivate, |
||||
}; |
||||
|
||||
static int __init morse_trig_init(void) |
||||
{ |
||||
return led_trigger_register(&morse_led_trigger); |
||||
} |
||||
|
||||
static void __exit morse_trig_exit(void) |
||||
{ |
||||
led_trigger_unregister(&morse_led_trigger); |
||||
} |
||||
|
||||
module_init(morse_trig_init); |
||||
module_exit(morse_trig_exit); |
||||
|
||||
MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>"); |
||||
MODULE_DESCRIPTION("Morse LED trigger"); |
||||
MODULE_LICENSE("GPL"); |
@ -1,28 +0,0 @@ |
||||
--- a/drivers/leds/trigger/Kconfig
|
||||
+++ b/drivers/leds/trigger/Kconfig
|
||||
@@ -108,4 +108,8 @@ config LEDS_TRIGGER_CAMERA
|
||||
This enables direct flash/torch on/off by the driver, kernel space.
|
||||
If unsure, say Y.
|
||||
|
||||
+config LEDS_TRIGGER_MORSE
|
||||
+ tristate "LED Morse Trigger"
|
||||
+ depends on LEDS_TRIGGERS
|
||||
+
|
||||
endif # LEDS_TRIGGERS
|
||||
--- a/drivers/leds/Makefile
|
||||
+++ b/drivers/leds/Makefile
|
||||
@@ -62,3 +62,4 @@ obj-$(CONFIG_LEDS_DAC124S085) += leds-d
|
||||
|
||||
# LED Triggers
|
||||
obj-$(CONFIG_LEDS_TRIGGERS) += trigger/
|
||||
+obj-$(CONFIG_LEDS_TRIGGER_MORSE) += ledtrig-morse.o
|
||||
--- a/drivers/leds/ledtrig-morse.c
|
||||
+++ b/drivers/leds/ledtrig-morse.c
|
||||
@@ -26,7 +26,6 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/device.h>
|
||||
-#include <linux/sysdev.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/leds.h>
|
@ -1,28 +0,0 @@ |
||||
--- a/drivers/leds/trigger/Kconfig
|
||||
+++ b/drivers/leds/trigger/Kconfig
|
||||
@@ -108,4 +108,8 @@ config LEDS_TRIGGER_CAMERA
|
||||
This enables direct flash/torch on/off by the driver, kernel space.
|
||||
If unsure, say Y.
|
||||
|
||||
+config LEDS_TRIGGER_MORSE
|
||||
+ tristate "LED Morse Trigger"
|
||||
+ depends on LEDS_TRIGGERS
|
||||
+
|
||||
endif # LEDS_TRIGGERS
|
||||
--- a/drivers/leds/Makefile
|
||||
+++ b/drivers/leds/Makefile
|
||||
@@ -65,3 +65,4 @@ obj-$(CONFIG_LEDS_DAC124S085) += leds-d
|
||||
|
||||
# LED Triggers
|
||||
obj-$(CONFIG_LEDS_TRIGGERS) += trigger/
|
||||
+obj-$(CONFIG_LEDS_TRIGGER_MORSE) += ledtrig-morse.o
|
||||
--- a/drivers/leds/ledtrig-morse.c
|
||||
+++ b/drivers/leds/ledtrig-morse.c
|
||||
@@ -26,7 +26,6 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/device.h>
|
||||
-#include <linux/sysdev.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/leds.h>
|
@ -1,28 +0,0 @@ |
||||
--- a/drivers/leds/trigger/Kconfig
|
||||
+++ b/drivers/leds/trigger/Kconfig
|
||||
@@ -108,4 +108,8 @@ config LEDS_TRIGGER_CAMERA
|
||||
This enables direct flash/torch on/off by the driver, kernel space.
|
||||
If unsure, say Y.
|
||||
|
||||
+config LEDS_TRIGGER_MORSE
|
||||
+ tristate "LED Morse Trigger"
|
||||
+ depends on LEDS_TRIGGERS
|
||||
+
|
||||
endif # LEDS_TRIGGERS
|
||||
--- a/drivers/leds/Makefile
|
||||
+++ b/drivers/leds/Makefile
|
||||
@@ -72,3 +72,4 @@ obj-$(CONFIG_LEDS_DAC124S085) += leds-d
|
||||
|
||||
# LED Triggers
|
||||
obj-$(CONFIG_LEDS_TRIGGERS) += trigger/
|
||||
+obj-$(CONFIG_LEDS_TRIGGER_MORSE) += ledtrig-morse.o
|
||||
--- a/drivers/leds/ledtrig-morse.c
|
||||
+++ b/drivers/leds/ledtrig-morse.c
|
||||
@@ -26,7 +26,6 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/device.h>
|
||||
-#include <linux/sysdev.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/leds.h>
|
Loading…
Reference in new issue