Tuesday, October 30, 2012

Kobo surgery

A few weeks ago my Kobo Wifi e-reader suffered an unfortunate accident. I got caught in a thunderstorm and the pocket of my messenger bag filled with water. (Good: my Brooks Barbican bag is waterproof. Bad: water can't get out once it's in.) It was a few hours before I noticed that my Kobo had been partly submerged for an extended period. The poor thing just displayed a plaintive "Please Charge Your eReader" message. Pressing the power button caused some lights to flash, but no activity on the screen. It wasn't completely dead, but it wasn't working either.

Coincidentally, the next day my friend Roo tweeted that he'd dropped his Kobo and broken the screen. I suspected that between the two of us we probably had enough parts to build a working Kobo, so I arranged to collect his e-reader so I could try to rebuild one.
Dead board (left) dead screen (right)
The first step was opening the cases. The Kobo cases just snap together, so you can pry them apart fairly easily. Be careful as you risk cracking the case if you bend it too much. I damaged the white case a bit but was able to get the black one off without any problem. The board is attached to the rear half of the case with four Phillips screws which are easily removed.
Naked Kobos

The Kobo is fairly simple inside. The e-ink screen is mounted on the circuit board and connected to it with a flexible flat cable which wraps over the right-hand side of the board to a plug on the reverse. There's a lithium-polymer battery in the lower left hand corner, and you can see the 5 buttons of the rubber navigation pad in the lower right corner.
Removing the screen.
It took me a while to figure out how the screen was attached. I was worried that it might be glued to to board. Fortunately, it's quite easy to remove once you know that it's only attached with four strips of double sided tape.

First, unplug the flexible connector, but be careful! The plug has a plastic clamp to hold the connector in place. These break easily and without the clamp you'll get a poor connection. You need to disconnect this so that you can have unobstructed access to the edge of the screen.

I found that a thin utility blade slipped easily between the screen and the board. Just run this around all four edges and you'll loosen the tape. The tape will re-adhere pretty quickly, but it's quite easy to pry the screen off with your fingers once you've cut through the tape.
Screen detached. You can see where the four pieces of tape were.
Once both screens were off it was a simple matter to swap them. The boards also have Micro-SD cards which are used to store your books. (This is in addition to the SD expansion slot at the top of the card. This means that if you want to expand your Kobo's capacity you could probably easily replace the 2GB Micro-SD card with a larger one.) I swapped the Micro-SD cards, too.
It's alive!
While it was open, my friend Trammell pointed out that there were some connectors near the navigation pad which looked suspiciously like a serial port. (They were marked Tx and Rx, which was a bit of a give-away!) We connected it to a terminal emulator and were able to watch the Linux kernel boot as the Kobo powered on. It seemed a shame to hide that in the case, so before I put the case back on Trammell helped me make a few small modifications. We added a small hole to the case and soldered a connector onto the serial port.
Serial connector. From top to bottom: V, Tx, Rx
I haven't played much with the serial port yet, but I expect it might expose some interesting opportunities.

After swapping the Micro-SD cards the new Kobo showed all of my books in my library, but would only let me read some of them. This suggests that the DRM scheme is tied to some serial number on the device, and also that not all books are protected by DRM. I did a factory reset on the Kobo, connected it to my laptop and resynced all of my books. This made all the books readable again.

Sunday, September 23, 2012

A Modest Proposal

For Minimizing the Obstruction of Bike Lanes in New York, and for Making the Department of Police Beneficial to the Publick.

NYPD at work
NYPD tow truck parked at 6th Ave and 32nd St
This morning at about 10:30 I encountered this oversized New York Police Department tow truck straddling the bike lane on 6th Avenue at 32nd Street. While I was watching, one of the officers returned to the truck with coffees, but, even caffeinated, they remained firmly in place, ignoring the cyclists (photographed) who had to detour into motor traffic to pass them. Particularly irksome is that they've pulled half way into the bike lane, but they're still obstructing a full lane of motor traffic. Instead of just blocking one lane, they're blocking two. (Also note that one of the cyclists photographed is going the wrong way, a.k.a. salmoning)

Taxis, town cars, delivery trucks, private cars and cops regularly block New York's otherwise excellent network of bike lanes (as, apparently, do fruit and vegetable carts). Many of the lanes are segregated, making it more challenging for drivers to block them, but many others, like the one pictured, are just painted and we rely on drivers' respect for the law and fellow road users to keep them clear. Like in other cities, this is a bit of wishful thinking, and given the poor example set by law enforcement it's not surprising that other drivers treat these lanes as short-term parking.

On Friday, over beers with some cow-orkers, I formulated a proposal which I think might be a pragmatic compromise to improve access to unobstructed bike lanes. First, we must recognize that we're not going to change the behavior of the police. So, instead of just complaining and building up resentment (as I've done above), let's work with them.

I propose that all unsegregated bike lanes in New York City be redesignated as police parking lanes. Let's change the bylaws so that these lanes are reserved for use by law enforcement, with an exception allowing cyclists to use them when they're not required for urgent police business (like the morning coffee run). We'll paint NYPD logos in the lanes alongside the cycling icons.

My theory is that the NYPD will be much more aggressive about ticketing motor vehicles obstructing police parking lanes. Those are their lanes! Other drivers aren't going to mess with the NYPD's parking lanes.

For cyclists, this Faustian bargain could significantly improve access to the approximately 1% of New York City's paved road surface currently designated as bike lanes. Of course we'd still have to swerve around parked cop cars, but at least the number of SUVs, FedEx trucks and taxis in the lanes would be lower.

Monday, May 7, 2012

In praise of idleness

C has some odd baggage in its APIs, but one API which I think ought to be emulated more often is free(). Specifically, free(NULL).

Many programmers don't realize that you can pass a NULL pointer to free() and that this has no effect. This isn't undefined behaviour. It's specified to work like that: If ptr is a null pointer, no action shall occur.

This makes cleanup code simpler. Instead of
  if (ptr != NULL) free(ptr);
you can just use
  free(ptr);

This has a number of advantages.

First of all, it reduces the amount of code you need to write for mundane housekeeping tasks.

Secondly, it encourages good habits (freeing memory when you're done with it) by not punishing programmers for using it. If free() crashed when called with a NULL pointer (or worse, corrupted memory) that would discourage programmers from using it. While it doesn't really reward you for writing good code, at least it doesn't kick you in the shin.

Finally, it's consistent with an unfortunate misfeature of its companion, malloc(). malloc(0) is permitted to return NULL. At least you can always pass the result of malloc() to free().

Unfortunately, many other common APIs don't follow free()'s good example. close(-1) and pthread_mutex_destroy(NULL) both invoke undefined behaviour, for example. (And don't get me started about zero as a legal file descriptor!)

Whenever I'm designing my own APIs which include destructor-style functions, I always try to make sure that they quietly ignore NULL. It just makes life simpler for users.

Tuesday, April 10, 2012

Frickin' lasers!

My apartment in New York is great. It's close to Central Park, close to the subway and close to Momofuku Milk Bar. But it's pretty small. Especially the kitchen. My kitchen drawers are only about six inches wide. Finding a cutlery organizer which fits in the drawer is pretty well impossible. So what to do? Build one!

Fortunately, one of my colleagues has access to a laser cutter at NYC Resistor. He helped me build a completely custom cutlery organizer which fits both my drawer and my cutlery perfectly.

Step 1: build a prototype from cardboard to check the dimensions and functionality.


Step 2: Using InkScape, design all of the pieces (with raster images which are etched with the laser at low power).

Step 3: Bring on the laser!

Step 4: Prepare all the pieces


Step 5: Put it all together!


Step 6: A perfect fit!

Next I'm going to build a small tray to sit on top of this one, giving me a bit of additional storage space for little utensils.

Sunday, March 25, 2012

C99 designated initializers

One of the very nice features added in C99 is the designated initializer. This allows you to write code like the following to initialize a structure:

    div_t d = { .quot=3, .rem=2 };

In C89 there was no way to reliably initialize a structure like this. The specification says that the quot and rem members may be in any order, so if you write:

    div_t d = { 3, 2 };

you can't be sure which member will be 3 and which will be 2.

In general I'm enamored with designated initializers. But I've run into an unfortunate case where the specification is somewhat ambiguous.

Paragraph §6.7.8.19 of the C99 standard (draft version available for free here) has this to say about the ordering of designated initializers:

  1. The initialization shall occur in initializer list order, each initializer provided for a particular subobject overriding any previously listed initializer for the same subobject;130 all subobjects that are not initialized explicitly shall be initialized implicitly the same as objects that have static storage duration.
(Footnote 130 reads "Any initializer for the subobject which is overridden and so not used to initialize that subobject might not be evaluated at all.")

The spec says that "initialization shall occur in initializer list order". To me, this suggests that one initializer can safely rely on the result of a previous initializer, e.g.:

    div_t d = { .quot=42, .rem=d.quot };

So the following program ought to only invoke well defined behaviour, right?

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    div_t d1 = { .quot=1, .rem=2, };
    printf("d1: quot=%i, rem=%i\n", d1.quot, d1.rem);

    div_t d2 = { .quot=1, .rem=d2.quot };
    printf("d2: quot=%i, rem=%i\n", d2.quot, d2.rem);

    div_t d3 = { .rem=2, .quot=d3.rem };
    printf("d3: quot=%i, rem=%i\n", d3.quot, d3.rem);

    return 0;
}

Let's compile it and see what happens:
  1. $ gcc -c99 -O3 -Wall -Wextra foo.c
    $ ./a.out
    d1: quot=1, rem=2
    d2: quot=1, rem=1
    d3: quot=2, rem=2

Excellent! That exactly what I would expect to happen. The initializers are run in order, allowing the second designated initializer to depend on the result of the first.

Now here's where things start to get weird:
  1. $ gcc -c99 -O0 -Wall -Wextra foo.c
    $ ./a.out
    d1: quot=1, rem=2
    d2: quot=1, rem=0
    d3: quot=0, rem=2

If we turn off optimization (-O0) the results suddenly change! Even worse, I've compiled with maximum warnings (-Wall -Wextra) and GCC doesn't even issue a warning about using an uninitialized variable!

How can we reconcile this behaviour with the specification? I think that we need to take paragraph §6.7.8.23 into account, as well:

  1. The order in which any side effects occur among the initialization list expressions is unspecified.131

(Footnote 131 reads "In particular, the evaluation order need not be the same as the order of subobject initialization.")

This suggests that evaluation and initialization are two separate steps: an implementation may evaluate all of the initialization expressions (in any order), record the results in temporary storage, and then apply them all in order. If you inspect the generated assembly code this does seem to match what happens in GCC at -O0.

So why have paragraph 19 at all? I don't see how you could write a C program which can observe the initialization order, except for the special case of one designated initializer overriding another. If that is its only purpose the specification could certainly be more explicit about it. (It's also possible that the specification has actually been clarified in this respect; I don't have access to the final version.)

I've tried this test case with a handful of different compilers and get similar results. However I would be curious to hear about results with other C99 compilers.

Update

It's been a while since I updated this blog. I've been a bit busy, but new articles will start appearing shortly. Since my last post, I have left IBM Canada and joined Two Sigma Investments in New York. I'm no longer developing virtual machines, but the name and scope of the blog will remain the same. I'm still doing low-level software development and I'm learning a lot about areas I haven't investigated in depth before, and from my new colleagues.