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 uint8_t sdp_avrcp_controller_service_buffer[200]; 156 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 stream_data_source_t data_source; 164 165 static int sine_phase; 166 167 static int hxcmod_initialized; 168 static modcontext mod_context; 169 static tracker_buffer_state trkbuf; 170 171 static uint16_t avrcp_controller_cid = 0; 172 173 /* AVRCP Target context START */ 174 static const uint8_t subunit_info[] = { 175 0,0,0,0, 176 1,1,1,1, 177 2,2,2,2, 178 3,3,3,3, 179 4,4,4,4, 180 5,5,5,5, 181 6,6,6,6, 182 7,7,7,7 183 }; 184 185 static uint32_t company_id = 0x112233; 186 static uint8_t companies_num = 1; 187 static uint8_t companies[] = { 188 0x00, 0x19, 0x58 //BT SIG registered CompanyID 189 }; 190 191 static uint8_t events_num = 13; 192 static uint8_t events[] = { 193 AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED, 194 AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED, 195 AVRCP_NOTIFICATION_EVENT_TRACK_REACHED_END, 196 AVRCP_NOTIFICATION_EVENT_TRACK_REACHED_START, 197 AVRCP_NOTIFICATION_EVENT_PLAYBACK_POS_CHANGED, 198 AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED, 199 AVRCP_NOTIFICATION_EVENT_SYSTEM_STATUS_CHANGED, 200 AVRCP_NOTIFICATION_EVENT_PLAYER_APPLICATION_SETTING_CHANGED, 201 AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED, 202 AVRCP_NOTIFICATION_EVENT_AVAILABLE_PLAYERS_CHANGED, 203 AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED, 204 AVRCP_NOTIFICATION_EVENT_UIDS_CHANGED, 205 AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED 206 }; 207 208 typedef struct { 209 uint8_t track_id[8]; 210 uint32_t song_length_ms; 211 avrcp_playback_status_t status; 212 uint32_t song_position_ms; // 0xFFFFFFFF if not supported 213 } avrcp_play_status_info_t; 214 215 // python -c "print('a'*512)" 216 static const char title[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 217 218 avrcp_track_t tracks[] = { 219 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, 1, "Sine", "Generated", "A2DP Source Demo", "monotone", 12345}, 220 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 2, "Nao-deceased", "Decease", "A2DP Source Demo", "vivid", 12345}, 221 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, 3, (char *)title, "Decease", "A2DP Source Demo", "vivid", 12345}, 222 }; 223 int current_track_index; 224 avrcp_play_status_info_t play_info; 225 226 /* AVRCP Target context END */ 227 228 /* @section Main Application Setup 229 * 230 * @text The Listing MainConfiguration shows how to setup AD2P Source and AVRCP Target services. 231 */ 232 233 /* LISTING_START(MainConfiguration): Setup Audio Source and AVRCP Target services */ 234 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size); 235 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 236 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 237 #ifdef HAVE_BTSTACK_STDIN 238 static void stdin_process(char cmd); 239 #endif 240 241 static int a2dp_source_and_avrcp_services_init(void){ 242 243 l2cap_init(); 244 // Initialize A2DP Source. 245 a2dp_source_init(); 246 a2dp_source_register_packet_handler(&a2dp_source_packet_handler); 247 248 // Create stream endpoint. 249 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)); 250 if (!local_stream_endpoint){ 251 printf("A2DP Source: not enough memory to create local stream endpoint\n"); 252 return 1; 253 } 254 media_tracker.local_seid = avdtp_local_seid(local_stream_endpoint); 255 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_STREAM_ESTABLISHED: 506 a2dp_subevent_stream_established_get_bd_addr(packet, address); 507 status = a2dp_subevent_stream_established_get_status(packet); 508 if (status){ 509 printf("A2DP Source: Stream failed, status 0x%02x.\n", status); 510 break; 511 } 512 local_seid = a2dp_subevent_stream_established_get_local_seid(packet); 513 if (local_seid != media_tracker.local_seid){ 514 printf("A2DP Source: Stream failed, wrong local seid %d, expected %d.\n", local_seid, media_tracker.local_seid); 515 break; 516 } 517 printf("A2DP Source: Stream established, address %s, a2dp cid 0x%02x, local seid %d, remote seid %d.\n", bd_addr_to_str(address), 518 media_tracker.a2dp_cid, media_tracker.local_seid, a2dp_subevent_stream_established_get_remote_seid(packet)); 519 media_tracker.stream_opened = 1; 520 data_source = STREAM_MOD; 521 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 522 break; 523 524 case A2DP_SUBEVENT_STREAM_RECONFIGURED: 525 status = a2dp_subevent_stream_reconfigured_get_status(packet); 526 printf("A2DP Source: Reconfigured, status 0x%02x\n", status); 527 break; 528 529 case A2DP_SUBEVENT_STREAM_STARTED: 530 play_info.status = AVRCP_PLAYBACK_STATUS_PLAYING; 531 if (media_tracker.avrcp_cid){ 532 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 533 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PLAYING); 534 } 535 a2dp_demo_timer_start(&media_tracker); 536 printf("A2DP Source: Stream started.\n"); 537 break; 538 539 case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW: 540 a2dp_demo_send_media_packet(); 541 break; 542 543 case A2DP_SUBEVENT_STREAM_SUSPENDED: 544 play_info.status = AVRCP_PLAYBACK_STATUS_PAUSED; 545 if (media_tracker.avrcp_cid){ 546 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PAUSED); 547 } 548 printf("A2DP Source: Stream paused.\n"); 549 a2dp_demo_timer_stop(&media_tracker); 550 break; 551 552 case A2DP_SUBEVENT_STREAM_RELEASED: 553 play_info.status = AVRCP_PLAYBACK_STATUS_STOPPED; 554 cid = a2dp_subevent_stream_released_get_a2dp_cid(packet); 555 if (cid == media_tracker.a2dp_cid) { 556 media_tracker.stream_opened = 0; 557 printf("A2DP Source: Stream released.\n"); 558 } 559 if (media_tracker.avrcp_cid){ 560 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); 561 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_STOPPED); 562 } 563 a2dp_demo_timer_stop(&media_tracker); 564 break; 565 case A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED: 566 cid = a2dp_subevent_signaling_connection_released_get_a2dp_cid(packet); 567 if (cid == media_tracker.a2dp_cid) { 568 media_tracker.avrcp_cid = 0; 569 media_tracker.a2dp_cid = 0; 570 printf("A2DP Source: Signaling released.\n\n"); 571 } 572 break; 573 default: 574 break; 575 } 576 } 577 578 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 579 UNUSED(channel); 580 UNUSED(size); 581 bd_addr_t event_addr; 582 uint16_t local_cid; 583 uint8_t status = ERROR_CODE_SUCCESS; 584 585 if (packet_type != HCI_EVENT_PACKET) return; 586 if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; 587 588 switch (packet[2]){ 589 case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: { 590 local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet); 591 // if (avrcp_cid != 0 && avrcp_cid != local_cid) { 592 // printf("AVRCP Target: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_cid, local_cid); 593 // return; 594 // } 595 // if (avrcp_cid != local_cid) break; 596 597 status = avrcp_subevent_connection_established_get_status(packet); 598 if (status != ERROR_CODE_SUCCESS){ 599 printf("AVRCP Target: Connection failed, status 0x%02x\n", status); 600 return; 601 } 602 media_tracker.avrcp_cid = local_cid; 603 avrcp_subevent_connection_established_get_bd_addr(packet, event_addr); 604 printf("AVRCP Target: Connected to %s, avrcp_cid 0x%02x\n", bd_addr_to_str(event_addr), local_cid); 605 606 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); 607 avrcp_target_set_unit_info(media_tracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, company_id); 608 avrcp_target_set_subunit_info(media_tracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, (uint8_t *)subunit_info, sizeof(subunit_info)); 609 return; 610 } 611 case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED: 612 printf("AVRCP Target: new volume %d\n", avrcp_subevent_notification_volume_changed_get_absolute_volume(packet)); 613 break; 614 case AVRCP_SUBEVENT_EVENT_IDS_QUERY: 615 status = avrcp_target_supported_events(media_tracker.avrcp_cid, events_num, events, sizeof(events)); 616 break; 617 case AVRCP_SUBEVENT_COMPANY_IDS_QUERY: 618 status = avrcp_target_supported_companies(media_tracker.avrcp_cid, companies_num, companies, sizeof(companies)); 619 break; 620 case AVRCP_SUBEVENT_PLAY_STATUS_QUERY: 621 status = avrcp_target_play_status(media_tracker.avrcp_cid, play_info.song_length_ms, play_info.song_position_ms, play_info.status); 622 break; 623 // case AVRCP_SUBEVENT_NOW_PLAYING_INFO_QUERY: 624 // status = avrcp_target_now_playing_info(avrcp_cid); 625 // break; 626 case AVRCP_SUBEVENT_OPERATION:{ 627 avrcp_operation_id_t operation_id = avrcp_subevent_operation_get_operation_id(packet); 628 switch (operation_id){ 629 case AVRCP_OPERATION_ID_PLAY: 630 printf("AVRCP Target: PLAY\n"); 631 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 632 break; 633 case AVRCP_OPERATION_ID_PAUSE: 634 printf("AVRCP Target: PAUSE\n"); 635 status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 636 break; 637 case AVRCP_OPERATION_ID_STOP: 638 printf("AVRCP Target: STOP\n"); 639 status = a2dp_source_disconnect(media_tracker.a2dp_cid); 640 break; 641 default: 642 printf("AVRCP Target: operation 0x%2x is not handled\n", operation_id); 643 return; 644 } 645 break; 646 } 647 case AVRCP_SUBEVENT_CONNECTION_RELEASED: 648 printf("AVRCP Target: Disconnected, avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); 649 media_tracker.avrcp_cid = 0; 650 return; 651 default: 652 break; 653 } 654 655 if (status != ERROR_CODE_SUCCESS){ 656 printf("Responding to event 0x%02x failed with status 0x%02x\n", packet[2], status); 657 } 658 } 659 660 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 661 UNUSED(channel); 662 UNUSED(size); 663 uint16_t local_cid; 664 uint8_t status = 0xFF; 665 bd_addr_t adress; 666 667 if (packet_type != HCI_EVENT_PACKET) return; 668 if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; 669 switch (packet[2]){ 670 case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: { 671 local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet); 672 if (avrcp_controller_cid != 0 && avrcp_controller_cid != local_cid) { 673 printf("AVRCP Controller: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_controller_cid, local_cid); 674 return; 675 } 676 677 status = avrcp_subevent_connection_established_get_status(packet); 678 if (status != ERROR_CODE_SUCCESS){ 679 printf("AVRCP Controller: Connection failed: status 0x%02x\n", status); 680 avrcp_controller_cid = 0; 681 return; 682 } 683 684 avrcp_controller_cid = local_cid; 685 avrcp_subevent_connection_established_get_bd_addr(packet, adress); 686 printf("AVRCP Controller: Channel successfully opened: %s, avrcp_controller_cid 0x%02x\n", bd_addr_to_str(adress), avrcp_controller_cid); 687 688 // automatically enable notifications 689 avrcp_controller_enable_notification(avrcp_controller_cid, AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED); 690 return; 691 } 692 case AVRCP_SUBEVENT_CONNECTION_RELEASED: 693 printf("AVRCP Controller: Channel released: avrcp_controller_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); 694 avrcp_controller_cid = 0; 695 return; 696 default: 697 break; 698 } 699 700 status = packet[5]; 701 if (!avrcp_controller_cid) return; 702 703 // ignore INTERIM status 704 if (status == AVRCP_CTYPE_RESPONSE_INTERIM) return; 705 706 switch (packet[2]){ 707 case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED:{ 708 int volume_percentage = avrcp_subevent_notification_volume_changed_get_absolute_volume(packet) * 100 / 127; 709 printf("AVRCP Controller: notification absolute volume changed %d %%\n", volume_percentage); 710 return; 711 } 712 default: 713 break; 714 } 715 } 716 717 #ifdef HAVE_BTSTACK_STDIN 718 static void show_usage(void){ 719 bd_addr_t iut_address; 720 gap_local_bd_addr(iut_address); 721 printf("\n--- Bluetooth A2DP Source/AVRCP Target Demo %s ---\n", bd_addr_to_str(iut_address)); 722 printf("b - A2DP Source create connection to addr %s\n", device_addr_string); 723 printf("B - A2DP Source disconnect\n"); 724 printf("c - AVRCP Target create connection to addr %s\n", device_addr_string); 725 printf("C - AVRCP Target disconnect\n"); 726 727 printf("x - start streaming sine\n"); 728 if (hxcmod_initialized){ 729 printf("z - start streaming '%s'\n", mod_name); 730 } 731 printf("p - pause streaming\n"); 732 printf("w - reconfigure stream for 44100 Hz\n"); 733 printf("e - reconfigure stream for 48000 Hz\n"); 734 printf("t - volume up\n"); 735 printf("T - volume down\n"); 736 printf("v - absolute volume of 50 percent\n"); 737 738 printf("\n--- Bluetooth AVRCP Target Commands %s ---\n", bd_addr_to_str(iut_address)); 739 printf("---\n"); 740 } 741 742 static void stdin_process(char cmd){ 743 uint8_t status = ERROR_CODE_SUCCESS; 744 switch (cmd){ 745 case 'b': 746 status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid); 747 printf("%c - Create A2DP Source connection to addr %s, cid 0x%02x.\n", cmd, bd_addr_to_str(device_addr), media_tracker.a2dp_cid); 748 break; 749 case 'B': 750 printf("%c - A2DP Source Disconnect from cid 0x%2x\n", cmd, media_tracker.a2dp_cid); 751 status = a2dp_source_disconnect(media_tracker.a2dp_cid); 752 break; 753 case 'c': 754 printf("%c - Create AVRCP Target connection to addr %s.\n", cmd, bd_addr_to_str(device_addr)); 755 status = avrcp_target_connect(device_addr, &media_tracker.avrcp_cid); 756 break; 757 case 'C': 758 printf("%c - AVRCP Target disconnect\n", cmd); 759 status = avrcp_target_disconnect(media_tracker.avrcp_cid); 760 break; 761 762 case '\n': 763 case '\r': 764 break; 765 766 case 't': 767 printf(" - volume up\n"); 768 status = avrcp_controller_volume_up(avrcp_controller_cid); 769 break; 770 case 'T': 771 printf(" - volume down\n"); 772 status = avrcp_controller_volume_down(avrcp_controller_cid); 773 break; 774 case 'v': 775 printf(" - absolute volume of 50%% (64)\n"); 776 status = avrcp_controller_set_absolute_volume(avrcp_controller_cid, 64); 777 break; 778 779 case 'x': 780 if (media_tracker.avrcp_cid){ 781 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 782 } 783 printf("%c - Play sine.\n", cmd); 784 data_source = STREAM_SINE; 785 if (!media_tracker.stream_opened) break; 786 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 787 break; 788 case 'z': 789 if (media_tracker.avrcp_cid){ 790 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 791 } 792 printf("%c - Play mod.\n", cmd); 793 data_source = STREAM_MOD; 794 if (!media_tracker.stream_opened) break; 795 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 796 break; 797 798 case 'p': 799 if (!media_tracker.stream_opened) break; 800 printf("%c - Pause stream.\n", cmd); 801 status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 802 break; 803 804 case 'w': 805 if (!media_tracker.stream_opened) break; 806 if (play_info.status == AVRCP_PLAYBACK_STATUS_PLAYING){ 807 printf("Stream cannot be reconfigured while playing, please pause stream first\n"); 808 break; 809 } 810 printf("%c - Reconfigure for 44100 Hz.\n", cmd); 811 status = a2dp_source_reconfigure_stream_sampling_frequency(media_tracker.a2dp_cid, 44100); 812 break; 813 814 case 'e': 815 if (!media_tracker.stream_opened) break; 816 if (play_info.status == AVRCP_PLAYBACK_STATUS_PLAYING){ 817 printf("Stream cannot be reconfigured while playing, please pause stream first\n"); 818 break; 819 } 820 printf("%c - Reconfigure for 48000 Hz.\n", cmd); 821 status = a2dp_source_reconfigure_stream_sampling_frequency(media_tracker.a2dp_cid, 48000); 822 break; 823 824 default: 825 show_usage(); 826 return; 827 } 828 if (status != ERROR_CODE_SUCCESS){ 829 printf("Could not perform command \'%c\', status 0x%2x\n", cmd, status); 830 } 831 } 832 #endif 833 834 835 int btstack_main(int argc, const char * argv[]); 836 int btstack_main(int argc, const char * argv[]){ 837 (void)argc; 838 (void)argv; 839 840 int err = a2dp_source_and_avrcp_services_init(); 841 if (err) return err; 842 // turn on! 843 hci_power_control(HCI_POWER_ON); 844 return 0; 845 } 846 /* EXAMPLE_END */ 847