Hypfer / fiio-bta30-protocol

Documentation on the BLE protocol of the FiiO BTA30 DAC & Bluetooth Transceiver

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Motivation

The FiiO BTA30 is a Hi-Fi-grade DAC and Bluetooth Transceiver, featuring USB-C for Data and Power, RCA analog output and also SPDIF in and out via both TOSLINK and Coax. According to the marketing material, a Qualcomm CSR8675 Bluetooth Chip is used.

While it does work out of the box, there are some additional tunables available via the official "FiiO Control" Android App. These include things such as the power-on-behaviour, whether the output level should be locked or which codecs should be used.

The app itself works fine, however it is unclear how long it will stay that way given that it is an Android app. Thus, here's some documentation on the protocol.

This may also be adaptable to other similar FiiO devices, however I only have a BTA 30.

Protocol

The FiiO BTA 30 uses Bluetooth Low Energy (BLE) for all its configuration needs. As with most BLE appliances, the implementation could be described as strange.

It seems that all FiiO-specific functionality is just piggybacked on top of the generic Qualcomm CSR102x OTAU functionality, which is probably some sample code provided by Qualcomm and it was just easier that way? Who knows.

Said OTAU characteristic is documented by Qualcomm in a PDF named csr102x_otau_overview.pdf, which I won't mirror here due to copyright concerns. At the time of writing, it is available for download off the official Qualcomm servers: https://developer.qualcomm.com/qfile/34081/csr102x_otau_overview.pdf

As the name suggest, there also seems to be some over-the-air-firmware-update functionality available, however it seems like that doesn't apply to the BTA30 (yet?)

Firware updates would likely be stored somewhere below http://fiio-bluetooth.oss-cn-beijing.aliyuncs.com/. There currently (2022-05-19) is a subfolder named BTA30, however it doesn't seem to contain a new firmware image.

Characteristics

We have one service with UUID 00001100-d102-11e1-9b23-00025b00a5a5 named CSR GAIA according to the Qualcomm docs.

This service features three characteristics:

  1. 00001101-d102-11e1-9b23-00025b00a5a5 (CSR GAIA Command Endpoint) Commands will be written to this characteristic

  2. 00001102-d102-11e1-9b23-00025b00a5a5 (CSR GAIA Response Endpoint) Replies to commands will be provided via this characteristic as notifications. It needs to be subscribed first before any commands are sent

  3. 00001103-d102-11e1-9b23-00025b00a5a5 (CSR GAIA Data Endpoint) No idea what this does

Commands

Requests

Command requests are written to the CSR GAIA Command Endpoint characteristic.

These consist of at least four bytes but may be longer if there is a payload.

The first 20 bits are a magic while the next 12 bits contain the command ID. After that, there may be 0-n bytes of payload.

Examples

Let's look at some examples to make this easier.

No Payload

This is an example without any payload

00 0a 04 3d

  • First, there's the magic: 0x000a0
  • Then, there's the command: 0x43d

That's it. Command 0x43d is the GET_LED_OFF command. On success, you will get the following response: 00 0a 84 3d 00 01. If your LED_OFF setting is false, then the 0x01 at the end will of course be 0x00.

Payload

Here's an example that features a payload:

00 0a 04 0b 01

  • First, there's the magic: 0x000a0
  • Then, there's the command: 0x40b
  • Finally, there's the payload: 0x01

Command 0x41c is the Set Boot Mode command and 0x01 means true. On success, you will get the following response: 00 0a 84 1c 00 01.

Replies

Command replies are provided via notifications of the CSR GAIA Response Endpoint characteristic.

These consist of at least five bytes but may be longer if there is a payload. The first 20 bits are a magic while the next 12 bits contain the command ID. This is followed by a single null byte. After that, there may be 0-n bytes of payload.

Examples

Let's look at some examples to make this easier.

No Payload

This is an example without any payload:

00 0a 84 25 00

  • First, there's the magic: 0x000a8
  • Then, there's the command: 0x425
  • Finally, there's the null byte 0x00

Command 0x425 is the Power Off command, which just turns of the device. Hence, there's no need for a payload. The reply confirms the successful receive of the command.

Payload

Here's an example that features a payload:

00 0a 84 1c 00 01

  • First, there's the magic: 0x000a8
  • Then, there's the command: 0x41c
  • Then, there's the null byte 0x00
  • Finally, there's the payload: 0x01

Command 0x41c is the Boot Mode command and 0x01 means true. Thus, this message means that the BTA 30 will turn on as soon as it receives power. If this was 0x00 you'd still have to manually press the power button.

List of Commands

Here are all available commands. Some of them may be read-only. Others can be written

Global Commands

Version

Description:
The Device Version + Type

GET Command:
0x418

Response:
3 Byte

  1. Major Version
  2. Minor Version
  3. Device Type (Always D4 for the BTA30)
Current Connection Codec

Description:
The Codec used by the current connection

Command:
0x416

Payload:
One Byte

Decimal:

  • 0 = A2DP OFF
  • 1 = SBC
  • 3 = AAC
  • 5 = APTX
  • 7 = APTX HD
  • 10 = LDAC
Boot Mode

Description:
Whether the Device should turn on as soon as it receives power

GET Command:
0x41C

SET Command:
0x40B

Payload:
Either 0x00 or 0x01

LED Mode

Description:
Whether the Device LEDs should be on or off

GET Command:
0x43D

SET Command:
0x43E

Payload:
Either 0x00 or 0x01

LED Pattern

Description:
Whether the LED flashes red-green or red-blue during connection setup

GET Command:
0x44A

SET Command:
0x44B

Payload:
Either 0x00 for red-green or 0x01 for blue-red

TX LDAC Quality Setting

Description:
Fetch the current TX LDAC Quality Setting

GET Command:
0x44C

SET Command:
0x44D

Payload:
1 Byte

  • Audio quality first (0x01)
  • Standard (0x02)
  • Connection first (0x03)
  • Adaptive (0x04)
SPDIF Volume Adjustment Setting

Description:
Whether the SPDIF Output level should be controlled by the volume knob

GET Command:
0x452

SET Command:
0x453

Payload:
Either 0x00 or 0x01

Upsampling Setting

Description:
Whether the DAC should upsample the audio data to 384KHz

GET Command:
0x450

SET Command:
0x451

Payload:
Either 0x00 or 0x01

Volume Setting

Description:
The current volume setting. This is usually controlled by the knob on the device.

GET Command:
0x412

SET Command:
0x402

Payload:
1 Byte 0x00-0x3C Decimal 0-60

DAC Lowpass Setting

Description:
The current DAC lowpass setting

GET Command:
0x411

SET Command:
0x401

Payload:
1 Byte

  • Sharp Roll-Off Filter (0x00)
  • Slow Roll-Off Filter (0x01)
  • Short Delay Sharp Roll-Off Filter (0x02)
  • Short Delay Slow Roll-Off Filter (0x03)
Output Balance

Description:
The current balance setting.

Values can be between L12 and R12 with 0 being R0 0x0200

GET Command:
0x413

SET Command:
0x403

Payload:
2 Byte

  1. L (0x01) or R (0x02)
  2. 0-12 Decimal Left or Right (0x00-0x0C)
Name

Description:
The bluetooth name advertised by the device. 30 Bytes UTF-8 max

GET Command:
0x445

SET Command:
0x446

Description:
Because the name can be up to 30 UTF-8 bytes long, this command behaves a bit differently from the others. One Set Name command may consist of up to four writes. You may even use emoji

Basic Example SET

This example contains the short name Hallo and therefore needs no splitting as it fits in a single message.

00 0a 04 46 ff 05 48 61 6c 6c 6f ff

  • First, there's the magic: 0x000a0
  • Then, there's the command: 0x446
  • Then, there's the start of payload marker: 0xff
  • Then, there's the length of the name payload: 0x05
  • Then, there are the UTF-8 Bytes of Hallo: 0x48616c6c6f
  • Finally, there's the end of payload marker: 0xff
Advanced example SET

This example contains the 30 character long name KlausKlausKlausKlausKlausKlaus, which was split into four messages.

  1. 00 0a 04 46 ff 1e 4b 6c 61 75 73 4b 6c 61 - KlausKla
  2. 00 0a 04 46 75 73 4b 6c 61 75 73 4b 6c 61 - usKlausKla
  3. 00 0a 04 46 75 73 4b 6c 61 75 73 4b 6c 61 - usKlausKla
  4. 00 0a 04 46 75 73 ff - us

In this example, the 0x1e represents the length of 30 characters.

Example GET

The same logic applies to the get name response. Here, the name is FiiO BTA30.

  1. 00 0a 04 46 ff 0a 46 69 69 4f 20 42 54 41 - Length: 0x0a (10), FiiO BTA
  2. 00 0a 04 46 33 30 ff - 30

Mode-dependant Commands

Input Sources

Description:
Fetch/select which sources are enabled for the mode

GET Command:
0x448

SET Command:
0x449

GET Payload:
1 Byte 0x01 for RX, 0x02 for TX

GET Response/SET Payload:
2 Bytes

  1. 0x01 for RX, 0x02 for TX
  2. Settings
    • USB (0x01)
    • Coax (0x02)
    • USB & Coax (0x03)
GET Volume Mode

Description:
Fetch/select the volume mode setting for the mode

GET Command:
0x44E

SET Command:
0x44F

GET Payload:
1 Byte 0x01 for RX, 0x02 for TX

GET Response/SET Payload:
2 Bytes

  1. 0x01 for RX, 0x02 for TX
  2. Settings
    • Adjustable (0x01)
    • Fixed at 30% (0x02)
    • Fixed at 50% (0x03)
    • Fixed at 70% (0x04)
    • Fixed at 100% (0x05)
GET Enabled Codecs

Description:
Fetch/set the enabled codecs for the mode APTX-LL seems to only be available in TX?

GET Command:
0x417

GET Command:
0x407

GET Payload:
1 Byte 0x01 for RX, 0x02 for TX

GET Response/SET Payload:
2 Bytes

  1. 0x01 for RX, 0x02 for TX
  2. Sum of supported codecs
    • AAC (2)
    • LDAC (4)
    • APTX (8)
    • APTX-LL (16)
    • APTX-HD (32)

Special SET-only commands

Factory reset

Description:
Does a factory reset

Command:
0x404

Response:
None

Power Off

Description:
Turns off the BTA30

Command:
0x425

Response:
None

Clear Pairing

Description:
Delete all pairing information from the BTA30

Command:
0x443

Response:
None

About

Documentation on the BLE protocol of the FiiO BTA30 DAC & Bluetooth Transceiver

License:Do What The F*ck You Want To Public License