Hi, bluetooth developers! I’m working on bluetooth driver for MT6622 bluetooth chip on MSB 2531 board. I need to be able to forward sound from that device to bluetooth headset using A2DP profile. That MT6622 chip has UART line for HCI control commands and I2S line for sound. I use bluez 5.50, bluez-alsa 1.4.0 and kernel 3.10.69 in buildroot. I’ve already gone so far that scanning devices, paring and connecting headset works now: # bluetoothctl -- info C0:7A:A5:01:48:F0 Device C0:7A:A5:01:48:F0 (public) Name: SVEN SEB-B270MV Alias: SVEN SEB-B270MV Class: 0x00240404 Icon: audio-card Paired: yes Trusted: no Blocked: no Connected: yes LegacyPairing: no UUID: Headset (00001108-0000-1000-8000-00805f9b34fb) UUID: Audio Sink (0000110b-0000-1000-8000-00805f9b34fb) UUID: A/V Remote Control Target (0000110c-0000-1000-8000-00805f9b34fb) UUID: A/V Remote Control (0000110e-0000-1000-8000-00805f9b34fb) UUID: Handsfree (0000111e-0000-1000-8000-00805f9b34fb) But when I try to play sound, I see that I’m almost there: state changed to SINK_STATE_PLAYING, then Starting IO loop: A2DP Source, but after that I got “Broken pipe” error (here is some logs with debug info): # aplay -D btheadset /my/maybe-next-time.wav ../shared/ctl-client.c:108: Connecting to socket: /var/run/bluealsa/hci0 bluealsa: ctl.c:596: Received new connection: 8 bluealsa: ctl.c:609: New client accepted: 8 bluealsa: ctl.c:634: +-+- ../shared/ctl-client.c:238: Getting transport for C0:7A:A5:01:48:F0 type 0x41 bluealsa: ctl.c:634: +-+- bluealsa-pcm.c:583: Setting constraints: 3 Playing WAVE '/my/maybe-next-time.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo bluealsa-pcm.c:307: Initializing HW: 3 ../shared/ctl-client.c:397: Requesting PCM open for C0:7A:A5:01:48:F0 bluealsa: ctl.c:329: PCM requested for C0:7A:A5:01:48:F0 type 0x41 bluetoothd[668]: profiles/audio/transport.c:media_owner_create() Owner created: sender=:1.1 bluetoothd[668]: profiles/audio/avdtp.c:avdtp_ref() 0x1ecc348: ref=2 bluetoothd[668]: profiles/audio/a2dp.c:a2dp_sep_lock() SEP 0x1ec7cd8 locked bluetoothd[668]: profiles/audio/avdtp.c:avdtp_ref() 0x1ecc348: ref=3 bluetoothd[668]: profiles/audio/a2dp.c:setup_ref() 0x1ecc2a8: ref=1 bluetoothd[668]: profiles/audio/transport.c:transport_set_state() State changed /org/bluez/hci0/dev_C0_7A_A5_01_48_F0/fd0: TRANSPORT_STATE_IDLE -> TRANSPORT_STATE_REQUESTING bluetoothd[668]: profiles/audio/transport.c:media_request_create() Request created: method=Acquire id=4 bluetoothd[668]: profiles/audio/transport.c:media_owner_add() Owner :1.1 Request Acquire bluetoothd[668]: profiles/audio/transport.c:media_transport_set_owner() Transport /org/bluez/hci0/dev_C0_7A_A5_01_48_F0/fd0 Owner :1.1 bluetoothd[668]: profiles/audio/avdtp.c:session_cb() bluetoothd[668]: profiles/audio/avdtp.c:avdtp_parse_resp() START request succeeded bluetoothd[668]: profiles/audio/a2dp.c:start_cfm() Source 0x1ec7cd8: Start_Cfm bluetoothd[668]: /org/bluez/hci0/dev_C0_7A_A5_01_48_F0/fd0: fd(17) ready bluetoothd[668]: profiles/audio/transport.c:media_owner_remove() Owner :1.1 Request Acquire bluetoothd[668]: profiles/audio/transport.c:transport_set_state() State changed /org/bluez/hci0/dev_C0_7A_A5_01_48_F0/fd0: TRANSPORT_STATE_REQUESTING -> TRANSPORT_STATE_ACTIVE bluetoothd[668]: profiles/audio/a2dp.c:setup_unref() 0x1ecc2a8: ref=0 bluetoothd[668]: profiles/audio/a2dp.c:setup_free() 0x1ecc2a8 bluetoothd[668]: profiles/audio/avdtp.c:avdtp_unref() 0x1ecc348: ref=2 bluetoothd[668]: profiles/audio/avdtp.c:avdtp_sep_set_state() stream state changed: OPEN -> STREAMING bluetoothd[668]: profiles/audio/sink.c:sink_set_state() State changed /org/bluez/hci0/dev_C0_7A_A5_01_48_F0: SINK_STATE_CONNECTED -> SINK_STATE_PLAYING bluetoothd[668]: profiles/audio/transport.c:transport_update_playing() /org/bluez/hci0/dev_C0_7A_A5_01_48_F0/fd0 State=TRANSPORT_STATE_ACTIVE Playing=1 bluealsa: ba-transport.c:669: New transport: 18 (MTU: R:672 W:895) bluealsa: ctl.c:634: +-+- bluealsa-pcm.c:330: FIFO buffer size: 4096 bluealsa-pcm.c:336: Selected HW buffer: 6 periods x 16380 bytes <= 98284 bytes bluealsa-pcm.c:351: Initializing SW: 3 bluealsa-pcm.c:351: Initializing SW: 3 bluealsa-pcm.c:351: Initializing SW: 3 bluealsa-pcm.c:373: Prepared: 3 bluealsa-pcm.c:351: Initializing SW: 3 bluealsa: bluez.c:1396: Signal: PropertiesChanged: org.bluez.MediaTransport1: State bluealsa: ba-transport.c:546: State transition: 0 -> 2 bluealsa: ba-transport.c:105: Created new IO thread: A2DP Source (SBC) bluealsa: io.c:428: Starting IO loop: A2DP Source (SBC) bluealsa-pcm.c:228: Starting: 3 ../shared/ctl-client.c:444: Requesting PCM resume for C0:7A:A5:01:48:F0 bluealsa: ba-transport.c:546: State transition: 2 -> 2 bluealsa: ctl.c:634: +-+- bluealsa-pcm.c:122: Starting IO loop: 6 bluetoothd[668]: profiles/audio/media.c:media_endpoint_exit() media_endpoint_exit bluetoothd[668]: profiles/audio/media.c:media_endpoint_exit() media_endpoint_exit bluetoothd[668]: src/adapter.c:adapter_service_remove() /org/bluez/hci0 bluetoothd[668]: src/adapter.c:remove_uuid() sending remove uuid command for index 0 bluetoothd[668]: src/sdpd-service.c:remove_record_from_server() Removing record with handle 0x10004 bluetoothd[668]: profiles/audio/media.c:release_endpoint() sender=:1.1 path=/hci0/A2DP/SBC/Sink/1 bluetoothd[668]: Endpoint unregistered: sender=:1.1 path=/hci0/A2DP/SBC/Sink/1 bluetoothd[668]: profiles/audio/media.c:media_endpoint_destroy() sender=:1.1 path=/hci0/A2DP/SBC/Sink/1 bluetoothd[668]: profiles/audio/avdtp.c:avdtp_unregister_sep() SEP 0x1ec7d00 unregistered: type:1 codec:0 seid:2 bluetoothd[668]: profiles/audio/media.c:media_endpoint_exit() media_endpoint_exit ALSA lib bluealsa-pcm.c:201:(io_thread) PCM FIFO write error: Broken pipe bluealsa-pcm.c:92: IO thread cleanup: 3 underrun!!! (at least 22.550 ms long) aplay: xrun:1642: xrun: prepare error: No such device bluealsa-pcm.c:268: Stopping: 3 Now I’m struggling at debugging the problem. It’s actually quite hard for me since bluez uses event driven architecture and call stacks in debugger usually point to some event dispatcher and it’s difficult to understand what code actually triggered what action. It’s unclear for me, what cased what, whether media_endpoint_exit() call: bluetoothd[668]: profiles/audio/media.c:media_endpoint_exit() media_endpoint_exit cased broken pipe: ALSA lib bluealsa-pcm.c:201:(io_thread) PCM FIFO write error: Broken pipe since it appears earlier in logs, or vice versa. I suspect that kernel bluetooth driver for MT6622 chip which I develop should provide some channel for bluetoothd daemon to be able to forward PCM data to the chip and without such channel broken pipe happens. The main obstacle for me now is that I’m having hard time finding any documentation about what low level interface should kernel driver provide for bluez for A2DP sound playing via I2S. I also miss big picture of how bluez communicates with bluetooth chip via UART and I2S lines, what should be done at kernel driver level and how. Do I need to integrate with sound kernel driver? I’ve found some presentation in youtube but it was too general for me, I need more details about bluetooth audio. After spending some time debugging bluetoothd daemon code I suspect that bluetoothd opens a socket or pipe for PCM data, and passes its handle to bluez-alsa to put PCM data into. But since kernel driver doesn’t implement such socket the problem arises. Could you please point me to some documentation, presentation, tutorial or, best of all, example kernel driver code? Any help would be very appreciated. Anton