programmable keyboard interceptor and hardware control system
The keyman64 is a programmable keyboard interceptor and hardware control system for computers equipped with a simple 64-key matrix keyboard.
It is installed between the keyboard and the computer, continually scanning the keyboard matrix and relaying the keyboard state to the computer using a crosspoint switch. To the computer, the crosspoint switch matrix looks just like a physical keyboard, while the keyman64 gains the ability to intercept keystrokes and control the matrix seen by the computer.
The keyman64 can be configured to intercept special key combinations and invoke arbitrary sequences of commands to alter the state of sixteen general purpose control lines provided on the board. These lines can be used to control additional hardware instead of using physical buttons or switches.
Additional features include the ability to send predefined keyboard macros or to redefine the keyboard layout. Commands can also be sent from a remote PC via USB, or send on simple serial wire interface, allowing remote control from either a PC or another microcontroller or similar device.
For some concrete examples of what the keyman64 can do, see the configuration examples.
Basic mode of operation
During normal operation, the device simply relays all keyboard events to the computer, except when a special key defined as the meta key is held down. As long as this key is held down, any additional key presses invoke the user-defined command sequences bound to the respective key. When the meta key is released again, the device continues to relay keyboard events to the computer.
If no special key has been pressed while the meta key was down, a press of the meta key itself is simulated on the matrix seen by the computer. This way the meta key is not lost, it can still be pressed as usual in order to type the associated character. The only difference is that the computer will notice the simulated key down and up events only after the physical key has been released.
This scheme works well if the meta key only needs to be pressed once, but not if the meta key is supposed to be held down for a longer period of time. But this can still be accomplished by using a key combination invoking the down command for the meta key itself, for example:
m: down ARROWLEFT
Assuming that the arrow-left key is used as the meta key, this binding
can be invoked by holding down arrow-left and pressing
virtual arrow-left key now appears held down to the computer as long
as the physical meta key is kept down. Once the physical meta key is
released, the device beings scanning and relaying the physical
keyboard state again, effectivly releasing the virtual meta key seen
by the computer.
The meta key defaults to the arrow-left key. To change it to a different key, use the meta command described below.
A simple commandline configuration and control utility is provided. Its main purpose is to convert a plain text configuration file into a binary format. The binary configuration file is flashed to the Atmegas EEPROM Memory. See Configuration for details.
In Addition, the utility allows remote control of the keyman64 via USB. Arbitrary commands can be send via USB and will be immediately executed on the keyman64.
The device is based on an Atmega1284p, a crosspoint switch IC and some discrete 74xx logic ICs. Supported crosspoint switches are the CD74HC22106 or the MT8808 in a DIP28 package. A USB socket is provided to allow easy configuration and firmware updates using a USB bootloader preinstalled on the Atmega. Plese see design documents in the source distribution and the relevant sections in this document for further details.
In theory, the device should work with any computer using a passive 8x8 matrix keyboard. However, the layout of the connectors and the keynames follow those of the C64. Also the type command will use key combinations specific to the C64 to type the ASCII characters given as the argument. If you need software support for a different homecomputer, please feel free to post a feature request on the github issue tracker, preferrably providing the required information.
- Building the hardware
- Installing the bootloader
- Installing the firmware
- Configuring USB devices on the PC
- Installing the configuration and control utility
- Commands for configuration and maintenance
- Commands for modifying control lines
- Commands for controlling the keyboard matrix
- Commands for controlling execution
- Configuation and control utility
- Configuration examples
- Serial interface
Latest stable is keyman64-1.1.tar.gz.
All releases can be found under /download/keyman64
Latest developments are available via github:
git clone https://github.com/hbekel/keyman64
- keyman64-firmware-1.1.hex (firmware for the Atmega1284p)
- keyman64-1.1.msi (configuration utility, Windows 32-bit installer package)
Building the hardware
Watch out for the polarity of the tantalum capacitors C3 and C4. The positive lead is usually denoted on the capacitor with a small plus sign. The location of the positive lead is denoted on the board’s silk screen for both capacitors. In case of C4, the positive lead is indeed connected to ground as this capacitor stabilizes the negative voltage provided by the ICL7660.
+5V must be supplied to the center pin of J1. You can either supply +5V from the computers main board directly to this pin, or use a jumper bridge to supply power from pin 4 of P1 (the mainboard keyboard socket) or from the USB socket. To supply power from the mainboard socket, bridge the left and center pin of J1. To supply power from USB, bridge the center and right pin of J1.
Supplying power from the USB socket is only recommended for standalone operation of the keyman64, i.e. when P1 it is not connected to the io ports of a computer and none of the external devices connected to the keyman64 are powered from a different source. In general, all devices involved (the computer, the keyman64 and the devices controlled by it) must be powered from the same source. For example, if the keyman64 was configured to source power over USB and the computer is powered on without the USB cable being connected, the keyman64 might still sink current over the ESD-protection diodes of the Atmels io ports from the io ports of the computer or the external devices, which might cause severe damage to any of the io ports involved.
The pin layouts of P1 and P2 follow the layout of the C64 keyboard connector. The RESTORE line is simply passed through on the board.
List of parts
|R1||Precision Resistor||1k5||6.5mm, ∅ 2.5mm|
|R2||Precision Resistor||68||6.5mm, ∅ 2.5mm|
|R3||Precision Resistor||68||6.5mm, ∅ 2.5mm|
|P3||USB Mini-B Socket||-||Through-Hole|
|SW1||Push Button||-||6x6mm print|
|SW2||Push Button||-||6x6mm print|
|U1||74HC22106 or MT8808||-||DIP28|
Placement on board
Installing the bootloader
If you have no means of programming the Atmega via ISP then you can send it to me and I will prepare it for you. Just drop me a line at firstname.lastname@example.org.
The Atmega1284p must contain the USBaspLoader, which must be uploaded to the Atmega via ISP prior to installing it on the board.
There is a preconfigured version of the bootloader available from my github account:
$ git clone https://github.com/hbekel/keyman64-bootloader $ cd keyman64-bootloader
Now edit the
Makefile.inc and adjust the
PROGRAMMER settings to
according to your setup. Then issue
$ make flash fuse
The Atmega can now be installed on the device. When entering the bootloader, it identifies itself to the host like this:
16c0:05dc Van Ooijen Technische Informatica shared ID for use with libusb
It can be accessed using
avrdude -p m1284p -c usbasp <commands...>
Note that you may need to configure the USB devices on your system beforehand.
Entering the bootloader
To manually enter the bootloader, hold down the BOOT Button and press the RESET button, then release the BOOT button again.
Once the device is installed you can configure a key combination using the boot command. For example, by using
you can enter the bootloader simply by pressing
You can also just send the
boot command via USB from the PC:
$ keyman64 boot
Installing the firmware
Once the Atmega is equipped with a USB bootloader the firmware can be installed with the following command:
$ avrdude -p m1284p -c usbasp -U flash:w:keyman64-firmware-1.0.hex
If you have build the firmware from source you can use the
target of the toplevel Makefile as well.
Configuring USB devices on the PC
The keyman64 implements two separate USB devices, a remote control device and a bootloader device.
During normal operation, the remote control device will be active and accessible from the PC using the configuration and control utility. This device will identify itself to the host using the following properties:
While in bootloader mode, the bootloader device will be accessible from the PC. This device will identify itself to the host using the following properties:
|Vendor||Van Ooijen Technische Informatica shared ID for use with libusb|
On Linux, the required udev rules are installed alongside the configuration and control utility. After installation, issue
# udevadm control --reload-rules
When in bootloader mode, the bootloader device will be symlinked to
/dev/usbasp. During normal operation, the keyman64 control device
will be symlinked to
/dev/keyman64. These symlinks are created with
0666, allowing access for any user.
Once you connect one of the usb devices for the first time, Windows will insist on trying to download and install a driver for these devices. Since both devices are general purpose USB devices, this is futile, since there simply are no drivers for windows to install. You must abort the windows driver installation dialog to prevent windows from permanently marking the device as unusable due to its perceived lack of “proper” drivers.
Instead, use the Zadig tool to generate and install minimal drivers that simply associate the devices with the subsystems required for general purpose access.
Run Zadig, connect the usb cable to the keyman64 and power up the
device. Zadig should now detect the
Keyman64 device. Install the
WinUSB driver for this device.
Now enter the bootloader. The Zadig tool
should now detect the
USBasp device. For use with
the libusb-win32 driver for this device. Also make sure that the
libusb0.dll is present on your system (it should come with
avrdude). If not, follow the link for libusb-win32 shown in the “More
information” section of the Zadig window and install libusb-win32 on
Installing the configuration and control utility
For the windows version, use the binary installer
package. This will also install the required
libusb-1.0.dll. The installation directory will be added to your
PATH environment variable.
Linux & MacOSX
libusb-1.0 and corresponding development packages (if any) need to
be installed on your system.
Extract the tarball, change to the source directory and type
make install to install the
keyman64 binary into
PREFIX variable can be used to install with a
different prefix, e.g. use
make PREFIX=/usr install to install into
/usr/bin instead. The
DESTDIR variable can be used for a staged
On linux, the udev rules required for the USB devices will be
/etc/udev/rules.d as well. As root, run
# udevadm control --reload-rules
If you’re using cygwin you can build a windows binary in the same way
as under Linux or MacOSX. The required pacackes are
libusb-1.0-devel. Note that the resulting binary will still need
cygwin dlls to be present.
A native win32 binary can be build using mingw32 under Linux or
Cygwin. If neccessary, edit the
Makefile and adjust the
variable to the proper prefix for your toolchain. Then use
win32 to build
The configuration file is a plain text file containing configuration commands and keybindings in a human readable format. Using the keyman64 utility this file is converted to a binary format which can be flashed into the EEPROM memory of the Microcontroller. See Transferring the configuration.
Whitespace and comments
Empty lines as well as leading and trailing whitespace characters are ignored. Whitespace is only significant to separate individual tokens and keywords.
Comments begin with a hash character
# and continue for the
remainder of the current line.
Commands and bindings
Each line must contain one command specification, optionally prefixed by a key specification:
[<key>:] <command> [<arguments>]
If no key specification is given, the command will be executed on powerup/reset of the microcontroller, and can thus be used to configure the initial state of the device.
If a key specification is given, the command will be bound to the specified key.
If multiple commands are bound to the same key, the commands will be executed in sequence, in the order in which they appear in the configuration file.
Command sequences can also be bound to “slots” by using numeric key
$FB. These command sequences can
not be invoked directly by a key combination, but may be invoked
indirectly via the exec command.
Keys can be specified by using literal key names like
ONE. To obtain a list of valid key names and their
Keys may also be specified by number, denoting the key position in the C64 keyboard matrix. Keys are numbered from left to right, from row 0, column 0 down to row 7, column 7.
$00 corresponds to the
$3f denotes the
Key numbers may be given in decimal or hexadecimal
notation. Hexadecimal numbers must be prefixed with a dollar sign
or the literal string
The sixteen control lines are organized into two 8-bit wide ports. For
commands modifying the state of these control lines, the respective
port can be specified using the keyword
port, followed by the
Commands modifying the state of the control lines can be limited to individual bits or ranges of successive bits. Bits are denoted by a decimal number in the range 0-7.
n denotes an individual and
e denote the start and
end bit of a bitrange (inclusive).
Durations can be specified by a series of decimal values and unit specifiers:
Available unit specifiers are
ms for days,
hours, minutes, seconds and milliseconds respectively. If no unit
specifier is given, the preceeding value is interpreted as
The maximum possible duration is 232 milliseconds, about 49 days. Specifications that exceed this value will be truncated accordingly.
1m30s = one minute and thirty seconds
1s500 = one second and fivehundred milliseconds
10 = ten milliseconds
Values can be specified in hexadecimal or binary notation. Hexadecimal
values need to be prefixed with
$. Binary values need to be prefixed
Commands for configuration and maintenance
Specify which crosspoint switch IC is installed in the device. Either
a CD74HC22106 or an MT8808 may be used. Default is
The meta command defines the meta key to be used. Default is
Enter the bootloader and expect configuration or firmware updates via USB. The device will remain bootloader mode until a new configuration or firmware has been programmed or the reset button has been pressed.
Commands for modifying control lines
set <port> [<bits>] [to <value>]
Sets the specified bits of the specified port to the specified value. If value is omitted, it defaults to setting all bits to 1 (high). If bits are ommitted, sets all bits of the specified port.
set port a bit 3 to 1 – sets bit 3 of port a to high
set port b bits 3-4 to 2 – sets bit 3 to low and bit 4 to high on port b
set port a – sets bits 0-7 to high
clear <port> [<bits>]
Clears the specified bits of the specified ports, i.e. sets them to 0 (low). If bits are ommitted, clears all bits of the specified port.
tristate <port> [<bits>]
Tristates the specified bits on the specified port. If bits are ommitted, tristates all bits on the specified port.
Tristating a line means setting it to a high-impendance state which is neither high nor low. This is equivalent to physically disconnecting the line.
invert <port> [<bits>]
Inverts the state of the specified bits on the specified ports. If bits are ommitted, inverts all bits of the specified port. If a bit has been set to tristate beforehand, it will be set to output high.
increment <port> [<bits>]
Increment the state of the specified bits on the specified port by one. If bits are ommitted, increments the state of all bits on the specified port.
This can be used to implement a binary counter on a port or a specific bit range on a port. If all bits are already set (e.g. the counter has reached its maximum) then all bits are cleared again.
Example of a four-bit binary up-counter in the lower part of port a:
increment port a bits 0-3
decrement <port> [<bits>]
Decrements the state of the specified bits. Works similar to the
Commands for controlling the keyboard matrix
Holds down the key on the matrix seen by the computer. The key will
remain held down until an
up command for the key is executed or the
meta key is released.
Releases the specified key on the matrix seen by the computer. The key
will remain released until a
down command for the key is executed or
the meta key is released.
Presses the specified key on the matrix seen by the computer, i.e. the key is held down for 20 milliseconds and then released again. This is a shortcut for
down <key> sleep 20 up <key>
Types the specified string on the matrix seen by the computer. The
~ is interpreted as
Lower case characters will cause the corresponding key to be pressed without modifiers. Upper case and special characters will be pressed in conjunction with shift if necessary to type the correct character. Only the lower 127 ascii characters will be interpreted. Results for ascii characters beyond 127 are undefined.
Example (on the C64):
type load"$",8,1~ – types
LOAD"$",8,1 and presses
swap <key> <key>
Swaps the specified keys against each other before relaying them to the computer. This can be used to redefine the keyboard layout, e.g. to switch to a QWERTZ layout on the C64:
swap Z Y
Note that this applies only to the keys relayed to the computer, not
to the keys interpreted as a part of a key binding. Commands bound to
the physical key
Z can still be invoked by pressing
Commands for controlling execution
Executes the command sequence bound to the specified key or slot number. Execution of the current command sequence will resume after the specified sequence has been executed.
Suspend execution of the current command sequence for the specified duration. No keyboard processing will occur during sleep, e.g. key presses will neither be relayed nor interpreted as bindings.
Configuation and control utility
$ keyman64 --help
keyman64 version 1.1 Copyright (C) 2015 Henning Bekel. License GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Usage: keyman64 <options> keyman64 convert [<infile>|-] [<outfile>|-] keyman64 [<options>] <command> keyman64 [<options>] [<file>] Options: -v, --version : print version information -h, --help : print this help text -d, --device : specify usb device (default: /dev/keyman64) -D, --delay : delay in ms between commands -k, --keys : list key names and synonyms Conversion arguments: <infile> : input file, format is autodetected <outfile> : output file, format determined by extension: *.conf : plain text config file format *.bin : binary file format (default) Missing arguments default to stdin or stdout Command: (any valid keyman64 command)
Transferring the Configuration
convert command of the configuration and control utility is used
to convert the configuration file to a binary format which can then be
written to the Atmega1284p’s EEPROM memory over USB.
Assuming you have written a configuration file named
you can convert it using
$ keyman64 convert keyman64.conf keyman64.bin
If no errors are encountered this results in the file
Make the keyman64 enter the bootloader.
avrdude to write the configuration to the EEPROM memory:
$ avrdude -p m1284p -c usbasp -U eeprom:w:keyman64.bin:r
After the configuration has been transfered, the keyman64 will reset and the new configuration should be in effect.
Any command can be send from the PC via USB to the keyman64, where it will be executed immediately.
A single command can be executed by passing it directly on the commandline, e.g.
$ keyman64 press F5
If no arguments are specified on the commandline, the keyman64 utility will read commands from STDIN, where one command can be given on each line. Note that the commands will get parsed and executed after STDIN has been closed, e.g. all commands have been entered/piped in:
$ keyman64 reading commands from stdin... > type load"$",8~ > sleep 5s > type list~ > ^D $
If the first argument to the keyman64 utility is a file, commands will be read from this file and subsequently sent to the keyman64.
Thus you can create a file containing a script like the following:
exec rightshift press f5 press cursordown press cursordown press cursordown press return
and run this script via
$ keyman64 --delay 250 script.txt
--delay option will add an additional delay of 250ms after each
command. This avoids having to add explicit
sleep commands in the
On Linux and MacOSX, the she-bang mechanism can be used to create an executable script. Just make the script executable and add an appropriate she-bang line at the top, e.g.
#!/usr/bin/keyman64 --delay 250 press f5 press cursordown press return
chmod +x the script and you can execute it like any other
Switching the kernal and performing a reset
Let’s assume you have a dual-kernal adapter installed in your C64. These adapters usually come with a switch that controls the highest address line of the eprom und thus chooses the kernal that is seen by the C64. You are expected to drill a hole in your C64 case to install the switch.
Using keyman64 you can avoid drilling a hole in your precious case.
Simply remove the switch and connect the highest address line of the
eprom to one of the 16 control lines of the keyman64. For this
example, we’ll assume that we’re using the highest line of the first
control port (
port a bit 7).
Create a configuration file with the following contents:
clear port a clear port b k: invert port a bit 7
Convert it using the
keyman64 command line tool:
keyman64 example.conf example.bin
And write the resulting binary file to the avr’s eprom:
avrdude -p m1284p -c usbasp -U eeprom:w:example.bin:r
After the configuration is written, the keyman64 will reset. First it
executes any command not bound to a key. This allows us to set the
initial state of the control lines. In this case, all lines are
initially pulled low using the
Now the key combination
<meta>-k will invert the state of the
eprom address line, effectively switching back and forth between the
two kernal images on each invocation.
While this does the job on the hardware level, it might still cause the C64 to crash, since you might swap the kernal contents while kernal code is being executed. So it would be nice to also reset the C64 after switching the kernal rom.
We’ll connect the C64 reset line to the first line of the first control port and change the configuration to:
tristate port a bit 0 clear port a bits 1-7 clear port b r: clear port a bit 0 r: sleep 10 r: tristate port a bit 0 k: invert port a bit 7 k: exec r
Now if we press
<meta>-r, the reset line will be driven from tristate
to low for 10 milliseconds and is then tristated again, effectively
causing the C64 to reset.
And if we press
<meta>-k, the kernal will be switched just like
before, but then the reset sequence bound to
<meta>-r will be
executed in addition.
Thus we can switch the kernal and immediately reset the C64 simply by
<meta>-k instead of having to turn off the C64, flip a
switch and turn the C64 back on every time we want to change the
Holding down a key during reset
Some expansion port modules execute special functions when a key is
held down during reset. Things like this can be simulated as well. The
following binding performs a reset while holding down the
u: down runstop u: clear port a bit 0 u: sleep 10 u: tristate port a bit 0 u: sleep 1s u: up runstop
Defining keyboard macros
type command can be bound to a key as well:
d: type load"$",8~
<meta>-d will type
symbol denotes a newline in this context.
Remapping the keyboard
swap command can be used to virtually swap two keys on the
keyboard. For example, to change the keyboard layout to QWERTZ, just add
swap z y
to your configuration.
If you want to switch between both layouts on the fly, you can simply bind the swap command to a key:
y: swap z y
The P4 connector offers a simple serial interface allowing remote control of the keyman64 by external hardware. The left pin provides the input for an active-low clock signal (denoted as /CLK on the board). The right pin provides the data input (denoted DATA). On the falling edge of the clock signal the value present on the data input is transferred to the keyman64.
Each command consists of a command-nibble, followed by an argument
byte. Both parts are transferred individualy in litte-endian order,
i.e. the least significant bit is send first. For example, to press
RUNSTOP, the actual command looks like this:
0100 00111111 => 0x4 (command) 0x3f (argument)
but must be transferred like this:
0010 11111100 => command, then argument, both lsb first.
The following commands are available:
0001 <key>: execute command sequence bound to key or slot number
0010 <key>: hold the specified key down
0011 <key>: release the specified key
0100 <key>: press the specified key (hold down for 20ms, then release again)
Note that if a key is held down via the serial interface it will remain in this state until explicitly released via the serial interface again. The state of the physical key will be ignored during this time.
Connecting the Serial interface to the C64
One possible way of using the serial interface is to connect it to the C64 via the bit 3 and 4 of the 6510 IO port. These are available as “Cassette Sense” and “Cassette Data” at the tapeport (assuming you don’t use the tapeport for anything else). “Cassette Sense” will be used as the /CLK signal and “Cassette Data” as the DATA signal.
The source distribution contains the file
in KickAssembler format. These files can be used to issue serial
commands from the C64 using the 6510 IO port.
For example, the following code will execute the command sequence
.import source "serial.h" jsr serial.open // configure the tapeport lines for output ldy #$04 // Y: number of bits to send lda #Command.exec // A: the actual bits to send jsr serial.write // right shift the bits out (i.e. lsb first) ldy #$08 // The same for the argument, but 8 bits this time lda #$3f // This is the "RUNSTOP" key jsr serial.write jsr serial.close // Reset tapeport lines to default state (input) rts .import source "serial.asm"
keyman64 Hardware, Firmware, and Software Copyright (c) 2015, Henning Bekel <email@example.com> GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS