Medieval Life versus Modern Medicine

I’m a pretty big fan of science — and by that, I mean the scientific method and its reliance upon testable theories and repeatable outcomes.  As a corollary, I generally respect modern medicine, and it’s not unusual to think, hey, without modern medicine, where would I be?  To put it another way, if I lived in the Middle Ages, wouldn’t life suck?

My last foray into modern medicine involved a rotator cuff tear, followed by surgery, frozen shoulder syndrome, and six months of excruciating physical therapy.  If I were a medieval peasant, I probably wouldn’t be able to use my arm at all, right?

Well, no, it turns out my shoulder problems were caused by the modern antibiotics Levaquin and Cipro, both of which I was taking for medically dubious reasons (as many people do) and other antibiotics weren’t available because of my allergy to Augmentin.

Augmentin was prescribed to me when I had contracted a horrible kidney infection, and I actually developed the allergy while taking it.  But hey, modern medicine saved me from a kidney infection, right?

Yes, but since I acquired it in a hospital, I’m going to put this in the medieval column.  I was in the hospital due to kidney stones, which were so big, they wouldn’t pass on their own.  After lithotripsy failed, the more invasive laser surgery was required.

Kidney stones are pretty horrible, and it’s easy to imagine myself in a medieval hamlet, blaming demons or whatever for my bone crunching pain.  However, it turns out my kidney stones were caused by high fructose corn syrup, so it’s more likely I’d be dancing around my medieval hamlet in no pain whatsoever, probably wearing tights, which I understand was acceptable back then.

I’d also been in the hospital to have my gall bladder removed, due to gallstones, which anybody who’s had them can tell you are almost as bad as kidney stones.  Oh no!  My medieval self would be unequipped to deal with gallstones … but (by now, you can see this coming) wouldn’t actually have gallstone problems in the first place.  In an ironic twist, cutting high fructose corn syrup and fat out of my diet to avoid kidney stones led directly to gallstones.

So far, the Middle Ages are beating modern medicine by at least three points, and I’m not even counting the clothes.

Not that I’m anti-modern-medicine, by any means, and I’m not about to revive the medieval practice of buying Head-On headache sticks to ward off brain goblins.  Instead, I’m going to give full credit to modern medicine for Imitrex, which is truly wonderful.


Games of Chance

As somebody with a firm grip on science and statistics, I’ve always had a weird relationship with games of chance.  Generally speaking, I’ll calculate the odds and opt out, being the opposite of a gambling man — not only is there nothing I like better than an iron-clad guarantee, but I’ll view that as somewhat dubious until I see results.

In the fifth grade, I was once motivated to try my luck by a carnival drawing where one of the prizes was a big orange kangaroo that I found compelling, for some reason.  The idea was to pay a quarter, reach one’s hand into a Tupperware cereal-keeper full of tickets, then check to see if one’s numbers matched one of the prizes.  After a few questions and some quick math, I calculated my odds of winning anything to be about one in a hundred, and my odds of winning the kangaroo about 1 in 700.  Not wonderful odds, and I’d be stupid to pay a quarter for the privilege of reading a non-winning number from a ticket, but that kangaroo somehow managed to convince my addled fifth-grade mind that if I rummaged around in there, the ticket would magically find my hand because my desire was so great.

I suspect that a lot of fiction has this same side effect on impressionable young minds, even those straining to be rational.  Intellectually, I knew this was a ridiculous notion, but I wanted it to be true so badly, I almost had myself convinced.  It was just enough so that I handed my last quarter to the lady and rooted around in the Tupperware.

When I unfurled my ticket, a healthy dose of skepticism and anticipation kept me from getting too excited, and I checked the number three times before handing it to the lady — and collecting the kangaroo I had won.  It sat on my bed for years as a loved reminder of how every now and then, long odds do pay off, and it may be worthwhile to loosen up on cold rationality every now and then.

Years later, I got the idea that I would buy a lottery ticket.  The odds of winning are calculated for you (“virtually impossible!”) so I was under no illusions that I’d win anything.  As a test of my mental resolve, I was going to play all ones — which is difficult to imagine ever coming up, but has the exact same odds as winning (“virtually impossible!”) as any other number.  In this case, I justified it to myself because I wanted to see one of the automated lottery tickets at the grocery store in operation.

I put $1 into the machine, which promptly jammed, and went out of order.  What were the odds?  I promptly gave up on the lottery.

I’ll fast forward past counting cards in Atlantic City to being at the zoo with my four-year-old daughter whose attention has been captured by a claw machine with a bin full of tightly-packed stuffed animals.  “I want the tiger!” she says, pointing to a tiger behind the glass.

It seemed like a good time for a harsh lesson on probabilities, so I lectured her at great length about how unlikely it is that we’d win it on the first try, and that those games work because the amount of people money put in trying to grab a prize is always more than the cost of the prizes, and how I didn’t want her to be too disappointed when she didn’t win.  She solemnly took the 50 cents I handed her and promised she wouldn’t beg to play again if she didn’t get the tiger.

We still have that tiger.   I suspect my lecture was instantly forgotten.

Today I decided that I’ve give the lottery another chance, partly because if I don’t win, a significant chunk of the money goes to the schools, and partly just to see what it’s about these days.  While it’s not possible to play online, it’s possible to print out a PDF that allows one to buy tickets by mail, so I figured, what the heck:  if I don’t win, I’m not out much money, and if I do, hey, free money.

My rational mind was immediately assailed by a number of roadblocks, that weirdly reminded me of the jammed lottery machine decades earlier:

  • It took several tries to get the PDF to download.  The first time I got a PDF, it was blank
  • After filling out the form, but before I was able to print, my computer crashed (which never happens.)
  • My printer jammed
  • I was going to use a credit card to pay, but I used it earlier and misplaced it within the house
  • After deciding to just write a check, my pen flakes out, ruining a check.  It takes me 20 minutes to clean and fix my pen.
  • My printer jams when printing the envelopes, which it never does — not just once, but four times, ruining a swath of envelopes and causing me to have to apply for postal refunds

Coincidence?  Gentle fate trying to save me from wasting my money, or cruel fate trying to keep me from winning millions?

I’ll let you know, assuming this letter ever makes it.


Voice Announcements via Modem

We have a PBX system through which it’s possible to make announcements, some of which I find myself making regularly.  Having an old voice modem lying about, I decided to program it to make regular announcements for me.

Rather than dedicate a modem to voice announcements, I decided to share a modem that’s also used for HylaFAX, on the principle that the less hardware to have to worry about, the better.  HylaFAX shares a locking system with minicom, meaning that if I use minicom for the voice announcements, I don’t have to worry about who has control of the modem, or of relinquishing control to HylaFAX.

I located an ancient voice command  manual for my US Robotics voice modem online.  While it took some trial-and-error, I eventually whanged together this script:

if [ "$1" = "--help" ] || [ "$1" = "" ] || [ "$2" = "" ]; then
echo 1>&2 Usage: $0 [# to dial] [voicefile.rmd]
echo --help      this message
exit 1
cd /tmp
echo print "starting" > /tmp/minicom.$PID
echo send "ATZ" >> /tmp/minicom.$PID
echo expect { >> /tmp/minicom.$PID
echo \"OK\" >> /tmp/minicom.$PID
echo } >> /tmp/minicom.$PID
echo send "AT#CLS=8" >> /tmp/minicom.$PID
echo expect { >> /tmp/minicom.$PID
echo \"OK\" >> /tmp/minicom.$PID
echo } >> /tmp/minicom.$PID
echo send "AT#VRN=0" >> /tmp/minicom.$PID
echo expect { >> /tmp/minicom.$PID
echo \"OK\" >> /tmp/minicom.$PID
echo } >> /tmp/minicom.$PID
echo send "AT#VRA=0" >> /tmp/minicom.$PID
echo expect { >> /tmp/minicom.$PID
echo \"OK\" >> /tmp/minicom.$PID
echo } >> /tmp/minicom.$PID
echo send "AT#VSM=129,8000" >> /tmp/minicom.$PID
echo expect { >> /tmp/minicom.$PID
echo \"OK\" >> /tmp/minicom.$PID
echo } >> /tmp/minicom.$PID
echo send "ATS46=255" >> /tmp/minicom.$PID
echo expect { >> /tmp/minicom.$PID
echo \"OK\" >> /tmp/minicom.$PID
echo } >> /tmp/minicom.$PID
echo send "AT#VRA=0" >> /tmp/minicom.$PID
echo expect { >> /tmp/minicom.$PID
echo \"OK\" >> /tmp/minicom.$PID
echo } >> /tmp/minicom.$PID
echo send "ATDT,$1" >> /tmp/minicom.$PID
echo expect { >> /tmp/minicom.$PID
echo \"VCON\" >> /tmp/minicom.$PID
echo } >> /tmp/minicom.$PID
echo "sleep 1" >> /tmp/minicom.$PID
# here's the voice part
echo send "AT#VTX" >> /tmp/minicom.$PID
echo expect { >> /tmp/minicom.$PID
echo \"CONNECT\" >> /tmp/minicom.$PID
echo } >> /tmp/minicom.$PID
echo "sleep 1" >> /tmp/minicom.$PID
echo "! cp $2 /dev/ttyUSB0" >> /tmp/minicom.$PID
# end
echo >> /tmp/minicom.$PID
echo sleep 2 >> /tmp/minicom.$PID
echo ! killall minicom >> /tmp/minicom.$PID
/usr/bin/minicom -S /tmp/minicom.$PID
cat /tmp/minicom.$PID
rm /tmp/minicom.$PID

It’s fairly linear — it puts the modem into voice mode, sets a number of parameters, and escapes to the shell to copy a file to the device.  What remained is to create a file in a format that the modem could consume.

Luckily, Ubuntu has a package called mgetty-pvftools which contains all the binary files necessary to make it happen.  (These files are bundled with vgetty on Gentoo, but vgetty conflicts with HylaFAX, and all I need are the audio conversion binaries.)

It’s several steps to convert, but this script does it handily:

if [ "$1" = "--help" ] || [ "$1" = "" ] || [ "$2" = "" ]; then
echo 1>&2 Usage: $0 [from.mp3] [to.rmd]
echo --help      this message
exit 1
echo "mp3->wav"
sox -V --norm $1 -r 8k -c 1 /tmp/$PID.wav
echo "wav->pvf"
wavtopvf /tmp/$PID.wav /tmp/$PID.pvf
echo "pvf->rmd"
pvftormd US_Robotics 4 /tmp/$PID.pvf $2
rm /tmp/$PID.wav
rm /tmp/$PID.pvf

So, all that’s left to do is to set up the first script in an “at” or “cron” job.  However, it turns out that minicom requires an interactive terminal to run, so simply running the first script from an “at” job resulted in this error:

No cursor motion capability (cm)

Since the script will run minicom without being attended, a simple way around this is to use the “screen” program to provide an interactive terminal for minicom to use within cron/at:

screen -d -m 111 announcefile.rmd

LED Isolators for HDD LEDs

LED Isolator

LED Isolator

A while ago, I posted a design for a home-made circuit designed to connect multiple hard drive add-on cards (and the motherboard) to a single case LED.  I made a handful of these for the servers around here, and in the three years or so since then, I’ve yet to see anything similar.  It’s possible that nobody but me actually cares if their case light reflects drive activity across all their drives — then again, it’s also possible that the people who actually cared simply made their own.

On the off chance that anybody wants one, I went to the trouble of making some professional-looking boards.  More detail is available here.


Fun with the Secretary of State

A short while ago, I was traveling through New York, and somehow managed to leave my driver’s license with the TSA. This wouldn’t have been so bad, except that I needed to fly out of Chicago the next day, and I needed to rent a car at my final destination, which probably isn’t possible without an actual driver’s license.

My strategy was to go to the Secretary of State’s office downtown (this is the Illinois equivalent of the DMV) before it opened, in what seemed like a futile effort to acquire a license before I needed to be at the airport. Fifteen minutes before it opened, there was already a crowd of fifteen people waiting for the doors to open.

After a moment, a lady with a clipboard came out, carefully locking the door behind her. She announced that she would be coming to each of us in the order that we showed up, and giving us numbers to speed things along. She came to each of us and asked why we were there and confirm that we had the required documentation. Ahead of me in line:

  • A man from Michigan wanting an Illinois driver’s license, who didn’t have his Michigan license because he lost it for driving under the influence. (Sent away)
  • A woman who wanted a state ID, but didn’t have her Social Security card, because it “got wet.” (Sent away, with the suggestion that she replace that first.)
  • A man in a suit with some kind of letter instead of one of the required documents. “They told me over the phone this would be sufficient,” he insisted. “Nobody told you that,” she said flatly, and sent him away.
  • A teenager with no paperwork whatsoever, seeking a state ID. (Sent away.)
  • A man seeking a driver’s license. After looking at his paperwork, she asked, “where do you live?” “Indiana,” he answered. She politely explained that you have to live in Illinois to get an Illinois driver’s license, and sent him away.

After a few variations on the above, she got to me last, and I showed her my paperwork, she handed me the number two. The doors opened, and $5 and 5 minutes later, I was holding a brand new driver’s license. I was utterly unprepared for this jaw-dropping display of government efficiency, which left me with plenty of time to catch my flight — time enough to go home first.

At home, the TSA from New York called, to let me know they had my driver’s license, which they offered to send me immediately. (Since I had to fly in a few hours, I would have needed a duplicate anyway, but I received my old license the next day.)

I contrast this sharply with my experience just a few years earlier at the same office of the same agency. I received in the mail a renewal notice for my license plates that had somebody else’s name on it. I tried calling first, and after an hour on hold, was informed that I’d have to go sort it out in person, and bring the physical license plates from my car.

After another hour and a half waiting in line, I explained the situation to the bored, slow-moving woman behind the counter who didn’t quite appear to be listening. “You want to change your name?”

I explained again that the name on my renewal notice was wrong, and handed her my license plates. She looked at the plates, at my renewal notice, and my driver’s license. After a few minutes of contemplation, she typed something into her computer.

“These aren’t your plates.”

Now we’re getting somewhere. “So, how do I get this corrected?”

“You have to bring in both sets of plates,” she explained.

“This is the only set I have. This is the set I was given… by you guys,” I tried to clarify further. “I only have one set.”

“Well, these are the ones you have to bring in,” she said, and gave me a plate number nothing like the ones I’d placed on the desk.

“So, you want me to find these license plates somewhere in the State of Illinois, detach them from whoever’s car they’re mounted on, and bring them in?”

“That’s right,” she beamed, apparently pleased that she had finally gotten through to me.

“So… Do you think the person whose name is on my renewal form has those plates?”

(blank stare)

“So… Can you tell me where you mailed the renewal notice for my plates?”

She looked this up on her computer, and compared it to the address on my driver’s license. “It doesn’t match your address here, so for security purposes, I can’t tell you what it is.”

“And this is the guy whose house you want me to drive to in order to retrieve the plates you sent him by mistake?”

(blank stare)

“Fine. I just want to renew these plates and correct my name.”

“You can’t do that, these aren’t your plates.”

It was my turn to stare blankly.

“You’ll get arrested if you put these on your car,” she explained slowly.

One of the two state troopers now standing immediately behind me said, “do we have a problem here?”

“If I didn’t have a problem, I don’t think I would’ve stood in line for so long,” I explained. “That’s kind of the whole point.”

Apparently deciding that I wasn’t a threat, they backed up … a little.

“Okay, look, I just want valid plates on my car that I can actually renew and that won’t get me arrested.”

She thought about this for a moment. “You can get new plates for $20 more.”

Unhappy, but with no alternatives, I handed over the money and she gave me a new set of plates.

“Just out of curiosity, are you going to tell the guy who has my plates? So he doesn’t accidentally renew them or whatever?”

“Oh, I’ve already updated the system,” she said languidly, “and there’s a warrant out for his arrest for the guy who stole your plates.”

“Wait… what? He didn’t steal my plates, you mailed them to him.”

“Yeah, but we don’t have a way to put that in the computer. I’m sure he can explain that when they pick him up.”

Epilogue: In an effort to spare some poor guy from being arrested for no particular reason, I called information and what little I knew and tried to call the guy whose name appeared on my renewal notice. The girl who answered the phone said he’d already sold the car “to some guy out of state.”


No Good Samaritan … Something Something

After witnessing several hundred seizures at the rehabilitation center where I worked, I came to recognize the early signs of a seizure.  They may be different for many people, but often there was a glassy look, a slight roll of the eyes, a twitch … some little sign that something major was about to happen.

In the days when the El actually had a conductor as well as an engineer — on a train with no seats available, and a smattering of people standing or leaning around the doors, I stood in the aisle.  In those days, it was common to see people walking between the trains, and it wasn’t unusual for people to pull the emergency cord at every stop.

An old man got in the train and made his way over to the aisle facing me as the train groaned and lurched forward.  He nodded slightly by way of greeting, then winked a little … then winked a bit more, with his eyes rolling back a bit … As he fell stiffly backwards, I took a look at where he was falling, and saw nothing but hard surfaces and metal seat supports everywhere.  I’ve seen people injure themselves with fewer hazards around during a grand mal, so I caught the old man, pulled him toward the doors where there was more room in the car, and held my hand under his head so it wouldn’t bang on the floor.

After a few minutes, the old man had stopped seizing and fallen into a deep sleep.  I checked to make sure he was breathing and stood up.  I now noticed that the train was stopped in the station, and all of the passengers had left the car.  The conductor made a nearly incomprehensible announcement over the PA system that the train would be stopped for a while.

The conductor walked over and I explained what happened.  He mentioned that he had called for paramedics and he’d appreciate it if I explained to them directly.  Within moments, they were carrying away the man on a gurney.  They didn’t ask me anything right there, but one of them said, “come with us” as they carried the gurney down the steps to the waiting ambulance.

It was a short trip to the hospital and they asked me to sit in the emergency room waiting room and they’d be back shortly to get my information.  At this point, I wasn’t entirely clear on what useful information I could provide, but thought they may have some more specific questions about anything I might have noticed that could be medically relevant.  Whatever it was, I hoped they would hurry up, since I was already pretty late for work.

After a while, a nurse came out, and said, “We have a few questions for you, if you don’t mind.”

“Finally!”  I said, “What would you like to know?”

“Well, first, what kind of insurance does your dad have?”

“What?”  I said, slightly off kilter.  “Did something happen to my dad?”  (In addition to being perfectly fine, my father was 800 miles away, so it was a nonsensical question, but it didn’t immediately occur to me why she asked.

“Your dad’s had a seizure.  Didn’t you come here with him?”

“No,” I said slowly.  “I came here with a man who had a seizure on the train, whom I do not actually know at all.  I don’t even know his name.”

At this, the nurse seemed slightly incredulous, as if I were involved in some kind of insurance scam.  “Why would you come all the way to the hospital and wait for somebody you don’t even know?”

At this moment, the paramedic who said, “come with us” walked through the waiting room.  I pointed to him and said, “because that guy asked me to.”

The paramedic gave me a sheepish grin, and explained, “uh, sorry, the conductor figured you must be related since you didn’t just leave the guy there.”

I had a heck of a time explaining why I was so late for work.


BackupPC and Bare Metal Restore of Windows XP

While it’s not well documented, it’s possible to do a bare-metal restore of a machine running Windows XP that’s been backed up via BackupPC (assuming, of course, that some method, such as that documented here, has been used to back up open files, such as the registry.)

Step 1:  Build a local tar file using BackupPC_tarCreate

The alternative, BackupPC_zipCreate, proved problematic; the gigantic archives that it created could not be completely recovered, yet tar archives proved intact.  At any rate, this is best accomplished from the command line, as the backuppc user:

BackupPC_tarCreate -t -n -1 -h borkstation -s C / > borkstation.tar

“borkstation” is the name of the host to recover, “-n -1” means the latest backup, and you’ll obviously need to have enough space where the tar file is going to store the entire backup, which will not be compressed.  Note the space between the “C”, which represents the share to restore, and the “/”, which represents the directory to restore.

Step 2:  Prepare bare XP

Basically, you want to install a working copy of the operating system.  Aside from network drivers, it really doesn’t matter if anything’s installed or working, you’re going to wipe it all out anyway.  The filesystem and the partitions will stay, so configure those the way that you want your system to finally end up.

Step 3:  Prepare Recovery Console

Using the same install CD, you can install the recovery console to speed things up a little versus booting from the CD, although either option will work.  To install the recovery console, use Start->Run, then

d:\i386\winnt32.exe /cmdcons

Where D: is the letter if the CD-ROM.  Whether you choose to install it or not isn’t really important, but what is important is that you open up the permissions for Recovery Console, or some of the remaining steps won’t work.

  1. Start->Run, then type secpol.msc
  2. Go to Security settings->Local policies->Security options
  3. Scroll down to “Recovery console: Allow floppy copy and access to all drives and all folders” and make sure it is enabled.

Step 4:  Install Cygwin

You’ll need a “tar” utility you can rely on for the next step, and experimenting with a plethora of them has shown that unless you build your own, you’ll really need Cygwin.  While installing, be sure to select the gnu tar package.  (Unless your backup contains Cygwin, you can just delete the c:\cygwin directory later to get rid of it all.)

Step 5: Unpack the tar file to the local drive

A prerequisite to this step is that you get access to the tar file created in step 1 — which you’ll have to wait for if it isn’t finished being built yet.  The simplest way to get access to the file is to map a drive to the *nix box that has the tar file. I mapped mine to the Z: drive, which was a pretty arbitrary choice.

Next, create a directory to put the recovered files into, because you do not want them going into the root directory yet.  I created a directory called “recovery.”  Launch Cygwin, then:

cd /cygdrive/c/recovery
tar -xvf /cygdrive/z/borkstation.tar

This part takes a while, but when it’s complete, the entire system as backed up will be in the c:\recovery directory.  N.B.:  this goes a little faster if you leave off the “v” parameter, but then you don’t see anything in the way of progress.  It also helps to occlude or minimize the cygwin window.

Step 6:  Rename and move files

There are three hardcoded paths in XP, that are probably the only folders in root on your minimal installation:  Program Files, Documents and Settings, and WINDOWS.  Within the c:\recovery directory, rename these to something else.  I chose “Program Files.recovery” and so on.

Once these three directories are renamed, cut and paste everything from c:\recovery to c:\.  There’s no need to replace any files in c:\, and there shouldn’t be any overlaps, so if Windows asks if you want to overwrite any files, say “no.”

Step 7:  Boot to Recovery Console and rename key folders

Here’s where Step 3 becomes pretty important.  Once you boot into Recovery Console, you’ll need to allow yourself to work in the root of the drive using the “set” command:

set AllowAllPaths = TRUE

Once that’s done, you can rename the three hardcoded directory paths, moving the originals out of the way for your recovered files.  For the sake of having a fallback position, I rename rather than delete them at this point:

ren "Program Files" "Program Files.delete"
ren "Program Files.recovery" "Program Files"
ren "Documents and Settings" "Documents and Settings.delete"
ren "Documents and Settings.recovery" "Documents and Settings"
ren WINDOWS.recovery WINDOWS

The suffix “.delete” has no inherent meaning, it just gets the folders out of the way and signals that I don’t need them any more.  Once this is done, and you’re sure there were no unfortunate typos, you can type “exit” to reboot to a recovered system.

Step 8:  Clean up

After rebooting, pretty much everything should be as it was, although you’ll have three extra directories with a “.deleted” suffix plus the cygwin directory to get rid of.  It may be necessary to take ownership and grant yourself permission to do so, but there’s really no reason not to wipe them all out, since your original folders and files should be intact.

While the “read only” flag has been preserved for recovered files, the “hidden” and “system” attributes have not.  For most files, this doesn’t seem to matter much, but the “desktop.ini” files that dot the drives can have weird side effects, like launching an editor upon boot and showing up.  It’s easy enough to fix from the command line:

cd \
attrib +h +s /s desktop.ini

This will grind away for a while, since it will reset all the desktop.ini files on the drive.  Once complete, you’re back to where you were upon your last backup.


Hyper-V Serial Ports and Windows 2008

Unlike many other virtualization solutions, it’s not particularly easy to connect a Windows 2008 Hyper-V guest to its host serial ports.  Perversely, there are settings to connect the guest COM ports to “named pipes,” but there’s no way on the host to connect COM ports to named pipes.  (It appears that this option is used primarily for debugging programs, rather than for using actual serial ports — it doesn’t appear to have been intended to be used to provide actual serial port access from the guest.)

The Hyper-V Deployment guide contains little more than this:

“Note:  No access to a physical COM port is available from a virtual machine.”

What follows is a recipe to access the physical COM ports on the host from a guest using com0com, and its related utilities.  The idea is to make a COM port on the host available via TCP/IP, and then attach to it via the guest, then make this process automatic.

First, on the guest, you’ll need an appropriate version of hub4com, and the batch file bundled with it, com2tcp-rfc2217.bat.  Naturally, I’m running 64-bit Windows 2008, and there doesn’t appear to be a version compiled for 64-bit Windows, so I had to compile my own.  This can be kind of a pain, especially if you’re using Visual Studio Express, so you’re welcome to download my 64-bit hub2com binaries here.

My device is on COM3, and I can make it available on port 7000 using the following command line:

com2tcp-rfc2217 COM3 7000

This gives me a DOS Window that shows me what’s going on — this is handy for debugging, but hardly something I want to leave on my screen all the time.  The simplest solution is to create a launcher script:

Set objShell = CreateObject ("WScript.Shell")
objShell.Run "cmd /K CD C:\Program Files (x86)\com0com & com2tcp-rfc2217 COM3 7000", 0, false

This script effectively hides the program so that it can run in the background, so all that remains is to have it launch when the system starts.  That’s best accomplished using the registry to create a new “Expandable String Value” under “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run”.  It doesn’t matter what the Name of the String Value is, but the Data should be the command line necessary to launch the script:

%WinDir%\system32\wscript "C:\Program Files (x86)\com0com\com3-listen.vbs"

When done this way, the port is made available whether or not anybody is actually logged into the machine.

The guest is only slightly trickier, requiring both com0com and hub2com binaries to be installed.  Since my guest is 32-bit Windows XP, I could use the precompiled “i386” binaries directly from the c0m0com sourceforge page.

The com0com installer wants to create a null modem pair from “cnca0” to “cncb0.”  You’ll need this pair of virtual devices, and you’ll want to turn on “baud rate emulation,” and rename one end like a regular COM port.    This can be accomplished from the com0com command line setup:

install EmuBR=yes EmuBR=yes
change CNCA0 PortName=COM3

Once the virtual port pair is available, one end can be connected to the host, using the hub2com batch file com2tcp-rfc2217:

com2tcp-rfc2217 \\.\CNCB0 host-hostname 7000

As before, this opens a DOS Window where you can see what’s going on.  At this point, COM3 on the guest is communicating directly with COM3 on the host.  As before, a small launcher script is created to hide this window:

Set objShell = CreateObject ("WScript.Shell")
objShell.Run "cmd /K CD C:\Program Files\com0com & com2tcp-rfc2217 \\.\CNCB0 skypiea 7000", 0, false

And, as before, a registry string is added to the guest to launch this automatically in its own “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run” key.

%WinDir%\system32\wscript "C:\Program Files\com0com\com3-client.vbs"

Simple, eh?  Well, perhaps not, but once it’s set up, the guest Hyper-V machine can communicate via COM3.  Additional ports can be added in the same way.


SIIG Cyber Serial under Windows 2008, or getting old drivers to work

I’m in the process of “upgrading” a server from Windows 2003 server to Windows 2008 server, and one of the things this server does is manage a few serial devices.  Therefore, it contains an old PCI serial board, but the manufacturer has since moved on to newer hardware, and hasn’t bothered to update the drivers.

Trying to install the Windows 2003 drivers yielded the following:

a service installation section in this inf is invalid

And, naturally, refused to install.  To track down the source of this error, there is a file created in \Windows\inf called “” that logs details about the driver installation process.  Reading through this file, the reason for the error is evident:

inf:       ServiceBinary=C:\Windows\system32\DRIVERS\mf.sys  (mf.inf line 39)
!!!  dvi:       Add Service: Binary 'C:\Windows\system32\DRIVERS\mf.sys' for service 'mf' is not present.
!!!  inf:  {Install Inf Section [] exit(0xe0000217)}

Intriguingly, a quick search through C:\Windows\System32\DriverStore\FileRepository showed that the driver does exist, it just happens not to be installed.  There’s a folder called mf.inf_Identifier (where “Identifier” appears to be random junk) that contains a file called mf.sys.  Copying this file into C:\Windows\System32\Drivers allowed the device drivers to install, and they appear to work perfectly well.


Tales of a Triumph

Triumph GT6+

Triumph GT6+

I once owned, and loved, a 1968 Triumph GT6+.  It had a beastly inline 6 cylinder engine with twin carburetors, and the drive wheels were attached with fancy little doodads called “rotoflex” connectors, which were essentially big rubber bands.  The net effect was that this car could move really well.

The car wasn’t without its problems — the gas gauge never worked all that well, it leaked from a few places, the carburetors would stick, and the electrical system was designed to work only when the stars and planets were perfectly aligned — none of which really dissuaded me from taking it out on lesser-used stretches of road and opening up the throttle.

After a few times of doing this, I agreed to let my girlfriend drive.  It was a much more harrowing experience from the passenger seat, for some reason, and when I wasn’t trying to climb under the seat I noticed that she had the speedometer well above the 140 mark.  In between flashes of my life up until that point, I wondered how good my tires really were.

On the way back from one of these forays, I saw flashing red and blue lights in my rear view window, clearly signaling for me to pull over.  I had just enough time to contemplate how often the third digit on police radar gets used when the cop approached the car.  I was poking through the tiny glove compartment for my insurance information when the cop said, “What year is this car?”

“Uh.  1968.”

“Can I look under the hood?” he said, with a sheepish enthusiasm.

“Sure!” I said, equally enthusiastic to not be getting a ticket, or worse.

Triumph GT6+

Triumph GT6+

While driving down Lakeshore Drive, the car’s temperamental electrical system shorted out and overheated, evidenced by some spectacular flames shooting up from the dashboard and in front of the windshield.   This had no discernible effect on the drivability of the car, so I decided to ignore it until I got home, about a mile away — since the alternative was to pull over on Lakeshore Drive (four lanes of crazy in each direction with no real shoulders or breakdown lanes) and try to fix it.

After a moment, a car pulled up beside me, its passenger gesturing wildly.  She then mouthed exaggeratedly, “your car is on fire!” while pointing frantically.

I’ll emphasize that the flames were right in front of my face.  I was looking through them to be able to drive the car down the road at all.  I paused a moment to consider what this good Samaritan thought I could possibly be looking at in order to miss the flames leaping up in front of my face?  Did she think I was sleep-driving?  Perhaps I thought the city was burning to the ground and didn’t realize my car was on fire?

In order not to dissuade this kind person from helping somebody truly stupid and in  need of having the obvious pointed out, I pretended to understand what she meant, gave her a thumbs-up, and a non-sarcastically exaggeratedly mouthed, “thanks!”

Perhaps the next life she saves will be somebody playfully pretending to ignore a “do not eat” label.