Date: Sat, 20 Apr 96 11:43:58 -0700 From: grady@XCF.Berkeley.EDU To: freebsd-hackers@freebsd.org Subject: Coin-reading LKM code dropped in incoming Message-ID: <199604201843.LAA02864@scam.XCF.Berkeley.EDU>
next in thread | raw e-mail | index | archive | help
I wrote a little LKM for reading the game port to determine if coins had been dropped into a coin slot. I've put the result in pub/FreeBSD/incoming/coin.lkm-0.2.tgz. (There's also a coin.lkm.tgz which I don't have permission to remove.) Here's the README (which is almost as long as the code): ======== (The code was adapted from Hellmuth Michaelis' example LED driver; this code could also be considered as an example, with a driver that supports read and select rather than write.) This driver provides a device that can track how many coins have been dropped into a coin-slot mechanism. It reads the first button on the game port, which is a standard interface for coin-doors in the video game industry. (Note that some dollar-bill acceptors generate clicks equivalent to four times the value of the bill, thus allowing the same coin code to be used.) A coin-drop is registered as a game-port button bit turned on for a duration that is within a certain range -- too short and it is probably a spurious reading, too long and it is probably a slug. This code has the range hard-coded as being between 20 and 100 milliseconds. In order to verify that the minimum time spans two reads, it is necessary to query the port at least 100 times per second. This driver supports open(), close(), read(), and select(). Open() and close() are standard. Read() always returns a short containing the number of coins that been dropped in since the last time the port was read. Select() operates in a slightly non-standard way -- it blocks until read() would return a non-zero value (since read() always returns a value, select()'s normal behavior of blocking until the device was ready to read doesn't have any use). An obvious question is: why use an lkm rather than a user program that reads the /dev/joy device? There are three reasons. First, because the joystick device is not an LKM. It is a pain to install a new kernel just to support reading coins. Secondly, and more importantly, there is no guarantee that a user-mode program will read the device in a timely fashion. During one test of the user-mode program, a $20 bill (generating 80 clicks) had only about 65 clicks register, due to other process activity on the system. A kernel driver, while not _guaranteed_ to process every click, is not nearly as likely to miss a click. Finally, putting the code in the kernel causes _much_ less overhead. The user-level program (consisting of Tcl plus a device-reading extension) used about 2% of the CPU, and imposed the additional loads of constant context switches, and a non-trivial resident set. In contrast, this device uses only a few K, and the reading program can now be swapped out until the select() returns. This is the minimal driver that supported my requirements. There are obvious possible extensions, including: handling multiple buttons on a single port handling multiple ports supporting ioctls to change the currently hard-coded constants All of these are simple, but I didn't need to do them, so I didn't bother... Included in this distribution is a sample program, catcoin.c, that reads the current value from the /dev/coin device. With an argument, it blocks until a coin is dropped in. Note that "isa.h" is also included. It is a copy of /usr/src/sys/i386/isa/isa.h, which is not put under the /usr/include tree, so may not be available to someone compiling this code. It is only used to get the game port address. Steven Grady grady@xcf.berkeley.edu ======== Steven
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199604201843.LAA02864>