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 * For more info on BTstack audio, see our blog post 58 * [A2DP Sink and Source on STM32 F4 Discovery Board](http://bluekitchen-gmbh.com/a2dp-sink-and-source-on-stm32-f4-discovery-board/). 59 * 60 */ 61 // ***************************************************************************** 62 63 64 #include <stdint.h> 65 #include <stdio.h> 66 #include <stdlib.h> 67 #include <string.h> 68 69 #include "btstack.h" 70 #include "hxcmod.h" 71 #include "mods/mod.h" 72 73 // logarithmic volume reduction, samples are divided by 2^x 74 // #define VOLUME_REDUCTION 3 75 // #undef HAVE_BTSTACK_STDIN 76 77 //#define AVRCP_BROWSING_ENABLED 78 79 #define NUM_CHANNELS 2 80 #define BYTES_PER_AUDIO_SAMPLE (2*NUM_CHANNELS) 81 #define AUDIO_TIMEOUT_MS 10 82 #define TABLE_SIZE_441HZ 100 83 84 #define SBC_STORAGE_SIZE 1030 85 86 typedef enum { 87 STREAM_SINE = 0, 88 STREAM_MOD, 89 STREAM_PTS_TEST 90 } stream_data_source_t; 91 92 typedef struct { 93 uint16_t a2dp_cid; 94 uint8_t local_seid; 95 uint8_t remote_seid; 96 uint8_t stream_opened; 97 uint16_t avrcp_cid; 98 99 uint32_t time_audio_data_sent; // ms 100 uint32_t acc_num_missed_samples; 101 uint32_t samples_ready; 102 btstack_timer_source_t audio_timer; 103 uint8_t streaming; 104 int max_media_payload_size; 105 106 uint8_t sbc_storage[SBC_STORAGE_SIZE]; 107 uint16_t sbc_storage_count; 108 uint8_t sbc_ready_to_send; 109 } a2dp_media_sending_context_t; 110 111 static uint8_t media_sbc_codec_capabilities[] = { 112 (AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO, 113 0xFF,//(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS, 114 2, 53 115 }; 116 117 // input signal: pre-computed int16 sine wave, 44100 Hz at 441 Hz 118 static const int16_t sine_int16_44100[] = { 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 0, -2057, -4107, -6140, -8149, -10126, -12062, -13952, -15786, -17557, 125 -19260, -20886, -22431, -23886, -25247, -26509, -27666, -28714, -29648, -30466, 126 -31163, -31738, -32187, -32509, -32702, -32767, -32702, -32509, -32187, -31738, 127 -31163, -30466, -29648, -28714, -27666, -26509, -25247, -23886, -22431, -20886, 128 -19260, -17557, -15786, -13952, -12062, -10126, -8149, -6140, -4107, -2057, 129 }; 130 131 static const int num_samples_sine_int16_44100 = sizeof(sine_int16_44100) / 2; 132 133 // input signal: pre-computed int16 sine wave, 48000 Hz at 441 Hz 134 static const int16_t sine_int16_48000[] = { 135 0, 1905, 3804, 5690, 7557, 9398, 11207, 12978, 14706, 16383, 136 18006, 19567, 21062, 22486, 23834, 25101, 26283, 27376, 28377, 29282, 137 30087, 30791, 31390, 31884, 32269, 32545, 32712, 32767, 32712, 32545, 138 32269, 31884, 31390, 30791, 30087, 29282, 28377, 27376, 26283, 25101, 139 23834, 22486, 21062, 19567, 18006, 16383, 14706, 12978, 11207, 9398, 140 7557, 5690, 3804, 1905, 0, -1905, -3804, -5690, -7557, -9398, 141 -11207, -12978, -14706, -16384, -18006, -19567, -21062, -22486, -23834, -25101, 142 -26283, -27376, -28377, -29282, -30087, -30791, -31390, -31884, -32269, -32545, 143 -32712, -32767, -32712, -32545, -32269, -31884, -31390, -30791, -30087, -29282, 144 -28377, -27376, -26283, -25101, -23834, -22486, -21062, -19567, -18006, -16384, 145 -14706, -12978, -11207, -9398, -7557, -5690, -3804, -1905, }; 146 147 static const int num_samples_sine_int16_48000 = sizeof(sine_int16_48000) / 2; 148 149 typedef struct { 150 int reconfigure; 151 int num_channels; 152 int sampling_frequency; 153 int channel_mode; 154 int block_length; 155 int subbands; 156 int allocation_method; 157 int min_bitpool_value; 158 int max_bitpool_value; 159 int frames_per_buffer; 160 } avdtp_media_codec_configuration_sbc_t; 161 162 static btstack_packet_callback_registration_t hci_event_callback_registration; 163 164 // pts: static const char * device_addr_string = "00:1B:DC:08:0A:A5"; 165 // pts: static const char * device_addr_string = "00:1B:DC:08:E2:72"; 166 // mac 2013: static const char * device_addr_string = "84:38:35:65:d1:15"; 167 // phone 2013: static const char * device_addr_string = "D8:BB:2C:DF:F0:F2"; 168 // Minijambox: 169 static const char * device_addr_string = "00:21:3C:AC:F7:38"; 170 // Philips SHB9100: static const char * device_addr_string = "00:22:37:05:FD:E8"; 171 // RT-B6: static const char * device_addr_string = "00:75:58:FF:C9:7D"; 172 // BT dongle: static const char * device_addr_string = "00:1A:7D:DA:71:0A"; 173 // Sony MDR-ZX330BT static const char * device_addr_string = "00:18:09:28:50:18"; 174 // Panda (BM6) static const char * device_addr_string = "4F:3F:66:52:8B:E0"; 175 // BeatsX: static const char * device_addr_string = "DC:D3:A2:89:57:FB"; 176 177 static bd_addr_t device_addr; 178 static uint8_t sdp_a2dp_source_service_buffer[150]; 179 static uint8_t sdp_avrcp_target_service_buffer[200]; 180 static uint8_t sdp_avrcp_controller_service_buffer[200]; 181 182 static avdtp_media_codec_configuration_sbc_t sbc_configuration; 183 static btstack_sbc_encoder_state_t sbc_encoder_state; 184 185 static uint8_t media_sbc_codec_configuration[4]; 186 static a2dp_media_sending_context_t media_tracker; 187 188 static stream_data_source_t data_source; 189 190 static int sine_phase; 191 static int sample_rate = 44100; 192 193 static int hxcmod_initialized; 194 static modcontext mod_context; 195 static tracker_buffer_state trkbuf; 196 197 static uint16_t avrcp_controller_cid = 0; 198 199 /* AVRCP Target context START */ 200 static const uint8_t subunit_info[] = { 201 0,0,0,0, 202 1,1,1,1, 203 2,2,2,2, 204 3,3,3,3, 205 4,4,4,4, 206 5,5,5,5, 207 6,6,6,6, 208 7,7,7,7 209 }; 210 211 static uint32_t company_id = 0x112233; 212 static uint8_t companies_num = 1; 213 static uint8_t companies[] = { 214 0x00, 0x19, 0x58 //BT SIG registered CompanyID 215 }; 216 217 static uint8_t events_num = 13; 218 static uint8_t events[] = { 219 AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED, 220 AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED, 221 AVRCP_NOTIFICATION_EVENT_TRACK_REACHED_END, 222 AVRCP_NOTIFICATION_EVENT_TRACK_REACHED_START, 223 AVRCP_NOTIFICATION_EVENT_PLAYBACK_POS_CHANGED, 224 AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED, 225 AVRCP_NOTIFICATION_EVENT_SYSTEM_STATUS_CHANGED, 226 AVRCP_NOTIFICATION_EVENT_PLAYER_APPLICATION_SETTING_CHANGED, 227 AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED, 228 AVRCP_NOTIFICATION_EVENT_AVAILABLE_PLAYERS_CHANGED, 229 AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED, 230 AVRCP_NOTIFICATION_EVENT_UIDS_CHANGED, 231 AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED 232 }; 233 234 typedef struct { 235 uint8_t track_id[8]; 236 uint32_t song_length_ms; 237 avrcp_playback_status_t status; 238 uint32_t song_position_ms; // 0xFFFFFFFF if not supported 239 } avrcp_play_status_info_t; 240 241 // python -c "print('a'*512)" 242 static const char title[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 243 244 avrcp_track_t tracks[] = { 245 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, 1, "Sine", "Generated", "A2DP Source Demo", "monotone", 12345}, 246 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 2, "Nao-deceased", "Decease", "A2DP Source Demo", "vivid", 12345}, 247 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, 3, (char *)title, "Decease", "A2DP Source Demo", "vivid", 12345}, 248 }; 249 int current_track_index; 250 avrcp_play_status_info_t play_info; 251 252 /* AVRCP Target context END */ 253 254 /* @section Main Application Setup 255 * 256 * @text The Listing MainConfiguration shows how to setup AD2P Source and AVRCP Target services. 257 */ 258 259 /* LISTING_START(MainConfiguration): Setup Audio Source and AVRCP Target services */ 260 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size); 261 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 262 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 263 #ifdef HAVE_BTSTACK_STDIN 264 static void stdin_process(char cmd); 265 #endif 266 267 static void a2dp_demo_reconfigure_sample_rate(int new_sample_rate){ 268 if (!hxcmod_initialized){ 269 hxcmod_initialized = hxcmod_init(&mod_context); 270 if (!hxcmod_initialized) { 271 printf("could not initialize hxcmod\n"); 272 return; 273 } 274 } 275 sample_rate = new_sample_rate; 276 media_tracker.sbc_storage_count = 0; 277 media_tracker.samples_ready = 0; 278 hxcmod_unload(&mod_context); 279 hxcmod_setcfg(&mod_context, sample_rate, 16, 1, 1, 1); 280 hxcmod_load(&mod_context, (void *) &mod_data, mod_len); 281 } 282 283 static int a2dp_source_and_avrcp_services_init(void){ 284 285 // request role change on reconnecting headset to always use them in slave mode 286 hci_set_master_slave_policy(0); 287 288 l2cap_init(); 289 // Initialize A2DP Source. 290 a2dp_source_init(); 291 a2dp_source_register_packet_handler(&a2dp_source_packet_handler); 292 293 // Create stream endpoint. 294 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)); 295 if (!local_stream_endpoint){ 296 printf("A2DP Source: not enough memory to create local stream endpoint\n"); 297 return 1; 298 } 299 media_tracker.local_seid = avdtp_local_seid(local_stream_endpoint); 300 avdtp_source_register_delay_reporting_category(media_tracker.local_seid); 301 302 avrcp_init(); 303 // Initialize AVRCP Target. 304 avrcp_target_init(); 305 avrcp_target_register_packet_handler(&avrcp_target_packet_handler); 306 // Initialize AVRCP Controller 307 avrcp_controller_init(); 308 avrcp_controller_register_packet_handler(&avrcp_controller_packet_handler); 309 310 // Initialize SDP, 311 sdp_init(); 312 313 // Create A2DP Source service record and register it with SDP. 314 memset(sdp_a2dp_source_service_buffer, 0, sizeof(sdp_a2dp_source_service_buffer)); 315 a2dp_source_create_sdp_record(sdp_a2dp_source_service_buffer, 0x10002, 1, NULL, NULL); 316 sdp_register_service(sdp_a2dp_source_service_buffer); 317 318 // Create AVRCP target service record and register it with SDP. 319 memset(sdp_avrcp_target_service_buffer, 0, sizeof(sdp_avrcp_target_service_buffer)); 320 uint16_t supported_features = (1 << AVRCP_TARGET_SUPPORTED_FEATURE_CATEGORY_PLAYER_OR_RECORDER); 321 #ifdef AVRCP_BROWSING_ENABLED 322 supported_features |= (1 << AVRCP_TARGET_SUPPORTED_FEATURE_BROWSING); 323 #endif 324 avrcp_target_create_sdp_record(sdp_avrcp_target_service_buffer, 0x10001, supported_features, NULL, NULL); 325 sdp_register_service(sdp_avrcp_target_service_buffer); 326 327 // setup AVRCP Controller 328 memset(sdp_avrcp_controller_service_buffer, 0, sizeof(sdp_avrcp_controller_service_buffer)); 329 uint16_t controller_supported_features = (1 << AVRCP_CONTROLLER_SUPPORTED_FEATURE_CATEGORY_MONITOR_OR_AMPLIFIER); 330 avrcp_controller_create_sdp_record(sdp_avrcp_controller_service_buffer, 0x10002, controller_supported_features, NULL, NULL); 331 sdp_register_service(sdp_avrcp_controller_service_buffer); 332 333 // Set local name with a template Bluetooth address, that will be automatically 334 // replaced with a actual address once it is available, i.e. when BTstack boots 335 // up and starts talking to a Bluetooth module. 336 gap_set_local_name("A2DP Source 00:00:00:00:00:00"); 337 gap_discoverable_control(1); 338 gap_set_class_of_device(0x200408); 339 340 // Register for HCI events. 341 hci_event_callback_registration.callback = &a2dp_source_packet_handler; 342 hci_add_event_handler(&hci_event_callback_registration); 343 344 a2dp_demo_reconfigure_sample_rate(sample_rate); 345 346 // Parse human readable Bluetooth address. 347 sscanf_bd_addr(device_addr_string, device_addr); 348 349 #ifdef HAVE_BTSTACK_STDIN 350 btstack_stdin_setup(stdin_process); 351 #endif 352 return 0; 353 } 354 /* LISTING_END */ 355 356 static void a2dp_demo_send_media_packet(void){ 357 int num_bytes_in_frame = btstack_sbc_encoder_sbc_buffer_length(); 358 int bytes_in_storage = media_tracker.sbc_storage_count; 359 uint8_t num_frames = bytes_in_storage / num_bytes_in_frame; 360 a2dp_source_stream_send_media_payload(media_tracker.a2dp_cid, media_tracker.local_seid, media_tracker.sbc_storage, bytes_in_storage, num_frames, 0); 361 media_tracker.sbc_storage_count = 0; 362 media_tracker.sbc_ready_to_send = 0; 363 } 364 365 static void produce_sine_audio(int16_t * pcm_buffer, int num_samples_to_write){ 366 int count; 367 for (count = 0; count < num_samples_to_write ; count++){ 368 switch (sample_rate){ 369 case 44100: 370 pcm_buffer[count * 2] = sine_int16_44100[sine_phase]; 371 pcm_buffer[count * 2 + 1] = sine_int16_44100[sine_phase]; 372 sine_phase++; 373 if (sine_phase >= num_samples_sine_int16_44100){ 374 sine_phase -= num_samples_sine_int16_44100; 375 } 376 break; 377 case 48000: 378 pcm_buffer[count * 2] = sine_int16_48000[sine_phase]; 379 pcm_buffer[count * 2 + 1] = sine_int16_48000[sine_phase]; 380 sine_phase++; 381 if (sine_phase >= num_samples_sine_int16_48000){ 382 sine_phase -= num_samples_sine_int16_48000; 383 } 384 break; 385 default: 386 break; 387 } 388 389 390 } 391 } 392 393 static void produce_mod_audio(int16_t * pcm_buffer, int num_samples_to_write){ 394 hxcmod_fillbuffer(&mod_context, (unsigned short *) &pcm_buffer[0], num_samples_to_write, &trkbuf); 395 } 396 397 static void produce_audio(int16_t * pcm_buffer, int num_samples){ 398 switch (data_source){ 399 case STREAM_SINE: 400 produce_sine_audio(pcm_buffer, num_samples); 401 break; 402 case STREAM_MOD: 403 produce_mod_audio(pcm_buffer, num_samples); 404 break; 405 default: 406 break; 407 } 408 #ifdef VOLUME_REDUCTION 409 int i; 410 for (i=0;i<num_samples*2;i++){ 411 if (pcm_buffer[i] > 0){ 412 pcm_buffer[i] = pcm_buffer[i] >> VOLUME_REDUCTION; 413 } else { 414 pcm_buffer[i] = -((-pcm_buffer[i]) >> VOLUME_REDUCTION); 415 } 416 } 417 #endif 418 } 419 420 static int a2dp_demo_fill_sbc_audio_buffer(a2dp_media_sending_context_t * context){ 421 // perform sbc encodin 422 int total_num_bytes_read = 0; 423 unsigned int num_audio_samples_per_sbc_buffer = btstack_sbc_encoder_num_audio_frames(); 424 while (context->samples_ready >= num_audio_samples_per_sbc_buffer 425 && (context->max_media_payload_size - context->sbc_storage_count) >= btstack_sbc_encoder_sbc_buffer_length()){ 426 427 int16_t pcm_frame[256*NUM_CHANNELS]; 428 429 produce_audio(pcm_frame, num_audio_samples_per_sbc_buffer); 430 btstack_sbc_encoder_process_data(pcm_frame); 431 432 uint16_t sbc_frame_size = btstack_sbc_encoder_sbc_buffer_length(); 433 uint8_t * sbc_frame = btstack_sbc_encoder_sbc_buffer(); 434 435 total_num_bytes_read += num_audio_samples_per_sbc_buffer; 436 memcpy(&context->sbc_storage[context->sbc_storage_count], sbc_frame, sbc_frame_size); 437 context->sbc_storage_count += sbc_frame_size; 438 context->samples_ready -= num_audio_samples_per_sbc_buffer; 439 } 440 return total_num_bytes_read; 441 } 442 443 static void a2dp_demo_audio_timeout_handler(btstack_timer_source_t * timer){ 444 a2dp_media_sending_context_t * context = (a2dp_media_sending_context_t *) btstack_run_loop_get_timer_context(timer); 445 btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS); 446 btstack_run_loop_add_timer(&context->audio_timer); 447 uint32_t now = btstack_run_loop_get_time_ms(); 448 449 uint32_t update_period_ms = AUDIO_TIMEOUT_MS; 450 if (context->time_audio_data_sent > 0){ 451 update_period_ms = now - context->time_audio_data_sent; 452 } 453 454 uint32_t num_samples = (update_period_ms * sample_rate) / 1000; 455 context->acc_num_missed_samples += (update_period_ms * sample_rate) % 1000; 456 457 while (context->acc_num_missed_samples >= 1000){ 458 num_samples++; 459 context->acc_num_missed_samples -= 1000; 460 } 461 context->time_audio_data_sent = now; 462 context->samples_ready += num_samples; 463 464 if (context->sbc_ready_to_send) return; 465 466 a2dp_demo_fill_sbc_audio_buffer(context); 467 468 if ((context->sbc_storage_count + btstack_sbc_encoder_sbc_buffer_length()) > context->max_media_payload_size){ 469 // schedule sending 470 context->sbc_ready_to_send = 1; 471 a2dp_source_stream_endpoint_request_can_send_now(context->a2dp_cid, context->local_seid); 472 } 473 } 474 475 static void a2dp_demo_timer_start(a2dp_media_sending_context_t * context){ 476 context->max_media_payload_size = btstack_min(a2dp_max_media_payload_size(context->a2dp_cid, context->local_seid), SBC_STORAGE_SIZE); 477 context->sbc_storage_count = 0; 478 context->sbc_ready_to_send = 0; 479 context->streaming = 1; 480 btstack_run_loop_remove_timer(&context->audio_timer); 481 btstack_run_loop_set_timer_handler(&context->audio_timer, a2dp_demo_audio_timeout_handler); 482 btstack_run_loop_set_timer_context(&context->audio_timer, context); 483 btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS); 484 btstack_run_loop_add_timer(&context->audio_timer); 485 } 486 487 static void a2dp_demo_timer_stop(a2dp_media_sending_context_t * context){ 488 context->time_audio_data_sent = 0; 489 context->acc_num_missed_samples = 0; 490 context->samples_ready = 0; 491 context->streaming = 1; 492 context->sbc_storage_count = 0; 493 context->sbc_ready_to_send = 0; 494 btstack_run_loop_remove_timer(&context->audio_timer); 495 } 496 497 static void dump_sbc_configuration(avdtp_media_codec_configuration_sbc_t * configuration){ 498 printf("Received media codec configuration:\n"); 499 printf(" - num_channels: %d\n", configuration->num_channels); 500 printf(" - sampling_frequency: %d\n", configuration->sampling_frequency); 501 printf(" - channel_mode: %d\n", configuration->channel_mode); 502 printf(" - block_length: %d\n", configuration->block_length); 503 printf(" - subbands: %d\n", configuration->subbands); 504 printf(" - allocation_method: %d\n", configuration->allocation_method); 505 printf(" - bitpool_value [%d, %d] \n", configuration->min_bitpool_value, configuration->max_bitpool_value); 506 } 507 508 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 509 UNUSED(channel); 510 UNUSED(size); 511 uint8_t status; 512 uint8_t local_seid; 513 bd_addr_t address; 514 uint16_t cid; 515 516 if (packet_type != HCI_EVENT_PACKET) return; 517 518 #ifndef HAVE_BTSTACK_STDIN 519 if (hci_event_packet_get_type(packet) == BTSTACK_EVENT_STATE){ 520 if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return; 521 printf("Create A2DP Source connection to addr %s.\n", bd_addr_to_str(device_addr)); 522 status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid); 523 if (status != ERROR_CODE_SUCCESS){ 524 printf("Could not perform command, status 0x%2x\n", status); 525 } 526 return; 527 } 528 #endif 529 if (hci_event_packet_get_type(packet) == HCI_EVENT_PIN_CODE_REQUEST) { 530 printf("Pin code request - using '0000'\n"); 531 hci_event_pin_code_request_get_bd_addr(packet, address); 532 gap_pin_code_response(address, "0000"); 533 return; 534 } 535 536 if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return; 537 538 switch (hci_event_a2dp_meta_get_subevent_code(packet)){ 539 case A2DP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED: 540 a2dp_subevent_signaling_connection_established_get_bd_addr(packet, address); 541 cid = a2dp_subevent_signaling_connection_established_get_a2dp_cid(packet); 542 status = a2dp_subevent_signaling_connection_established_get_status(packet); 543 544 if (status != ERROR_CODE_SUCCESS){ 545 printf("A2DP Source: Connection failed, status 0x%02x, cid 0x%02x, a2dp_cid 0x%02x \n", status, cid, media_tracker.a2dp_cid); 546 media_tracker.a2dp_cid = 0; 547 break; 548 } 549 media_tracker.a2dp_cid = cid; 550 printf("A2DP Source: Connected to address %s, a2dp cid 0x%02x, local seid %d.\n", bd_addr_to_str(address), media_tracker.a2dp_cid, media_tracker.local_seid); 551 break; 552 553 case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{ 554 cid = avdtp_subevent_signaling_media_codec_sbc_configuration_get_avdtp_cid(packet); 555 if (cid != media_tracker.a2dp_cid) return; 556 media_tracker.remote_seid = a2dp_subevent_signaling_media_codec_sbc_configuration_get_acp_seid(packet); 557 558 sbc_configuration.reconfigure = a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet); 559 sbc_configuration.num_channels = a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet); 560 sbc_configuration.sampling_frequency = a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet); 561 sbc_configuration.channel_mode = a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet); 562 sbc_configuration.block_length = a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet); 563 sbc_configuration.subbands = a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet); 564 sbc_configuration.allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet); 565 sbc_configuration.min_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet); 566 sbc_configuration.max_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet); 567 sbc_configuration.frames_per_buffer = sbc_configuration.subbands * sbc_configuration.block_length; 568 printf("A2DP Source: Received SBC codec configuration, sampling frequency %u, a2dp_cid 0x%02x, local seid %d (expected %d), remote seid %d .\n", 569 sbc_configuration.sampling_frequency, cid, 570 a2dp_subevent_signaling_media_codec_sbc_configuration_get_int_seid(packet), 571 media_tracker.local_seid, 572 media_tracker.remote_seid); 573 574 // Adapt Bluetooth spec definition to SBC Encoder expected input 575 sbc_configuration.allocation_method -= 1; 576 sbc_configuration.num_channels = 2; 577 switch (sbc_configuration.channel_mode){ 578 case AVDTP_SBC_JOINT_STEREO: 579 sbc_configuration.channel_mode = 3; 580 break; 581 case AVDTP_SBC_STEREO: 582 sbc_configuration.channel_mode = 2; 583 break; 584 case AVDTP_SBC_DUAL_CHANNEL: 585 sbc_configuration.channel_mode = 1; 586 break; 587 case AVDTP_SBC_MONO: 588 sbc_configuration.channel_mode = 0; 589 sbc_configuration.num_channels = 1; 590 break; 591 } 592 dump_sbc_configuration(&sbc_configuration); 593 594 btstack_sbc_encoder_init(&sbc_encoder_state, SBC_MODE_STANDARD, 595 sbc_configuration.block_length, sbc_configuration.subbands, 596 sbc_configuration.allocation_method, sbc_configuration.sampling_frequency, 597 sbc_configuration.max_bitpool_value, 598 sbc_configuration.channel_mode); 599 break; 600 } 601 602 case A2DP_SUBEVENT_SIGNALING_DELAY_REPORTING_CAPABILITY: 603 printf("A2DP Source: remote supports delay report, remote seid %d\n", 604 avdtp_subevent_signaling_delay_reporting_capability_get_remote_seid(packet)); 605 break; 606 case A2DP_SUBEVENT_SIGNALING_CAPABILITIES_DONE: 607 printf("A2DP Source: All capabilities reported, remote seid %d\n", 608 avdtp_subevent_signaling_capabilities_done_get_remote_seid(packet)); 609 break; 610 611 case A2DP_SUBEVENT_SIGNALING_DELAY_REPORT: 612 printf("A2DP Source: Received delay report of %d.%0d ms, local seid %d\n", 613 avdtp_subevent_signaling_delay_report_get_delay_100us(packet)/10, avdtp_subevent_signaling_delay_report_get_delay_100us(packet)%10, 614 avdtp_subevent_signaling_delay_report_get_local_seid(packet)); 615 break; 616 617 case A2DP_SUBEVENT_STREAM_ESTABLISHED: 618 a2dp_subevent_stream_established_get_bd_addr(packet, address); 619 status = a2dp_subevent_stream_established_get_status(packet); 620 if (status){ 621 printf("A2DP Source: Stream failed, status 0x%02x.\n", status); 622 break; 623 } 624 625 local_seid = a2dp_subevent_stream_established_get_local_seid(packet); 626 cid = a2dp_subevent_stream_established_get_a2dp_cid(packet); 627 printf("A2DP_SUBEVENT_STREAM_ESTABLISHED: a2dp_cid [expected 0x%02x, received 0x%02x], local_seid %d (expected %d), remote_seid %d (expected %d)\n", 628 media_tracker.a2dp_cid, cid, 629 local_seid, media_tracker.local_seid, 630 a2dp_subevent_stream_established_get_remote_seid(packet), media_tracker.remote_seid); 631 632 if (local_seid != media_tracker.local_seid){ 633 printf("A2DP Source: Stream failed, wrong local seid %d, expected %d.\n", local_seid, media_tracker.local_seid); 634 break; 635 } 636 printf("A2DP Source: Stream established, address %s, a2dp cid 0x%02x, local seid %d, remote seid %d.\n", bd_addr_to_str(address), 637 media_tracker.a2dp_cid, media_tracker.local_seid, a2dp_subevent_stream_established_get_remote_seid(packet)); 638 media_tracker.stream_opened = 1; 639 data_source = STREAM_MOD; 640 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 641 break; 642 643 case A2DP_SUBEVENT_STREAM_RECONFIGURED: 644 status = a2dp_subevent_stream_reconfigured_get_status(packet); 645 local_seid = a2dp_subevent_stream_reconfigured_get_local_seid(packet); 646 cid = a2dp_subevent_stream_reconfigured_get_a2dp_cid(packet); 647 648 printf("A2DP Source: Reconfigured: a2dp_cid [expected 0x%02x, received 0x%02x], local_seid [expected %d, received %d]\n", media_tracker.a2dp_cid, cid, media_tracker.local_seid, local_seid); 649 printf("Status 0x%02x\n", status); 650 break; 651 652 case A2DP_SUBEVENT_STREAM_STARTED: 653 local_seid = a2dp_subevent_stream_started_get_local_seid(packet); 654 cid = a2dp_subevent_stream_started_get_a2dp_cid(packet); 655 656 play_info.status = AVRCP_PLAYBACK_STATUS_PLAYING; 657 if (media_tracker.avrcp_cid){ 658 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 659 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PLAYING); 660 } 661 a2dp_demo_timer_start(&media_tracker); 662 printf("A2DP Source: Stream started: a2dp_cid [expected 0x%02x, received 0x%02x], local_seid [expected %d, received %d]\n", media_tracker.a2dp_cid, cid, media_tracker.local_seid, local_seid); 663 break; 664 665 case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW: 666 local_seid = a2dp_subevent_streaming_can_send_media_packet_now_get_local_seid(packet); 667 cid = a2dp_subevent_signaling_media_codec_sbc_configuration_get_a2dp_cid(packet); 668 // printf("A2DP Source: can send media packet: a2dp_cid [expected 0x%02x, received 0x%02x], local_seid [expected %d, received %d]\n", media_tracker.a2dp_cid, cid, media_tracker.local_seid, local_seid); 669 a2dp_demo_send_media_packet(); 670 break; 671 672 case A2DP_SUBEVENT_STREAM_SUSPENDED: 673 local_seid = a2dp_subevent_stream_suspended_get_local_seid(packet); 674 cid = a2dp_subevent_stream_suspended_get_a2dp_cid(packet); 675 676 play_info.status = AVRCP_PLAYBACK_STATUS_PAUSED; 677 if (media_tracker.avrcp_cid){ 678 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PAUSED); 679 } 680 printf("A2DP Source: Stream paused: a2dp_cid [expected 0x%02x, received 0x%02x], local_seid [expected %d, received %d]\n", media_tracker.a2dp_cid, cid, media_tracker.local_seid, local_seid); 681 682 a2dp_demo_timer_stop(&media_tracker); 683 break; 684 685 case A2DP_SUBEVENT_STREAM_RELEASED: 686 play_info.status = AVRCP_PLAYBACK_STATUS_STOPPED; 687 cid = a2dp_subevent_stream_released_get_a2dp_cid(packet); 688 local_seid = a2dp_subevent_stream_released_get_local_seid(packet); 689 690 printf("A2DP Source: Stream released: a2dp_cid [expected 0x%02x, received 0x%02x], local_seid [expected %d, received %d]\n", media_tracker.a2dp_cid, cid, media_tracker.local_seid, local_seid); 691 692 if (cid == media_tracker.a2dp_cid) { 693 media_tracker.stream_opened = 0; 694 printf("A2DP Source: Stream released.\n"); 695 } 696 if (media_tracker.avrcp_cid){ 697 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); 698 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_STOPPED); 699 } 700 701 a2dp_demo_timer_stop(&media_tracker); 702 break; 703 case A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED: 704 cid = a2dp_subevent_signaling_connection_released_get_a2dp_cid(packet); 705 if (cid == media_tracker.a2dp_cid) { 706 media_tracker.avrcp_cid = 0; 707 media_tracker.a2dp_cid = 0; 708 printf("A2DP Source: Signaling released.\n\n"); 709 } 710 break; 711 default: 712 break; 713 } 714 } 715 716 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 717 UNUSED(channel); 718 UNUSED(size); 719 bd_addr_t event_addr; 720 uint16_t local_cid; 721 uint8_t status = ERROR_CODE_SUCCESS; 722 723 if (packet_type != HCI_EVENT_PACKET) return; 724 if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; 725 726 switch (packet[2]){ 727 case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: { 728 local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet); 729 // if (avrcp_cid != 0 && avrcp_cid != local_cid) { 730 // printf("AVRCP Target: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_cid, local_cid); 731 // return; 732 // } 733 // if (avrcp_cid != local_cid) break; 734 735 status = avrcp_subevent_connection_established_get_status(packet); 736 if (status != ERROR_CODE_SUCCESS){ 737 printf("AVRCP Target: Connection failed, status 0x%02x\n", status); 738 return; 739 } 740 media_tracker.avrcp_cid = local_cid; 741 avrcp_subevent_connection_established_get_bd_addr(packet, event_addr); 742 printf("AVRCP Target: Connected to %s, avrcp_cid 0x%02x\n", bd_addr_to_str(event_addr), local_cid); 743 744 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); 745 avrcp_target_set_unit_info(media_tracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, company_id); 746 avrcp_target_set_subunit_info(media_tracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, (uint8_t *)subunit_info, sizeof(subunit_info)); 747 return; 748 } 749 case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED: 750 printf("AVRCP Target: new volume %d\n", avrcp_subevent_notification_volume_changed_get_absolute_volume(packet)); 751 break; 752 case AVRCP_SUBEVENT_EVENT_IDS_QUERY: 753 status = avrcp_target_supported_events(media_tracker.avrcp_cid, events_num, events, sizeof(events)); 754 break; 755 case AVRCP_SUBEVENT_COMPANY_IDS_QUERY: 756 status = avrcp_target_supported_companies(media_tracker.avrcp_cid, companies_num, companies, sizeof(companies)); 757 break; 758 case AVRCP_SUBEVENT_PLAY_STATUS_QUERY: 759 status = avrcp_target_play_status(media_tracker.avrcp_cid, play_info.song_length_ms, play_info.song_position_ms, play_info.status); 760 break; 761 // case AVRCP_SUBEVENT_NOW_PLAYING_INFO_QUERY: 762 // status = avrcp_target_now_playing_info(avrcp_cid); 763 // break; 764 case AVRCP_SUBEVENT_OPERATION:{ 765 avrcp_operation_id_t operation_id = avrcp_subevent_operation_get_operation_id(packet); 766 switch (operation_id){ 767 case AVRCP_OPERATION_ID_PLAY: 768 printf("AVRCP Target: PLAY\n"); 769 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 770 break; 771 case AVRCP_OPERATION_ID_PAUSE: 772 printf("AVRCP Target: PAUSE\n"); 773 status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 774 break; 775 case AVRCP_OPERATION_ID_STOP: 776 printf("AVRCP Target: STOP\n"); 777 status = a2dp_source_disconnect(media_tracker.a2dp_cid); 778 break; 779 default: 780 printf("AVRCP Target: operation 0x%2x is not handled\n", operation_id); 781 return; 782 } 783 break; 784 } 785 case AVRCP_SUBEVENT_CONNECTION_RELEASED: 786 printf("AVRCP Target: Disconnected, avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); 787 media_tracker.avrcp_cid = 0; 788 return; 789 default: 790 break; 791 } 792 793 if (status != ERROR_CODE_SUCCESS){ 794 printf("Responding to event 0x%02x failed with status 0x%02x\n", packet[2], status); 795 } 796 } 797 798 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 799 UNUSED(channel); 800 UNUSED(size); 801 uint16_t local_cid; 802 uint8_t status = 0xFF; 803 bd_addr_t adress; 804 805 if (packet_type != HCI_EVENT_PACKET) return; 806 if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; 807 switch (packet[2]){ 808 case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: { 809 local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet); 810 if (avrcp_controller_cid != 0 && avrcp_controller_cid != local_cid) { 811 printf("AVRCP Controller: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_controller_cid, local_cid); 812 return; 813 } 814 815 status = avrcp_subevent_connection_established_get_status(packet); 816 if (status != ERROR_CODE_SUCCESS){ 817 printf("AVRCP Controller: Connection failed: status 0x%02x\n", status); 818 avrcp_controller_cid = 0; 819 return; 820 } 821 822 avrcp_controller_cid = local_cid; 823 avrcp_subevent_connection_established_get_bd_addr(packet, adress); 824 printf("AVRCP Controller: Channel successfully opened: %s, avrcp_controller_cid 0x%02x\n", bd_addr_to_str(adress), avrcp_controller_cid); 825 826 // automatically enable notifications 827 avrcp_controller_enable_notification(avrcp_controller_cid, AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED); 828 return; 829 } 830 case AVRCP_SUBEVENT_CONNECTION_RELEASED: 831 printf("AVRCP Controller: Channel released: avrcp_controller_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); 832 avrcp_controller_cid = 0; 833 return; 834 default: 835 break; 836 } 837 838 status = packet[5]; 839 if (!avrcp_controller_cid) return; 840 841 // ignore INTERIM status 842 if (status == AVRCP_CTYPE_RESPONSE_INTERIM) return; 843 844 switch (packet[2]){ 845 case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED:{ 846 int volume_percentage = avrcp_subevent_notification_volume_changed_get_absolute_volume(packet) * 100 / 127; 847 printf("AVRCP Controller: notification absolute volume changed %d %%\n", volume_percentage); 848 return; 849 } 850 default: 851 break; 852 } 853 } 854 855 #ifdef HAVE_BTSTACK_STDIN 856 static void show_usage(void){ 857 bd_addr_t iut_address; 858 gap_local_bd_addr(iut_address); 859 printf("\n--- Bluetooth A2DP Source/AVRCP Target Demo %s ---\n", bd_addr_to_str(iut_address)); 860 printf("b - A2DP Source create connection to addr %s\n", device_addr_string); 861 printf("B - A2DP Source disconnect\n"); 862 printf("c - AVRCP Target create connection to addr %s\n", device_addr_string); 863 printf("C - AVRCP Target disconnect\n"); 864 865 printf("x - start streaming sine\n"); 866 if (hxcmod_initialized){ 867 printf("z - start streaming '%s'\n", mod_name); 868 } 869 printf("p - pause streaming\n"); 870 printf("w - reconfigure stream for 44100 Hz\n"); 871 printf("e - reconfigure stream for 48000 Hz\n"); 872 printf("t - volume up\n"); 873 printf("T - volume down\n"); 874 printf("v - absolute volume of 50 percent\n"); 875 876 printf("\n--- Bluetooth AVRCP Target Commands %s ---\n", bd_addr_to_str(iut_address)); 877 printf("---\n"); 878 } 879 880 static void stdin_process(char cmd){ 881 uint8_t status = ERROR_CODE_SUCCESS; 882 switch (cmd){ 883 case 'b': 884 status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid); 885 printf("%c - Create A2DP Source connection to addr %s, cid 0x%02x.\n", cmd, bd_addr_to_str(device_addr), media_tracker.a2dp_cid); 886 break; 887 case 'B': 888 printf("%c - A2DP Source Disconnect from cid 0x%2x\n", cmd, media_tracker.a2dp_cid); 889 status = a2dp_source_disconnect(media_tracker.a2dp_cid); 890 break; 891 case 'c': 892 printf("%c - Create AVRCP Target connection to addr %s.\n", cmd, bd_addr_to_str(device_addr)); 893 status = avrcp_target_connect(device_addr, &media_tracker.avrcp_cid); 894 break; 895 case 'C': 896 printf("%c - AVRCP Target disconnect\n", cmd); 897 status = avrcp_target_disconnect(media_tracker.avrcp_cid); 898 break; 899 900 case '\n': 901 case '\r': 902 break; 903 904 case 't': 905 printf(" - volume up\n"); 906 status = avrcp_controller_volume_up(avrcp_controller_cid); 907 break; 908 case 'T': 909 printf(" - volume down\n"); 910 status = avrcp_controller_volume_down(avrcp_controller_cid); 911 break; 912 case 'v': 913 printf(" - absolute volume of 50%% (64)\n"); 914 status = avrcp_controller_set_absolute_volume(avrcp_controller_cid, 64); 915 break; 916 917 case 'x': 918 if (media_tracker.avrcp_cid){ 919 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 920 } 921 printf("%c - Play sine.\n", cmd); 922 data_source = STREAM_SINE; 923 if (!media_tracker.stream_opened) break; 924 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 925 break; 926 case 'z': 927 if (media_tracker.avrcp_cid){ 928 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 929 } 930 printf("%c - Play mod.\n", cmd); 931 data_source = STREAM_MOD; 932 if (!media_tracker.stream_opened) break; 933 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 934 if (status == ERROR_CODE_SUCCESS){ 935 a2dp_demo_reconfigure_sample_rate(sample_rate); 936 } 937 break; 938 939 case 'p': 940 if (!media_tracker.stream_opened) break; 941 printf("%c - Pause stream.\n", cmd); 942 status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 943 break; 944 945 case 'w': 946 if (!media_tracker.stream_opened) break; 947 if (play_info.status == AVRCP_PLAYBACK_STATUS_PLAYING){ 948 printf("Stream cannot be reconfigured while playing, please pause stream first\n"); 949 break; 950 } 951 printf("%c - Reconfigure for %d Hz.\n", cmd, sample_rate); 952 status = a2dp_source_reconfigure_stream_sampling_frequency(media_tracker.a2dp_cid, 44100); 953 if (status == ERROR_CODE_SUCCESS){ 954 a2dp_demo_reconfigure_sample_rate(44100); 955 } 956 break; 957 958 case 'e': 959 if (!media_tracker.stream_opened) break; 960 if (play_info.status == AVRCP_PLAYBACK_STATUS_PLAYING){ 961 printf("Stream cannot be reconfigured while playing, please pause stream first\n"); 962 break; 963 } 964 printf("%c - Reconfigure for %d Hz.\n", cmd, sample_rate); 965 status = a2dp_source_reconfigure_stream_sampling_frequency(media_tracker.a2dp_cid, 48000); 966 if (status == ERROR_CODE_SUCCESS){ 967 a2dp_demo_reconfigure_sample_rate(48000); 968 } 969 break; 970 971 default: 972 show_usage(); 973 return; 974 } 975 if (status != ERROR_CODE_SUCCESS){ 976 printf("Could not perform command \'%c\', status 0x%2x\n", cmd, status); 977 } 978 } 979 #endif 980 981 982 int btstack_main(int argc, const char * argv[]); 983 int btstack_main(int argc, const char * argv[]){ 984 (void)argc; 985 (void)argv; 986 987 int err = a2dp_source_and_avrcp_services_init(); 988 if (err) return err; 989 // turn on! 990 hci_power_control(HCI_POWER_ON); 991 return 0; 992 } 993 /* EXAMPLE_END */ 994