xref: /btstack/example/a2dp_source_demo.c (revision d5e631f6ca1c5ad46a054413a54902968f0875db)
1 /*
2  * Copyright (C) 2016 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 #define __BTSTACK_FILE__ "a2dp_source_demo.c"
39 
40 /*
41  * a2dp_source_demo.c
42  */
43 
44 // *****************************************************************************
45 /* EXAMPLE_START(a2dp_source_demo): Serve audio stream and handle remote playback control and queries.
46  *
47  * @text This A2DP Source example demonstrates how to send an audio data stream
48  * to a remote A2DP Sink device and how to switch between two audio data sources.
49  * In addition, the AVRCP Target is used to answer queries on currently played media,
50  * as well as to handle remote playback control, i.e. play, stop, repeat, etc.
51  *
52  * @test To test with a remote device, e.g. a Bluetooth speaker,
53  * set the device_addr_string to the Bluetooth address of your
54  * remote device in the code, and use the UI to connect and start playback.
55  * Tap SPACE on the console to show the available commands.
56  */
57 // *****************************************************************************
58 
59 
60 #include <stdint.h>
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64 
65 #include "btstack.h"
66 
67 #include "hxcmod.h"
68 #include "mods/mod.h"
69 
70 
71 #define AVRCP_BROWSING_ENABLED 0
72 
73 #define NUM_CHANNELS                2
74 #define A2DP_SAMPLE_RATE            44100
75 #define BYTES_PER_AUDIO_SAMPLE      (2*NUM_CHANNELS)
76 #define AUDIO_TIMEOUT_MS            10
77 #define TABLE_SIZE_441HZ            100
78 
79 typedef enum {
80     STREAM_SINE = 0,
81     STREAM_MOD,
82     STREAM_PTS_TEST
83 } stream_data_source_t;
84 
85 typedef struct {
86     uint16_t a2dp_cid;
87     uint8_t  local_seid;
88     uint8_t  connected;
89 
90     uint32_t time_audio_data_sent; // ms
91     uint32_t acc_num_missed_samples;
92     uint32_t samples_ready;
93     btstack_timer_source_t audio_timer;
94     uint8_t  streaming;
95     int      max_media_payload_size;
96 
97     uint8_t  sbc_storage[1030];
98     uint16_t sbc_storage_count;
99     uint8_t  sbc_ready_to_send;
100 } a2dp_media_sending_context_t;
101 
102 static  uint8_t media_sbc_codec_capabilities[] = {
103     (AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO,
104     0xFF,//(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS,
105     2, 53
106 };
107 
108 static const int16_t sine_int16[] = {
109      0,    2057,    4107,    6140,    8149,   10126,   12062,   13952,   15786,   17557,
110  19260,   20886,   22431,   23886,   25247,   26509,   27666,   28714,   29648,   30466,
111  31163,   31738,   32187,   32509,   32702,   32767,   32702,   32509,   32187,   31738,
112  31163,   30466,   29648,   28714,   27666,   26509,   25247,   23886,   22431,   20886,
113  19260,   17557,   15786,   13952,   12062,   10126,    8149,    6140,    4107,    2057,
114      0,   -2057,   -4107,   -6140,   -8149,  -10126,  -12062,  -13952,  -15786,  -17557,
115 -19260,  -20886,  -22431,  -23886,  -25247,  -26509,  -27666,  -28714,  -29648,  -30466,
116 -31163,  -31738,  -32187,  -32509,  -32702,  -32767,  -32702,  -32509,  -32187,  -31738,
117 -31163,  -30466,  -29648,  -28714,  -27666,  -26509,  -25247,  -23886,  -22431,  -20886,
118 -19260,  -17557,  -15786,  -13952,  -12062,  -10126,   -8149,   -6140,   -4107,   -2057,
119 };
120 
121 static btstack_packet_callback_registration_t hci_event_callback_registration;
122 
123 // mac 2011:    static const char * device_addr_string = "04:0C:CE:E4:85:D3";
124 // pts:         static const char * device_addr_string = "00:1B:DC:08:0A:A5";
125 // mac 2013:    static const char * device_addr_string = "84:38:35:65:d1:15";
126 // phone 2013:  static const char * device_addr_string = "D8:BB:2C:DF:F0:F2";
127 // minijambox:
128 static const char * device_addr_string = "00:21:3C:AC:F7:38";
129 // head phones: static const char * device_addr_string = "00:18:09:28:50:18";
130 // bt dongle:   static const char * device_addr_string = "00:15:83:5F:9D:46";
131 // RT-B6:       static const char * device_addr_string = "00:75:58:FF:C9:7D";
132 
133 static bd_addr_t device_addr;
134 static uint8_t sdp_a2dp_source_service_buffer[150];
135 static uint8_t sdp_avrcp_target_service_buffer[200];
136 
137 static uint8_t media_sbc_codec_configuration[4];
138 static a2dp_media_sending_context_t media_tracker;
139 
140 static uint16_t avrcp_cid;
141 static uint8_t  avrcp_connected;
142 
143 static stream_data_source_t data_source;
144 
145 static int sine_phase;
146 
147 static int hxcmod_initialized;
148 static modcontext mod_context;
149 static tracker_buffer_state trkbuf;
150 
151 
152 /* AVRCP Target context START */
153 static const uint8_t subunit_info[] = {
154     0,0,0,0,
155     1,1,1,1,
156     2,2,2,2,
157     3,3,3,3,
158     4,4,4,4,
159     5,5,5,5,
160     6,6,6,6,
161     7,7,7,7
162 };
163 
164 static uint32_t company_id = 0x112233;
165 static uint8_t companies_num = 1;
166 static uint8_t companies[] = {
167     0x00, 0x19, 0x58 //BT SIG registered CompanyID
168 };
169 
170 static uint8_t events_num = 13;
171 static uint8_t events[] = {
172     AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED,
173     AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED,
174     AVRCP_NOTIFICATION_EVENT_TRACK_REACHED_END,
175     AVRCP_NOTIFICATION_EVENT_TRACK_REACHED_START,
176     AVRCP_NOTIFICATION_EVENT_PLAYBACK_POS_CHANGED,
177     AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED,
178     AVRCP_NOTIFICATION_EVENT_SYSTEM_STATUS_CHANGED,
179     AVRCP_NOTIFICATION_EVENT_PLAYER_APPLICATION_SETTING_CHANGED,
180     AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED,
181     AVRCP_NOTIFICATION_EVENT_AVAILABLE_PLAYERS_CHANGED,
182     AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED,
183     AVRCP_NOTIFICATION_EVENT_UIDS_CHANGED,
184     AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED
185 };
186 
187 typedef struct {
188     uint8_t track_id[8];
189     uint32_t song_length_ms;
190     avrcp_playback_status_t status;
191     uint32_t song_position_ms; // 0xFFFFFFFF if not supported
192 } avrcp_play_status_info_t;
193 
194 // python -c "print('a'*512)"
195 static const char title[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
196 
197 avrcp_track_t tracks[] = {
198     {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, 1, "Sine", "Generated", "AVRCP Demo", "monotone", 12345},
199     {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 2, "Nao-deceased", "Decease", "AVRCP Demo", "vivid", 12345},
200     {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, 3, (char *)title, "Decease", "AVRCP Demo", "vivid", 12345},
201 };
202 int current_track_index;
203 avrcp_play_status_info_t play_info;
204 
205 /* AVRCP Target context END */
206 
207 /* @section Main Application Setup
208  *
209  * @text The Listing MainConfiguration shows how to setup AD2P Source and AVRCP Target services.
210  */
211 
212 /* LISTING_START(MainConfiguration): Setup Audio Source and AVRCP Target services */
213 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size);
214 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
215 #ifdef HAVE_BTSTACK_STDIN
216 static void stdin_process(char cmd);
217 #endif
218 
219 static int a2dp_source_and_avrcp_services_init(void){
220     // Register for HCI events.
221     hci_event_callback_registration.callback = &a2dp_source_packet_handler;
222     hci_add_event_handler(&hci_event_callback_registration);
223 
224     l2cap_init();
225     // Initialize A2DP Source.
226     a2dp_source_init();
227     a2dp_source_register_packet_handler(&a2dp_source_packet_handler);
228 
229     // Create stream endpoint.
230     avdtp_stream_endpoint_t * local_stream_endpoint = a2dp_source_create_stream_endpoint(AVDTP_AUDIO, AVDTP_CODEC_SBC, media_sbc_codec_capabilities, sizeof(media_sbc_codec_capabilities), media_sbc_codec_configuration, sizeof(media_sbc_codec_configuration));
231     if (!local_stream_endpoint){
232         printf("A2DP source demo: not enough memory to create local stream endpoint\n");
233         return 1;
234     }
235     media_tracker.local_seid = avdtp_local_seid(local_stream_endpoint);
236 
237     // Initialize AVRCP Target.
238     avrcp_target_init();
239     avrcp_target_register_packet_handler(&avrcp_target_packet_handler);
240 
241     // Initialize SDP,
242     sdp_init();
243 
244     // Create A2DP source service record and register it with SDP.
245     memset(sdp_a2dp_source_service_buffer, 0, sizeof(sdp_a2dp_source_service_buffer));
246     a2dp_source_create_sdp_record(sdp_a2dp_source_service_buffer, 0x10002, 1, NULL, NULL);
247     sdp_register_service(sdp_a2dp_source_service_buffer);
248 
249     // Create AVRCP target service record and register it with SDP.
250     memset(sdp_avrcp_target_service_buffer, 0, sizeof(sdp_avrcp_target_service_buffer));
251     avrcp_target_create_sdp_record(sdp_avrcp_target_service_buffer, 0x10001, AVRCP_BROWSING_ENABLED, 1, NULL, NULL);
252     sdp_register_service(sdp_avrcp_target_service_buffer);
253 
254     // Set local name with a template Bluetooth address, that will be automatically
255     // replaced with a actual address once it is available, i.e. when BTstack boots
256     // up and starts talking to a Bluetooth module.
257     gap_set_local_name("A2DP Source Demo 00:00:00:00:00:00");
258     gap_discoverable_control(1);
259     gap_set_class_of_device(0x200408);
260 
261     hxcmod_initialized = hxcmod_init(&mod_context);
262     if (hxcmod_initialized){
263         hxcmod_setcfg(&mod_context, A2DP_SAMPLE_RATE, 16, 1, 1, 1);
264         hxcmod_load(&mod_context, (void *) &mod_data, mod_len);
265         printf("loaded mod '%s', size %u\n", mod_name, mod_len);
266     }
267     // Parse human readable Bluetooth address.
268     sscanf_bd_addr(device_addr_string, device_addr);
269 
270 #ifdef HAVE_BTSTACK_STDIN
271     btstack_stdin_setup(stdin_process);
272 #endif
273     return 0;
274 }
275 /* LISTING_END */
276 
277 static void a2dp_demo_send_media_packet(void){
278     int num_bytes_in_frame = btstack_sbc_encoder_sbc_buffer_length();
279     int bytes_in_storage = media_tracker.sbc_storage_count;
280     uint8_t num_frames = bytes_in_storage / num_bytes_in_frame;
281     a2dp_source_stream_send_media_payload(media_tracker.a2dp_cid, media_tracker.local_seid, media_tracker.sbc_storage, bytes_in_storage, num_frames, 0);
282     media_tracker.sbc_storage_count = 0;
283     media_tracker.sbc_ready_to_send = 0;
284 }
285 
286 static void produce_sine_audio(int16_t * pcm_buffer, int num_samples_to_write){
287     int count;
288     for (count = 0; count < num_samples_to_write ; count++){
289         pcm_buffer[count * 2]     = sine_int16[sine_phase];
290         pcm_buffer[count * 2 + 1] = sine_int16[sine_phase];
291         sine_phase++;
292         if (sine_phase >= TABLE_SIZE_441HZ){
293             sine_phase -= TABLE_SIZE_441HZ;
294         }
295     }
296 }
297 
298 static void produce_mod_audio(int16_t * pcm_buffer, int num_samples_to_write){
299     hxcmod_fillbuffer(&mod_context, (unsigned short *) &pcm_buffer[0], num_samples_to_write, &trkbuf);
300 }
301 
302 static void produce_audio(int16_t * pcm_buffer, int num_samples){
303     switch (data_source){
304         case STREAM_SINE:
305             produce_sine_audio(pcm_buffer, num_samples);
306             break;
307         case STREAM_MOD:
308             produce_mod_audio(pcm_buffer, num_samples);
309             break;
310         default:
311             break;
312     }
313 }
314 
315 static int a2dp_demo_fill_sbc_audio_buffer(a2dp_media_sending_context_t * context){
316     // perform sbc encodin
317     int total_num_bytes_read = 0;
318     unsigned int num_audio_samples_per_sbc_buffer = btstack_sbc_encoder_num_audio_frames();
319     while (context->samples_ready >= num_audio_samples_per_sbc_buffer
320         && (context->max_media_payload_size - context->sbc_storage_count) >= btstack_sbc_encoder_sbc_buffer_length()){
321 
322         int16_t pcm_frame[256*NUM_CHANNELS];
323 
324         produce_audio(pcm_frame, num_audio_samples_per_sbc_buffer);
325         btstack_sbc_encoder_process_data(pcm_frame);
326 
327         uint16_t sbc_frame_size = btstack_sbc_encoder_sbc_buffer_length();
328         uint8_t * sbc_frame = btstack_sbc_encoder_sbc_buffer();
329 
330         total_num_bytes_read += num_audio_samples_per_sbc_buffer;
331         memcpy(&context->sbc_storage[context->sbc_storage_count], sbc_frame, sbc_frame_size);
332         context->sbc_storage_count += sbc_frame_size;
333         context->samples_ready -= num_audio_samples_per_sbc_buffer;
334     }
335     return total_num_bytes_read;
336 }
337 
338 static void a2dp_demo_audio_timeout_handler(btstack_timer_source_t * timer){
339     a2dp_media_sending_context_t * context = (a2dp_media_sending_context_t *) btstack_run_loop_get_timer_context(timer);
340     btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS);
341     btstack_run_loop_add_timer(&context->audio_timer);
342     uint32_t now = btstack_run_loop_get_time_ms();
343 
344     uint32_t update_period_ms = AUDIO_TIMEOUT_MS;
345     if (context->time_audio_data_sent > 0){
346         update_period_ms = now - context->time_audio_data_sent;
347     }
348 
349     uint32_t num_samples = (update_period_ms * A2DP_SAMPLE_RATE) / 1000;
350     context->acc_num_missed_samples += (update_period_ms * A2DP_SAMPLE_RATE) % 1000;
351 
352     while (context->acc_num_missed_samples >= 1000){
353         num_samples++;
354         context->acc_num_missed_samples -= 1000;
355     }
356     context->time_audio_data_sent = now;
357     context->samples_ready += num_samples;
358 
359     if (context->sbc_ready_to_send) return;
360 
361     a2dp_demo_fill_sbc_audio_buffer(context);
362 
363     if ((context->sbc_storage_count + btstack_sbc_encoder_sbc_buffer_length()) > context->max_media_payload_size){
364         // schedule sending
365         context->sbc_ready_to_send = 1;
366         a2dp_source_stream_endpoint_request_can_send_now(context->a2dp_cid, context->local_seid);
367     }
368 }
369 
370 static void a2dp_demo_timer_start(a2dp_media_sending_context_t * context){
371     context->max_media_payload_size = a2dp_max_media_payload_size(context->a2dp_cid, context->local_seid);
372     context->sbc_storage_count = 0;
373     context->sbc_ready_to_send = 0;
374     context->streaming = 1;
375     btstack_run_loop_remove_timer(&context->audio_timer);
376     btstack_run_loop_set_timer_handler(&context->audio_timer, a2dp_demo_audio_timeout_handler);
377     btstack_run_loop_set_timer_context(&context->audio_timer, context);
378     btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS);
379     btstack_run_loop_add_timer(&context->audio_timer);
380 }
381 
382 static void a2dp_demo_timer_stop(a2dp_media_sending_context_t * context){
383     context->time_audio_data_sent = 0;
384     context->acc_num_missed_samples = 0;
385     context->samples_ready = 0;
386     context->streaming = 1;
387     context->sbc_storage_count = 0;
388     context->sbc_ready_to_send = 0;
389     btstack_run_loop_remove_timer(&context->audio_timer);
390 }
391 
392 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
393     UNUSED(channel);
394     UNUSED(size);
395     uint8_t status;
396     uint8_t local_seid;
397     bd_addr_t address;
398     uint16_t cid;
399 
400     if (packet_type != HCI_EVENT_PACKET) return;
401 
402 #ifndef HAVE_BTSTACK_STDIN
403     if (hci_event_packet_get_type(packet) == BTSTACK_EVENT_STATE){
404         if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
405         printf("Create AVDTP Source connection to addr %s.\n", bd_addr_to_str(device_addr));
406         status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid);
407         if (status != ERROR_CODE_SUCCESS){
408             printf("Could not perform command, status 0x%2x\n", status);
409         }
410         return;
411     }
412 #endif
413 
414     if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return;
415     switch (packet[2]){
416         case A2DP_SUBEVENT_INCOMING_CONNECTION_ESTABLISHED:
417             // TODO: check incoming cid
418             a2dp_subevent_incoming_connection_established_get_bd_addr(packet, address);
419             cid = a2dp_subevent_incoming_connection_established_get_a2dp_cid(packet);
420             printf("A2DP_SUBEVENT_INCOMING_CONNECTION_ESTABLISHED, cid 0x%02x,  media_tracker.a2dp_cid 0x%02x\n", cid, media_tracker.a2dp_cid);
421             if (cid != media_tracker.a2dp_cid) break;
422 
423             media_tracker.connected = 1;
424             printf("A2DP: Incoming connection established: address %s, a2dp cid 0x%02x. Create stream on local seid %d.\n",
425                 bd_addr_to_str(address), media_tracker.a2dp_cid, media_tracker.local_seid);
426             status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid);
427             if (status != ERROR_CODE_SUCCESS){
428                 printf("Could not perform command, status 0x%2x\n", status);
429             }
430             break;
431         case A2DP_SUBEVENT_STREAM_ESTABLISHED:
432             media_tracker.connected = 1;
433             a2dp_subevent_stream_established_get_bd_addr(packet, address);
434             status = a2dp_subevent_stream_established_get_status(packet);
435             if (status){
436                 printf("A2DP: Stream establishment failed: status 0x%02x.\n", status);
437                 break;
438             }
439             local_seid = a2dp_subevent_stream_established_get_local_seid(packet);
440             if (local_seid != media_tracker.local_seid){
441                 printf("A2DP: Stream establishment failed: wrong local seid %d, expected %d.\n", local_seid, media_tracker.local_seid);
442                 break;
443             }
444             media_tracker.a2dp_cid = a2dp_subevent_stream_established_get_a2dp_cid(packet);
445             printf("A2DP: Stream established: address %s, a2dp cid 0x%02x, local seid %d, remote seid %d.\n", bd_addr_to_str(address),
446                 media_tracker.a2dp_cid, media_tracker.local_seid, a2dp_subevent_stream_established_get_remote_seid(packet));
447             printf("Start playing mod, cid 0x%02x.\n", media_tracker.a2dp_cid);
448             data_source = STREAM_MOD;
449             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
450             break;
451 
452         case A2DP_SUBEVENT_STREAM_STARTED:
453             play_info.status = AVRCP_PLAYBACK_STATUS_PLAYING;
454             avrcp_target_set_now_playing_info(avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t));
455             avrcp_target_set_playback_status(avrcp_cid, AVRCP_PLAYBACK_STATUS_PLAYING);
456             a2dp_demo_timer_start(&media_tracker);
457             printf("A2DP: Stream started.\n");
458             break;
459 
460         case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW:
461             a2dp_demo_send_media_packet();
462             break;
463 
464         case A2DP_SUBEVENT_STREAM_SUSPENDED:
465             play_info.status = AVRCP_PLAYBACK_STATUS_PAUSED;
466             avrcp_target_set_playback_status(avrcp_cid, AVRCP_PLAYBACK_STATUS_PAUSED);
467             printf("A2DP: Stream paused.\n");
468             a2dp_demo_timer_stop(&media_tracker);
469             break;
470 
471         case A2DP_SUBEVENT_STREAM_RELEASED:
472             avrcp_target_set_now_playing_info(avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t));
473             play_info.status = AVRCP_PLAYBACK_STATUS_STOPPED;
474             avrcp_target_set_playback_status(avrcp_cid, AVRCP_PLAYBACK_STATUS_STOPPED);
475             printf("A2DP: Stream released.\n");
476             a2dp_demo_timer_stop(&media_tracker);
477             break;
478         case A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED:
479             printf("A2DP: Signaling released.\n");
480             cid = a2dp_subevent_signaling_connection_released_get_a2dp_cid(packet);
481             if (cid == media_tracker.a2dp_cid) {
482                 media_tracker.connected = 0;
483                 media_tracker.a2dp_cid = 0;
484             }
485             break;
486         default:
487             printf("A2DP: event 0x%02x is not parsed\n", packet[2]);
488             break;
489     }
490 }
491 
492 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
493     UNUSED(channel);
494     UNUSED(size);
495     bd_addr_t event_addr;
496     uint16_t local_cid;
497     uint8_t  status = ERROR_CODE_SUCCESS;
498 
499     if (packet_type != HCI_EVENT_PACKET) return;
500     if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return;
501 
502     switch (packet[2]){
503         case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: {
504             local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet);
505             // if (avrcp_cid != 0 && avrcp_cid != local_cid) {
506             //     printf("AVRCP: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_cid, local_cid);
507             //     return;
508             // }
509             // if (avrcp_cid != local_cid) break;
510 
511             status = avrcp_subevent_connection_established_get_status(packet);
512             if (status != ERROR_CODE_SUCCESS){
513                 printf("AVRCP: Connection failed: status 0x%02x\n", status);
514                 return;
515             }
516             avrcp_connected = 1;
517             avrcp_cid = local_cid;
518             avrcp_subevent_connection_established_get_bd_addr(packet, event_addr);
519             printf("AVRCP: connected to %s, avrcp_cid 0x%02x\n", bd_addr_to_str(event_addr), local_cid);
520 
521             avrcp_target_set_now_playing_info(avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t));
522             avrcp_target_set_unit_info(avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, company_id);
523             avrcp_target_set_subunit_info(avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, (uint8_t *)subunit_info, sizeof(subunit_info));
524             return;
525         }
526 
527         case AVRCP_SUBEVENT_EVENT_IDS_QUERY:
528             status = avrcp_target_supported_events(avrcp_cid, events_num, events, sizeof(events));
529             break;
530         case AVRCP_SUBEVENT_COMPANY_IDS_QUERY:
531             status = avrcp_target_supported_companies(avrcp_cid, companies_num, companies, sizeof(companies));
532             break;
533         case AVRCP_SUBEVENT_PLAY_STATUS_QUERY:
534             status = avrcp_target_play_status(avrcp_cid, play_info.song_length_ms, play_info.song_position_ms, play_info.status);
535             break;
536         // case AVRCP_SUBEVENT_NOW_PLAYING_INFO_QUERY:
537         //     status = avrcp_target_now_playing_info(avrcp_cid);
538         //     break;
539         case AVRCP_SUBEVENT_OPERATION:{
540             avrcp_operation_id_t operation_id = avrcp_subevent_operation_get_operation_id(packet);
541             if (!media_tracker.connected) break;
542             switch (operation_id){
543                 case AVRCP_OPERATION_ID_PLAY:
544                     printf("AVRCP: PLAY\n");
545                     status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
546                     break;
547                 case AVRCP_OPERATION_ID_PAUSE:
548                     printf("AVRCP: PAUSE\n");
549                     status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
550                     break;
551                 case AVRCP_OPERATION_ID_STOP:
552                     printf("AVRCP: STOP\n");
553                     status = a2dp_source_disconnect(media_tracker.a2dp_cid);
554                     break;
555                 default:
556                     return;
557             }
558             break;
559         }
560         case AVRCP_SUBEVENT_CONNECTION_RELEASED:
561             printf("AVRCP: Channel released: avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet));
562             avrcp_cid = 0;
563             return;
564         default:
565             printf("AVRCP: event not parsed %02x\n", packet[2]);
566             break;
567     }
568 
569     if (status != ERROR_CODE_SUCCESS){
570         printf("Responding to event 0x%02x failed with status 0x%02x\n", packet[2], status);
571     }
572 }
573 
574 #ifdef HAVE_BTSTACK_STDIN
575 static void show_usage(void){
576     bd_addr_t      iut_address;
577     gap_local_bd_addr(iut_address);
578     printf("\n--- Bluetooth A2DP Source/AVRCP Target Demo %s ---\n", bd_addr_to_str(iut_address));
579     printf("b      - AVDTP Source create  connection to addr %s\n", device_addr_string);
580     printf("B      - AVDTP Source disconnect\n");
581     printf("c      - AVRCP Target create connection to addr %s\n", device_addr_string);
582     printf("C      - AVRCP Target disconnect\n");
583     printf("0      - AVRCP reset now playing info\n");
584 
585     printf("x      - start streaming sine\n");
586     if (hxcmod_initialized){
587         printf("z      - start streaming '%s'\n", mod_name);
588     }
589     printf("p      - pause streaming\n");
590 
591     printf("\n--- Bluetooth  AVRCP Target Commands %s ---\n", bd_addr_to_str(iut_address));
592     printf("---\n");
593 }
594 
595 static void stdin_process(char cmd){
596     uint8_t status = ERROR_CODE_SUCCESS;
597     switch (cmd){
598         case 'b':
599             status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid);
600             printf(" - Create AVDTP Source connection to addr %s, cid 0x%02x.\n", bd_addr_to_str(device_addr), media_tracker.a2dp_cid);
601             break;
602         case 'B':
603             printf(" - AVDTP Source Disconnect from cid 0x%2x\n", media_tracker.a2dp_cid);
604             status = a2dp_source_disconnect(media_tracker.a2dp_cid);
605             break;
606         case 'c':
607             printf(" - Create AVRCP Target connection to addr %s.\n", bd_addr_to_str(device_addr));
608             status = avrcp_target_connect(device_addr, &avrcp_cid);
609             break;
610         case 'C':
611             printf(" - AVRCP Target disconnect\n");
612             status = avrcp_target_disconnect(avrcp_cid);
613             break;
614 
615         case '\n':
616         case '\r':
617             break;
618 
619         case 't':
620             printf("STREAM_PTS_TEST.\n");
621             data_source = STREAM_PTS_TEST;
622             avrcp_target_set_now_playing_info(avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t));
623             if (!media_tracker.connected) break;
624             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
625             break;
626 
627         case 'x':
628             avrcp_target_set_now_playing_info(avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t));
629             printf("Playing sine.\n");
630             data_source = STREAM_SINE;
631             if (!media_tracker.connected) break;
632             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
633             break;
634         case 'z':
635             avrcp_target_set_now_playing_info(avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t));
636             printf("Playing mod.\n");
637             data_source = STREAM_MOD;
638             if (!media_tracker.connected) break;
639             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
640             break;
641         case 'p':
642             if (!media_tracker.connected) break;
643             printf("Pause stream.\n");
644             status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
645             break;
646         case '0':
647             avrcp_target_set_now_playing_info(avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t));
648             printf("Reset now playing info\n");
649             break;
650         default:
651             show_usage();
652             return;
653     }
654     if (status != ERROR_CODE_SUCCESS){
655         printf("Could not perform command, status 0x%2x\n", status);
656     }
657 }
658 #endif
659 
660 
661 int btstack_main(int argc, const char * argv[]);
662 int btstack_main(int argc, const char * argv[]){
663     (void)argc;
664     (void)argv;
665 
666     int err = a2dp_source_and_avrcp_services_init();
667     if (err) return err;
668     // turn on!
669     hci_power_control(HCI_POWER_ON);
670     return 0;
671 }
672 /* EXAMPLE_END */
673