I’m fed up of making notes on scrappy bits of paper that I lose, so with some money I got for Christmas I got myself a Boogie Board Rip. I’m not going to do a full-blown review here, but essentially it’s an etch-a-sketch on top of a portable graphics tablet. The graphics tablet bit is battery powered, and converts what you draw to PDF. The PDFs can be accessed by plugging the board into a PC via a Micro USB cable. Some people complain that it’s not very good for drawing, but I only wanted it for writing and it’s great for that.

After using the board for a couple of days, it turns out that as well as appearing as a USB storage device when plugged in, it also appears as a human interface device and spits out a stream of binary (32 bytes of it to be exact) for each event that occurs on the device (button presses, movement of the stylus, etc). With a bit of help from the aforementioned blog post I’ve managed to decode the binary and write a short Ruby script that reports what’s happened each time you do something.

The script as it stands at time of posting is shown below. The latest version is available on github.

begin
    lsusb = `lsusb`
    if lsusb.split("\n").select{|l| l.include? "2047:ffe7"}.count == 
        raise "Boogie Board Rip not currently connected"
    end

    begin
        dmesg = `dmesg`
        bbdev = dmesg.split("\n").select{|l| l.match "2047:FFE7.*hidraw[0-9]"}.pop.match("(hidraw[0-9]+)").to_s
        raise RuntimeError if bbdev.empty? 
    rescue NoMethodError, RuntimeError
        raise "Boogie Board Rip detected, but device's path could not be determined"
    end

    events = []
    threads = []

    thread = Thread.new do
        board = File.new("/dev/"+bbdev, 'r')
        while true do
            data = board.sysread(32)
            event = Array.new()
            data.bytes { |b| event << b }
            events << event
        end
    end
    threads << thread

    thread = Thread.new do
        previous = Array.new(32, )
        current = []
        while true do
            current = events.shift
            next if current.nil?

            if current[10] != previous[10]
                state = current[10]
                pstate = previous[10]
                lock = 32
                erase = 4
                wake = 2
                if (pstate == pstate | lock) && (state != state | lock)
                    puts "Board unlocked"
                elsif (pstate != pstate | lock) && (state == state | lock)
                    puts "Board locked"
                end
                if (pstate == pstate | erase) && (state != state | erase)
                    puts "Erase released"
                elsif (pstate != pstate | erase) && (state == state | erase)
                    puts "Erase Pressed"
                end
                if (pstate == pstate | wake) && (state != state | wake)
                    puts "Wake released"
                elsif (pstate != pstate | wake) && (state == state | wake)
                    puts "Wake Pressed"
                end
            end
            if current[3] != previous[3]
                state = current[3]
                pstate = previous[3]
                detected = 32
                contact = 1
                if (pstate == pstate | detected) && (state != state | detected)
                    puts "Pen Lost"
                elsif (pstate != pstate | detected) && (state == state | detected)
                    puts "Pen Detected"
                end
                if (pstate == pstate | contact) && (state != state | contact)
                    puts "Pen contact lost"
                elsif (pstate != pstate | contact) && (state == state | contact)
                    puts "Pen contact detected"
                end
            end
            cury = current[4]+(current[5]*256)
            curx = current[6]+(current[7]*256)
            prey = previous[4]+(previous[5]*256)
            prex = previous[6]+(previous[7]*256)
            if cury != prey || curx != prex
                puts "Pen moved from ("+prex.to_s+","+prey.to_s+") to ("+curx.to_s+","+cury.to_s+")"
            end    
            previous = current
        end
    end
    threads << thread

    threads.each{ |thread| thread.join}
    
rescue RuntimeError => error
    puts error
end

It’s very rudimentary at the moment, and needs to be run as root so the device can be accessed, but hopefully with a bit more hacking I’ll be able to get something graphical up and running. It also strikes me that you should be able to use the Boogie Board like a Wacom tablet if someone would be good enough to write a device driver. It’s a bit beyond me but the information’s pretty much all there in the script!