xref: /btstack/example/a2dp_source_demo.c (revision cfd2437ec63a01d0af049500b4a1d2d2cf8bad03)
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 0
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     avrcp_target_create_sdp_record(sdp_avrcp_target_service_buffer, 0x10001, AVRCP_BROWSING_ENABLED, 1, NULL, NULL);
267     sdp_register_service(sdp_avrcp_target_service_buffer);
268 
269     // Set local name with a template Bluetooth address, that will be automatically
270     // replaced with a actual address once it is available, i.e. when BTstack boots
271     // up and starts talking to a Bluetooth module.
272     gap_set_local_name("A2DP Source 00:00:00:00:00:00");
273     gap_discoverable_control(1);
274     gap_set_class_of_device(0x200408);
275 
276     // Register for HCI events.
277     hci_event_callback_registration.callback = &a2dp_source_packet_handler;
278     hci_add_event_handler(&hci_event_callback_registration);
279 
280     hxcmod_initialized = hxcmod_init(&mod_context);
281     if (hxcmod_initialized){
282         hxcmod_setcfg(&mod_context, A2DP_SAMPLE_RATE, 16, 1, 1, 1);
283         hxcmod_load(&mod_context, (void *) &mod_data, mod_len);
284         printf("loaded mod '%s', size %u\n", mod_name, mod_len);
285     }
286 
287     // Parse human readable Bluetooth address.
288     sscanf_bd_addr(device_addr_string, device_addr);
289 
290 #ifdef HAVE_BTSTACK_STDIN
291     btstack_stdin_setup(stdin_process);
292 #endif
293     return 0;
294 }
295 /* LISTING_END */
296 
297 static void a2dp_demo_send_media_packet(void){
298     int num_bytes_in_frame = btstack_sbc_encoder_sbc_buffer_length();
299     int bytes_in_storage = media_tracker.sbc_storage_count;
300     uint8_t num_frames = bytes_in_storage / num_bytes_in_frame;
301     a2dp_source_stream_send_media_payload(media_tracker.a2dp_cid, media_tracker.local_seid, media_tracker.sbc_storage, bytes_in_storage, num_frames, 0);
302     media_tracker.sbc_storage_count = 0;
303     media_tracker.sbc_ready_to_send = 0;
304 }
305 
306 static void produce_sine_audio(int16_t * pcm_buffer, int num_samples_to_write){
307     int count;
308     for (count = 0; count < num_samples_to_write ; count++){
309         pcm_buffer[count * 2]     = sine_int16[sine_phase];
310         pcm_buffer[count * 2 + 1] = sine_int16[sine_phase];
311         sine_phase++;
312         if (sine_phase >= TABLE_SIZE_441HZ){
313             sine_phase -= TABLE_SIZE_441HZ;
314         }
315     }
316 }
317 
318 static void produce_mod_audio(int16_t * pcm_buffer, int num_samples_to_write){
319     hxcmod_fillbuffer(&mod_context, (unsigned short *) &pcm_buffer[0], num_samples_to_write, &trkbuf);
320 }
321 
322 static void produce_audio(int16_t * pcm_buffer, int num_samples){
323     switch (data_source){
324         case STREAM_SINE:
325             produce_sine_audio(pcm_buffer, num_samples);
326             break;
327         case STREAM_MOD:
328             produce_mod_audio(pcm_buffer, num_samples);
329             break;
330         default:
331             break;
332     }
333 #ifdef VOLUME_REDUCTION
334     int i;
335     for (i=0;i<num_samples*2;i++){
336         if (pcm_buffer[i] > 0){
337             pcm_buffer[i] =     pcm_buffer[i]  >> VOLUME_REDUCTION;
338         } else {
339             pcm_buffer[i] = -((-pcm_buffer[i]) >> VOLUME_REDUCTION);
340         }
341     }
342 #endif
343 }
344 
345 static int a2dp_demo_fill_sbc_audio_buffer(a2dp_media_sending_context_t * context){
346     // perform sbc encodin
347     int total_num_bytes_read = 0;
348     unsigned int num_audio_samples_per_sbc_buffer = btstack_sbc_encoder_num_audio_frames();
349     while (context->samples_ready >= num_audio_samples_per_sbc_buffer
350         && (context->max_media_payload_size - context->sbc_storage_count) >= btstack_sbc_encoder_sbc_buffer_length()){
351 
352         int16_t pcm_frame[256*NUM_CHANNELS];
353 
354         produce_audio(pcm_frame, num_audio_samples_per_sbc_buffer);
355         btstack_sbc_encoder_process_data(pcm_frame);
356 
357         uint16_t sbc_frame_size = btstack_sbc_encoder_sbc_buffer_length();
358         uint8_t * sbc_frame = btstack_sbc_encoder_sbc_buffer();
359 
360         total_num_bytes_read += num_audio_samples_per_sbc_buffer;
361         memcpy(&context->sbc_storage[context->sbc_storage_count], sbc_frame, sbc_frame_size);
362         context->sbc_storage_count += sbc_frame_size;
363         context->samples_ready -= num_audio_samples_per_sbc_buffer;
364     }
365     return total_num_bytes_read;
366 }
367 
368 static void a2dp_demo_audio_timeout_handler(btstack_timer_source_t * timer){
369     a2dp_media_sending_context_t * context = (a2dp_media_sending_context_t *) btstack_run_loop_get_timer_context(timer);
370     btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS);
371     btstack_run_loop_add_timer(&context->audio_timer);
372     uint32_t now = btstack_run_loop_get_time_ms();
373 
374     uint32_t update_period_ms = AUDIO_TIMEOUT_MS;
375     if (context->time_audio_data_sent > 0){
376         update_period_ms = now - context->time_audio_data_sent;
377     }
378 
379     uint32_t num_samples = (update_period_ms * A2DP_SAMPLE_RATE) / 1000;
380     context->acc_num_missed_samples += (update_period_ms * A2DP_SAMPLE_RATE) % 1000;
381 
382     while (context->acc_num_missed_samples >= 1000){
383         num_samples++;
384         context->acc_num_missed_samples -= 1000;
385     }
386     context->time_audio_data_sent = now;
387     context->samples_ready += num_samples;
388 
389     if (context->sbc_ready_to_send) return;
390 
391     a2dp_demo_fill_sbc_audio_buffer(context);
392 
393     if ((context->sbc_storage_count + btstack_sbc_encoder_sbc_buffer_length()) > context->max_media_payload_size){
394         // schedule sending
395         context->sbc_ready_to_send = 1;
396         a2dp_source_stream_endpoint_request_can_send_now(context->a2dp_cid, context->local_seid);
397     }
398 }
399 
400 static void a2dp_demo_timer_start(a2dp_media_sending_context_t * context){
401     context->max_media_payload_size = btstack_min(a2dp_max_media_payload_size(context->a2dp_cid, context->local_seid), SBC_STORAGE_SIZE);
402     context->sbc_storage_count = 0;
403     context->sbc_ready_to_send = 0;
404     context->streaming = 1;
405     btstack_run_loop_remove_timer(&context->audio_timer);
406     btstack_run_loop_set_timer_handler(&context->audio_timer, a2dp_demo_audio_timeout_handler);
407     btstack_run_loop_set_timer_context(&context->audio_timer, context);
408     btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS);
409     btstack_run_loop_add_timer(&context->audio_timer);
410 }
411 
412 static void a2dp_demo_timer_stop(a2dp_media_sending_context_t * context){
413     context->time_audio_data_sent = 0;
414     context->acc_num_missed_samples = 0;
415     context->samples_ready = 0;
416     context->streaming = 1;
417     context->sbc_storage_count = 0;
418     context->sbc_ready_to_send = 0;
419     btstack_run_loop_remove_timer(&context->audio_timer);
420 }
421 
422 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
423     UNUSED(channel);
424     UNUSED(size);
425     uint8_t status;
426     uint8_t local_seid;
427     bd_addr_t address;
428     uint16_t cid;
429 
430     if (packet_type != HCI_EVENT_PACKET) return;
431 
432 #ifndef HAVE_BTSTACK_STDIN
433     if (hci_event_packet_get_type(packet) == BTSTACK_EVENT_STATE){
434         if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
435         printf("Create A2DP Source connection to addr %s.\n", bd_addr_to_str(device_addr));
436         status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid);
437         if (status != ERROR_CODE_SUCCESS){
438             printf("Could not perform command, status 0x%2x\n", status);
439         }
440         return;
441     }
442 #endif
443     if (hci_event_packet_get_type(packet) == HCI_EVENT_PIN_CODE_REQUEST) {
444         printf("Pin code request - using '0000'\n");
445         hci_event_pin_code_request_get_bd_addr(packet, address);
446         gap_pin_code_response(address, "0000");
447         return;
448     }
449 
450     if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return;
451 
452     printf("A2DP Meta %x\n", hci_event_a2dp_meta_get_subevent_code(packet));
453 
454     switch (hci_event_a2dp_meta_get_subevent_code(packet)){
455         case A2DP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED:
456             a2dp_subevent_signaling_connection_established_get_bd_addr(packet, address);
457             cid = a2dp_subevent_signaling_connection_established_get_a2dp_cid(packet);
458             status = a2dp_subevent_signaling_connection_established_get_status(packet);
459 
460             if (status != ERROR_CODE_SUCCESS){
461                 printf("A2DP Source: Connection failed, status 0x%02x, cid 0x%02x, a2dp_cid 0x%02x \n", status, cid, media_tracker.a2dp_cid);
462                 media_tracker.a2dp_cid = 0;
463                 break;
464             }
465             media_tracker.a2dp_cid = cid;
466             printf("A2DP Source: Connected to address %s, a2dp cid 0x%02x.\n", bd_addr_to_str(address), media_tracker.a2dp_cid);
467             break;
468 
469          case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{
470             sbc_configuration.reconfigure = a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet);
471             sbc_configuration.num_channels = a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet);
472             sbc_configuration.sampling_frequency = a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet);
473             sbc_configuration.channel_mode = a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet);
474             sbc_configuration.block_length = a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet);
475             sbc_configuration.subbands = a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet);
476             sbc_configuration.allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet);
477             sbc_configuration.min_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet);
478             sbc_configuration.max_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet);
479             sbc_configuration.frames_per_buffer = sbc_configuration.subbands * sbc_configuration.block_length;
480             printf("A2DP Source: Received SBC codec configuration, sampling frequency %u.\n", sbc_configuration.sampling_frequency);
481 
482             btstack_sbc_encoder_init(&sbc_encoder_state, SBC_MODE_STANDARD,
483                 sbc_configuration.block_length, sbc_configuration.subbands,
484                 sbc_configuration.allocation_method, sbc_configuration.sampling_frequency,
485                 sbc_configuration.max_bitpool_value,
486                 sbc_configuration.channel_mode);
487             break;
488         }
489 
490         case A2DP_SUBEVENT_STREAM_ESTABLISHED:
491             a2dp_subevent_stream_established_get_bd_addr(packet, address);
492             status = a2dp_subevent_stream_established_get_status(packet);
493             if (status){
494                 printf("A2DP Source: Stream failed, status 0x%02x.\n", status);
495                 break;
496             }
497             local_seid = a2dp_subevent_stream_established_get_local_seid(packet);
498             if (local_seid != media_tracker.local_seid){
499                 printf("A2DP Source: Stream failed, wrong local seid %d, expected %d.\n", local_seid, media_tracker.local_seid);
500                 break;
501             }
502             printf("A2DP Source: Stream established, address %s, a2dp cid 0x%02x, local seid %d, remote seid %d.\n", bd_addr_to_str(address),
503                 media_tracker.a2dp_cid, media_tracker.local_seid, a2dp_subevent_stream_established_get_remote_seid(packet));
504             media_tracker.stream_opened = 1;
505             data_source = STREAM_MOD;
506             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
507             break;
508 
509         case A2DP_SUBEVENT_STREAM_RECONFIGURED:
510             status = a2dp_subevent_stream_reconfigured_get_status(packet);
511             printf("A2DP Source: Reconfigured, status 0x%02x\n", status);
512             break;
513 
514         case A2DP_SUBEVENT_STREAM_STARTED:
515             play_info.status = AVRCP_PLAYBACK_STATUS_PLAYING;
516             if (media_tracker.avrcp_cid){
517                 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t));
518                 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PLAYING);
519             }
520             a2dp_demo_timer_start(&media_tracker);
521             printf("A2DP Source: Stream started.\n");
522             break;
523 
524         case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW:
525             a2dp_demo_send_media_packet();
526             break;
527 
528         case A2DP_SUBEVENT_STREAM_SUSPENDED:
529             play_info.status = AVRCP_PLAYBACK_STATUS_PAUSED;
530             if (media_tracker.avrcp_cid){
531                 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PAUSED);
532             }
533             printf("A2DP Source: Stream paused.\n");
534             a2dp_demo_timer_stop(&media_tracker);
535             break;
536 
537         case A2DP_SUBEVENT_STREAM_RELEASED:
538             play_info.status = AVRCP_PLAYBACK_STATUS_STOPPED;
539             cid = a2dp_subevent_stream_released_get_a2dp_cid(packet);
540             if (cid == media_tracker.a2dp_cid) {
541                 media_tracker.stream_opened = 0;
542                 printf("A2DP Source: Stream released.\n");
543             }
544             if (media_tracker.avrcp_cid){
545                 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t));
546                 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_STOPPED);
547             }
548             a2dp_demo_timer_stop(&media_tracker);
549             break;
550         case A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED:
551             cid = a2dp_subevent_signaling_connection_released_get_a2dp_cid(packet);
552             if (cid == media_tracker.a2dp_cid) {
553                 media_tracker.avrcp_cid = 0;
554                 media_tracker.a2dp_cid = 0;
555                 printf("A2DP Source: Signaling released.\n\n");
556             }
557             break;
558         default:
559             break;
560     }
561 }
562 
563 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
564     UNUSED(channel);
565     UNUSED(size);
566     bd_addr_t event_addr;
567     uint16_t local_cid;
568     uint8_t  status = ERROR_CODE_SUCCESS;
569 
570     if (packet_type != HCI_EVENT_PACKET) return;
571     if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return;
572 
573     switch (packet[2]){
574         case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: {
575             local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet);
576             // if (avrcp_cid != 0 && avrcp_cid != local_cid) {
577             //     printf("AVRCP Target: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_cid, local_cid);
578             //     return;
579             // }
580             // if (avrcp_cid != local_cid) break;
581 
582             status = avrcp_subevent_connection_established_get_status(packet);
583             if (status != ERROR_CODE_SUCCESS){
584                 printf("AVRCP Target: Connection failed, status 0x%02x\n", status);
585                 return;
586             }
587             media_tracker.avrcp_cid = local_cid;
588             avrcp_subevent_connection_established_get_bd_addr(packet, event_addr);
589             printf("AVRCP Target: Connected to %s, avrcp_cid 0x%02x\n", bd_addr_to_str(event_addr), local_cid);
590 
591             avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t));
592             avrcp_target_set_unit_info(media_tracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, company_id);
593             avrcp_target_set_subunit_info(media_tracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, (uint8_t *)subunit_info, sizeof(subunit_info));
594             return;
595         }
596 
597         case AVRCP_SUBEVENT_EVENT_IDS_QUERY:
598             status = avrcp_target_supported_events(media_tracker.avrcp_cid, events_num, events, sizeof(events));
599             break;
600         case AVRCP_SUBEVENT_COMPANY_IDS_QUERY:
601             status = avrcp_target_supported_companies(media_tracker.avrcp_cid, companies_num, companies, sizeof(companies));
602             break;
603         case AVRCP_SUBEVENT_PLAY_STATUS_QUERY:
604             status = avrcp_target_play_status(media_tracker.avrcp_cid, play_info.song_length_ms, play_info.song_position_ms, play_info.status);
605             break;
606         // case AVRCP_SUBEVENT_NOW_PLAYING_INFO_QUERY:
607         //     status = avrcp_target_now_playing_info(avrcp_cid);
608         //     break;
609         case AVRCP_SUBEVENT_OPERATION:{
610             avrcp_operation_id_t operation_id = avrcp_subevent_operation_get_operation_id(packet);
611             switch (operation_id){
612                 case AVRCP_OPERATION_ID_PLAY:
613                     printf("AVRCP Target: PLAY\n");
614                     status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
615                     break;
616                 case AVRCP_OPERATION_ID_PAUSE:
617                     printf("AVRCP Target: PAUSE\n");
618                     status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
619                     break;
620                 case AVRCP_OPERATION_ID_STOP:
621                     printf("AVRCP Target: STOP\n");
622                     status = a2dp_source_disconnect(media_tracker.a2dp_cid);
623                     break;
624                 default:
625                     printf("AVRCP Target: operation 0x%2x is not handled\n", operation_id);
626                     return;
627             }
628             break;
629         }
630         case AVRCP_SUBEVENT_CONNECTION_RELEASED:
631             printf("AVRCP Target: Disconnected, avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet));
632             media_tracker.avrcp_cid = 0;
633             return;
634         default:
635             break;
636     }
637 
638     if (status != ERROR_CODE_SUCCESS){
639         printf("Responding to event 0x%02x failed with status 0x%02x\n", packet[2], status);
640     }
641 }
642 
643 #ifdef HAVE_BTSTACK_STDIN
644 static void show_usage(void){
645     bd_addr_t      iut_address;
646     gap_local_bd_addr(iut_address);
647     printf("\n--- Bluetooth  A2DP Source/AVRCP Target Demo %s ---\n", bd_addr_to_str(iut_address));
648     printf("b      - A2DP Source create connection to addr %s\n", device_addr_string);
649     printf("B      - A2DP Source disconnect\n");
650     printf("c      - AVRCP Target create connection to addr %s\n", device_addr_string);
651     printf("C      - AVRCP Target disconnect\n");
652 
653     printf("x      - start streaming sine\n");
654     if (hxcmod_initialized){
655         printf("z      - start streaming '%s'\n", mod_name);
656     }
657     printf("p      - pause streaming\n");
658     printf("w      - reconfigure stream for 44100 Hz\n");
659     printf("e      - reconfigure stream for 48000 Hz\n");
660 
661     printf("\n--- Bluetooth  AVRCP Target Commands %s ---\n", bd_addr_to_str(iut_address));
662     printf("---\n");
663 }
664 
665 static void stdin_process(char cmd){
666     uint8_t status = ERROR_CODE_SUCCESS;
667     switch (cmd){
668         case 'b':
669             status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid);
670             printf("%c - Create A2DP Source connection to addr %s, cid 0x%02x.\n", cmd, bd_addr_to_str(device_addr), media_tracker.a2dp_cid);
671             break;
672         case 'B':
673             printf("%c - A2DP Source Disconnect from cid 0x%2x\n", cmd, media_tracker.a2dp_cid);
674             status = a2dp_source_disconnect(media_tracker.a2dp_cid);
675             break;
676         case 'c':
677             printf("%c - Create AVRCP Target connection to addr %s.\n", cmd, bd_addr_to_str(device_addr));
678             status = avrcp_target_connect(device_addr, &media_tracker.avrcp_cid);
679             break;
680         case 'C':
681             printf("%c - AVRCP Target disconnect\n", cmd);
682             status = avrcp_target_disconnect(media_tracker.avrcp_cid);
683             break;
684 
685         case '\n':
686         case '\r':
687             break;
688 
689         case 'x':
690             if (media_tracker.avrcp_cid){
691                 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t));
692             }
693             printf("%c - Play sine.\n", cmd);
694             data_source = STREAM_SINE;
695             if (!media_tracker.stream_opened) break;
696             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
697             break;
698         case 'z':
699             if (media_tracker.avrcp_cid){
700                 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t));
701             }
702             printf("%c - Play mod.\n", cmd);
703             data_source = STREAM_MOD;
704             if (!media_tracker.stream_opened) break;
705             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
706             break;
707 
708         case 'p':
709             if (!media_tracker.stream_opened) break;
710             printf("%c - Pause stream.\n", cmd);
711             status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
712             break;
713 
714         case 'w':
715             if (!media_tracker.stream_opened) break;
716             if (play_info.status == AVRCP_PLAYBACK_STATUS_PLAYING){
717                 printf("Stream cannot be reconfigured while playing, please pause stream first\n");
718                 break;
719             }
720             printf("%c - Reconfigure for 44100 Hz.\n", cmd);
721             status = a2dp_source_reconfigure_stream_sampling_frequency(media_tracker.a2dp_cid, 44100);
722             break;
723 
724         case 'e':
725             if (!media_tracker.stream_opened) break;
726             if (play_info.status == AVRCP_PLAYBACK_STATUS_PLAYING){
727                 printf("Stream cannot be reconfigured while playing, please pause stream first\n");
728                 break;
729             }
730             printf("%c - Reconfigure for 48000 Hz.\n", cmd);
731             status = a2dp_source_reconfigure_stream_sampling_frequency(media_tracker.a2dp_cid, 48000);
732             break;
733 
734         default:
735             show_usage();
736             return;
737     }
738     if (status != ERROR_CODE_SUCCESS){
739         printf("Could not perform command \'%c\', status 0x%2x\n", cmd, status);
740     }
741 }
742 #endif
743 
744 
745 int btstack_main(int argc, const char * argv[]);
746 int btstack_main(int argc, const char * argv[]){
747     (void)argc;
748     (void)argv;
749 
750     int err = a2dp_source_and_avrcp_services_init();
751     if (err) return err;
752     // turn on!
753     hci_power_control(HCI_POWER_ON);
754     return 0;
755 }
756 /* EXAMPLE_END */
757