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