1 /* 2 * Copyright (C) 2016 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 #define BTSTACK_FILE__ "a2dp_source_demo.c" 39 40 /* 41 * a2dp_source_demo.c 42 */ 43 44 // ***************************************************************************** 45 /* EXAMPLE_START(a2dp_source_demo): Serve audio stream and handle remote playback control and queries. 46 * 47 * @text This A2DP Source example demonstrates how to send an audio data stream 48 * to a remote A2DP Sink device and how to switch between two audio data sources. 49 * In addition, the AVRCP Target is used to answer queries on currently played media, 50 * as well as to handle remote playback control, i.e. play, stop, repeat, etc. 51 * 52 * @test To test with a remote device, e.g. a Bluetooth speaker, 53 * set the device_addr_string to the Bluetooth address of your 54 * remote device in the code, and use the UI to connect and start playback. 55 * Tap SPACE on the console to show the available commands. 56 */ 57 // ***************************************************************************** 58 59 60 #include <stdint.h> 61 #include <stdio.h> 62 #include <stdlib.h> 63 #include <string.h> 64 65 #include "btstack.h" 66 #include "hxcmod.h" 67 #include "mods/mod.h" 68 69 // logarithmic volume reduction, samples are divided by 2^x 70 // #define VOLUME_REDUCTION 3 71 // #undef HAVE_BTSTACK_STDIN 72 73 //#define AVRCP_BROWSING_ENABLED 74 75 #define NUM_CHANNELS 2 76 #define A2DP_SAMPLE_RATE 44100 77 #define BYTES_PER_AUDIO_SAMPLE (2*NUM_CHANNELS) 78 #define AUDIO_TIMEOUT_MS 10 79 #define TABLE_SIZE_441HZ 100 80 81 #define SBC_STORAGE_SIZE 1030 82 83 typedef enum { 84 STREAM_SINE = 0, 85 STREAM_MOD, 86 STREAM_PTS_TEST 87 } stream_data_source_t; 88 89 typedef struct { 90 uint16_t a2dp_cid; 91 uint8_t local_seid; 92 uint8_t stream_opened; 93 uint16_t avrcp_cid; 94 95 uint32_t time_audio_data_sent; // ms 96 uint32_t acc_num_missed_samples; 97 uint32_t samples_ready; 98 btstack_timer_source_t audio_timer; 99 uint8_t streaming; 100 int max_media_payload_size; 101 102 uint8_t sbc_storage[SBC_STORAGE_SIZE]; 103 uint16_t sbc_storage_count; 104 uint8_t sbc_ready_to_send; 105 } a2dp_media_sending_context_t; 106 107 static uint8_t media_sbc_codec_capabilities[] = { 108 (AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO, 109 0xFF,//(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS, 110 2, 53 111 }; 112 113 static const int16_t sine_int16[] = { 114 0, 2057, 4107, 6140, 8149, 10126, 12062, 13952, 15786, 17557, 115 19260, 20886, 22431, 23886, 25247, 26509, 27666, 28714, 29648, 30466, 116 31163, 31738, 32187, 32509, 32702, 32767, 32702, 32509, 32187, 31738, 117 31163, 30466, 29648, 28714, 27666, 26509, 25247, 23886, 22431, 20886, 118 19260, 17557, 15786, 13952, 12062, 10126, 8149, 6140, 4107, 2057, 119 0, -2057, -4107, -6140, -8149, -10126, -12062, -13952, -15786, -17557, 120 -19260, -20886, -22431, -23886, -25247, -26509, -27666, -28714, -29648, -30466, 121 -31163, -31738, -32187, -32509, -32702, -32767, -32702, -32509, -32187, -31738, 122 -31163, -30466, -29648, -28714, -27666, -26509, -25247, -23886, -22431, -20886, 123 -19260, -17557, -15786, -13952, -12062, -10126, -8149, -6140, -4107, -2057, 124 }; 125 126 typedef struct { 127 int reconfigure; 128 int num_channels; 129 int sampling_frequency; 130 int channel_mode; 131 int block_length; 132 int subbands; 133 int allocation_method; 134 int min_bitpool_value; 135 int max_bitpool_value; 136 int frames_per_buffer; 137 } avdtp_media_codec_configuration_sbc_t; 138 139 static btstack_packet_callback_registration_t hci_event_callback_registration; 140 141 // pts: static const char * device_addr_string = "00:1B:DC:08:0A:A5"; 142 // pts: 143 static const char * device_addr_string = "00:1B:DC:08:E2:72"; 144 // mac 2013: static const char * device_addr_string = "84:38:35:65:d1:15"; 145 // phone 2013: static const char * device_addr_string = "D8:BB:2C:DF:F0:F2"; 146 // Minijambox: static const char * device_addr_string = "00:21:3C:AC:F7:38"; 147 // Philips SHB9100: static const char * device_addr_string = "00:22:37:05:FD:E8"; 148 // RT-B6: static const char * device_addr_string = "00:75:58:FF:C9:7D"; 149 // BT dongle: static const char * device_addr_string = "00:1A:7D:DA:71:0A"; 150 // Sony MDR-ZX330BT static const char * device_addr_string = "00:18:09:28:50:18"; 151 // Panda (BM6) static const char * device_addr_string = "4F:3F:66:52:8B:E0"; 152 153 static bd_addr_t device_addr; 154 static uint8_t sdp_a2dp_source_service_buffer[150]; 155 static uint8_t sdp_avrcp_target_service_buffer[200]; 156 static uint8_t sdp_avrcp_controller_service_buffer[200]; 157 158 static avdtp_media_codec_configuration_sbc_t sbc_configuration; 159 static btstack_sbc_encoder_state_t sbc_encoder_state; 160 161 static uint8_t media_sbc_codec_configuration[4]; 162 static a2dp_media_sending_context_t media_tracker; 163 164 static stream_data_source_t data_source; 165 166 static int sine_phase; 167 168 static int hxcmod_initialized; 169 static modcontext mod_context; 170 static tracker_buffer_state trkbuf; 171 172 static uint16_t avrcp_controller_cid = 0; 173 174 /* AVRCP Target context START */ 175 static const uint8_t subunit_info[] = { 176 0,0,0,0, 177 1,1,1,1, 178 2,2,2,2, 179 3,3,3,3, 180 4,4,4,4, 181 5,5,5,5, 182 6,6,6,6, 183 7,7,7,7 184 }; 185 186 static uint32_t company_id = 0x112233; 187 static uint8_t companies_num = 1; 188 static uint8_t companies[] = { 189 0x00, 0x19, 0x58 //BT SIG registered CompanyID 190 }; 191 192 static uint8_t events_num = 13; 193 static uint8_t events[] = { 194 AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED, 195 AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED, 196 AVRCP_NOTIFICATION_EVENT_TRACK_REACHED_END, 197 AVRCP_NOTIFICATION_EVENT_TRACK_REACHED_START, 198 AVRCP_NOTIFICATION_EVENT_PLAYBACK_POS_CHANGED, 199 AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED, 200 AVRCP_NOTIFICATION_EVENT_SYSTEM_STATUS_CHANGED, 201 AVRCP_NOTIFICATION_EVENT_PLAYER_APPLICATION_SETTING_CHANGED, 202 AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED, 203 AVRCP_NOTIFICATION_EVENT_AVAILABLE_PLAYERS_CHANGED, 204 AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED, 205 AVRCP_NOTIFICATION_EVENT_UIDS_CHANGED, 206 AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED 207 }; 208 209 typedef struct { 210 uint8_t track_id[8]; 211 uint32_t song_length_ms; 212 avrcp_playback_status_t status; 213 uint32_t song_position_ms; // 0xFFFFFFFF if not supported 214 } avrcp_play_status_info_t; 215 216 // python -c "print('a'*512)" 217 static const char title[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 218 219 avrcp_track_t tracks[] = { 220 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, 1, "Sine", "Generated", "A2DP Source Demo", "monotone", 12345}, 221 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 2, "Nao-deceased", "Decease", "A2DP Source Demo", "vivid", 12345}, 222 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, 3, (char *)title, "Decease", "A2DP Source Demo", "vivid", 12345}, 223 }; 224 int current_track_index; 225 avrcp_play_status_info_t play_info; 226 227 /* AVRCP Target context END */ 228 229 /* @section Main Application Setup 230 * 231 * @text The Listing MainConfiguration shows how to setup AD2P Source and AVRCP Target services. 232 */ 233 234 /* LISTING_START(MainConfiguration): Setup Audio Source and AVRCP Target services */ 235 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size); 236 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 237 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 238 #ifdef HAVE_BTSTACK_STDIN 239 static void stdin_process(char cmd); 240 #endif 241 242 static int a2dp_source_and_avrcp_services_init(void){ 243 244 l2cap_init(); 245 // Initialize A2DP Source. 246 a2dp_source_init(); 247 a2dp_source_register_packet_handler(&a2dp_source_packet_handler); 248 249 // Create stream endpoint. 250 avdtp_stream_endpoint_t * local_stream_endpoint = a2dp_source_create_stream_endpoint(AVDTP_AUDIO, AVDTP_CODEC_SBC, media_sbc_codec_capabilities, sizeof(media_sbc_codec_capabilities), media_sbc_codec_configuration, sizeof(media_sbc_codec_configuration)); 251 if (!local_stream_endpoint){ 252 printf("A2DP Source: not enough memory to create local stream endpoint\n"); 253 return 1; 254 } 255 media_tracker.local_seid = avdtp_local_seid(local_stream_endpoint); 256 // Initialize AVRCP Target. 257 avrcp_target_init(); 258 avrcp_target_register_packet_handler(&avrcp_target_packet_handler); 259 // Initialize AVRCP Controller 260 avrcp_controller_init(); 261 avrcp_controller_register_packet_handler(&avrcp_controller_packet_handler); 262 263 // Initialize SDP, 264 sdp_init(); 265 266 // Create A2DP Source service record and register it with SDP. 267 memset(sdp_a2dp_source_service_buffer, 0, sizeof(sdp_a2dp_source_service_buffer)); 268 a2dp_source_create_sdp_record(sdp_a2dp_source_service_buffer, 0x10002, 1, NULL, NULL); 269 sdp_register_service(sdp_a2dp_source_service_buffer); 270 271 // Create AVRCP target service record and register it with SDP. 272 memset(sdp_avrcp_target_service_buffer, 0, sizeof(sdp_avrcp_target_service_buffer)); 273 uint16_t supported_features = (1 << AVRCP_TARGET_SUPPORTED_FEATURE_CATEGORY_PLAYER_OR_RECORDER); 274 #ifdef AVRCP_BROWSING_ENABLED 275 supported_features |= (1 << AVRCP_TARGET_SUPPORTED_FEATURE_BROWSING); 276 #endif 277 avrcp_target_create_sdp_record(sdp_avrcp_target_service_buffer, 0x10001, supported_features, NULL, NULL); 278 sdp_register_service(sdp_avrcp_target_service_buffer); 279 280 // setup AVRCP Controller 281 memset(sdp_avrcp_controller_service_buffer, 0, sizeof(sdp_avrcp_controller_service_buffer)); 282 uint16_t controller_supported_features = (1 << AVRCP_CONTROLLER_SUPPORTED_FEATURE_CATEGORY_MONITOR_OR_AMPLIFIER); 283 avrcp_controller_create_sdp_record(sdp_avrcp_controller_service_buffer, 0x10002, controller_supported_features, NULL, NULL); 284 sdp_register_service(sdp_avrcp_controller_service_buffer); 285 286 // Set local name with a template Bluetooth address, that will be automatically 287 // replaced with a actual address once it is available, i.e. when BTstack boots 288 // up and starts talking to a Bluetooth module. 289 gap_set_local_name("A2DP Source 00:00:00:00:00:00"); 290 gap_discoverable_control(1); 291 gap_set_class_of_device(0x200408); 292 293 // Register for HCI events. 294 hci_event_callback_registration.callback = &a2dp_source_packet_handler; 295 hci_add_event_handler(&hci_event_callback_registration); 296 297 hxcmod_initialized = hxcmod_init(&mod_context); 298 if (hxcmod_initialized){ 299 hxcmod_setcfg(&mod_context, A2DP_SAMPLE_RATE, 16, 1, 1, 1); 300 hxcmod_load(&mod_context, (void *) &mod_data, mod_len); 301 printf("loaded mod '%s', size %u\n", mod_name, mod_len); 302 } 303 304 // Parse human readable Bluetooth address. 305 sscanf_bd_addr(device_addr_string, device_addr); 306 307 #ifdef HAVE_BTSTACK_STDIN 308 btstack_stdin_setup(stdin_process); 309 #endif 310 return 0; 311 } 312 /* LISTING_END */ 313 314 static void a2dp_demo_send_media_packet(void){ 315 int num_bytes_in_frame = btstack_sbc_encoder_sbc_buffer_length(); 316 int bytes_in_storage = media_tracker.sbc_storage_count; 317 uint8_t num_frames = bytes_in_storage / num_bytes_in_frame; 318 a2dp_source_stream_send_media_payload(media_tracker.a2dp_cid, media_tracker.local_seid, media_tracker.sbc_storage, bytes_in_storage, num_frames, 0); 319 media_tracker.sbc_storage_count = 0; 320 media_tracker.sbc_ready_to_send = 0; 321 } 322 323 static void produce_sine_audio(int16_t * pcm_buffer, int num_samples_to_write){ 324 int count; 325 for (count = 0; count < num_samples_to_write ; count++){ 326 pcm_buffer[count * 2] = sine_int16[sine_phase]; 327 pcm_buffer[count * 2 + 1] = sine_int16[sine_phase]; 328 sine_phase++; 329 if (sine_phase >= TABLE_SIZE_441HZ){ 330 sine_phase -= TABLE_SIZE_441HZ; 331 } 332 } 333 } 334 335 static void produce_mod_audio(int16_t * pcm_buffer, int num_samples_to_write){ 336 hxcmod_fillbuffer(&mod_context, (unsigned short *) &pcm_buffer[0], num_samples_to_write, &trkbuf); 337 } 338 339 static void produce_audio(int16_t * pcm_buffer, int num_samples){ 340 switch (data_source){ 341 case STREAM_SINE: 342 produce_sine_audio(pcm_buffer, num_samples); 343 break; 344 case STREAM_MOD: 345 produce_mod_audio(pcm_buffer, num_samples); 346 break; 347 default: 348 break; 349 } 350 #ifdef VOLUME_REDUCTION 351 int i; 352 for (i=0;i<num_samples*2;i++){ 353 if (pcm_buffer[i] > 0){ 354 pcm_buffer[i] = pcm_buffer[i] >> VOLUME_REDUCTION; 355 } else { 356 pcm_buffer[i] = -((-pcm_buffer[i]) >> VOLUME_REDUCTION); 357 } 358 } 359 #endif 360 } 361 362 static int a2dp_demo_fill_sbc_audio_buffer(a2dp_media_sending_context_t * context){ 363 // perform sbc encodin 364 int total_num_bytes_read = 0; 365 unsigned int num_audio_samples_per_sbc_buffer = btstack_sbc_encoder_num_audio_frames(); 366 while (context->samples_ready >= num_audio_samples_per_sbc_buffer 367 && (context->max_media_payload_size - context->sbc_storage_count) >= btstack_sbc_encoder_sbc_buffer_length()){ 368 369 int16_t pcm_frame[256*NUM_CHANNELS]; 370 371 produce_audio(pcm_frame, num_audio_samples_per_sbc_buffer); 372 btstack_sbc_encoder_process_data(pcm_frame); 373 374 uint16_t sbc_frame_size = btstack_sbc_encoder_sbc_buffer_length(); 375 uint8_t * sbc_frame = btstack_sbc_encoder_sbc_buffer(); 376 377 total_num_bytes_read += num_audio_samples_per_sbc_buffer; 378 memcpy(&context->sbc_storage[context->sbc_storage_count], sbc_frame, sbc_frame_size); 379 context->sbc_storage_count += sbc_frame_size; 380 context->samples_ready -= num_audio_samples_per_sbc_buffer; 381 } 382 return total_num_bytes_read; 383 } 384 385 static void a2dp_demo_audio_timeout_handler(btstack_timer_source_t * timer){ 386 a2dp_media_sending_context_t * context = (a2dp_media_sending_context_t *) btstack_run_loop_get_timer_context(timer); 387 btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS); 388 btstack_run_loop_add_timer(&context->audio_timer); 389 uint32_t now = btstack_run_loop_get_time_ms(); 390 391 uint32_t update_period_ms = AUDIO_TIMEOUT_MS; 392 if (context->time_audio_data_sent > 0){ 393 update_period_ms = now - context->time_audio_data_sent; 394 } 395 396 uint32_t num_samples = (update_period_ms * A2DP_SAMPLE_RATE) / 1000; 397 context->acc_num_missed_samples += (update_period_ms * A2DP_SAMPLE_RATE) % 1000; 398 399 while (context->acc_num_missed_samples >= 1000){ 400 num_samples++; 401 context->acc_num_missed_samples -= 1000; 402 } 403 context->time_audio_data_sent = now; 404 context->samples_ready += num_samples; 405 406 if (context->sbc_ready_to_send) return; 407 408 a2dp_demo_fill_sbc_audio_buffer(context); 409 410 if ((context->sbc_storage_count + btstack_sbc_encoder_sbc_buffer_length()) > context->max_media_payload_size){ 411 // schedule sending 412 context->sbc_ready_to_send = 1; 413 a2dp_source_stream_endpoint_request_can_send_now(context->a2dp_cid, context->local_seid); 414 } 415 } 416 417 static void a2dp_demo_timer_start(a2dp_media_sending_context_t * context){ 418 context->max_media_payload_size = btstack_min(a2dp_max_media_payload_size(context->a2dp_cid, context->local_seid), SBC_STORAGE_SIZE); 419 context->sbc_storage_count = 0; 420 context->sbc_ready_to_send = 0; 421 context->streaming = 1; 422 btstack_run_loop_remove_timer(&context->audio_timer); 423 btstack_run_loop_set_timer_handler(&context->audio_timer, a2dp_demo_audio_timeout_handler); 424 btstack_run_loop_set_timer_context(&context->audio_timer, context); 425 btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS); 426 btstack_run_loop_add_timer(&context->audio_timer); 427 } 428 429 static void a2dp_demo_timer_stop(a2dp_media_sending_context_t * context){ 430 context->time_audio_data_sent = 0; 431 context->acc_num_missed_samples = 0; 432 context->samples_ready = 0; 433 context->streaming = 1; 434 context->sbc_storage_count = 0; 435 context->sbc_ready_to_send = 0; 436 btstack_run_loop_remove_timer(&context->audio_timer); 437 } 438 439 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 440 UNUSED(channel); 441 UNUSED(size); 442 uint8_t status; 443 uint8_t local_seid; 444 bd_addr_t address; 445 uint16_t cid; 446 447 if (packet_type != HCI_EVENT_PACKET) return; 448 449 #ifndef HAVE_BTSTACK_STDIN 450 if (hci_event_packet_get_type(packet) == BTSTACK_EVENT_STATE){ 451 if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return; 452 printf("Create A2DP Source connection to addr %s.\n", bd_addr_to_str(device_addr)); 453 status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid); 454 if (status != ERROR_CODE_SUCCESS){ 455 printf("Could not perform command, status 0x%2x\n", status); 456 } 457 return; 458 } 459 #endif 460 if (hci_event_packet_get_type(packet) == HCI_EVENT_PIN_CODE_REQUEST) { 461 printf("Pin code request - using '0000'\n"); 462 hci_event_pin_code_request_get_bd_addr(packet, address); 463 gap_pin_code_response(address, "0000"); 464 return; 465 } 466 467 if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return; 468 469 switch (hci_event_a2dp_meta_get_subevent_code(packet)){ 470 case A2DP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED: 471 a2dp_subevent_signaling_connection_established_get_bd_addr(packet, address); 472 cid = a2dp_subevent_signaling_connection_established_get_a2dp_cid(packet); 473 status = a2dp_subevent_signaling_connection_established_get_status(packet); 474 475 if (status != ERROR_CODE_SUCCESS){ 476 printf("A2DP Source: Connection failed, status 0x%02x, cid 0x%02x, a2dp_cid 0x%02x \n", status, cid, media_tracker.a2dp_cid); 477 media_tracker.a2dp_cid = 0; 478 break; 479 } 480 media_tracker.a2dp_cid = cid; 481 printf("A2DP Source: Connected to address %s, a2dp cid 0x%02x.\n", bd_addr_to_str(address), media_tracker.a2dp_cid); 482 break; 483 484 case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{ 485 sbc_configuration.reconfigure = a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet); 486 sbc_configuration.num_channels = a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet); 487 sbc_configuration.sampling_frequency = a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet); 488 sbc_configuration.channel_mode = a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet); 489 sbc_configuration.block_length = a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet); 490 sbc_configuration.subbands = a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet); 491 sbc_configuration.allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet); 492 sbc_configuration.min_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet); 493 sbc_configuration.max_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet); 494 sbc_configuration.frames_per_buffer = sbc_configuration.subbands * sbc_configuration.block_length; 495 printf("A2DP Source: Received SBC codec configuration, sampling frequency %u.\n", sbc_configuration.sampling_frequency); 496 497 btstack_sbc_encoder_init(&sbc_encoder_state, SBC_MODE_STANDARD, 498 sbc_configuration.block_length, sbc_configuration.subbands, 499 sbc_configuration.allocation_method, sbc_configuration.sampling_frequency, 500 sbc_configuration.max_bitpool_value, 501 sbc_configuration.channel_mode); 502 break; 503 } 504 505 case A2DP_SUBEVENT_SIGNALING_DELAY_REPORT: 506 printf("A2DP Source: received delay report of %d.%0d ms, local seid %d\n", 507 avdtp_subevent_signaling_delay_report_get_delay_100us(packet)/10, avdtp_subevent_signaling_delay_report_get_delay_100us(packet)%10, 508 avdtp_subevent_signaling_delay_report_get_local_seid(packet)); 509 break; 510 511 case A2DP_SUBEVENT_STREAM_ESTABLISHED: 512 a2dp_subevent_stream_established_get_bd_addr(packet, address); 513 status = a2dp_subevent_stream_established_get_status(packet); 514 if (status){ 515 printf("A2DP Source: Stream failed, status 0x%02x.\n", status); 516 break; 517 } 518 local_seid = a2dp_subevent_stream_established_get_local_seid(packet); 519 if (local_seid != media_tracker.local_seid){ 520 printf("A2DP Source: Stream failed, wrong local seid %d, expected %d.\n", local_seid, media_tracker.local_seid); 521 break; 522 } 523 printf("A2DP Source: Stream established, address %s, a2dp cid 0x%02x, local seid %d, remote seid %d.\n", bd_addr_to_str(address), 524 media_tracker.a2dp_cid, media_tracker.local_seid, a2dp_subevent_stream_established_get_remote_seid(packet)); 525 media_tracker.stream_opened = 1; 526 data_source = STREAM_MOD; 527 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 528 break; 529 530 case A2DP_SUBEVENT_STREAM_RECONFIGURED: 531 status = a2dp_subevent_stream_reconfigured_get_status(packet); 532 printf("A2DP Source: Reconfigured, status 0x%02x\n", status); 533 break; 534 535 case A2DP_SUBEVENT_STREAM_STARTED: 536 play_info.status = AVRCP_PLAYBACK_STATUS_PLAYING; 537 if (media_tracker.avrcp_cid){ 538 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 539 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PLAYING); 540 } 541 a2dp_demo_timer_start(&media_tracker); 542 printf("A2DP Source: Stream started.\n"); 543 break; 544 545 case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW: 546 a2dp_demo_send_media_packet(); 547 break; 548 549 case A2DP_SUBEVENT_STREAM_SUSPENDED: 550 play_info.status = AVRCP_PLAYBACK_STATUS_PAUSED; 551 if (media_tracker.avrcp_cid){ 552 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PAUSED); 553 } 554 printf("A2DP Source: Stream paused.\n"); 555 a2dp_demo_timer_stop(&media_tracker); 556 break; 557 558 case A2DP_SUBEVENT_STREAM_RELEASED: 559 play_info.status = AVRCP_PLAYBACK_STATUS_STOPPED; 560 cid = a2dp_subevent_stream_released_get_a2dp_cid(packet); 561 if (cid == media_tracker.a2dp_cid) { 562 media_tracker.stream_opened = 0; 563 printf("A2DP Source: Stream released.\n"); 564 } 565 if (media_tracker.avrcp_cid){ 566 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); 567 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_STOPPED); 568 } 569 a2dp_demo_timer_stop(&media_tracker); 570 break; 571 case A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED: 572 cid = a2dp_subevent_signaling_connection_released_get_a2dp_cid(packet); 573 if (cid == media_tracker.a2dp_cid) { 574 media_tracker.avrcp_cid = 0; 575 media_tracker.a2dp_cid = 0; 576 printf("A2DP Source: Signaling released.\n\n"); 577 } 578 break; 579 default: 580 break; 581 } 582 } 583 584 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 585 UNUSED(channel); 586 UNUSED(size); 587 bd_addr_t event_addr; 588 uint16_t local_cid; 589 uint8_t status = ERROR_CODE_SUCCESS; 590 591 if (packet_type != HCI_EVENT_PACKET) return; 592 if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; 593 594 switch (packet[2]){ 595 case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: { 596 local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet); 597 // if (avrcp_cid != 0 && avrcp_cid != local_cid) { 598 // printf("AVRCP Target: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_cid, local_cid); 599 // return; 600 // } 601 // if (avrcp_cid != local_cid) break; 602 603 status = avrcp_subevent_connection_established_get_status(packet); 604 if (status != ERROR_CODE_SUCCESS){ 605 printf("AVRCP Target: Connection failed, status 0x%02x\n", status); 606 return; 607 } 608 media_tracker.avrcp_cid = local_cid; 609 avrcp_subevent_connection_established_get_bd_addr(packet, event_addr); 610 printf("AVRCP Target: Connected to %s, avrcp_cid 0x%02x\n", bd_addr_to_str(event_addr), local_cid); 611 612 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); 613 avrcp_target_set_unit_info(media_tracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, company_id); 614 avrcp_target_set_subunit_info(media_tracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, (uint8_t *)subunit_info, sizeof(subunit_info)); 615 return; 616 } 617 case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED: 618 printf("AVRCP Target: new volume %d\n", avrcp_subevent_notification_volume_changed_get_absolute_volume(packet)); 619 break; 620 case AVRCP_SUBEVENT_EVENT_IDS_QUERY: 621 status = avrcp_target_supported_events(media_tracker.avrcp_cid, events_num, events, sizeof(events)); 622 break; 623 case AVRCP_SUBEVENT_COMPANY_IDS_QUERY: 624 status = avrcp_target_supported_companies(media_tracker.avrcp_cid, companies_num, companies, sizeof(companies)); 625 break; 626 case AVRCP_SUBEVENT_PLAY_STATUS_QUERY: 627 status = avrcp_target_play_status(media_tracker.avrcp_cid, play_info.song_length_ms, play_info.song_position_ms, play_info.status); 628 break; 629 // case AVRCP_SUBEVENT_NOW_PLAYING_INFO_QUERY: 630 // status = avrcp_target_now_playing_info(avrcp_cid); 631 // break; 632 case AVRCP_SUBEVENT_OPERATION:{ 633 avrcp_operation_id_t operation_id = avrcp_subevent_operation_get_operation_id(packet); 634 switch (operation_id){ 635 case AVRCP_OPERATION_ID_PLAY: 636 printf("AVRCP Target: PLAY\n"); 637 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 638 break; 639 case AVRCP_OPERATION_ID_PAUSE: 640 printf("AVRCP Target: PAUSE\n"); 641 status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 642 break; 643 case AVRCP_OPERATION_ID_STOP: 644 printf("AVRCP Target: STOP\n"); 645 status = a2dp_source_disconnect(media_tracker.a2dp_cid); 646 break; 647 default: 648 printf("AVRCP Target: operation 0x%2x is not handled\n", operation_id); 649 return; 650 } 651 break; 652 } 653 case AVRCP_SUBEVENT_CONNECTION_RELEASED: 654 printf("AVRCP Target: Disconnected, avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); 655 media_tracker.avrcp_cid = 0; 656 return; 657 default: 658 break; 659 } 660 661 if (status != ERROR_CODE_SUCCESS){ 662 printf("Responding to event 0x%02x failed with status 0x%02x\n", packet[2], status); 663 } 664 } 665 666 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 667 UNUSED(channel); 668 UNUSED(size); 669 uint16_t local_cid; 670 uint8_t status = 0xFF; 671 bd_addr_t adress; 672 673 if (packet_type != HCI_EVENT_PACKET) return; 674 if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; 675 switch (packet[2]){ 676 case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: { 677 local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet); 678 if (avrcp_controller_cid != 0 && avrcp_controller_cid != local_cid) { 679 printf("AVRCP Controller: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_controller_cid, local_cid); 680 return; 681 } 682 683 status = avrcp_subevent_connection_established_get_status(packet); 684 if (status != ERROR_CODE_SUCCESS){ 685 printf("AVRCP Controller: Connection failed: status 0x%02x\n", status); 686 avrcp_controller_cid = 0; 687 return; 688 } 689 690 avrcp_controller_cid = local_cid; 691 avrcp_subevent_connection_established_get_bd_addr(packet, adress); 692 printf("AVRCP Controller: Channel successfully opened: %s, avrcp_controller_cid 0x%02x\n", bd_addr_to_str(adress), avrcp_controller_cid); 693 694 // automatically enable notifications 695 avrcp_controller_enable_notification(avrcp_controller_cid, AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED); 696 return; 697 } 698 case AVRCP_SUBEVENT_CONNECTION_RELEASED: 699 printf("AVRCP Controller: Channel released: avrcp_controller_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); 700 avrcp_controller_cid = 0; 701 return; 702 default: 703 break; 704 } 705 706 status = packet[5]; 707 if (!avrcp_controller_cid) return; 708 709 // ignore INTERIM status 710 if (status == AVRCP_CTYPE_RESPONSE_INTERIM) return; 711 712 switch (packet[2]){ 713 case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED:{ 714 int volume_percentage = avrcp_subevent_notification_volume_changed_get_absolute_volume(packet) * 100 / 127; 715 printf("AVRCP Controller: notification absolute volume changed %d %%\n", volume_percentage); 716 return; 717 } 718 default: 719 break; 720 } 721 } 722 723 #ifdef HAVE_BTSTACK_STDIN 724 static void show_usage(void){ 725 bd_addr_t iut_address; 726 gap_local_bd_addr(iut_address); 727 printf("\n--- Bluetooth A2DP Source/AVRCP Target Demo %s ---\n", bd_addr_to_str(iut_address)); 728 printf("b - A2DP Source create connection to addr %s\n", device_addr_string); 729 printf("B - A2DP Source disconnect\n"); 730 printf("c - AVRCP Target create connection to addr %s\n", device_addr_string); 731 printf("C - AVRCP Target disconnect\n"); 732 733 printf("x - start streaming sine\n"); 734 if (hxcmod_initialized){ 735 printf("z - start streaming '%s'\n", mod_name); 736 } 737 printf("p - pause streaming\n"); 738 printf("w - reconfigure stream for 44100 Hz\n"); 739 printf("e - reconfigure stream for 48000 Hz\n"); 740 printf("t - volume up\n"); 741 printf("T - volume down\n"); 742 printf("v - absolute volume of 50 percent\n"); 743 744 printf("\n--- Bluetooth AVRCP Target Commands %s ---\n", bd_addr_to_str(iut_address)); 745 printf("---\n"); 746 } 747 748 static void stdin_process(char cmd){ 749 uint8_t status = ERROR_CODE_SUCCESS; 750 switch (cmd){ 751 case 'b': 752 status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid); 753 printf("%c - Create A2DP Source connection to addr %s, cid 0x%02x.\n", cmd, bd_addr_to_str(device_addr), media_tracker.a2dp_cid); 754 break; 755 case 'B': 756 printf("%c - A2DP Source Disconnect from cid 0x%2x\n", cmd, media_tracker.a2dp_cid); 757 status = a2dp_source_disconnect(media_tracker.a2dp_cid); 758 break; 759 case 'c': 760 printf("%c - Create AVRCP Target connection to addr %s.\n", cmd, bd_addr_to_str(device_addr)); 761 status = avrcp_target_connect(device_addr, &media_tracker.avrcp_cid); 762 break; 763 case 'C': 764 printf("%c - AVRCP Target disconnect\n", cmd); 765 status = avrcp_target_disconnect(media_tracker.avrcp_cid); 766 break; 767 768 case '\n': 769 case '\r': 770 break; 771 772 case 't': 773 printf(" - volume up\n"); 774 status = avrcp_controller_volume_up(avrcp_controller_cid); 775 break; 776 case 'T': 777 printf(" - volume down\n"); 778 status = avrcp_controller_volume_down(avrcp_controller_cid); 779 break; 780 case 'v': 781 printf(" - absolute volume of 50%% (64)\n"); 782 status = avrcp_controller_set_absolute_volume(avrcp_controller_cid, 64); 783 break; 784 785 case 'x': 786 if (media_tracker.avrcp_cid){ 787 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 788 } 789 printf("%c - Play sine.\n", cmd); 790 data_source = STREAM_SINE; 791 if (!media_tracker.stream_opened) break; 792 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 793 break; 794 case 'z': 795 if (media_tracker.avrcp_cid){ 796 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 797 } 798 printf("%c - Play mod.\n", cmd); 799 data_source = STREAM_MOD; 800 if (!media_tracker.stream_opened) break; 801 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 802 break; 803 804 case 'p': 805 if (!media_tracker.stream_opened) break; 806 printf("%c - Pause stream.\n", cmd); 807 status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 808 break; 809 810 case 'w': 811 if (!media_tracker.stream_opened) break; 812 if (play_info.status == AVRCP_PLAYBACK_STATUS_PLAYING){ 813 printf("Stream cannot be reconfigured while playing, please pause stream first\n"); 814 break; 815 } 816 printf("%c - Reconfigure for 44100 Hz.\n", cmd); 817 status = a2dp_source_reconfigure_stream_sampling_frequency(media_tracker.a2dp_cid, 44100); 818 break; 819 820 case 'e': 821 if (!media_tracker.stream_opened) break; 822 if (play_info.status == AVRCP_PLAYBACK_STATUS_PLAYING){ 823 printf("Stream cannot be reconfigured while playing, please pause stream first\n"); 824 break; 825 } 826 printf("%c - Reconfigure for 48000 Hz.\n", cmd); 827 status = a2dp_source_reconfigure_stream_sampling_frequency(media_tracker.a2dp_cid, 48000); 828 break; 829 830 default: 831 show_usage(); 832 return; 833 } 834 if (status != ERROR_CODE_SUCCESS){ 835 printf("Could not perform command \'%c\', status 0x%2x\n", cmd, status); 836 } 837 } 838 #endif 839 840 841 int btstack_main(int argc, const char * argv[]); 842 int btstack_main(int argc, const char * argv[]){ 843 (void)argc; 844 (void)argv; 845 846 int err = a2dp_source_and_avrcp_services_init(); 847 if (err) return err; 848 // turn on! 849 hci_power_control(HCI_POWER_ON); 850 return 0; 851 } 852 /* EXAMPLE_END */ 853