
This is "kiss", the "Keyboard Informative Status Signals" module,
used to show how misc drivers interact with the rest of the kernel.

	COMPILING
	---------

Just try "make". However, it might fail with an error like:

  kiss.c:31: linux/../../drivers/char/kbd_kern.h: No such file or directory

If this is the case, the fix is explained here below. If the compilation
is clean you can just jump to the next section: "loading".

The kiss module must refer to internal data structures of the keyboard
driver, and for this reason it must include the header "kbd_kern.h",
which lives in "drivers/char" in the kernel sources. If you don't have
the source files installed in your system, than compilation fails.
Installing the kernel source will fix the problem.

The unusually strange "#include" directive relies on the notion that
"/usr/include/linux" should be a symlink to
"/usr/src/linux/include/linux", or the equivalent directory in your
kernel sources. Since the compiler looks for "<>"-type includes
starting from /usr/include, the "linux/../.." pathname will lead from
/usr/include to the root directory of your kernel sources.

If you are used to include version-specific linux headers by
specifying "-I/you/directory/tree/linux-version/include" to the
compiler the "linux/../.." pathname will continue to work. Actually,
by uncommenting and editing line 2 of the provided Makefile you can
include headers from your preferred kernel version.

Not that production-quality code shouldn't rely on internal header
files, but this is just a silly sample module.


	LOADING
	-------

The kernel doesn't export led access to client modules. This
means that the normal "insmod" type of linking is not enough to do
what I promised to. The module needs to access other global kernel
symbols in addition to the ones exported to modules. To access these
symbols you need a system map (the one that is found in
/usr/src/linux/System.map after a successfull kernel compilation).

To load the module and create /dev/kiss, run "./kiss_load" after
specifying a MAPFILE variable. For example, my map lives in
/zImage.2034.map:

bash:
	MAPFILE=/zImage.2034.map ./kiss_load
csh:
	setenv MAPFILE /zImage.2034.map; ./kiss_load

After that, you can read the status of keyboard leds from /dev/kiss
and write to the node to change the led status. The driver affects the
current virtual console.

Note that specifying the wrong map file will result in unpleasant
segmentation faults. Usually the map file for a freshly installed
system is available with names similar to /boot/vmlinuz.map or
/boot/System.map.


	UNLOADING
	---------

That's easy: ./kiss_unload


	READING
	-------

Reading the driver returns a sequence of bytes, each of them
representing a snapshot of the led status. The status is returned as a
digit, '0' through '7' inclusive. I chose ASCII instead of binary to
allow issuing "cat /dev/kiss" and see meaningul stuff.

The weigth of the three leds is:

  Scroll Lock:  1
  Num Lock:     2
  Caps Lock:    4


	WRITING
	-------

Writing to the device changes the status of keyboard leds (for the
current virtual console). Each byte is a command, and unrecognized
bytes are just ignored.

The driver understands the following commands

	n:    turn off num-lock
	N:    turn on num-lock
	s:    turn off scroll-lock
	S:    turn on scroll-lock
	c:    turn off caps-lock
	C:    turn on caps-lock
	0:    all off
	7:    all on
	1..6: show numeric value as binary
	-:    turn back to normal display (caps-lock etc)

	t:    delay one tenth of a second
	T:    delay one second
	f:    flash once
	F:    flash three times 

The following sh script, therefore, simulates a heartbeat on the caps
lock led:

	while true; do echo "CtctCtcttttttt" > /dev/kiss; done

Note that the write() implementation is a blocking one: the driver
ignores the O_NONBLOCK option. This means that there's no
bufferization at hardware level, and the hearthbeat shown above
will begin to hic when the system is heavily loaded (there will
be delays between successive beats, even though the beat
itself

