Yamaha YAS-207's Bluetooth protocol: basic recon
Introduction
As explained in the Introductory post, I’m reversing the control interfaces of the Yamaha YAS-207 soundbar.
In this installment I’m doing a basic recon of the Bluetooth part.
And as before with the infrared protocol, my plans were thwarted by reality. If you don’t care about the journey, maybe skip to the next post when it’s available. Or maybe just to the Closing words section.
Problem
Figure out the bluetooth protocol used in YAS-207 soundbar’s remote app, the “Home Theater Controller”. Because I want to drive the soundbar from a raspi.
Sniff me some Bluetooth LE… or not
Having an Adafruit’s Bluefruit LE Sniffer1 I thought this part might be easy.
Pic originally by Adafruit (CC-NC-SA 2.0 licensed), resized+cropped by me.
Only to find out that no, YAS-207 doesn’t support BLE. It speaks Bluetooth classic.
I guess reading the Specs page a little bit more carefully would help me avoid this blunder.
Because on the manufacturer’s website it not-so-clearly says:
(Version) Ver. 4.1 + EDR
(Profile) A2DP, SPP
(Audio Codec) SBC, MPEG AAC
It is my fault for interpreting it as BLE and/or Classic.
Moving on, we’ll have to do this some other way.
Now, since sniffing Bluetooth Classic is hard2, this situation got a lot more interesting.
Basic recon
OK, so that was a fail. Let’s at least see what protocols the device speaks:
# hcitool scan
Scanning ...
C8:84:xx:xx:xx:xx YAS-207 Yamaha
# hcitool info C8:84:xx:xx:xx:xx
Requesting information ...
BD Address: C8:84:xx:xx:xx:xx
Device Name: YAS-207 Yamaha
LMP Version: 4.2 (0x8) LMP Subversion: 0x30e7
Manufacturer: Cambridge Silicon Radio (10)
Features page 0: 0xff 0xff 0x8f 0xfe 0xdb 0xff 0x5b 0x87
<3-slot packets> <5-slot packets> <encryption> <slot offset>
<timing accuracy> <role switch> <hold mode> <sniff mode>
<park state> <RSSI> <channel quality> <SCO link> <HV2 packets>
<HV3 packets> <u-law log> <A-law log> <CVSD> <paging scheme>
<power control> <transparent SCO> <broadcast encrypt>
<EDR ACL 2 Mbps> <EDR ACL 3 Mbps> <enhanced iscan>
<interlaced iscan> <interlaced pscan> <inquiry with RSSI>
<extended SCO> <EV4 packets> <EV5 packets> <AFH cap. slave>
<AFH class. slave> <LE support> <3-slot EDR ACL>
<5-slot EDR ACL> <sniff subrating> <pause encryption>
<AFH cap. master> <AFH class. master> <EDR eSCO 2 Mbps>
<EDR eSCO 3 Mbps> <3-slot EDR eSCO> <extended inquiry>
<LE and BR/EDR> <simple pairing> <encapsulated PDU>
<non-flush flag> <LSTO> <inquiry TX power> <EPC>
<extended features>
Features page 1: 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Features page 2: 0x0f 0x00 0x00 0x00 0x00 0x00 0x00 0x00
So that doesn’t tell me much (not exactly Bluetooth expert, me).
Let’s pair with it and then begin interrogation:
# bluetoothctl pair C8:84:xx:xx:xx:xx
Attempting to pair with C8:84:xx:xx:xx:xx
[CHG] Device C8:84:xx:xx:xx:xx Connected: yes
[CHG] Device C8:84:xx:xx:xx:xx UUIDs: 00000000-deca-fade-deca-deafdecacaff
[CHG] Device C8:84:xx:xx:xx:xx UUIDs: 00001000-d102-11e1-9b23-00025b00a5a5
[CHG] Device C8:84:xx:xx:xx:xx UUIDs: 00001101-0000-1000-8000-00805f9b34fb
[CHG] Device C8:84:xx:xx:xx:xx UUIDs: 0000110b-0000-1000-8000-00805f9b34fb
[CHG] Device C8:84:xx:xx:xx:xx UUIDs: 00001200-0000-1000-8000-00805f9b34fb
[CHG] Device C8:84:xx:xx:xx:xx ServicesResolved: yes
[CHG] Device C8:84:xx:xx:xx:xx Paired: yes
Pairing successful
# bluetoothctl info C8:84:xx:xx:xx:xx
Device C8:84:xx:xx:xx:xx (public)
Name: YAS-207 Yamaha
Alias: YAS-207 Yamaha
Class: 0x00240428
Icon: audio-card
Paired: yes
Trusted: yes
Blocked: no
Connected: no
LegacyPairing: no
UUID: Vendor specific (00000000-deca-fade-deca-deafdecacaff)
UUID: Vendor specific (00001000-d102-11e1-9b23-00025b00a5a5)
UUID: Serial Port (00001101-0000-1000-8000-00805f9b34fb)
UUID: Audio Sink (0000110b-0000-1000-8000-00805f9b34fb)
UUID: PnP Information (00001200-0000-1000-8000-00805f9b34fb)
Now we’re getting somewhere. They weren’t kidding about the serial port
(1101
is SPP_UUID
) and Audio Sink (110b
is A2DP_SINK_UUID
).
But there are multiple other services:
00000000-deca-fade-deca-deafdecacaff
= Apple accessory, needed to be auto-recognized by iOS300001000-d102-11e1-9b23-00025b00a5a5
= ?00001200-0000-1000-8000-00805f9b34fb
= Plug-and-Pray, to have it auto-recognized by others
Let’s dig further:
# sdptool records C8:84:xx:xx:xx:xx
Service RecHandle: 0x10000
Service Class ID List:
"Audio Sink" (0x110b)
Protocol Descriptor List:
"L2CAP" (0x0100)
PSM: 25
"AVDTP" (0x0019)
uint16: 0x0103
Profile Descriptor List:
"Advanced Audio" (0x110d)
Version: 0x0103
Service RecHandle: 0x10001
Service Class ID List:
"PnP Information" (0x1200)
Service Name: SUBWOOFER
Service Description: Wireless Subwoofer
Service Provider: CSR
Service RecHandle: 0x10002
Service Class ID List:
UUID 128: 00001000-d102-11e1-9b23-00025b00a5a5
Protocol Descriptor List:
"L2CAP" (0x0100)
PSM: 32769
Language Base Attr List:
code_ISO639: 0x656e
encoding: 0x6a
base_offset: 0x100
Service Name: Wireless iAP
Service RecHandle: 0x10004
Service Class ID List:
UUID 128: 00000000-deca-fade-deca-deafdecacaff
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 14
Language Base Attr List:
code_ISO639: 0x656e
encoding: 0x6a
base_offset: 0x100
Service Name: SPP Dev
Service RecHandle: 0x10006
Service Class ID List:
"Serial Port" (0x1101)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 1
Language Base Attr List:
code_ISO639: 0x656e
encoding: 0x6a
base_offset: 0x100
Profile Descriptor List:
"Serial Port" (0x1101)
Version: 0x0102
OK, so the 00001000-d102-11e1-9b23-00025b00a5a5
is a service to support the
wireless subwoofer. Makes sense.
There’s bunch more info to be had using sdptool records --tree C8:84:xx:xx:xx:xx
but the output is rather long, and mostly boring, so I’ll skip it.
In any case, given the protocols exported, I’m betting that the remote control is done using the serial port.
But to get at it, I’ll have to get the communication dump elsewhere.
Second try: Let’s sniff it using Android
Fortunately, YAS-207 comes not only with an iOS app, but also with an Android app. And even though I’m nearly an Android virgin4 —
Little searching around the ’Net will score you an *.apk
(application archive)
of the “Home Theater Controller” in a jiffy. Wow. Such an (apk)pure experience.
Not having any Android hardware, I went on a hunt for an emulator… and ended up with something better. The nice people at android-x86.org did all the heavy lifting of getting Android to run on x865.
Thus one download of android-x86_64-7.1-r5.iso
later, my VirtualBox was humming
happily with fresh Android 7.1.26, connected to the VirtWifi
wifi :-).
In order to sniff Bluetooth, you become a developer7, and in the “Developer options” enable:
- “Stay awake”
- “Enable Bluetooth HCI snoop log”
- “USB debugging”
and optionally disable “Verify apps over USB”.
And now the fun starts.
On my desktop, it pretty much went thusly:
$ adb connect 1.2.3.4
$ adb install the_home_controller.apk
Then I had the HT Controller app talk to the YAS-207. Successfully, I might add.
But now the question is – where do I get the promised log of all Bluetooth
communication, the btsnoop_hci.log
?
Turns out, on newer(?) androids the location is mentioned in
/etc/bluetooth/bt_stack.conf
. Therefore:
$ adb shell grep BtSnoopFileName /etc/bluetooth/bt_stack.conf
BtSnoopFileName=/data/misc/bluetooth/logs/btsnoop_hci.log
and then:
$ adb shell su -c "'cat /data/misc/bluetooth/logs/btsnoop_hci.log'" > btsnoop_hci.log
$ file btsnoop_hci.log
btsnoop_hci.log: BTSnoop version 1, HCI UART (H4)
So, yay! We can sniff. And wireshark reads that file natively
(wireshark btsnoop_hci.log
):
Closing words
In this somewhat lengthy piece8 I’ve done basic recon of the Bluetooth properties of the Yamaha YAS-207 soundbar, as well as some prep work for sniffing the traffic.
Findings so far:
- YAS-207 speaks Bluetooth Classic, not Bluetooth LE.
- The protocol is probably through Serial-over-Bluetooth (SPP), on channel 1.9
- I can dump (sniff) the communication log from Android in
BTSnoop version 1, HCI UART (H4)
format.
But I dislike the manualness of this process:
- I would like streaming solution, not one-off done by downloading a file.
- I need to find a way to parse the HCI log somehow.
More on that in next installment(s), watch the yas 207 tag.
-
An nRF51822-based stick that costs about $25. The sniffer version has promiscuous firmware that streams to Wireshark, see Adafruit’s guide for intro, install instructions, etc. ↩
-
I don’t have the hardware; donations of “Ubertooth One” are welcome. :-) ↩
-
Surprisingly (as you’ll find out below), this is another Serial-over-BT protocol, but we don’t care about it. From what I was able to gather, the communication is guarded by a crypto chip – to separate the deep-pocketed royalty from the plebs. ↩
-
Never owned an Android phone. Also aside from brief stint with Android Wear never used it much. ↩
-
I bet you did not expect that punchline. ↩
-
There are guides how to run it in VirtualBox, but essentially: boot it with BT dongle attached in the
Live CD VESA
mode (from the “Advanced options” menu). ↩ -
Click the
Build number
bunch of times inSettings
→About tablet
. ↩ -
I blame the debug outputs. It for sure can’t be my blundering around due to sheer lack of qualification. ↩
-
Forgot to mention – had a brief looksie at the BT specs and the A2DP sink isn’t capable of remote control; there’s a different protocol for that. So either it’s the SPP, or Yamaha went the Microsoft way and extended existing protocol with a proprietary addon. Hope it’s the former. ↩