This Space for Rent

New (and woefully undocumented) Code!

Last week, as part of my plan to make my public servers a little lonelier, I went out and bought a pair of Berkshire Products PC watchdogs to wedge into them. The watchdogs I bought were the USB versions, which seemed like they'd be the easiest to cram into my FreeBSD boxes after doing a bit of tweaking to the existing (Linux) device drivers.

Well, it turned out that the Linux device drivers weren't really suited (they were doing, in kernelspace, reads and writes to the watchdog) for moving to FreeBSD (and they'll certainly not work on Pell, because 2.0.28 doesn't have support for USB,) so I had to sit down and write my own driver program.

It's not actually documented yet (yeah, yeah, what else is new? My documentation always lags my software development by at least one release), but it's got a -h flag that spits out the following help screen:

usage: pcwatchdog [-f device] [-h]
       pcwatchdog [-f device] command{,command}
 
If not specified, pcwatchdog uses the device /dev/uhid0
 
 the commands are:
ping      -- ping the watchdog card, resetting the alarm clock.
temp      -- read the pcwatchdog thermometer.
status    -- read the current status of the pcwatchdog.
switches  -- show the current settings on the dip switch bank.
version   -- show the firmware version#.
armtime   -- show (=set) the startup arming delay.
alarm     -- show the remaining alarm time (=set the default alarm time).
trigger   -- show (=0; clear) how many times the watchdog was been pinged.
enable    -- turn the watchdog on.
disable   -- turn the watchdog off.
relay     -- show (=set) external relay parameters.
buzzer    -- show (=set) buzzer parameters.
count     -- show (=0; clear) how many times the computer has been reset.
pulse     -- show (=configure) how long a reset lasts.
reset     -- press the Big Red Switch.
 
the command ``pcwatchdog command=?'' returns a description of
the valid arguments for the command

Fortunately, the FreeBSD usb stack lets you use read() and write() to HID devices, so writing the driver was merely a case of spending my lunch hour writing a little front-end program that translates english into pcwatchdog command. And then I simply put an entry into crontab to run it on 2 minute headways and (modulo FreeBSD 4.4 not supporting read() and write() to HID devices) *poof* I've got a watchdog.

A mean-hearted person might notice that this watchdog program doesn't actually attempt to autodetect a Berkshire PC watchdog, but just blindly attempts to talk to the device. Well, that's because I couldn't find any simple way to do an ioctl that would tell me what USB device is associated with an open file descriptor. There's one that you can use to do a device walk, but it doesn't actually appear to do any mapping from usb address to usb device name, so it's enough to convert this whole process into a more-than-one-lunch-hour procedure, so I'm leaving that off until after I've got a chance to grovel through the kernel source looking at USB ioctls.

But as it stands it's perfectly usable for a server that doesn't see much in the way of plugging and unplugging USB hardware.