2003-02-18 13:41:40

by Tomas Szepe

[permalink] [raw]
Subject: [PATCH] morse code panics for 2.5.62

Hi Linus, Alan,

Morse code panics for 2.5.62:

o Completely arch-independent.
o No longer touches atkbd (as suggested by Vojtech Pavlik).
o With minimal changes to existing code.
o Introducing morse code ops -- a good hack value (MOST IMPORTANT!!).
o Useful to people who spend most of their time in X.

Please review,
--
Tomas Szepe <[email protected]>


diff -urN a/drivers/char/keyboard.c b/drivers/char/keyboard.c
--- a/drivers/char/keyboard.c 2003-02-15 10:20:06.000000000 +0100
+++ b/drivers/char/keyboard.c 2003-02-15 10:21:35.000000000 +0100
@@ -260,6 +260,27 @@
}

/*
+ * Turn all possible leds on or off.
+ */
+void kd_turn_all_leds(int on_or_off)
+{
+ struct list_head *node;
+ on_or_off = on_or_off ? 1 : 0;
+
+ list_for_each(node, &kbd_handler.h_list) {
+ struct input_handle *handle = to_handle_h(node);
+ if (test_bit(EV_LED, handle->dev->evbit)) {
+ int led;
+ for (led = 0; led <= LED_MAX; led++) {
+ if (test_bit(led, handle->dev->ledbit))
+ input_event(handle->dev, EV_LED, led,
+ on_or_off);
+ }
+ }
+ }
+}
+
+/*
* Setting the keyboard rate.
*/
static inline unsigned int ms_to_jiffies(unsigned int ms) {
diff -urN a/include/linux/morseops.h b/include/linux/morseops.h
--- a/include/linux/morseops.h 1970-01-01 01:00:00.000000000 +0100
+++ b/include/linux/morseops.h 2003-02-15 10:21:35.000000000 +0100
@@ -0,0 +1,26 @@
+/* Yes, it's morse code ops indeed. */
+
+#ifndef _LINUX_MORSEOPS_H
+#define _LINUX_MORSEOPS_H
+
+#include <linux/config.h>
+
+#if defined(CONFIG_MORSE_PANICS)
+
+extern const unsigned char morsetable[]; /* in kernel/morse.c */
+void panic_morseblink(char *buf); /* in kernel/morse.c */
+
+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;
+}
+
+#else /* CONFIG_MORSE_PANICS */
+ #define panic_morseblink(buf)
+#endif /* CONFIG_MORSE_PANICS */
+
+#endif /* _LINUX_MORSEOPS_H */
diff -urN a/include/linux/vt_kern.h b/include/linux/vt_kern.h
--- a/include/linux/vt_kern.h 2002-12-16 07:01:55.000000000 +0100
+++ b/include/linux/vt_kern.h 2003-02-15 10:21:35.000000000 +0100
@@ -33,7 +33,10 @@
wait_queue_head_t paste_wait;
} *vt_cons[MAX_NR_CONSOLES];

+/* keyboard.c */
+
extern void kd_mksound(unsigned int hz, unsigned int ticks);
+extern void kd_turn_all_leds(int on_or_off);
extern int kbd_rate(struct kbd_repeat *rep);

/* console.c */
diff -urN a/init/Kconfig b/init/Kconfig
--- a/init/Kconfig 2003-02-11 01:09:48.000000000 +0100
+++ b/init/Kconfig 2003-02-15 10:21:35.000000000 +0100
@@ -98,6 +98,21 @@
13 => 8 KB
12 => 4 KB

+config MORSE_PANICS
+ bool "Morse code panics"
+ depends on VT
+ help
+ When enabled, this code will make a panicking kernel cry for
+ help in morse code, signalling on the leds of a possibly attached
+ keyboard and/or a bleeper. You can enable/disable your morse
+ output devices of choice using the "panicmorse" kernel boot
+ parameter. Currently, "panicmorse=0" will disable the signalling
+ completely, "panicmorse=1" (the default) will only blink the leds,
+ "panicmorse=2" will only beep, and "panicmorse=3" will do both.
+
+ If unsure, say Y. This feature is very helpful to those who
+ spend most of their time in X.
+
endmenu


diff -urN a/kernel/Makefile b/kernel/Makefile
--- a/kernel/Makefile 2003-02-11 01:09:48.000000000 +0100
+++ b/kernel/Makefile 2003-02-15 10:21:35.000000000 +0100
@@ -18,6 +18,7 @@
obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o
obj-$(CONFIG_COMPAT) += compat.o
+obj-$(CONFIG_MORSE_PANICS) += morse.o

ifneq ($(CONFIG_IA64),y)
# According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
diff -urN a/kernel/morse.c b/kernel/morse.c
--- a/kernel/morse.c 1970-01-01 01:00:00.000000000 +0100
+++ b/kernel/morse.c 2003-02-15 10:21:35.000000000 +0100
@@ -0,0 +1,125 @@
+/*
+ * kernel/morse.c
+ *
+ * Copyright (C) 2002 Andrew Rodland <[email protected]>
+ * Copyright (C) 2003 Tomas Szepe <[email protected]>
+ *
+ * Tell the user who may be running in X and not see the console that
+ * we have panic'd. This is to distingush panics from "real lockups."
+ * Could in theory send the panic message as morse, but that is left
+ * as an exercise for the reader.
+ *
+ * And now it's done! LED and speaker morse code by Andrew Rodland
+ * <[email protected]>, with improvements based on suggestions from
+ * [email protected] and a host of others.
+ *
+ * Initial 2.5 morsepanics port and cleanup by
+ * Tomas Szepe <[email protected]>, January 2003.
+ */
+
+#include <linux/config.h>
+#include <linux/morseops.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/vt_kern.h>
+
+#define DITLEN (HZ / 5)
+#define DAHLEN (3 * DITLEN)
+#define SPACELEN (7 * DITLEN)
+#define FREQ 844
+
+static int morse_setting = 1;
+
+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 /* [\]^_ */
+};
+
+void panic_morseblink(char *buf)
+{
+ static unsigned long next_jiffie = 0;
+ static char * bufpos = 0;
+ static unsigned char morse = 0;
+ static char state = 1;
+
+ if (!morse_setting)
+ return;
+
+ if (!buf)
+ buf = "Uh oh, we lost the panic msg.";
+
+ /* Waiting for something? */
+ if (bufpos && time_after(next_jiffie, jiffies))
+ return;
+
+ if (state) { /* Coming off of a blink. */
+ if (morse_setting & 0x01)
+ kd_turn_all_leds(0);
+
+ state = 0;
+
+ if (morse > 1) {
+ /* Not done yet, just a one-dit pause. */
+ next_jiffie = jiffies + DITLEN;
+ } else {
+ /* Get a new char, figure out how much space. */
+
+ /* First time through */
+ if (!bufpos)
+ bufpos = (char *) buf;
+
+ if (!*bufpos) {
+ /* Repeating */
+ bufpos = (char *) buf;
+ next_jiffie = jiffies + SPACELEN;
+ } else {
+ /* Inter-letter space */
+ next_jiffie = jiffies + DAHLEN;
+ }
+
+ if (!(morse = tomorse(*bufpos))) {
+ next_jiffie = jiffies + SPACELEN;
+ state = 1; /* And get us back here */
+ }
+ bufpos++;
+ }
+ } else {
+ /* Starting a new blink. We have a valid code in morse. */
+ int len;
+
+ len = (morse & 001) ? DAHLEN : DITLEN;
+
+ if (morse_setting & 0x02)
+ kd_mksound(FREQ, len);
+
+ next_jiffie = jiffies + len;
+
+ if (morse_setting & 0x01)
+ kd_turn_all_leds(1);
+
+ state = 1;
+ morse >>= 1;
+ }
+}
+
+static int __init panicmorse_setup(char *str)
+{
+ int par;
+ if (get_option(&str, &par))
+ morse_setting = par;
+ return 1;
+}
+
+/* "panicmorse=0" disables the blinking as it caused problems with
+ * certain console switches.
+ *
+ * "panicmorse | 1" does the show using kbd leds.
+ * "panicmorse | 2" throws in bleeping via kd_mksound().
+ */
+__setup("panicmorse=", panicmorse_setup);
diff -urN a/kernel/panic.c b/kernel/panic.c
--- a/kernel/panic.c 2003-01-09 14:25:40.000000000 +0100
+++ b/kernel/panic.c 2003-02-15 10:21:35.000000000 +0100
@@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/sysrq.h>
#include <linux/interrupt.h>
+#include <linux/morseops.h>

asmlinkage void sys_sync(void); /* it's really int */

@@ -95,7 +96,8 @@
disabled_wait(caller);
#endif
local_irq_enable();
- for(;;) {
+ for (;;) {
+ panic_morseblink(buf);
CHECK_EMERGENCY_SYNC
}
}


2003-02-18 14:08:00

by Jan-Benedict Glaw

[permalink] [raw]
Subject: Re: [PATCH] morse code panics for 2.5.62

On Tue, 2003-02-18 14:50:38 +0100, Tomas Szepe <[email protected]>
wrote in message <[email protected]>:

This is the first time I really look at the code, so please forgive if I
talk about things where already a consens was given...

> diff -urN a/include/linux/morseops.h b/include/linux/morseops.h
> --- a/include/linux/morseops.h 1970-01-01 01:00:00.000000000 +0100
> +++ b/include/linux/morseops.h 2003-02-15 10:21:35.000000000 +0100
> @@ -0,0 +1,26 @@
> +/* Yes, it's morse code ops indeed. */
> +
> +#ifndef _LINUX_MORSEOPS_H
> +#define _LINUX_MORSEOPS_H
> +
> +#include <linux/config.h>
> +
> +#if defined(CONFIG_MORSE_PANICS)
> +
> +extern const unsigned char morsetable[]; /* in kernel/morse.c */
> +void panic_morseblink(char *buf); /* in kernel/morse.c */
> +
> +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;
> +}
> +
> +#else /* CONFIG_MORSE_PANICS */
> + #define panic_morseblink(buf)

I think this has to read:

+# define panic_morseblink(buf)

IIRC there's no leading whitespace allowed for the '#', but there may
follow some...


> +#endif /* CONFIG_MORSE_PANICS */
> +
> +#endif /* _LINUX_MORSEOPS_H */
> diff -urN a/include/linux/vt_kern.h b/include/linux/vt_kern.h
> --- a/include/linux/vt_kern.h 2002-12-16 07:01:55.000000000 +0100
> +++ b/include/linux/vt_kern.h 2003-02-15 10:21:35.000000000 +0100
> @@ -33,7 +33,10 @@
> wait_queue_head_t paste_wait;
> } *vt_cons[MAX_NR_CONSOLES];
>
> +/* keyboard.c */
> +
> extern void kd_mksound(unsigned int hz, unsigned int ticks);
> +extern void kd_turn_all_leds(int on_or_off);

Please, s/on_or_off/enlightened/ or something like that. That would keep
the semantics clear:-)

> extern int kbd_rate(struct kbd_repeat *rep);
>
> /* console.c */
> +#include <linux/jiffies.h>
> +#include <linux/vt_kern.h>
> +
> +#define DITLEN (HZ / 5)
> +#define DAHLEN (3 * DITLEN)
> +#define SPACELEN (7 * DITLEN)
> +#define FREQ 844
> +
> +static int morse_setting = 1;
> +
> +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 /* [\]^_ */
> +};

You're using a set bit for long and an unset bit for a short beep, don't
you? Storing these values in octal/as chars is quite low on memory
consumption, but I'd like to learn so I suggest:

#define NO 0 /* neither long nor short */
#define LB 1 /* long beep */
#define SB 0 /* short beep */
#define MORSE(letter, beep1, beep2, beep3, beep4, beep5, beep6, beep7) \
(beep1 << 6 | beep2 << 5 | beep3 << 4 | beep4 << 3 \
| beep5 << 2 | beep6 << 1 | beep7 << 0)

Then, do somethink like
const unsigned char morsetable[] = {
MORSE('A', NO, NO, NO, NO, LB, LB, SB),
...
};

(My values aren't right for sure, but this way, we all can easily learn
morse code:-)

MfG, JBG

--
Jan-Benedict Glaw [email protected] . +49-172-7608481
"Eine Freie Meinung in einem Freien Kopf | Gegen Zensur
fuer einen Freien Staat voll Freier B?rger" | im Internet!
Shell Script APT-Proxy: http://lug-owl.de/~jbglaw/software/ap2/


Attachments:
(No filename) (3.46 kB)
(No filename) (189.00 B)
Download all attachments

2003-02-18 15:53:05

by Andrew Rodland

[permalink] [raw]
Subject: Re: [PATCH] morse code panics for 2.5.62

<posted & mailed>

Jan-Benedict Glaw wrote:

> On Tue, 2003-02-18 14:50:38 +0100, Tomas Szepe <[email protected]>
> wrote in message <[email protected]>:
>
> This is the first time I really look at the code, so please forgive if I
> talk about things where already a consens was given...

>> +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 /* [\]^_ */
>> +};

>
> You're using a set bit for long and an unset bit for a short beep, don't
> you? Storing these values in octal/as chars is quite low on memory
> consumption, but I'd like to learn so I suggest:

It's slightly more complicated than that:
It's set bits for long, unset bits for short, and termination when the byte
equals 0x01 (in other words, there's an extra set bit to the left of what
we want). This lets us represent any variable-length morse of up to 7
dits/dahs with a byte, which is cool because nothing is more than 6, that
I've ever seen.

The use of macros is an OK hack though, it reminds me of the nethack source.
:)

The reason someone proposed this in the first place is because I had had

const unsigned char * morsetable [] = {
".-..-.", NULL, "...-..-"

and so on in the initial revision of my patch, which is quite readable, but
takes up a lot more space, and makes the code actually a bit messier too.

--Andrew

2003-02-18 17:02:51

by Jan-Benedict Glaw

[permalink] [raw]
Subject: Re: [PATCH] morse code panics for 2.5.62

On Tue, 2003-02-18 11:00:23 -0500, Andrew Rodland <[email protected]>
wrote in message <[email protected]>:
> Jan-Benedict Glaw wrote:
> > On Tue, 2003-02-18 14:50:38 +0100, Tomas Szepe <[email protected]>
> > wrote in message <[email protected]>:
> >
> > This is the first time I really look at the code, so please forgive if I
> > talk about things where already a consens was given...
>
> >> +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 /* [\]^_ */
> >> +};
>
> >
> > You're using a set bit for long and an unset bit for a short beep, don't
> > you? Storing these values in octal/as chars is quite low on memory
> > consumption, but I'd like to learn so I suggest:
>
> It's slightly more complicated than that:
> It's set bits for long, unset bits for short, and termination when the byte
> equals 0x01 (in other words, there's an extra set bit to the left of what
> we want). This lets us represent any variable-length morse of up to 7
> dits/dahs with a byte, which is cool because nothing is more than 6, that
> I've ever seen.

So you've got a leading I bit set. Morse alphabet has got 2, 3, 4, 5 or
6 dots/dashes, right? Then I vote for either having a macro like this:

#define MORSE(letter, len, b1, b2, b3, b4, b5, b6, b7) \
(1<<(len)| [all the shifting stuff here as of the last mail])

or let's have5 separate macros for all possible lengths (which are
possibly defined by using the above macro).

Really, I'm 100% for learning!

> The use of macros is an OK hack though, it reminds me of the nethack source.
> :)
>
> The reason someone proposed this in the first place is because I had had
>
> const unsigned char * morsetable [] = {
> ".-..-.", NULL, "...-..-"
>
> and so on in the initial revision of my patch, which is quite readable, but
> takes up a lot more space, and makes the code actually a bit messier too.

Oh, that's long, too...


What about

#define IS_DASH(letter, shift) \
((letter) == '-'? (1 << shift): (0 << shift))
MORSE(shift, b1, b2, b3, b4, b5, b6) \
(1 << (shift) | IS_DASH((b1), 5) | IS_DASH((b2), 4) \
| IS_DASH((b3), 3) | IS_DASH((b4), 2) \
| IS_DASH((b5), 1) | IS_DASH((b6), 0)
#define MORSE1(letter, b1) \
MORSE(1, '.', '.', '.', '.', '.', (b1)))
#define MORSE2(letter, b1, b2) \
MORSE(2, '.', '.', '.', '.', (b1), (b2)))
#define MORSE3(letter, b1, b2, b3) \
MORSE(3, '.', '.', '.', (b1), (b2), (b3))
#define MORSE4(letter, b1, b2, b3, b4) \
MORSE(4, '.', '.', (b1), (b1), (b3), (b4))
#define MORSE5(letter, b1, b2, b3, b4, b5) \
MORSE(5, '.', (b1), (b2), (b3), (b4), (b5))
#define MORSE6(letter, b1, b2, b3, b4, b5, b6) \
MORSE(6, (b1), (b2), (b3), (b4), (b5), (b6))

Then, you can have
const char morses[] = {
MORSE2('A', '.', '-'),
MORSE4('B', '-', '.', '.', '.'),
MORSE4('C', '-', '.', '-', '.'),
MORSE3('D', '-', '.', '.'),
MORSE1('E', '.'),
MORSE4('F', '.', '.', '-', '.')
...
};

That's going to take exactly the same memory in the compiled vmlinux
image, *and* it's really readable:-) Of course, gcc will optimize any
added "bloat" away...

MfG, JBG

--
Jan-Benedict Glaw [email protected] . +49-172-7608481
"Eine Freie Meinung in einem Freien Kopf | Gegen Zensur
fuer einen Freien Staat voll Freier B?rger" | im Internet!
Shell Script APT-Proxy: http://lug-owl.de/~jbglaw/software/ap2/


Attachments:
(No filename) (3.88 kB)
(No filename) (189.00 B)
Download all attachments

2003-02-18 22:39:54

by Tomas Szepe

[permalink] [raw]
Subject: Re: [PATCH] morse code panics for 2.5.62

> [[email protected]]
>
> Then, you can have
> const char morses[] = {
> MORSE2('A', '.', '-'),
> MORSE4('B', '-', '.', '.', '.'),
> MORSE4('C', '-', '.', '-', '.'),
> MORSE3('D', '-', '.', '.'),
> MORSE1('E', '.'),
> MORSE4('F', '.', '.', '-', '.')
> ...
> };
>
> That's going to take exactly the same memory in the compiled vmlinux
> image, *and* it's really readable:-) Of course, gcc will optimize any
> added "bloat" away...

Looks good to me, can you send an updated patch?

--
Tomas Szepe <[email protected]>

2003-02-19 08:57:43

by Jan-Benedict Glaw

[permalink] [raw]
Subject: Re: [PATCH] morse code panics for 2.5.62

On Tue, 2003-02-18 23:49:46 +0100, Tomas Szepe <[email protected]>
wrote in message <[email protected]>:
> > [[email protected]]
> >
> > Then, you can have
> > const char morses[] = {
> > MORSE2('A', '.', '-'),
> > MORSE4('B', '-', '.', '.', '.'),
> > MORSE4('C', '-', '.', '-', '.'),
> > MORSE3('D', '-', '.', '.'),
> > MORSE1('E', '.'),
> > MORSE4('F', '.', '.', '-', '.')
> > ...
> > };
> >
> > That's going to take exactly the same memory in the compiled vmlinux
> > image, *and* it's really readable:-) Of course, gcc will optimize any
> > added "bloat" away...
>
> Looks good to me, can you send an updated patch?

Okay, I'll first have to import your original patch:-) and have a real
look at it (how does it exactly store the data...). Then, I'll do an
undated patch. Please give me an hour ot two...

MfG, JBG

--
Jan-Benedict Glaw [email protected] . +49-172-7608481
"Eine Freie Meinung in einem Freien Kopf | Gegen Zensur
fuer einen Freien Staat voll Freier B?rger" | im Internet!
Shell Script APT-Proxy: http://lug-owl.de/~jbglaw/software/ap2/


Attachments:
(No filename) (1.10 kB)
(No filename) (189.00 B)
Download all attachments