REST service with per-device calibration data / Documentation of non-HID USB interface


#1

Apologies if this is the wrong place to ask this question. Currently, the Looking Glass SDK targets macOS and Windows only. In particular, the code to read the device-specific calibration data relies on a OS-specific binary that reads data directly via USB. I am looking for ways to enable convenient ways to enable the Looking Glass on other platforms such as Linux and the Browser. The only way, I got this working so far is by providing a way to load the Quilt.Config from a configuration file LKG_calibration/visual.json that one must previously export from macOS or Windows.

I have basically two questions:

  1. I can see that each Looking Glass has a unique serial number. Do you store the calibration data at the factory? If so, could you provide a way to obtain each device’s configuration file by its serial number? That way, a user would only need to type their serial number into a form field and the application could download the necessary configuration.

  2. Are you willing to document your USB protocol? In particular, is there a way to read the config/buttons without going through USB HID (which is not supported by WebUSB any longer)?

I can see that the Looking Glass supports HID (presumably to avoid custom drivers on Windows) and two additional interfaces. I didn’t attach a USB protocol analyzer: Are those endpoints capable of exposing the calibration data and/or button events?

Cheers,
Heiko

DEVICE ID 04d8:ef7e on Bus 020 Address 019 =================
 bLength                :   0x12 (18 bytes)
 bDescriptorType        :    0x1 Device
 bcdUSB                 :  0x200 USB 2.0
 bDeviceClass           :   0xef Miscellaneous
 bDeviceSubClass        :    0x2
 bDeviceProtocol        :    0x1
 bMaxPacketSize0        :   0x40 (64 bytes)
 idVendor               : 0x04d8
 idProduct              : 0xef7e
 bcdDevice              :  0x100 Device 1.0
 iManufacturer          :    0x1 Unknown
 iProduct               :    0x2 HoloPlay
 iSerialNumber          :    0x3 C
 bNumConfigurations     :    0x1
  CONFIGURATION 1: 500 mA ==================================
   bLength              :    0x9 (9 bytes)
   bDescriptorType      :    0x2 Configuration
   wTotalLength         :   0x64 (100 bytes)
   bNumInterfaces       :    0x3
   bConfigurationValue  :    0x1
   iConfiguration       :    0x0 
   bmAttributes         :   0xa0 Bus Powered, Remote Wakeup
   bMaxPower            :   0xfa (500 mA)
    INTERFACE 0: CDC Communication =========================
     bLength            :    0x9 (9 bytes)
     bDescriptorType    :    0x4 Interface
     bInterfaceNumber   :    0x0
     bAlternateSetting  :    0x0
     bNumEndpoints      :    0x1
     bInterfaceClass    :    0x2 CDC Communication
     bInterfaceSubClass :    0x2
     bInterfaceProtocol :    0x0
     iInterface         :    0x0 
      ENDPOINT 0x81: Interrupt IN ==========================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x81 IN
       bmAttributes     :    0x3 Interrupt
       wMaxPacketSize   :   0x10 (16 bytes)
       bInterval        :   0x40
    INTERFACE 1: CDC Data ==================================
     bLength            :    0x9 (9 bytes)
     bDescriptorType    :    0x4 Interface
     bInterfaceNumber   :    0x1
     bAlternateSetting  :    0x0
     bNumEndpoints      :    0x2
     bInterfaceClass    :    0xa CDC Data
     bInterfaceSubClass :    0x0
     bInterfaceProtocol :    0x0
     iInterface         :    0x0 
      ENDPOINT 0x2: Bulk OUT ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :    0x2 OUT
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :   0x40 (64 bytes)
       bInterval        :    0x0
      ENDPOINT 0x83: Bulk IN ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x83 IN
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :   0x40 (64 bytes)
       bInterval        :    0x0
    INTERFACE 2: Human Interface Device ====================
     bLength            :    0x9 (9 bytes)
     bDescriptorType    :    0x4 Interface
     bInterfaceNumber   :    0x2
     bAlternateSetting  :    0x0
     bNumEndpoints      :    0x1
     bInterfaceClass    :    0x3 Human Interface Device
     bInterfaceSubClass :    0x0
     bInterfaceProtocol :    0x0
     iInterface         :    0x0 
      ENDPOINT 0x84: Interrupt IN ==========================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x84 IN
       bmAttributes     :    0x3 Interrupt
       wMaxPacketSize   :   0x40 (64 bytes)
       bInterval        :    0x1

#2

Hi Heiko,

Yep, the Looking Glass identifies as a USB joystick (for the button data) and packs calibration into the HID packets.

All of our SDKs include a small binary that requests the calibration data from the internal MCU and returns it as a json string. I’ve compiled this under Linux and it works, but we’re primarily a Mac/Windows office and so it has not been tested as exhaustively as the other versions.

As for browser-based Looking Glass projects - our three.js SDK should be live soon, so if you are interested in building WebGL applications I would just recommend waiting for it to release! If you’re curious about how that loads calibration, I also went through the whole issue with WebUSB and ended up abandoning it for another solution - a driver that will pass calibration to three.js (or any other) applications via websocketd running on localhost.

tl;dr I’ve already built most of what you’re requesting but it is as yet unreleased and untested - we’ll see what we can get you in the near future.

Loved Piny Wings btw, and I remember checking out your Rocky Reality port on Pebble when it came out. Small world!

Evan


#3

Hey Evan,

Ha! Nice to read that someone remembers Piny Wings and Rocky Reality :slight_smile: You might enjoy Intrinsic Gravelty too.

I am particularly interested in running a Looking Glass experience in a browser without downloading + installing any additional programs (e.g. an “untrusted” extra application that proxies USB to make it accessible via web sockets). The experience I am striving for is basically “zero-install for end-users” when visiting a website while having a Looking Glass attached.

Do you have answers about the REST service (would reduce the UX to entering a serial number) or if there’s a way to access the USB data via WebUSB? You mentioned that you discarded that approach at some point?

Maybe the announced App Library browser could act as a proxy similar to the websocketd (assuming most end-users will have it installed anyway)?
Also, if you happen to need beta-testers for Linux, I could try it out for you.

Heiko


#4

Unfortunately we don’t have a publicly accessible database of calibrations linked to serial number.
I did look into loading this calibration via WebUSB but as you may know this standard is a bit of a shitshow – WebUSB support was yanked entirely from Chrome earlier this year, due to a security concern involving web apps sniffing hardware auth keys. It seems a fair bet that with so much desktop functionality making its way to the web that a more secure implementation will reappear in Chrome and the other major browsers within the next year or so, but the dust has yet to settle on browser support so I’m going to wait for a little while before I take another crack at it.

I did prototype a JS calibration loader with chrome.hid, but that library is only available in Chrome apps, which also requires an installation step - also, the entire Chrome app store is getting axed in the next year or so anyways. The final nail in the coffin was that Chrome apps are sandboxed from sending information to other open webpages (for security reasons similar to those that caused the demise of WebUSB); so even once I could get the data into the browser I couldn’t find an easy way to get it to another open tab without doing something horrible like forwarding it via an external server.

Suggestion re: app library is not a bad one – no matter what, I’m sure there will be a more seamless way to do this very soon.