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