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