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