1 /* 2 * Copyright (C) 2016 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 #define __BTSTACK_FILE__ "a2dp_source_demo.c" 39 40 /* 41 * a2dp_source_demo.c 42 */ 43 44 // ***************************************************************************** 45 /* EXAMPLE_START(a2dp_source_demo): Serve audio stream and handle remote playback control and queries. 46 * 47 * @text This A2DP Source example demonstrates how to send an audio data stream 48 * to a remote A2DP Sink device and how to switch between two audio data sources. 49 * In addition, the AVRCP Target is used to answer queries on currently played media, 50 * as well as to handle remote playback control, i.e. play, stop, repeat, etc. 51 * 52 * @test To test with a remote device, e.g. a Bluetooth speaker, 53 * set the device_addr_string to the Bluetooth address of your 54 * remote device in the code, and use the UI to connect and start playback. 55 * Tap SPACE on the console to show the available commands. 56 */ 57 // ***************************************************************************** 58 59 60 #include <stdint.h> 61 #include <stdio.h> 62 #include <stdlib.h> 63 #include <string.h> 64 65 #include "btstack.h" 66 #include "hxcmod.h" 67 #include "mods/mod.h" 68 69 // logarithmic volume reduction, samples are divided by 2^x 70 // #define VOLUME_REDUCTION 3 71 // #undef HAVE_BTSTACK_STDIN 72 73 //#define AVRCP_BROWSING_ENABLED 74 75 #define NUM_CHANNELS 2 76 #define A2DP_SAMPLE_RATE 44100 77 #define BYTES_PER_AUDIO_SAMPLE (2*NUM_CHANNELS) 78 #define AUDIO_TIMEOUT_MS 10 79 #define TABLE_SIZE_441HZ 100 80 81 #define SBC_STORAGE_SIZE 1030 82 83 typedef enum { 84 STREAM_SINE = 0, 85 STREAM_MOD, 86 STREAM_PTS_TEST 87 } stream_data_source_t; 88 89 typedef struct { 90 uint16_t a2dp_cid; 91 uint8_t local_seid; 92 uint8_t stream_opened; 93 uint16_t avrcp_cid; 94 95 uint32_t time_audio_data_sent; // ms 96 uint32_t acc_num_missed_samples; 97 uint32_t samples_ready; 98 btstack_timer_source_t audio_timer; 99 uint8_t streaming; 100 int max_media_payload_size; 101 102 uint8_t sbc_storage[SBC_STORAGE_SIZE]; 103 uint16_t sbc_storage_count; 104 uint8_t sbc_ready_to_send; 105 } a2dp_media_sending_context_t; 106 107 static uint8_t media_sbc_codec_capabilities[] = { 108 (AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO, 109 0xFF,//(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS, 110 2, 53 111 }; 112 113 static const int16_t sine_int16[] = { 114 0, 2057, 4107, 6140, 8149, 10126, 12062, 13952, 15786, 17557, 115 19260, 20886, 22431, 23886, 25247, 26509, 27666, 28714, 29648, 30466, 116 31163, 31738, 32187, 32509, 32702, 32767, 32702, 32509, 32187, 31738, 117 31163, 30466, 29648, 28714, 27666, 26509, 25247, 23886, 22431, 20886, 118 19260, 17557, 15786, 13952, 12062, 10126, 8149, 6140, 4107, 2057, 119 0, -2057, -4107, -6140, -8149, -10126, -12062, -13952, -15786, -17557, 120 -19260, -20886, -22431, -23886, -25247, -26509, -27666, -28714, -29648, -30466, 121 -31163, -31738, -32187, -32509, -32702, -32767, -32702, -32509, -32187, -31738, 122 -31163, -30466, -29648, -28714, -27666, -26509, -25247, -23886, -22431, -20886, 123 -19260, -17557, -15786, -13952, -12062, -10126, -8149, -6140, -4107, -2057, 124 }; 125 126 typedef struct { 127 int reconfigure; 128 int num_channels; 129 int sampling_frequency; 130 int channel_mode; 131 int block_length; 132 int subbands; 133 int allocation_method; 134 int min_bitpool_value; 135 int max_bitpool_value; 136 int frames_per_buffer; 137 } avdtp_media_codec_configuration_sbc_t; 138 139 static btstack_packet_callback_registration_t hci_event_callback_registration; 140 141 // pts: static const char * device_addr_string = "00:1B:DC:08:0A:A5"; 142 // 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 uint16_t supported_features = (1 << AVRCP_TARGET_SUPPORTED_FEATURE_CATEGORY_PLAYER_OR_RECORDER); 267 #ifdef AVRCP_BROWSING_ENABLED 268 supported_features |= (1 << AVRCP_TARGET_SUPPORTED_FEATURE_BROWSING); 269 #endif 270 271 avrcp_target_create_sdp_record(sdp_avrcp_target_service_buffer, 0x10001, supported_features, 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 00:00:00:00:00:00"); 278 gap_discoverable_control(1); 279 gap_set_class_of_device(0x200408); 280 281 // Register for HCI events. 282 hci_event_callback_registration.callback = &a2dp_source_packet_handler; 283 hci_add_event_handler(&hci_event_callback_registration); 284 285 hxcmod_initialized = hxcmod_init(&mod_context); 286 if (hxcmod_initialized){ 287 hxcmod_setcfg(&mod_context, A2DP_SAMPLE_RATE, 16, 1, 1, 1); 288 hxcmod_load(&mod_context, (void *) &mod_data, mod_len); 289 printf("loaded mod '%s', size %u\n", mod_name, mod_len); 290 } 291 292 // Parse human readable Bluetooth address. 293 sscanf_bd_addr(device_addr_string, device_addr); 294 295 #ifdef HAVE_BTSTACK_STDIN 296 btstack_stdin_setup(stdin_process); 297 #endif 298 return 0; 299 } 300 /* LISTING_END */ 301 302 static void a2dp_demo_send_media_packet(void){ 303 int num_bytes_in_frame = btstack_sbc_encoder_sbc_buffer_length(); 304 int bytes_in_storage = media_tracker.sbc_storage_count; 305 uint8_t num_frames = bytes_in_storage / num_bytes_in_frame; 306 a2dp_source_stream_send_media_payload(media_tracker.a2dp_cid, media_tracker.local_seid, media_tracker.sbc_storage, bytes_in_storage, num_frames, 0); 307 media_tracker.sbc_storage_count = 0; 308 media_tracker.sbc_ready_to_send = 0; 309 } 310 311 static void produce_sine_audio(int16_t * pcm_buffer, int num_samples_to_write){ 312 int count; 313 for (count = 0; count < num_samples_to_write ; count++){ 314 pcm_buffer[count * 2] = sine_int16[sine_phase]; 315 pcm_buffer[count * 2 + 1] = sine_int16[sine_phase]; 316 sine_phase++; 317 if (sine_phase >= TABLE_SIZE_441HZ){ 318 sine_phase -= TABLE_SIZE_441HZ; 319 } 320 } 321 } 322 323 static void produce_mod_audio(int16_t * pcm_buffer, int num_samples_to_write){ 324 hxcmod_fillbuffer(&mod_context, (unsigned short *) &pcm_buffer[0], num_samples_to_write, &trkbuf); 325 } 326 327 static void produce_audio(int16_t * pcm_buffer, int num_samples){ 328 switch (data_source){ 329 case STREAM_SINE: 330 produce_sine_audio(pcm_buffer, num_samples); 331 break; 332 case STREAM_MOD: 333 produce_mod_audio(pcm_buffer, num_samples); 334 break; 335 default: 336 break; 337 } 338 #ifdef VOLUME_REDUCTION 339 int i; 340 for (i=0;i<num_samples*2;i++){ 341 if (pcm_buffer[i] > 0){ 342 pcm_buffer[i] = pcm_buffer[i] >> VOLUME_REDUCTION; 343 } else { 344 pcm_buffer[i] = -((-pcm_buffer[i]) >> VOLUME_REDUCTION); 345 } 346 } 347 #endif 348 } 349 350 static int a2dp_demo_fill_sbc_audio_buffer(a2dp_media_sending_context_t * context){ 351 // perform sbc encodin 352 int total_num_bytes_read = 0; 353 unsigned int num_audio_samples_per_sbc_buffer = btstack_sbc_encoder_num_audio_frames(); 354 while (context->samples_ready >= num_audio_samples_per_sbc_buffer 355 && (context->max_media_payload_size - context->sbc_storage_count) >= btstack_sbc_encoder_sbc_buffer_length()){ 356 357 int16_t pcm_frame[256*NUM_CHANNELS]; 358 359 produce_audio(pcm_frame, num_audio_samples_per_sbc_buffer); 360 btstack_sbc_encoder_process_data(pcm_frame); 361 362 uint16_t sbc_frame_size = btstack_sbc_encoder_sbc_buffer_length(); 363 uint8_t * sbc_frame = btstack_sbc_encoder_sbc_buffer(); 364 365 total_num_bytes_read += num_audio_samples_per_sbc_buffer; 366 memcpy(&context->sbc_storage[context->sbc_storage_count], sbc_frame, sbc_frame_size); 367 context->sbc_storage_count += sbc_frame_size; 368 context->samples_ready -= num_audio_samples_per_sbc_buffer; 369 } 370 return total_num_bytes_read; 371 } 372 373 static void a2dp_demo_audio_timeout_handler(btstack_timer_source_t * timer){ 374 a2dp_media_sending_context_t * context = (a2dp_media_sending_context_t *) btstack_run_loop_get_timer_context(timer); 375 btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS); 376 btstack_run_loop_add_timer(&context->audio_timer); 377 uint32_t now = btstack_run_loop_get_time_ms(); 378 379 uint32_t update_period_ms = AUDIO_TIMEOUT_MS; 380 if (context->time_audio_data_sent > 0){ 381 update_period_ms = now - context->time_audio_data_sent; 382 } 383 384 uint32_t num_samples = (update_period_ms * A2DP_SAMPLE_RATE) / 1000; 385 context->acc_num_missed_samples += (update_period_ms * A2DP_SAMPLE_RATE) % 1000; 386 387 while (context->acc_num_missed_samples >= 1000){ 388 num_samples++; 389 context->acc_num_missed_samples -= 1000; 390 } 391 context->time_audio_data_sent = now; 392 context->samples_ready += num_samples; 393 394 if (context->sbc_ready_to_send) return; 395 396 a2dp_demo_fill_sbc_audio_buffer(context); 397 398 if ((context->sbc_storage_count + btstack_sbc_encoder_sbc_buffer_length()) > context->max_media_payload_size){ 399 // schedule sending 400 context->sbc_ready_to_send = 1; 401 a2dp_source_stream_endpoint_request_can_send_now(context->a2dp_cid, context->local_seid); 402 } 403 } 404 405 static void a2dp_demo_timer_start(a2dp_media_sending_context_t * context){ 406 context->max_media_payload_size = btstack_min(a2dp_max_media_payload_size(context->a2dp_cid, context->local_seid), SBC_STORAGE_SIZE); 407 context->sbc_storage_count = 0; 408 context->sbc_ready_to_send = 0; 409 context->streaming = 1; 410 btstack_run_loop_remove_timer(&context->audio_timer); 411 btstack_run_loop_set_timer_handler(&context->audio_timer, a2dp_demo_audio_timeout_handler); 412 btstack_run_loop_set_timer_context(&context->audio_timer, context); 413 btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS); 414 btstack_run_loop_add_timer(&context->audio_timer); 415 } 416 417 static void a2dp_demo_timer_stop(a2dp_media_sending_context_t * context){ 418 context->time_audio_data_sent = 0; 419 context->acc_num_missed_samples = 0; 420 context->samples_ready = 0; 421 context->streaming = 1; 422 context->sbc_storage_count = 0; 423 context->sbc_ready_to_send = 0; 424 btstack_run_loop_remove_timer(&context->audio_timer); 425 } 426 427 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 428 UNUSED(channel); 429 UNUSED(size); 430 uint8_t status; 431 uint8_t local_seid; 432 bd_addr_t address; 433 uint16_t cid; 434 435 if (packet_type != HCI_EVENT_PACKET) return; 436 437 #ifndef HAVE_BTSTACK_STDIN 438 if (hci_event_packet_get_type(packet) == BTSTACK_EVENT_STATE){ 439 if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return; 440 printf("Create A2DP Source connection to addr %s.\n", bd_addr_to_str(device_addr)); 441 status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid); 442 if (status != ERROR_CODE_SUCCESS){ 443 printf("Could not perform command, status 0x%2x\n", status); 444 } 445 return; 446 } 447 #endif 448 if (hci_event_packet_get_type(packet) == HCI_EVENT_PIN_CODE_REQUEST) { 449 printf("Pin code request - using '0000'\n"); 450 hci_event_pin_code_request_get_bd_addr(packet, address); 451 gap_pin_code_response(address, "0000"); 452 return; 453 } 454 455 if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return; 456 457 printf("A2DP Meta %x\n", hci_event_a2dp_meta_get_subevent_code(packet)); 458 459 switch (hci_event_a2dp_meta_get_subevent_code(packet)){ 460 case A2DP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED: 461 a2dp_subevent_signaling_connection_established_get_bd_addr(packet, address); 462 cid = a2dp_subevent_signaling_connection_established_get_a2dp_cid(packet); 463 status = a2dp_subevent_signaling_connection_established_get_status(packet); 464 465 if (status != ERROR_CODE_SUCCESS){ 466 printf("A2DP Source: Connection failed, status 0x%02x, cid 0x%02x, a2dp_cid 0x%02x \n", status, cid, media_tracker.a2dp_cid); 467 media_tracker.a2dp_cid = 0; 468 break; 469 } 470 media_tracker.a2dp_cid = cid; 471 printf("A2DP Source: Connected to address %s, a2dp cid 0x%02x.\n", bd_addr_to_str(address), media_tracker.a2dp_cid); 472 break; 473 474 case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{ 475 sbc_configuration.reconfigure = a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet); 476 sbc_configuration.num_channels = a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet); 477 sbc_configuration.sampling_frequency = a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet); 478 sbc_configuration.channel_mode = a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet); 479 sbc_configuration.block_length = a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet); 480 sbc_configuration.subbands = a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet); 481 sbc_configuration.allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet); 482 sbc_configuration.min_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet); 483 sbc_configuration.max_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet); 484 sbc_configuration.frames_per_buffer = sbc_configuration.subbands * sbc_configuration.block_length; 485 printf("A2DP Source: Received SBC codec configuration, sampling frequency %u.\n", sbc_configuration.sampling_frequency); 486 487 btstack_sbc_encoder_init(&sbc_encoder_state, SBC_MODE_STANDARD, 488 sbc_configuration.block_length, sbc_configuration.subbands, 489 sbc_configuration.allocation_method, sbc_configuration.sampling_frequency, 490 sbc_configuration.max_bitpool_value, 491 sbc_configuration.channel_mode); 492 break; 493 } 494 495 case A2DP_SUBEVENT_STREAM_ESTABLISHED: 496 a2dp_subevent_stream_established_get_bd_addr(packet, address); 497 status = a2dp_subevent_stream_established_get_status(packet); 498 if (status){ 499 printf("A2DP Source: Stream failed, status 0x%02x.\n", status); 500 break; 501 } 502 local_seid = a2dp_subevent_stream_established_get_local_seid(packet); 503 if (local_seid != media_tracker.local_seid){ 504 printf("A2DP Source: Stream failed, wrong local seid %d, expected %d.\n", local_seid, media_tracker.local_seid); 505 break; 506 } 507 printf("A2DP Source: Stream established, address %s, a2dp cid 0x%02x, local seid %d, remote seid %d.\n", bd_addr_to_str(address), 508 media_tracker.a2dp_cid, media_tracker.local_seid, a2dp_subevent_stream_established_get_remote_seid(packet)); 509 media_tracker.stream_opened = 1; 510 data_source = STREAM_MOD; 511 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 512 break; 513 514 case A2DP_SUBEVENT_STREAM_RECONFIGURED: 515 status = a2dp_subevent_stream_reconfigured_get_status(packet); 516 printf("A2DP Source: Reconfigured, status 0x%02x\n", status); 517 break; 518 519 case A2DP_SUBEVENT_STREAM_STARTED: 520 play_info.status = AVRCP_PLAYBACK_STATUS_PLAYING; 521 if (media_tracker.avrcp_cid){ 522 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 523 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PLAYING); 524 } 525 a2dp_demo_timer_start(&media_tracker); 526 printf("A2DP Source: Stream started.\n"); 527 break; 528 529 case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW: 530 a2dp_demo_send_media_packet(); 531 break; 532 533 case A2DP_SUBEVENT_STREAM_SUSPENDED: 534 play_info.status = AVRCP_PLAYBACK_STATUS_PAUSED; 535 if (media_tracker.avrcp_cid){ 536 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PAUSED); 537 } 538 printf("A2DP Source: Stream paused.\n"); 539 a2dp_demo_timer_stop(&media_tracker); 540 break; 541 542 case A2DP_SUBEVENT_STREAM_RELEASED: 543 play_info.status = AVRCP_PLAYBACK_STATUS_STOPPED; 544 cid = a2dp_subevent_stream_released_get_a2dp_cid(packet); 545 if (cid == media_tracker.a2dp_cid) { 546 media_tracker.stream_opened = 0; 547 printf("A2DP Source: Stream released.\n"); 548 } 549 if (media_tracker.avrcp_cid){ 550 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); 551 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_STOPPED); 552 } 553 a2dp_demo_timer_stop(&media_tracker); 554 break; 555 case A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED: 556 cid = a2dp_subevent_signaling_connection_released_get_a2dp_cid(packet); 557 if (cid == media_tracker.a2dp_cid) { 558 media_tracker.avrcp_cid = 0; 559 media_tracker.a2dp_cid = 0; 560 printf("A2DP Source: Signaling released.\n\n"); 561 } 562 break; 563 default: 564 break; 565 } 566 } 567 568 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 569 UNUSED(channel); 570 UNUSED(size); 571 bd_addr_t event_addr; 572 uint16_t local_cid; 573 uint8_t status = ERROR_CODE_SUCCESS; 574 575 if (packet_type != HCI_EVENT_PACKET) return; 576 if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; 577 578 switch (packet[2]){ 579 case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: { 580 local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet); 581 // if (avrcp_cid != 0 && avrcp_cid != local_cid) { 582 // printf("AVRCP Target: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_cid, local_cid); 583 // return; 584 // } 585 // if (avrcp_cid != local_cid) break; 586 587 status = avrcp_subevent_connection_established_get_status(packet); 588 if (status != ERROR_CODE_SUCCESS){ 589 printf("AVRCP Target: Connection failed, status 0x%02x\n", status); 590 return; 591 } 592 media_tracker.avrcp_cid = local_cid; 593 avrcp_subevent_connection_established_get_bd_addr(packet, event_addr); 594 printf("AVRCP Target: Connected to %s, avrcp_cid 0x%02x\n", bd_addr_to_str(event_addr), local_cid); 595 596 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); 597 avrcp_target_set_unit_info(media_tracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, company_id); 598 avrcp_target_set_subunit_info(media_tracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, (uint8_t *)subunit_info, sizeof(subunit_info)); 599 return; 600 } 601 602 case AVRCP_SUBEVENT_EVENT_IDS_QUERY: 603 status = avrcp_target_supported_events(media_tracker.avrcp_cid, events_num, events, sizeof(events)); 604 break; 605 case AVRCP_SUBEVENT_COMPANY_IDS_QUERY: 606 status = avrcp_target_supported_companies(media_tracker.avrcp_cid, companies_num, companies, sizeof(companies)); 607 break; 608 case AVRCP_SUBEVENT_PLAY_STATUS_QUERY: 609 status = avrcp_target_play_status(media_tracker.avrcp_cid, play_info.song_length_ms, play_info.song_position_ms, play_info.status); 610 break; 611 // case AVRCP_SUBEVENT_NOW_PLAYING_INFO_QUERY: 612 // status = avrcp_target_now_playing_info(avrcp_cid); 613 // break; 614 case AVRCP_SUBEVENT_OPERATION:{ 615 avrcp_operation_id_t operation_id = avrcp_subevent_operation_get_operation_id(packet); 616 switch (operation_id){ 617 case AVRCP_OPERATION_ID_PLAY: 618 printf("AVRCP Target: PLAY\n"); 619 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 620 break; 621 case AVRCP_OPERATION_ID_PAUSE: 622 printf("AVRCP Target: PAUSE\n"); 623 status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 624 break; 625 case AVRCP_OPERATION_ID_STOP: 626 printf("AVRCP Target: STOP\n"); 627 status = a2dp_source_disconnect(media_tracker.a2dp_cid); 628 break; 629 default: 630 printf("AVRCP Target: operation 0x%2x is not handled\n", operation_id); 631 return; 632 } 633 break; 634 } 635 case AVRCP_SUBEVENT_CONNECTION_RELEASED: 636 printf("AVRCP Target: Disconnected, avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); 637 media_tracker.avrcp_cid = 0; 638 return; 639 default: 640 break; 641 } 642 643 if (status != ERROR_CODE_SUCCESS){ 644 printf("Responding to event 0x%02x failed with status 0x%02x\n", packet[2], status); 645 } 646 } 647 648 #ifdef HAVE_BTSTACK_STDIN 649 static void show_usage(void){ 650 bd_addr_t iut_address; 651 gap_local_bd_addr(iut_address); 652 printf("\n--- Bluetooth A2DP Source/AVRCP Target Demo %s ---\n", bd_addr_to_str(iut_address)); 653 printf("b - A2DP Source create connection to addr %s\n", device_addr_string); 654 printf("B - A2DP Source disconnect\n"); 655 printf("c - AVRCP Target create connection to addr %s\n", device_addr_string); 656 printf("C - AVRCP Target disconnect\n"); 657 658 printf("x - start streaming sine\n"); 659 if (hxcmod_initialized){ 660 printf("z - start streaming '%s'\n", mod_name); 661 } 662 printf("p - pause streaming\n"); 663 printf("w - reconfigure stream for 44100 Hz\n"); 664 printf("e - reconfigure stream for 48000 Hz\n"); 665 666 printf("\n--- Bluetooth AVRCP Target Commands %s ---\n", bd_addr_to_str(iut_address)); 667 printf("---\n"); 668 } 669 670 static void stdin_process(char cmd){ 671 uint8_t status = ERROR_CODE_SUCCESS; 672 switch (cmd){ 673 case 'b': 674 status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid); 675 printf("%c - Create A2DP Source connection to addr %s, cid 0x%02x.\n", cmd, bd_addr_to_str(device_addr), media_tracker.a2dp_cid); 676 break; 677 case 'B': 678 printf("%c - A2DP Source Disconnect from cid 0x%2x\n", cmd, media_tracker.a2dp_cid); 679 status = a2dp_source_disconnect(media_tracker.a2dp_cid); 680 break; 681 case 'c': 682 printf("%c - Create AVRCP Target connection to addr %s.\n", cmd, bd_addr_to_str(device_addr)); 683 status = avrcp_target_connect(device_addr, &media_tracker.avrcp_cid); 684 break; 685 case 'C': 686 printf("%c - AVRCP Target disconnect\n", cmd); 687 status = avrcp_target_disconnect(media_tracker.avrcp_cid); 688 break; 689 690 case '\n': 691 case '\r': 692 break; 693 694 case 'x': 695 if (media_tracker.avrcp_cid){ 696 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 697 } 698 printf("%c - Play sine.\n", cmd); 699 data_source = STREAM_SINE; 700 if (!media_tracker.stream_opened) break; 701 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 702 break; 703 case 'z': 704 if (media_tracker.avrcp_cid){ 705 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 706 } 707 printf("%c - Play mod.\n", cmd); 708 data_source = STREAM_MOD; 709 if (!media_tracker.stream_opened) break; 710 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 711 break; 712 713 case 'p': 714 if (!media_tracker.stream_opened) break; 715 printf("%c - Pause stream.\n", cmd); 716 status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 717 break; 718 719 case 'w': 720 if (!media_tracker.stream_opened) break; 721 if (play_info.status == AVRCP_PLAYBACK_STATUS_PLAYING){ 722 printf("Stream cannot be reconfigured while playing, please pause stream first\n"); 723 break; 724 } 725 printf("%c - Reconfigure for 44100 Hz.\n", cmd); 726 status = a2dp_source_reconfigure_stream_sampling_frequency(media_tracker.a2dp_cid, 44100); 727 break; 728 729 case 'e': 730 if (!media_tracker.stream_opened) break; 731 if (play_info.status == AVRCP_PLAYBACK_STATUS_PLAYING){ 732 printf("Stream cannot be reconfigured while playing, please pause stream first\n"); 733 break; 734 } 735 printf("%c - Reconfigure for 48000 Hz.\n", cmd); 736 status = a2dp_source_reconfigure_stream_sampling_frequency(media_tracker.a2dp_cid, 48000); 737 break; 738 739 default: 740 show_usage(); 741 return; 742 } 743 if (status != ERROR_CODE_SUCCESS){ 744 printf("Could not perform command \'%c\', status 0x%2x\n", cmd, status); 745 } 746 } 747 #endif 748 749 750 int btstack_main(int argc, const char * argv[]); 751 int btstack_main(int argc, const char * argv[]){ 752 (void)argc; 753 (void)argv; 754 755 int err = a2dp_source_and_avrcp_services_init(); 756 if (err) return err; 757 // turn on! 758 hci_power_control(HCI_POWER_ON); 759 return 0; 760 } 761 /* EXAMPLE_END */ 762