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