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 // pts: 143 static const char * device_addr_string = "00:1B:DC:08:E2:72"; 144 // mac 2013: static const char * device_addr_string = "84:38:35:65:d1:15"; 145 // phone 2013: static const char * device_addr_string = "D8:BB:2C:DF:F0:F2"; 146 // Minijambox: static const char * device_addr_string = "00:21:3C:AC:F7:38"; 147 // Philips SHB9100: static const char * device_addr_string = "00:22:37:05:FD:E8"; 148 // RT-B6: static const char * device_addr_string = "00:75:58:FF:C9:7D"; 149 // BT dongle: static const char * device_addr_string = "00:1A:7D:DA:71:0A"; 150 // Sony MDR-ZX330BT static const char * device_addr_string = "00:18:09:28:50:18"; 151 // Panda (BM6) static const char * device_addr_string = "4F:3F:66:52:8B:E0"; 152 153 static bd_addr_t device_addr; 154 static uint8_t sdp_a2dp_source_service_buffer[150]; 155 static uint8_t sdp_avrcp_target_service_buffer[200]; 156 static uint8_t sdp_avrcp_controller_service_buffer[200]; 157 158 static avdtp_media_codec_configuration_sbc_t sbc_configuration; 159 static btstack_sbc_encoder_state_t sbc_encoder_state; 160 161 static uint8_t media_sbc_codec_configuration[4]; 162 static a2dp_media_sending_context_t media_tracker; 163 164 static stream_data_source_t data_source; 165 166 static int sine_phase; 167 168 static int hxcmod_initialized; 169 static modcontext mod_context; 170 static tracker_buffer_state trkbuf; 171 172 static uint16_t avrcp_controller_cid = 0; 173 174 /* AVRCP Target context START */ 175 static const uint8_t subunit_info[] = { 176 0,0,0,0, 177 1,1,1,1, 178 2,2,2,2, 179 3,3,3,3, 180 4,4,4,4, 181 5,5,5,5, 182 6,6,6,6, 183 7,7,7,7 184 }; 185 186 static uint32_t company_id = 0x112233; 187 static uint8_t companies_num = 1; 188 static uint8_t companies[] = { 189 0x00, 0x19, 0x58 //BT SIG registered CompanyID 190 }; 191 192 static uint8_t events_num = 13; 193 static uint8_t events[] = { 194 AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED, 195 AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED, 196 AVRCP_NOTIFICATION_EVENT_TRACK_REACHED_END, 197 AVRCP_NOTIFICATION_EVENT_TRACK_REACHED_START, 198 AVRCP_NOTIFICATION_EVENT_PLAYBACK_POS_CHANGED, 199 AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED, 200 AVRCP_NOTIFICATION_EVENT_SYSTEM_STATUS_CHANGED, 201 AVRCP_NOTIFICATION_EVENT_PLAYER_APPLICATION_SETTING_CHANGED, 202 AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED, 203 AVRCP_NOTIFICATION_EVENT_AVAILABLE_PLAYERS_CHANGED, 204 AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED, 205 AVRCP_NOTIFICATION_EVENT_UIDS_CHANGED, 206 AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED 207 }; 208 209 typedef struct { 210 uint8_t track_id[8]; 211 uint32_t song_length_ms; 212 avrcp_playback_status_t status; 213 uint32_t song_position_ms; // 0xFFFFFFFF if not supported 214 } avrcp_play_status_info_t; 215 216 // python -c "print('a'*512)" 217 static const char title[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 218 219 avrcp_track_t tracks[] = { 220 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, 1, "Sine", "Generated", "A2DP Source Demo", "monotone", 12345}, 221 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 2, "Nao-deceased", "Decease", "A2DP Source Demo", "vivid", 12345}, 222 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, 3, (char *)title, "Decease", "A2DP Source Demo", "vivid", 12345}, 223 }; 224 int current_track_index; 225 avrcp_play_status_info_t play_info; 226 227 /* AVRCP Target context END */ 228 229 /* @section Main Application Setup 230 * 231 * @text The Listing MainConfiguration shows how to setup AD2P Source and AVRCP Target services. 232 */ 233 234 /* LISTING_START(MainConfiguration): Setup Audio Source and AVRCP Target services */ 235 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size); 236 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 237 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 238 #ifdef HAVE_BTSTACK_STDIN 239 static void stdin_process(char cmd); 240 #endif 241 242 static int a2dp_source_and_avrcp_services_init(void){ 243 244 l2cap_init(); 245 // Initialize A2DP Source. 246 a2dp_source_init(); 247 a2dp_source_register_packet_handler(&a2dp_source_packet_handler); 248 249 // Create stream endpoint. 250 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)); 251 if (!local_stream_endpoint){ 252 printf("A2DP Source: not enough memory to create local stream endpoint\n"); 253 return 1; 254 } 255 media_tracker.local_seid = avdtp_local_seid(local_stream_endpoint); 256 // Initialize AVRCP Target. 257 avrcp_target_init(); 258 avrcp_target_register_packet_handler(&avrcp_target_packet_handler); 259 // Initialize AVRCP Controller 260 avrcp_controller_init(); 261 avrcp_controller_register_packet_handler(&avrcp_controller_packet_handler); 262 263 // Initialize SDP, 264 sdp_init(); 265 266 // Create A2DP Source service record and register it with SDP. 267 memset(sdp_a2dp_source_service_buffer, 0, sizeof(sdp_a2dp_source_service_buffer)); 268 a2dp_source_create_sdp_record(sdp_a2dp_source_service_buffer, 0x10002, 1, NULL, NULL); 269 sdp_register_service(sdp_a2dp_source_service_buffer); 270 271 // Create AVRCP target service record and register it with SDP. 272 memset(sdp_avrcp_target_service_buffer, 0, sizeof(sdp_avrcp_target_service_buffer)); 273 uint16_t supported_features = (1 << AVRCP_TARGET_SUPPORTED_FEATURE_CATEGORY_PLAYER_OR_RECORDER); 274 #ifdef AVRCP_BROWSING_ENABLED 275 supported_features |= (1 << AVRCP_TARGET_SUPPORTED_FEATURE_BROWSING); 276 #endif 277 avrcp_target_create_sdp_record(sdp_avrcp_target_service_buffer, 0x10001, supported_features, NULL, NULL); 278 sdp_register_service(sdp_avrcp_target_service_buffer); 279 280 // setup AVRCP Controller 281 memset(sdp_avrcp_controller_service_buffer, 0, sizeof(sdp_avrcp_controller_service_buffer)); 282 uint16_t controller_supported_features = (1 << AVRCP_CONTROLLER_SUPPORTED_FEATURE_CATEGORY_MONITOR_OR_AMPLIFIER); 283 avrcp_controller_create_sdp_record(sdp_avrcp_controller_service_buffer, 0x10002, controller_supported_features, NULL, NULL); 284 sdp_register_service(sdp_avrcp_controller_service_buffer); 285 286 // Set local name with a template Bluetooth address, that will be automatically 287 // replaced with a actual address once it is available, i.e. when BTstack boots 288 // up and starts talking to a Bluetooth module. 289 gap_set_local_name("A2DP Source 00:00:00:00:00:00"); 290 gap_discoverable_control(1); 291 gap_set_class_of_device(0x200408); 292 293 // Register for HCI events. 294 hci_event_callback_registration.callback = &a2dp_source_packet_handler; 295 hci_add_event_handler(&hci_event_callback_registration); 296 297 hxcmod_initialized = hxcmod_init(&mod_context); 298 if (hxcmod_initialized){ 299 hxcmod_setcfg(&mod_context, A2DP_SAMPLE_RATE, 16, 1, 1, 1); 300 hxcmod_load(&mod_context, (void *) &mod_data, mod_len); 301 printf("loaded mod '%s', size %u\n", mod_name, mod_len); 302 } 303 304 // Parse human readable Bluetooth address. 305 sscanf_bd_addr(device_addr_string, device_addr); 306 307 #ifdef HAVE_BTSTACK_STDIN 308 btstack_stdin_setup(stdin_process); 309 #endif 310 return 0; 311 } 312 /* LISTING_END */ 313 314 static void a2dp_demo_send_media_packet(void){ 315 int num_bytes_in_frame = btstack_sbc_encoder_sbc_buffer_length(); 316 int bytes_in_storage = media_tracker.sbc_storage_count; 317 uint8_t num_frames = bytes_in_storage / num_bytes_in_frame; 318 a2dp_source_stream_send_media_payload(media_tracker.a2dp_cid, media_tracker.local_seid, media_tracker.sbc_storage, bytes_in_storage, num_frames, 0); 319 media_tracker.sbc_storage_count = 0; 320 media_tracker.sbc_ready_to_send = 0; 321 } 322 323 static void produce_sine_audio(int16_t * pcm_buffer, int num_samples_to_write){ 324 int count; 325 for (count = 0; count < num_samples_to_write ; count++){ 326 pcm_buffer[count * 2] = sine_int16[sine_phase]; 327 pcm_buffer[count * 2 + 1] = sine_int16[sine_phase]; 328 sine_phase++; 329 if (sine_phase >= TABLE_SIZE_441HZ){ 330 sine_phase -= TABLE_SIZE_441HZ; 331 } 332 } 333 } 334 335 static void produce_mod_audio(int16_t * pcm_buffer, int num_samples_to_write){ 336 hxcmod_fillbuffer(&mod_context, (unsigned short *) &pcm_buffer[0], num_samples_to_write, &trkbuf); 337 } 338 339 static void produce_audio(int16_t * pcm_buffer, int num_samples){ 340 switch (data_source){ 341 case STREAM_SINE: 342 produce_sine_audio(pcm_buffer, num_samples); 343 break; 344 case STREAM_MOD: 345 produce_mod_audio(pcm_buffer, num_samples); 346 break; 347 default: 348 break; 349 } 350 #ifdef VOLUME_REDUCTION 351 int i; 352 for (i=0;i<num_samples*2;i++){ 353 if (pcm_buffer[i] > 0){ 354 pcm_buffer[i] = pcm_buffer[i] >> VOLUME_REDUCTION; 355 } else { 356 pcm_buffer[i] = -((-pcm_buffer[i]) >> VOLUME_REDUCTION); 357 } 358 } 359 #endif 360 } 361 362 static int a2dp_demo_fill_sbc_audio_buffer(a2dp_media_sending_context_t * context){ 363 // perform sbc encodin 364 int total_num_bytes_read = 0; 365 unsigned int num_audio_samples_per_sbc_buffer = btstack_sbc_encoder_num_audio_frames(); 366 while (context->samples_ready >= num_audio_samples_per_sbc_buffer 367 && (context->max_media_payload_size - context->sbc_storage_count) >= btstack_sbc_encoder_sbc_buffer_length()){ 368 369 int16_t pcm_frame[256*NUM_CHANNELS]; 370 371 produce_audio(pcm_frame, num_audio_samples_per_sbc_buffer); 372 btstack_sbc_encoder_process_data(pcm_frame); 373 374 uint16_t sbc_frame_size = btstack_sbc_encoder_sbc_buffer_length(); 375 uint8_t * sbc_frame = btstack_sbc_encoder_sbc_buffer(); 376 377 total_num_bytes_read += num_audio_samples_per_sbc_buffer; 378 memcpy(&context->sbc_storage[context->sbc_storage_count], sbc_frame, sbc_frame_size); 379 context->sbc_storage_count += sbc_frame_size; 380 context->samples_ready -= num_audio_samples_per_sbc_buffer; 381 } 382 return total_num_bytes_read; 383 } 384 385 static void a2dp_demo_audio_timeout_handler(btstack_timer_source_t * timer){ 386 a2dp_media_sending_context_t * context = (a2dp_media_sending_context_t *) btstack_run_loop_get_timer_context(timer); 387 btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS); 388 btstack_run_loop_add_timer(&context->audio_timer); 389 uint32_t now = btstack_run_loop_get_time_ms(); 390 391 uint32_t update_period_ms = AUDIO_TIMEOUT_MS; 392 if (context->time_audio_data_sent > 0){ 393 update_period_ms = now - context->time_audio_data_sent; 394 } 395 396 uint32_t num_samples = (update_period_ms * A2DP_SAMPLE_RATE) / 1000; 397 context->acc_num_missed_samples += (update_period_ms * A2DP_SAMPLE_RATE) % 1000; 398 399 while (context->acc_num_missed_samples >= 1000){ 400 num_samples++; 401 context->acc_num_missed_samples -= 1000; 402 } 403 context->time_audio_data_sent = now; 404 context->samples_ready += num_samples; 405 406 if (context->sbc_ready_to_send) return; 407 408 a2dp_demo_fill_sbc_audio_buffer(context); 409 410 if ((context->sbc_storage_count + btstack_sbc_encoder_sbc_buffer_length()) > context->max_media_payload_size){ 411 // schedule sending 412 context->sbc_ready_to_send = 1; 413 a2dp_source_stream_endpoint_request_can_send_now(context->a2dp_cid, context->local_seid); 414 } 415 } 416 417 static void a2dp_demo_timer_start(a2dp_media_sending_context_t * context){ 418 context->max_media_payload_size = btstack_min(a2dp_max_media_payload_size(context->a2dp_cid, context->local_seid), SBC_STORAGE_SIZE); 419 context->sbc_storage_count = 0; 420 context->sbc_ready_to_send = 0; 421 context->streaming = 1; 422 btstack_run_loop_remove_timer(&context->audio_timer); 423 btstack_run_loop_set_timer_handler(&context->audio_timer, a2dp_demo_audio_timeout_handler); 424 btstack_run_loop_set_timer_context(&context->audio_timer, context); 425 btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS); 426 btstack_run_loop_add_timer(&context->audio_timer); 427 } 428 429 static void a2dp_demo_timer_stop(a2dp_media_sending_context_t * context){ 430 context->time_audio_data_sent = 0; 431 context->acc_num_missed_samples = 0; 432 context->samples_ready = 0; 433 context->streaming = 1; 434 context->sbc_storage_count = 0; 435 context->sbc_ready_to_send = 0; 436 btstack_run_loop_remove_timer(&context->audio_timer); 437 } 438 439 static void dump_sbc_configuration(avdtp_media_codec_configuration_sbc_t * configuration){ 440 printf("Received media codec configuration:\n"); 441 printf(" - num_channels: %d\n", configuration->num_channels); 442 printf(" - sampling_frequency: %d\n", configuration->sampling_frequency); 443 printf(" - channel_mode: %d\n", configuration->channel_mode); 444 printf(" - block_length: %d\n", configuration->block_length); 445 printf(" - subbands: %d\n", configuration->subbands); 446 printf(" - allocation_method: %d\n", configuration->allocation_method); 447 printf(" - bitpool_value [%d, %d] \n", configuration->min_bitpool_value, configuration->max_bitpool_value); 448 } 449 450 451 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 452 UNUSED(channel); 453 UNUSED(size); 454 uint8_t status; 455 uint8_t local_seid; 456 bd_addr_t address; 457 uint16_t cid; 458 459 if (packet_type != HCI_EVENT_PACKET) return; 460 461 #ifndef HAVE_BTSTACK_STDIN 462 if (hci_event_packet_get_type(packet) == BTSTACK_EVENT_STATE){ 463 if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return; 464 printf("Create A2DP Source connection to addr %s.\n", bd_addr_to_str(device_addr)); 465 status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid); 466 if (status != ERROR_CODE_SUCCESS){ 467 printf("Could not perform command, status 0x%2x\n", status); 468 } 469 return; 470 } 471 #endif 472 if (hci_event_packet_get_type(packet) == HCI_EVENT_PIN_CODE_REQUEST) { 473 printf("Pin code request - using '0000'\n"); 474 hci_event_pin_code_request_get_bd_addr(packet, address); 475 gap_pin_code_response(address, "0000"); 476 return; 477 } 478 479 if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return; 480 481 switch (hci_event_a2dp_meta_get_subevent_code(packet)){ 482 case A2DP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED: 483 a2dp_subevent_signaling_connection_established_get_bd_addr(packet, address); 484 cid = a2dp_subevent_signaling_connection_established_get_a2dp_cid(packet); 485 status = a2dp_subevent_signaling_connection_established_get_status(packet); 486 487 if (status != ERROR_CODE_SUCCESS){ 488 printf("A2DP Source: Connection failed, status 0x%02x, cid 0x%02x, a2dp_cid 0x%02x \n", status, cid, media_tracker.a2dp_cid); 489 media_tracker.a2dp_cid = 0; 490 break; 491 } 492 media_tracker.a2dp_cid = cid; 493 printf("A2DP Source: Connected to address %s, a2dp cid 0x%02x.\n", bd_addr_to_str(address), media_tracker.a2dp_cid); 494 break; 495 496 case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{ 497 sbc_configuration.reconfigure = a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet); 498 sbc_configuration.num_channels = a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet); 499 sbc_configuration.sampling_frequency = a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet); 500 sbc_configuration.channel_mode = a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet); 501 sbc_configuration.block_length = a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet); 502 sbc_configuration.subbands = a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet); 503 sbc_configuration.allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet); 504 sbc_configuration.min_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet); 505 sbc_configuration.max_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet); 506 sbc_configuration.frames_per_buffer = sbc_configuration.subbands * sbc_configuration.block_length; 507 printf("A2DP Source: Received SBC codec configuration, sampling frequency %u.\n", sbc_configuration.sampling_frequency); 508 509 // Adapt Bluetooth spec definition to SBC Encoder expected input 510 sbc_configuration.allocation_method -= 1; 511 sbc_configuration.num_channels = 2; 512 switch (sbc_configuration.channel_mode){ 513 case AVDTP_SBC_JOINT_STEREO: 514 sbc_configuration.channel_mode = 3; 515 break; 516 case AVDTP_SBC_STEREO: 517 sbc_configuration.channel_mode = 2; 518 break; 519 case AVDTP_SBC_DUAL_CHANNEL: 520 sbc_configuration.channel_mode = 1; 521 break; 522 case AVDTP_SBC_MONO: 523 sbc_configuration.channel_mode = 0; 524 sbc_configuration.num_channels = 1; 525 break; 526 } 527 dump_sbc_configuration(&sbc_configuration); 528 529 btstack_sbc_encoder_init(&sbc_encoder_state, SBC_MODE_STANDARD, 530 sbc_configuration.block_length, sbc_configuration.subbands, 531 sbc_configuration.allocation_method, sbc_configuration.sampling_frequency, 532 sbc_configuration.max_bitpool_value, 533 sbc_configuration.channel_mode); 534 break; 535 } 536 537 case A2DP_SUBEVENT_SIGNALING_DELAY_REPORT: 538 printf("A2DP Source: received delay report of %d.%0d ms, local seid %d\n", 539 avdtp_subevent_signaling_delay_report_get_delay_100us(packet)/10, avdtp_subevent_signaling_delay_report_get_delay_100us(packet)%10, 540 avdtp_subevent_signaling_delay_report_get_local_seid(packet)); 541 break; 542 543 case A2DP_SUBEVENT_STREAM_ESTABLISHED: 544 a2dp_subevent_stream_established_get_bd_addr(packet, address); 545 status = a2dp_subevent_stream_established_get_status(packet); 546 if (status){ 547 printf("A2DP Source: Stream failed, status 0x%02x.\n", status); 548 break; 549 } 550 local_seid = a2dp_subevent_stream_established_get_local_seid(packet); 551 if (local_seid != media_tracker.local_seid){ 552 printf("A2DP Source: Stream failed, wrong local seid %d, expected %d.\n", local_seid, media_tracker.local_seid); 553 break; 554 } 555 printf("A2DP Source: Stream established, address %s, a2dp cid 0x%02x, local seid %d, remote seid %d.\n", bd_addr_to_str(address), 556 media_tracker.a2dp_cid, media_tracker.local_seid, a2dp_subevent_stream_established_get_remote_seid(packet)); 557 media_tracker.stream_opened = 1; 558 data_source = STREAM_MOD; 559 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 560 break; 561 562 case A2DP_SUBEVENT_STREAM_RECONFIGURED: 563 status = a2dp_subevent_stream_reconfigured_get_status(packet); 564 printf("A2DP Source: Reconfigured, status 0x%02x\n", status); 565 break; 566 567 case A2DP_SUBEVENT_STREAM_STARTED: 568 play_info.status = AVRCP_PLAYBACK_STATUS_PLAYING; 569 if (media_tracker.avrcp_cid){ 570 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 571 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PLAYING); 572 } 573 a2dp_demo_timer_start(&media_tracker); 574 printf("A2DP Source: Stream started.\n"); 575 break; 576 577 case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW: 578 a2dp_demo_send_media_packet(); 579 break; 580 581 case A2DP_SUBEVENT_STREAM_SUSPENDED: 582 play_info.status = AVRCP_PLAYBACK_STATUS_PAUSED; 583 if (media_tracker.avrcp_cid){ 584 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PAUSED); 585 } 586 printf("A2DP Source: Stream paused.\n"); 587 a2dp_demo_timer_stop(&media_tracker); 588 break; 589 590 case A2DP_SUBEVENT_STREAM_RELEASED: 591 play_info.status = AVRCP_PLAYBACK_STATUS_STOPPED; 592 cid = a2dp_subevent_stream_released_get_a2dp_cid(packet); 593 if (cid == media_tracker.a2dp_cid) { 594 media_tracker.stream_opened = 0; 595 printf("A2DP Source: Stream released.\n"); 596 } 597 if (media_tracker.avrcp_cid){ 598 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); 599 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_STOPPED); 600 } 601 a2dp_demo_timer_stop(&media_tracker); 602 break; 603 case A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED: 604 cid = a2dp_subevent_signaling_connection_released_get_a2dp_cid(packet); 605 if (cid == media_tracker.a2dp_cid) { 606 media_tracker.avrcp_cid = 0; 607 media_tracker.a2dp_cid = 0; 608 printf("A2DP Source: Signaling released.\n\n"); 609 } 610 break; 611 default: 612 break; 613 } 614 } 615 616 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 617 UNUSED(channel); 618 UNUSED(size); 619 bd_addr_t event_addr; 620 uint16_t local_cid; 621 uint8_t status = ERROR_CODE_SUCCESS; 622 623 if (packet_type != HCI_EVENT_PACKET) return; 624 if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; 625 626 switch (packet[2]){ 627 case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: { 628 local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet); 629 // if (avrcp_cid != 0 && avrcp_cid != local_cid) { 630 // printf("AVRCP Target: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_cid, local_cid); 631 // return; 632 // } 633 // if (avrcp_cid != local_cid) break; 634 635 status = avrcp_subevent_connection_established_get_status(packet); 636 if (status != ERROR_CODE_SUCCESS){ 637 printf("AVRCP Target: Connection failed, status 0x%02x\n", status); 638 return; 639 } 640 media_tracker.avrcp_cid = local_cid; 641 avrcp_subevent_connection_established_get_bd_addr(packet, event_addr); 642 printf("AVRCP Target: Connected to %s, avrcp_cid 0x%02x\n", bd_addr_to_str(event_addr), local_cid); 643 644 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); 645 avrcp_target_set_unit_info(media_tracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, company_id); 646 avrcp_target_set_subunit_info(media_tracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, (uint8_t *)subunit_info, sizeof(subunit_info)); 647 return; 648 } 649 case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED: 650 printf("AVRCP Target: new volume %d\n", avrcp_subevent_notification_volume_changed_get_absolute_volume(packet)); 651 break; 652 case AVRCP_SUBEVENT_EVENT_IDS_QUERY: 653 status = avrcp_target_supported_events(media_tracker.avrcp_cid, events_num, events, sizeof(events)); 654 break; 655 case AVRCP_SUBEVENT_COMPANY_IDS_QUERY: 656 status = avrcp_target_supported_companies(media_tracker.avrcp_cid, companies_num, companies, sizeof(companies)); 657 break; 658 case AVRCP_SUBEVENT_PLAY_STATUS_QUERY: 659 status = avrcp_target_play_status(media_tracker.avrcp_cid, play_info.song_length_ms, play_info.song_position_ms, play_info.status); 660 break; 661 // case AVRCP_SUBEVENT_NOW_PLAYING_INFO_QUERY: 662 // status = avrcp_target_now_playing_info(avrcp_cid); 663 // break; 664 case AVRCP_SUBEVENT_OPERATION:{ 665 avrcp_operation_id_t operation_id = avrcp_subevent_operation_get_operation_id(packet); 666 switch (operation_id){ 667 case AVRCP_OPERATION_ID_PLAY: 668 printf("AVRCP Target: PLAY\n"); 669 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 670 break; 671 case AVRCP_OPERATION_ID_PAUSE: 672 printf("AVRCP Target: PAUSE\n"); 673 status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 674 break; 675 case AVRCP_OPERATION_ID_STOP: 676 printf("AVRCP Target: STOP\n"); 677 status = a2dp_source_disconnect(media_tracker.a2dp_cid); 678 break; 679 default: 680 printf("AVRCP Target: operation 0x%2x is not handled\n", operation_id); 681 return; 682 } 683 break; 684 } 685 case AVRCP_SUBEVENT_CONNECTION_RELEASED: 686 printf("AVRCP Target: Disconnected, avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); 687 media_tracker.avrcp_cid = 0; 688 return; 689 default: 690 break; 691 } 692 693 if (status != ERROR_CODE_SUCCESS){ 694 printf("Responding to event 0x%02x failed with status 0x%02x\n", packet[2], status); 695 } 696 } 697 698 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 699 UNUSED(channel); 700 UNUSED(size); 701 uint16_t local_cid; 702 uint8_t status = 0xFF; 703 bd_addr_t adress; 704 705 if (packet_type != HCI_EVENT_PACKET) return; 706 if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; 707 switch (packet[2]){ 708 case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: { 709 local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet); 710 if (avrcp_controller_cid != 0 && avrcp_controller_cid != local_cid) { 711 printf("AVRCP Controller: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_controller_cid, local_cid); 712 return; 713 } 714 715 status = avrcp_subevent_connection_established_get_status(packet); 716 if (status != ERROR_CODE_SUCCESS){ 717 printf("AVRCP Controller: Connection failed: status 0x%02x\n", status); 718 avrcp_controller_cid = 0; 719 return; 720 } 721 722 avrcp_controller_cid = local_cid; 723 avrcp_subevent_connection_established_get_bd_addr(packet, adress); 724 printf("AVRCP Controller: Channel successfully opened: %s, avrcp_controller_cid 0x%02x\n", bd_addr_to_str(adress), avrcp_controller_cid); 725 726 // automatically enable notifications 727 avrcp_controller_enable_notification(avrcp_controller_cid, AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED); 728 return; 729 } 730 case AVRCP_SUBEVENT_CONNECTION_RELEASED: 731 printf("AVRCP Controller: Channel released: avrcp_controller_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); 732 avrcp_controller_cid = 0; 733 return; 734 default: 735 break; 736 } 737 738 status = packet[5]; 739 if (!avrcp_controller_cid) return; 740 741 // ignore INTERIM status 742 if (status == AVRCP_CTYPE_RESPONSE_INTERIM) return; 743 744 switch (packet[2]){ 745 case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED:{ 746 int volume_percentage = avrcp_subevent_notification_volume_changed_get_absolute_volume(packet) * 100 / 127; 747 printf("AVRCP Controller: notification absolute volume changed %d %%\n", volume_percentage); 748 return; 749 } 750 default: 751 break; 752 } 753 } 754 755 #ifdef HAVE_BTSTACK_STDIN 756 static void show_usage(void){ 757 bd_addr_t iut_address; 758 gap_local_bd_addr(iut_address); 759 printf("\n--- Bluetooth A2DP Source/AVRCP Target Demo %s ---\n", bd_addr_to_str(iut_address)); 760 printf("b - A2DP Source create connection to addr %s\n", device_addr_string); 761 printf("B - A2DP Source disconnect\n"); 762 printf("c - AVRCP Target create connection to addr %s\n", device_addr_string); 763 printf("C - AVRCP Target disconnect\n"); 764 765 printf("x - start streaming sine\n"); 766 if (hxcmod_initialized){ 767 printf("z - start streaming '%s'\n", mod_name); 768 } 769 printf("p - pause streaming\n"); 770 printf("w - reconfigure stream for 44100 Hz\n"); 771 printf("e - reconfigure stream for 48000 Hz\n"); 772 printf("t - volume up\n"); 773 printf("T - volume down\n"); 774 printf("v - absolute volume of 50 percent\n"); 775 776 printf("\n--- Bluetooth AVRCP Target Commands %s ---\n", bd_addr_to_str(iut_address)); 777 printf("---\n"); 778 } 779 780 static void stdin_process(char cmd){ 781 uint8_t status = ERROR_CODE_SUCCESS; 782 switch (cmd){ 783 case 'b': 784 status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid); 785 printf("%c - Create A2DP Source connection to addr %s, cid 0x%02x.\n", cmd, bd_addr_to_str(device_addr), media_tracker.a2dp_cid); 786 break; 787 case 'B': 788 printf("%c - A2DP Source Disconnect from cid 0x%2x\n", cmd, media_tracker.a2dp_cid); 789 status = a2dp_source_disconnect(media_tracker.a2dp_cid); 790 break; 791 case 'c': 792 printf("%c - Create AVRCP Target connection to addr %s.\n", cmd, bd_addr_to_str(device_addr)); 793 status = avrcp_target_connect(device_addr, &media_tracker.avrcp_cid); 794 break; 795 case 'C': 796 printf("%c - AVRCP Target disconnect\n", cmd); 797 status = avrcp_target_disconnect(media_tracker.avrcp_cid); 798 break; 799 800 case '\n': 801 case '\r': 802 break; 803 804 case 't': 805 printf(" - volume up\n"); 806 status = avrcp_controller_volume_up(avrcp_controller_cid); 807 break; 808 case 'T': 809 printf(" - volume down\n"); 810 status = avrcp_controller_volume_down(avrcp_controller_cid); 811 break; 812 case 'v': 813 printf(" - absolute volume of 50%% (64)\n"); 814 status = avrcp_controller_set_absolute_volume(avrcp_controller_cid, 64); 815 break; 816 817 case 'x': 818 if (media_tracker.avrcp_cid){ 819 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 820 } 821 printf("%c - Play sine.\n", cmd); 822 data_source = STREAM_SINE; 823 if (!media_tracker.stream_opened) break; 824 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 825 break; 826 case 'z': 827 if (media_tracker.avrcp_cid){ 828 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 829 } 830 printf("%c - Play mod.\n", cmd); 831 data_source = STREAM_MOD; 832 if (!media_tracker.stream_opened) break; 833 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 834 break; 835 836 case 'p': 837 if (!media_tracker.stream_opened) break; 838 printf("%c - Pause stream.\n", cmd); 839 status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 840 break; 841 842 case 'w': 843 if (!media_tracker.stream_opened) break; 844 if (play_info.status == AVRCP_PLAYBACK_STATUS_PLAYING){ 845 printf("Stream cannot be reconfigured while playing, please pause stream first\n"); 846 break; 847 } 848 printf("%c - Reconfigure for 44100 Hz.\n", cmd); 849 status = a2dp_source_reconfigure_stream_sampling_frequency(media_tracker.a2dp_cid, 44100); 850 break; 851 852 case 'e': 853 if (!media_tracker.stream_opened) break; 854 if (play_info.status == AVRCP_PLAYBACK_STATUS_PLAYING){ 855 printf("Stream cannot be reconfigured while playing, please pause stream first\n"); 856 break; 857 } 858 printf("%c - Reconfigure for 48000 Hz.\n", cmd); 859 status = a2dp_source_reconfigure_stream_sampling_frequency(media_tracker.a2dp_cid, 48000); 860 break; 861 862 default: 863 show_usage(); 864 return; 865 } 866 if (status != ERROR_CODE_SUCCESS){ 867 printf("Could not perform command \'%c\', status 0x%2x\n", cmd, status); 868 } 869 } 870 #endif 871 872 873 int btstack_main(int argc, const char * argv[]); 874 int btstack_main(int argc, const char * argv[]){ 875 (void)argc; 876 (void)argv; 877 878 int err = a2dp_source_and_avrcp_services_init(); 879 if (err) return err; 880 // turn on! 881 hci_power_control(HCI_POWER_ON); 882 return 0; 883 } 884 /* EXAMPLE_END */ 885