Tuesday, June 28, 2011

Towards decent mouse wheel support in Android

One thing everyone would notice on attaching a USB mouse to an Android device is that mouse wheel is not supported, which makes interaction very tedious. I take a quick look at the state of its support.

Android-x86 project advertises mouse wheel support, but looking at their patch, they translate mouse wheel clicks into up/down buttons. That's better than not supporting wheel at all of course, but still not intuitive usage. What I'd like to have is not analog of up/down key press, but actual scroll, i.e. analog of drag.

But probably, such behavior couldn't be reliably emulated on the lower level of input processing, (or this might lead to adverse effects, like mouse wheel movement interpreted as click). Instead, higher-level controls should have explicit support for discrete scroll events. For example this event handler block should be factored out to be callable for such event and be passed just deltaY.

Of course, that would be more or less big refactor, so another approach would be just waiting until Google thinks it gave enough competitive advantage to big vendors over small and finally releases 3.0+ source code, which supposedly implements wheel support.

Monday, June 27, 2011

Links for June 2011

Sunday, June 26, 2011

Hacking Luxeon SP-1

I finally going to get Arduino, and while I'm choosing flavor and waiting for it, I can't help but disassembling all devices I have at home, each time speaking: "This must have Arduino inside!" (meaning of course that I expect it to be based on general-purpose MCU). Gosh, I usually get "blob chip" (uncased chip with blob of epoxy on top).

Well, I finally had my expectations fulfilled - Luxeon SP-1 voltage stabilizer/cutter features ATMEGA48V-10PU (Flash: 4k, EEPROM: 256, RAM:512). Not only that, it is installed in DIP socket! Buy from Luxeon, they're hacker-friendly ;-).

I bought the device actually for a wattmeter it features (which fact is hard to figure out from common specs found in the shops, I accidentally read somebody mentioning it on a forum). The wattmeter is of course not bright - for a lamp rated 100W it shows 88W, and for more powerful equipment (like perforator) understates wattage even more (maybe it's difference between real and apparent power factor).

Still, for $17 you get Arudino-alike with voltage/current sensor and hacking possibility. Woot!

BOM:
High-power board:
  • Relay: Coil: 24VDC, 5A/240VAC
  • 7805
  • Coil transformer LR-019B
MCU board:
  •  ATMEGA48V-10PU
  • 2 buttons
  • 2 LEDs (red & green)
  • 3-digit 7-segment LED indicator

    Hacking Technoline WS 585 weatherstation


    Technoline WS 585 is a simple consumer weatherstation offering builtin indoor temperature sensor and outdoor wireless (433MHz) temperature sensor. But as funny extra, it comes with wireless USB dongle which, being attached to computer running special (Windows) software, transmits to the base station weather forecast for next few days as well as extra weather data for today.

    There're two problems with that: I prefer my weather forecast site, not one hardcoded by the vendor, and, I don't have constantly running Windows box. Besides, this device is essentially low-resolution wireless LCD (albeit with funny pixel shape), so one may want to show build status or loadavg on it.

    So, I wanted to hack a Linux driver for it for a long time. Wider-scope, I wanted to grok USB and hack driver for it for longer time. Few times before I had a look at usbsnoop log of something, It seemed for overwhelming and I didn't really put much effort into it.

    So well, I read up USB docs (Usb in a NutShell is a good summarization of the spec), and started to look at USB descriptors and logs with understanding eye.

    Here are info and descriptors for WS585 dongle btw:

    dmesg:

    [1118327.253222] usb 2-1.3: new low speed USB device using ehci_hcd and address 3
    [1118327.524340] usbcore: registered new interface driver hiddev
    [1118327.527975] input: Tenx Non standard Device as /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.3/2-1.3:1.0/input/input51
    [1118327.528162] generic-usb 0003:1130:0202.0001: input,hidraw0: USB HID v1.10 Device [Tenx Non standard Device] on usb-0000:00:1d.0-1.3/input0
    [1118327.530011] input: Tenx Non standard Device as /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.3/2-1.3:1.1/input/input52
    [1118327.530182] generic-usb 0003:1130:0202.0002: input,hidraw1: USB HID v1.10 Device [Tenx Non standard Device] on usb-0000:00:1d.0-1.3/input1
    [1118327.530554] usbcore: registered new interface driver usbhid
    [1118327.530557] usbhid: USB HID core driver

    lsusb:
    Bus 002 Device 003: ID 1130:0202 Tenx Technology, Inc. 

    lsusb -v:

    Device: ID 1130:0202 Tenx Technology, Inc. 
    Device Descriptor:
      bLength                18
      bDescriptorType         1
      bcdUSB               1.10
      bDeviceClass            0 (Defined at Interface level)
      bDeviceSubClass         0 
      bDeviceProtocol         0 
      bMaxPacketSize0         8
      idVendor           0x1130 Tenx Technology, Inc.
      idProduct          0x0202 
      bcdDevice            1.00
      iManufacturer           0 
      iProduct                2 Tenx Non standard Device
      iSerial                 0 
      bNumConfigurations      1
      Configuration Descriptor:
        bLength                 9
        bDescriptorType         2
        wTotalLength           59
        bNumInterfaces          2
        bConfigurationValue     1
        iConfiguration          0 
        bmAttributes         0x80
          (Bus Powered)
        MaxPower              100mA
        Interface Descriptor:
          bLength                 9
          bDescriptorType         4
          bInterfaceNumber        0
          bAlternateSetting       0
          bNumEndpoints           1
          bInterfaceClass         3 Human Interface Device
          bInterfaceSubClass      0 No Subclass
          bInterfaceProtocol      0 None
          iInterface              0 
            HID Device Descriptor:
              bLength                 9
              bDescriptorType        33
              bcdHID               1.10
              bCountryCode            0 Not supported
              bNumDescriptors         1
              bDescriptorType        34 Report
              wDescriptorLength      41
             Report Descriptors: 
               ** UNAVAILABLE **
          Endpoint Descriptor:
            bLength                 7
            bDescriptorType         5
            bEndpointAddress     0x81  EP 1 IN
            bmAttributes            3
              Transfer Type            Interrupt
              Synch Type               None
              Usage Type               Data
            wMaxPacketSize     0x0008  1x 8 bytes
            bInterval              10
        Interface Descriptor:
          bLength                 9
          bDescriptorType         4
          bInterfaceNumber        1
          bAlternateSetting       0
          bNumEndpoints           1
          bInterfaceClass         3 Human Interface Device
          bInterfaceSubClass      0 No Subclass
          bInterfaceProtocol      0 None
          iInterface              0 
            HID Device Descriptor:
              bLength                 9
              bDescriptorType        33
              bcdHID               1.10
              bCountryCode            0 Not supported
              bNumDescriptors         1
              bDescriptorType        34 Report
              wDescriptorLength      23
             Report Descriptors: 
               ** UNAVAILABLE **
          Endpoint Descriptor:
            bLength                 7
            bDescriptorType         5
            bEndpointAddress     0x82  EP 2 IN
            bmAttributes            3
              Transfer Type            Interrupt
              Synch Type               None
              Usage Type               Data
            wMaxPacketSize     0x0008  1x 8 bytes
            bInterval              10
    Device Status:     0x0000
      (Bus Powered)

    So, it uses well-known programmable microcontroller chip from Tenx Technology, found in bunch of other devices like USB missile launchers, etc.

    By the end of day I had a PyUSB app which implemented the protocol seen in usbsnoop log. It received all the same (way, similar) responses from the chip. But it didn't exhibit external behavior. Specifically, under Windows, LED on the dongle blinks about every 55s (sic, less than whole minute), and right at the same time weather station updates its display. Under Linux with my app, LED never blinks, and no updates are shown on the display. I tried to to adjust my app to use the same delays between requests as seen in the original log, but no avail.

    So, I have 2 ideas here: I made some mistake transcribing log into PyUSB calls, or, it's all timing related, and I didn't get the timing right. I tried to capture USB log around the blink, and don't see any request which could make explicit "transmit" request. I have following hypothesis: base station doesn't listen air all the time, it turns on it radio only ~ once a minute. So, dongle at first synchronizes to the base station. Then, it just transmits data at predefined intervals. And control requests from host don't transmit stuff immediately, but put it into buffer for the next transmission.

    Is that true or not, hard to tell. But this device is for sure more complicated than other Tenx-based ones due to its wireless and trickle-transmit features.

    I've put my current code together with USB logs to git at https://gitorious.org/homeauto/homeauto-devices

    Sunday, June 12, 2011

    Comparison of OpenSource PDF readers for Android


    Today we're going to review few open-source PDF readers for Android platform. The table below provides links and feature-by-feature comparison, with more detailed discussion of features below the table. It should be noted that all these readers are based on the same PDF rendering library - MuPDF, so offer roughly the same rendering quality, the differences may be only due different version of the library used, or different configuration options (for example, some readers compile MuPDF without JPEG2000/JBIG support, or without standard PDF fonts).

    The review summarizes with expectable conclusion - there's no perfect reader so far, but selects clear winner, which is worth to be hacked on.

    Feature DroidReader 0.5 APV aka PDFViewer 0.2.9 VuDroid 1.4 MuPDF Android Client 0.8.165
    Builtin open file - + + -
    On-screen zoom - + + +
    Continuous pages - + + -
    Page smaller than screen - (force close on attempt) + - -
    In-app rotate + + - -
    Go to page + + + -
    Table of contents - - - -
    Find text - + - -
    JPEG2000/JBIG - (doesn't recognize pdf) + - +
    Other formats - - DJVU -

    • Builtin open file - whether you can start application and select file to view, or must have a compatible file manager and open PDF in it using "open with".
    • On-screen zoom - whether you can zoom by direct manipulation on screen (like, pinch zoom, zoom in/out widgets) or need to go to menu. Needless to say, without on-screen zoom a reader is hard to use for real reading.
    • Continuous pages - whether you see single page at time and need to use explicit next/prev page actions, or can just scroll a page away and see next/previous page. (Arguably, continuous page reading is easier and more productive.)
    • Page smaller than screen - whether you can zoom out page so it is smaller than screen. For continuous pages reader, that would mean showing more than 2 pages at the same time on the screen. While this seems like neat feature, it actually just complicates real reading, when you need to take extra care to zoom back carefully after occasional zoom-in. (That's of course why most apps don't bother to implement it.)
    • In-app rotate - whether app has own support for rotating pages, or relies on OS to support rotation. Got a vendor-crippled device without OS support for rotation? You're lost without in-app rotate, so that's boon.
    • Go to page - basic navigation feature. That's not much convenient for real reading, but without this, you can't do any real reading at all.
    • Table of contents - real navigation. For an app to be really usable, it must support this. Nope of apps in review does though.
    • Find text - other very useful navigational feature. You hardly can read technical/reference docs without this.
    • JPEG2000/JBIG images support - Apps which doesn't support these images format don't really support PDF, just some crippled subset of it.
    • Other formats support: You found your perfect PDF reader? Congrats, now repeat that for all other ebook formats you use. Don't wanna waste time like that? Choose readers which support all reasonably similar formats. For already typeset ebook, there're actually two formats: PDF & DJVU, so good reader should support both. For TXT, HTML, CHM you indeed would rather look for different reader with different featureset.

    And the winner is...

    Based on the table above, the clear winner is VuDroid: it supports both typeset-ebook formats, PDF & DJVU, and has reasonable usability features (like has limit for page zoom out, as well as adjusts zoom on rotation). One serious, but easy to fix thing lack of JPEG2000/JBIG support (fixable by extending MuPDF config). Other thing it lacks comparing to APV is text find. Well, all readers in review lack ToC support, which a perfect reader must have. Back to VuDroid, it's UI is rather bare - there's no even About dialog, so you can't know that you're running VuDroid at all, or its version!