Foreground: while the trip is going on, you can see what's up by checking my spot and/or fuelly.

Background: A friend of mine moved to Maryland from California and didn't want to take his bike, so he made it my problem. It's a good bike, but I live in St Louis, so I made a trip to California for a camping trip and annual labour day party and decided to ride it back home. Then I decided "why not make it a coast to coast ride?". So the plan is to ride to St Louis by next Monday (I have an appointment to make), do some maintenance/switch bikes, and then go to Deal's Gap and back. And then probably do more maintenance.

So that's the plan. After over over 600 shakedown miles in the 4 previous days (including the titularly required jaunt to Alice's and another trip to Cambria and back along 25S/1N), a rather short day 1 ended at my in-laws in Modesto


Google makes billions of dollars in revenue each fiscal quarter. That money comes about by the same process that all companies use: They sell a product to their customers. Their customers pay money for that product.

Who’s Google’s customer? You? Really? When’s the last time you paid Google for anything?

Advertisers are Google’s customer. What do they sell to advertisers? They sell you. Or, at least, they rent you out, or provide access to you.Mike Elgan

Assuming I'm going to see ads on the internet anyway, my total experience is improved the more relevant and helpful they are in connecting me to what I'm looking for. To the extent that my information helps Google improve my experience on the web, they're welcome to it.

Would I rather no ads at all? Yes. Realistically speaking that is not going to happen.


Just over a month ago, some friends and I went to Death Valley, taking what seemed like all the closed roads we could find. 2 SV650S and one SV650N (as well as a V-Strom, F800GS, and FZ6) went on the trip.

This post is a combination of forum posts originally found on svrider.

It ends with this picture:


A while ago I was trying to get descriptors asynchronously from devices since in some situations, like if you catch a Mass Storage device while it's busy servicing a CDB, the device could drop control pipe requests on the floor, causing DeviceIoControl to block until Windows loses patience with the device and resets it (about five seconds).

The naïve approach is to use an OVERLAPPED structure with DeviceIoControl, since that's how you do async IO on Windows, but this doesn't work. It's up to the device driver to determine whether the call will be completed synchronously or not, and the Windows USB drivers complete all calls synchronously unless the pipe gets stalled by the device (normally between a URB submission and completion the device just NAKs until the result is ready). This is extremely uncommon, and impossible for the control pipe (which is where descriptor requests go) because the control pipe is used to clear stalls. Stall the control pipe and you wedge the device, leaving a device reset as the only option. In five seconds.

The solution I wound up using is not one I'm particularly proud of, but it does have the advantage of working: I didn't mind a synchronous call (in fact, it made things easier), but I didn't want to deal with getting wedged when a device went out to lunch, so I spawned a thread1 and used WaitForSingleObject to set my timeout. Plan on waiting 80ms or so per quarter-kilobyte expected. Measured very unscientifically, a config descriptor without interfaces (nine bytes) takes less than 10ms, average 4.7ms, standard deviation 0.00831.

Note that you want to open the HANDLE you're using in the DeviceIoControl call in the thread too—if there's another request in flight, opening the file handle will block until it's completed, which is exactly what we're trying so hard to avoid. You shouldn't really be calling for another descriptor from the same device right after it's failed though, because it's likely about to be reset by Windows.

Bonus pitfall: For configuration and string descriptors, you don't know how big the descriptor is, so you can grab a portion of it, get the bLength (wTotalLength for configuration descriptors) and use that to get the rest of the descriptor, or you can just request UINT16_MAX and cross your fingers.

It turns out that neither of these approaches work for all devices for any value of n. To save some space, but keep the number of round trips to the device low, I always used a 256 byte buffer in my requests, and failed over to a larger buffer if the descriptor was too big. Unfortunately, in the classic "just bang on it until it starts working" approach of USB vendors, some devices will just not respond if you make a request with a buffer size that is not the exact size of the descriptor or sizeof UsbConfigurationDescriptor (nine bytes). The reason for this appears to be one of convenience—Windows itself only requests either nine bytes or the entirety of descriptors, so some device firmwares were written with only these two cases in mind.


1 more accurately: reused a vthread, but the internal implementation of our threading library is not germane to this article

In the physical world the race to the bottom is won by mass manufacturers in third world countries paying their workers 2¢ an hour. That's bad. And in the race for lowest per-unit cost, low-quality products get shipped.

In the software world there are no significant manufacturing costs, so commoditization doesn't rely on reducing per-unit product cost and actually results in higher product quality. This is achieved when someone builds and releases a functioning1 Thing for free with the source code available, and other people take interest and offer to help. Game over, this thing is free and getting attention and if it doesn't exactly fit your needs, you can adapt it at a lower cost than writing another Thing from scratch. The result is always better than something you built yourself. This allows you to concentrate on the truly new and unexplored work behind the great products of today. The flywheel of software development gets a little bit faster.2

Open source is not the Only Way. People are entitled to be rewarded for coming up with new and interesting things that other people want. Successful free software tends to be commoditized software—stuff that other people have written many times before. These projects benefit most from the "collective bargaining" development style of open source, with the mistakes of all those previous implementations in mind and addressed in a package that anyone can use.

OpenSSL is a great example of this. Encryption software is terrifically hard to write, and everyone should be using it. Any bug could mean that someone owns your sensitive data, and even if it runs correctly, you're probably vulnerable to side channel attacks that monitor timing, power usage, sound, or math faults. Everyone who writes their own security routines falls for this stuff, including the open source libraries.

The best part about commoditization in software: you're better off using OpenSSL instead of DIYSSL because they've already run into these problems. Early versions had security vulnerabilities, but those have been fixed and the library is under constant analysis and attack by others and you benefit from it directly just by consuming it3. You stand on the shoulders of giants.

It's not just security either. Want high performance code? Someone probably wrote a free library that does what you want. And someone else came along later and improved it. This iteration is what makes open source software such a powerful force.

Open source software has a place in the world, and everyone in the ecosystem relies on it. As the industry matures, it becomes impossible to build a compelling new product without it4.


1 many open source projects fail at "functioning", a sign that the technology they're attempting to implement has not yet become sufficiently commoditized.
2 this is easy to prove: every modern product with a microprocessor contains at least one open source component.
3 as long as you don't screw with it
4 but you should probably bring something of your own to the table, too.