As promised in my previous post, here is some information that may prove useful for those attempting to write USB drivers for Saffire 6USB Mk I (MkII is audio class 2 compliant and should not need a driver on Linux). Its not going to be that different for our other USB 1.1 products (Ultranova, VRM Box etc.) so could be extended for those devices later.
Before we get started, a word of warning – this is a work in progress and quite likely to be error prone, so please bear with us – we’ll try to correct any mistakes or omissions as they are discovered.
Finally, you may want to get access to a USB bus analyser, we find them incredibly useful for development!
Audio is transferred to and from Saffire 6USB on Interface 0, alternate setting 1. Endpoint 0x01 is the output, transmitting four channels, interleaved in 24-bit little-endian format. Endpoint 0x82 provides two channels of input in the same format.
Saffire 6USB runs from the USB SOF (start of frame) clock, as such it transfers a predictable number of samples for each 1ms USB frame.
At 48kHz, each packet contains 48 samples per channel. At 44.1kHz, its not possible to transfer an integer number of samples per frame, so instead we transmit / receive nine transfers of 44 samples followed by one of 45 samples (hence transferring 441 samples every 10ms).
To read and set the sample rate, we use the same format as for USB audio class devices, documented in section 188.8.131.52.1 and 184.108.40.206.3.1.
After changing sample rates, it is advisable to wait for a few hundred milliseconds before attempting to start transfers again (the device needs to resynchronise its PLL).
MIDI is transferred on Interface 1, transmitting up to 8 bytes of data per packet on endpoint 0x03, and receiving up to 16 bytes on endpoint 0x84. The format is raw MIDI, not USB class formatted. The hardware does not process the stream in any way, it just passes it directly to / from the physical ports.
No data will be transferred unless the device has been set to configuration 1.
Below is a dump of the device descriptor, in case it proves useful!
Device Descriptor Descriptor Version Number: 0x0100 Device Class: 0 (Composite) Device Subclass: 0 Device Protocol: 0 Device MaxPacketSize: 8 Device VendorID/ProductID: 0x1235/0x0010 (unknown vendor) Device Version Number: 0x0100 Number of Configurations: 1 Manufacturer String: 1 "Focusrite Audio Engineering" Product String: 2 "Saffire 6USB" Serial Number String: 0 (none) Configuration Descriptor Length (and contents): 64 Raw Descriptor (hex) 0000: 09 02 40 00 02 01 00 80 F9 09 04 00 00 00 FF 00 Raw Descriptor (hex) 0010: 00 00 09 04 00 01 02 FF 00 00 00 07 05 01 01 4C Raw Descriptor (hex) 0020: 02 01 07 05 82 01 26 01 01 09 04 01 00 02 FF 00 Raw Descriptor (hex) 0030: 00 00 07 05 03 03 08 00 01 07 05 84 03 10 00 01 Unknown Descriptor 0040: Number of Interfaces: 2 Configuration Value: 1 Attributes: 0x80 (bus-powered) MaxPower: 498 ma Interface #0 - Vendor-specific Alternate Setting 0 Number of Endpoints 0 Interface Class: 255 (Vendor-specific) Interface Subclass; 0 (Vendor-specific) Interface Protocol: 0 Interface #0 - Vendor-specific (#1) Alternate Setting 1 Number of Endpoints 2 Interface Class: 255 (Vendor-specific) Interface Subclass; 0 (Vendor-specific) Interface Protocol: 0 Endpoint 0x01 - Isochronous Output Address: 0x01 (OUT) Attributes: 0x01 (Isochronous no synchronization data endpoint) Max Packet Size: 588 Polling Interval: 1 ms Endpoint 0x82 - Isochronous Input Address: 0x82 (IN) Attributes: 0x01 (Isochronous no synchronization data endpoint) Max Packet Size: 294 Polling Interval: 1 ms Interface #1 - Vendor-specific Alternate Setting 0 Number of Endpoints 2 Interface Class: 255 (Vendor-specific) Interface Subclass; 0 (Vendor-specific) Interface Protocol: 0 Endpoint 0x03 - Interrupt Output Address: 0x03 (OUT) Attributes: 0x03 (Interrupt no synchronization data endpoint) Max Packet Size: 8 Polling Interval: 1 ms Endpoint 0x84 - Interrupt Input Address: 0x84 (IN) Attributes: 0x03 (Interrupt no synchronization data endpoint) Max Packet Size: 16 Polling Interval: 1 ms