Skip to content
Snippets Groups Projects
fc_protocol_usb.md 9.11 KiB
Newer Older
  • Learn to ignore specific revisions
  • Fadecandy: USB Protocol
    =======================
    
    To achieve the best CPU efficiency, Fadecandy uses a custom packet-oriented USB protocol rather than emulating a USB serial device. This simple USB protocol is easy to speak using cross-platform libraries like [libusb](http://www.libusb.org) and [PyUSB](http://pyusb.sourceforge.net/). Examples are included.
    
    If you use the included `fcserver` daemon, you need not worry about the USB protocol at all.
    
    Device Information
    ------------------
    
    Attribute       | Value
    --------------- | -----
    Vendor ID       | 0x1d50
    Product ID      | 0x607a
    Manufacturer    | "scanlime"
    Product         | "Fadecandy"
    Serial          | Unique ID string
    Device Class    | Vendor-specific
    
    Device Version  | See below
    
    Configurations  | 1
    Endpoints       | 1
    Endpoint 1      | Bulk OUT (Host to Device), 64-byte packets
    
    
    The Fadecandy device has one USB Configuration with two Interfaces:
    
    * **Interface #0** is a vendor-specific interface with one Bulk OUT endpoint for communicating control data and video keyframes.
    * **Interface #1** is compatible with the USB Device Firmware Update spec. It's used during firmware upgrade to ask the device to enter bootloader mode. During normal operation, it's safe to ignore this interface.
    
    
    Some device version codes may be used to indicate experimental or unofficial firmware. Currently, versions in the range 0x0300 through 0x03FF are reserved for unofficial Fadecandy firmware forks.
    
    
    Getting Started
    ---------------
    
    To use the Fadecandy Controller's USB protocol directly, you'll need to:
    
    1. **Search** for the device you're interested in. You can look for all Fadecandy devices by looking at the Vendor and Product IDs. You can find a specific Fadecandy device by looking at its USB serial number string.
    3. **Open** the device, and set its configuration. Depending on the operating system, you may also need to claim interface #0 so your application has exclusive access to it.
    4. Set up a **Color Look-Up Table**. There is no default table, the firmware expects you to calculate one based on the gamma and whitepoint you'd like to use.
    5. Send **Video Frames** at any time. When you complete a frame, the firmware immediately begins interpolating to it.
    
    There's a [minimal example](https://github.com/scanlime/fadecandy/blob/master/examples/python/usb-lowlevel.py) written in Python using PyUSB. It calculates a simple Color LUT and sends random video frames.
    
    To compare with the Color LUT calculation used by `fcserver`, see the [FCDevice::writeColorCorrection](https://github.com/scanlime/fadecandy/blob/47a4e551a71444923a1e6754f29f424e28a62090/server/src/fcdevice.cpp#L233) function in the fcserver source code.
    
    
    
    Bulk Endpoint
    -------------
    
    The device has a single Bulk OUT endpoint which expects packets of up to 64 bytes. Multiple packets may be transmitted in one LibUSB "write" operation, as long as the buffer you provide is a multiple of 64 bytes in length.
    
    Each packet begins with an 8-bit control byte, which is divided into three bit-fields:
    
    Bits 7..6  | Bit 5       | Bits 4..0
    ---------- | ----------- | ------------
    Type code  | 'Final' bit | Packet index
    
    * The 'type' code indicates what kind of packet this is.
    * The 'final' bit, if set, causes the most recent group of packets to take effect
    * The packet index is used to sequence packets within a particular type code
    
    The following packet types are recognized:
    
    Type code | Meaning of 'final' bit          | Index range | Packet contents
    --------- | ------------------------------- | ----------- | -------------------------------------
    0         | Interpolate to new video frame  | 0 … 24      | Up to 21 pixels, 24-bit RGB
    1         | Instantly apply new color LUT   | 0 … 24      | Up to 31 16-bit lookup table entries
    2         | (reserved)                      | 0           | Set configuration data
    3         |                                 |             | (reserved)
    
    Video Packets
    -------------
    
    In a type 0 packet, the USB packet contains up to 21 pixels of 24-bit RGB color data. The last packet (index 24) only needs to contain 8 valid pixels. Pixels 9-20 in these packets are ignored.
    
    Byte Offset   | Description
    ------------- | ------------
    0             | Control byte
    1             | Pixel 0, Red
    2             | Pixel 0, Green
    3             | Pixel 0, Blue
    4             | Pixel 1, Red
    5             | Pixel 1, Green
    6             | Pixel 1, Blue
    …             | …
    61            | Pixel 20, Red
    62            | Pixel 20, Green
    63            | Pixel 20, Blue
    
    Color LUT Packets
    -----------------
    
    In a type 1 packet, the USB packet contains up to 31 lookup-table entries. The lookup table is structured as three arrays of 257 entries, starting with the entire red-channel LUT, then the green-channel LUT, then the blue-channel LUT. Each packet is structured as follows:
    
    Byte Offset   | Description
    ------------- | ------------
    0             | Control byte
    1             | Reserved (0)
    2             | LUT entry #0, low byte
    3             | LUT entry #0, high byte
    4             | LUT entry #1, low byte
    5             | LUT entry #1, high byte
    …             | …
    62            | LUT entry #30, low byte
    63            | LUT entry #30, high byte
    
    Configuration Packet
    --------------------
    
    A type 2 packet sets optional device-wide configuration settings:
    
    Byte Offset | Bits   | Description
    ----------- | ------ | ------------
    0           | 7 … 0  | Control byte
    
    1           | 7 … 5  | (reserved)
    1           | 4      | 0 = Normal mode, 1 = Reserved operation mode
    
    1           | 3      | Manual LED control bit
    1           | 2      | 0 = LED shows USB activity, 1 = LED under manual control
    1           | 1      | Disable keyframe interpolation
    1           | 0      | Disable dithering
    2 … 63      | 7 … 0  | (reserved)
    
    
    The "reserved operation mode" may be used by unofficial Fadecandy firmware that includes experimental or application-specific effects. This reserved bit is guaranteed not to be used during normal operation by future versions of fcserver.
    
    
    Control Requests
    ----------------
    
    In addition to the OUT endpoint, the device also supports vendor-specific control requests:
    
    bmRequestType | bRequest | wValue | wIndex | wLength | Description
    ------------- | -------- | ------ | ------ | ------- | ---------------------------------------------
    0xC0          | 0x01     | 0      | 0      | 4       | Read rendered frame counter (32-bit, little endian)
    0xC0          | 0x01     | 0      | 1      | 4       | Read received keyframe counter (32-bit, little endian)
    0xC0          | 0x7E     | x      | 4      | x       | Read Microsoft WCID descriptor
    0xC0          | 0x7E     | x      | 5      | x       | Read Microsoft Extended Properties descriptor
    
    
    USB Descriptors
    ---------------
    
    For reference, this is sample output from the Mac OS X [USB Prober](https://developer.apple.com/library/mac/qa/qa1370/_index.html) diagnostics tool:
    
    	Full Speed device @ 15 (0x14200000): Composite device: "Fadecandy"
    	    Port Information:   0x101a
    	           Not Captive
    	           Attached to Root Hub
    	           External Device
    	           Connected
    	           Enabled
    	           Connected to External Port
    	    Number Of Endpoints (includes EP0):   
    	        Total Endpoints for Configuration 1 (current):   2
    	    Device Descriptor   
    	        Descriptor Version Number:   0x0200
    	        Device Class:   0   (Composite)
    	        Device Subclass:   0
    	        Device Protocol:   0
    	        Device MaxPacketSize:   64
    	        Device VendorID/ProductID:   0x1D50/0x607A   (unknown vendor)
    	        Device Version Number:   0x0108
    	        Number of Configurations:   1
    	        Manufacturer String:   1 "scanlime"
    	        Product String:   2 "Fadecandy"
    	        Serial Number String:   3 "ENICCULVLDQJQDWD"
    	    Configuration Descriptor (current config)   
    	        Length (and contents):   43
    	            Raw Descriptor (hex)    0000: 09 02 2B 00 02 01 00 80  32 09 04 00 00 01 FF 00  
    	            Raw Descriptor (hex)    0010: 00 00 07 05 01 02 40 00  00 09 04 01 00 00 FE 01  
    	            Raw Descriptor (hex)    0020: 01 04 09 21 0D 10 27 00  04 01 01 
    	        Number of Interfaces:   2
    	        Configuration Value:   1
    	        Attributes:   0x80 (bus-powered)
    	        MaxPower:   100 mA
    	        Interface #0 - Vendor-specific   
    	            Alternate Setting   0
    	            Number of Endpoints   1
    	            Interface Class:   255   (Vendor-specific)
    	            Interface Subclass;   0   (Vendor-specific)
    	            Interface Protocol:   0
    	            Endpoint 0x01 - Bulk Output   
    	                Address:   0x01  (OUT)
    	                Attributes:   0x02  (Bulk)
    	                Max Packet Size:   64
    	                Polling Interval:   0 ms
    	        Interface #1 - Application Specific/Device Firmware Update "Fadecandy Bootloader"
    	            Alternate Setting   0
    	            Number of Endpoints   0
    	            Interface Class:   254   (Application Specific)
    	            Interface Subclass;   1   (Device Firmware Update)
    	            Interface Protocol:   1
    	            DFU Functional Descriptor   
    	                bmAttributes:   0x0d (Download, No Upload, Manifestation Tolerant, Reserved bits: 0x08)
    	                wDetachTimeout:   10000 ms
    	                wTransferSize:   1024 bytes