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 0 74 75 #define NUM_CHANNELS 2 76 #define A2DP_SAMPLE_RATE 44100 77 #define BYTES_PER_AUDIO_SAMPLE (2*NUM_CHANNELS) 78 #define AUDIO_TIMEOUT_MS 10 79 #define TABLE_SIZE_441HZ 100 80 81 #define SBC_STORAGE_SIZE 1030 82 83 typedef enum { 84 STREAM_SINE = 0, 85 STREAM_MOD, 86 STREAM_PTS_TEST 87 } stream_data_source_t; 88 89 typedef struct { 90 uint16_t a2dp_cid; 91 uint8_t local_seid; 92 uint8_t 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", "AVRCP Demo", "monotone", 12345}, 217 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 2, "Nao-deceased", "Decease", "AVRCP Demo", "vivid", 12345}, 218 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, 3, (char *)title, "Decease", "AVRCP 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 avrcp_target_create_sdp_record(sdp_avrcp_target_service_buffer, 0x10001, AVRCP_BROWSING_ENABLED, 1, NULL, NULL); 267 sdp_register_service(sdp_avrcp_target_service_buffer); 268 269 // Set local name with a template Bluetooth address, that will be automatically 270 // replaced with a actual address once it is available, i.e. when BTstack boots 271 // up and starts talking to a Bluetooth module. 272 gap_set_local_name("A2DP Source 00:00:00:00:00:00"); 273 gap_discoverable_control(1); 274 gap_set_class_of_device(0x200408); 275 276 // Register for HCI events. 277 hci_event_callback_registration.callback = &a2dp_source_packet_handler; 278 hci_add_event_handler(&hci_event_callback_registration); 279 280 hxcmod_initialized = hxcmod_init(&mod_context); 281 if (hxcmod_initialized){ 282 hxcmod_setcfg(&mod_context, A2DP_SAMPLE_RATE, 16, 1, 1, 1); 283 hxcmod_load(&mod_context, (void *) &mod_data, mod_len); 284 printf("loaded mod '%s', size %u\n", mod_name, mod_len); 285 } 286 287 // Parse human readable Bluetooth address. 288 sscanf_bd_addr(device_addr_string, device_addr); 289 290 #ifdef HAVE_BTSTACK_STDIN 291 btstack_stdin_setup(stdin_process); 292 #endif 293 return 0; 294 } 295 /* LISTING_END */ 296 297 static void a2dp_demo_send_media_packet(void){ 298 int num_bytes_in_frame = btstack_sbc_encoder_sbc_buffer_length(); 299 int bytes_in_storage = media_tracker.sbc_storage_count; 300 uint8_t num_frames = bytes_in_storage / num_bytes_in_frame; 301 a2dp_source_stream_send_media_payload(media_tracker.a2dp_cid, media_tracker.local_seid, media_tracker.sbc_storage, bytes_in_storage, num_frames, 0); 302 media_tracker.sbc_storage_count = 0; 303 media_tracker.sbc_ready_to_send = 0; 304 } 305 306 static void produce_sine_audio(int16_t * pcm_buffer, int num_samples_to_write){ 307 int count; 308 for (count = 0; count < num_samples_to_write ; count++){ 309 pcm_buffer[count * 2] = sine_int16[sine_phase]; 310 pcm_buffer[count * 2 + 1] = sine_int16[sine_phase]; 311 sine_phase++; 312 if (sine_phase >= TABLE_SIZE_441HZ){ 313 sine_phase -= TABLE_SIZE_441HZ; 314 } 315 } 316 } 317 318 static void produce_mod_audio(int16_t * pcm_buffer, int num_samples_to_write){ 319 hxcmod_fillbuffer(&mod_context, (unsigned short *) &pcm_buffer[0], num_samples_to_write, &trkbuf); 320 } 321 322 static void produce_audio(int16_t * pcm_buffer, int num_samples){ 323 switch (data_source){ 324 case STREAM_SINE: 325 produce_sine_audio(pcm_buffer, num_samples); 326 break; 327 case STREAM_MOD: 328 produce_mod_audio(pcm_buffer, num_samples); 329 break; 330 default: 331 break; 332 } 333 #ifdef VOLUME_REDUCTION 334 int i; 335 for (i=0;i<num_samples*2;i++){ 336 if (pcm_buffer[i] > 0){ 337 pcm_buffer[i] = pcm_buffer[i] >> VOLUME_REDUCTION; 338 } else { 339 pcm_buffer[i] = -((-pcm_buffer[i]) >> VOLUME_REDUCTION); 340 } 341 } 342 #endif 343 } 344 345 static int a2dp_demo_fill_sbc_audio_buffer(a2dp_media_sending_context_t * context){ 346 // perform sbc encodin 347 int total_num_bytes_read = 0; 348 unsigned int num_audio_samples_per_sbc_buffer = btstack_sbc_encoder_num_audio_frames(); 349 while (context->samples_ready >= num_audio_samples_per_sbc_buffer 350 && (context->max_media_payload_size - context->sbc_storage_count) >= btstack_sbc_encoder_sbc_buffer_length()){ 351 352 int16_t pcm_frame[256*NUM_CHANNELS]; 353 354 produce_audio(pcm_frame, num_audio_samples_per_sbc_buffer); 355 btstack_sbc_encoder_process_data(pcm_frame); 356 357 uint16_t sbc_frame_size = btstack_sbc_encoder_sbc_buffer_length(); 358 uint8_t * sbc_frame = btstack_sbc_encoder_sbc_buffer(); 359 360 total_num_bytes_read += num_audio_samples_per_sbc_buffer; 361 memcpy(&context->sbc_storage[context->sbc_storage_count], sbc_frame, sbc_frame_size); 362 context->sbc_storage_count += sbc_frame_size; 363 context->samples_ready -= num_audio_samples_per_sbc_buffer; 364 } 365 return total_num_bytes_read; 366 } 367 368 static void a2dp_demo_audio_timeout_handler(btstack_timer_source_t * timer){ 369 a2dp_media_sending_context_t * context = (a2dp_media_sending_context_t *) btstack_run_loop_get_timer_context(timer); 370 btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS); 371 btstack_run_loop_add_timer(&context->audio_timer); 372 uint32_t now = btstack_run_loop_get_time_ms(); 373 374 uint32_t update_period_ms = AUDIO_TIMEOUT_MS; 375 if (context->time_audio_data_sent > 0){ 376 update_period_ms = now - context->time_audio_data_sent; 377 } 378 379 uint32_t num_samples = (update_period_ms * A2DP_SAMPLE_RATE) / 1000; 380 context->acc_num_missed_samples += (update_period_ms * A2DP_SAMPLE_RATE) % 1000; 381 382 while (context->acc_num_missed_samples >= 1000){ 383 num_samples++; 384 context->acc_num_missed_samples -= 1000; 385 } 386 context->time_audio_data_sent = now; 387 context->samples_ready += num_samples; 388 389 if (context->sbc_ready_to_send) return; 390 391 a2dp_demo_fill_sbc_audio_buffer(context); 392 393 if ((context->sbc_storage_count + btstack_sbc_encoder_sbc_buffer_length()) > context->max_media_payload_size){ 394 // schedule sending 395 context->sbc_ready_to_send = 1; 396 a2dp_source_stream_endpoint_request_can_send_now(context->a2dp_cid, context->local_seid); 397 } 398 } 399 400 static void a2dp_demo_timer_start(a2dp_media_sending_context_t * context){ 401 context->max_media_payload_size = btstack_min(a2dp_max_media_payload_size(context->a2dp_cid, context->local_seid), SBC_STORAGE_SIZE); 402 context->sbc_storage_count = 0; 403 context->sbc_ready_to_send = 0; 404 context->streaming = 1; 405 btstack_run_loop_remove_timer(&context->audio_timer); 406 btstack_run_loop_set_timer_handler(&context->audio_timer, a2dp_demo_audio_timeout_handler); 407 btstack_run_loop_set_timer_context(&context->audio_timer, context); 408 btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS); 409 btstack_run_loop_add_timer(&context->audio_timer); 410 } 411 412 static void a2dp_demo_timer_stop(a2dp_media_sending_context_t * context){ 413 context->time_audio_data_sent = 0; 414 context->acc_num_missed_samples = 0; 415 context->samples_ready = 0; 416 context->streaming = 1; 417 context->sbc_storage_count = 0; 418 context->sbc_ready_to_send = 0; 419 btstack_run_loop_remove_timer(&context->audio_timer); 420 } 421 422 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 423 UNUSED(channel); 424 UNUSED(size); 425 uint8_t status; 426 uint8_t local_seid; 427 bd_addr_t address; 428 uint16_t cid; 429 430 if (packet_type != HCI_EVENT_PACKET) return; 431 432 #ifndef HAVE_BTSTACK_STDIN 433 if (hci_event_packet_get_type(packet) == BTSTACK_EVENT_STATE){ 434 if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return; 435 printf("Create AVDTP Source connection to addr %s.\n", bd_addr_to_str(device_addr)); 436 status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid); 437 if (status != ERROR_CODE_SUCCESS){ 438 printf("Could not perform command, status 0x%2x\n", status); 439 } 440 return; 441 } 442 #endif 443 if (hci_event_packet_get_type(packet) == HCI_EVENT_PIN_CODE_REQUEST) { 444 printf("Pin code request - using '0000'\n"); 445 hci_event_pin_code_request_get_bd_addr(packet, address); 446 gap_pin_code_response(address, "0000"); 447 return; 448 } 449 450 if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return; 451 switch (packet[2]){ 452 case A2DP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED: 453 a2dp_subevent_signaling_connection_established_get_bd_addr(packet, address); 454 cid = a2dp_subevent_signaling_connection_established_get_a2dp_cid(packet); 455 status = a2dp_subevent_signaling_connection_established_get_status(packet); 456 457 if (status != ERROR_CODE_SUCCESS){ 458 printf("A2DP Source: Connection failed, status 0x%02x, cid 0x%02x, a2dp_cid 0x%02x \n", status, cid, media_tracker.a2dp_cid); 459 media_tracker.a2dp_cid = 0; 460 break; 461 } 462 media_tracker.a2dp_cid = cid; 463 printf("A2DP Source: Connected to address %s, a2dp cid 0x%02x.\n", bd_addr_to_str(address), media_tracker.a2dp_cid); 464 break; 465 466 case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{ 467 printf("A2DP Source: Received SBC codec configuration.\n"); 468 sbc_configuration.reconfigure = a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet); 469 sbc_configuration.num_channels = a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet); 470 sbc_configuration.sampling_frequency = a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet); 471 sbc_configuration.channel_mode = a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet); 472 sbc_configuration.block_length = a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet); 473 sbc_configuration.subbands = a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet); 474 sbc_configuration.allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet); 475 sbc_configuration.min_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet); 476 sbc_configuration.max_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet); 477 sbc_configuration.frames_per_buffer = sbc_configuration.subbands * sbc_configuration.block_length; 478 479 btstack_sbc_encoder_init(&sbc_encoder_state, SBC_MODE_STANDARD, 480 sbc_configuration.block_length, sbc_configuration.subbands, 481 sbc_configuration.allocation_method, sbc_configuration.sampling_frequency, 482 sbc_configuration.max_bitpool_value, 483 sbc_configuration.channel_mode); 484 485 // status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid); 486 // if (status != ERROR_CODE_SUCCESS){ 487 // printf("Could not perform command, status 0x%2x\n", status); 488 // } 489 break; 490 } 491 492 case A2DP_SUBEVENT_STREAM_ESTABLISHED: 493 a2dp_subevent_stream_established_get_bd_addr(packet, address); 494 status = a2dp_subevent_stream_established_get_status(packet); 495 if (status){ 496 printf("A2DP Source: Stream failed, status 0x%02x.\n", status); 497 break; 498 } 499 local_seid = a2dp_subevent_stream_established_get_local_seid(packet); 500 if (local_seid != media_tracker.local_seid){ 501 printf("A2DP Source: Stream failed, wrong local seid %d, expected %d.\n", local_seid, media_tracker.local_seid); 502 break; 503 } 504 printf("A2DP Source: Stream established, address %s, a2dp cid 0x%02x, local seid %d, remote seid %d.\n", bd_addr_to_str(address), 505 media_tracker.a2dp_cid, media_tracker.local_seid, a2dp_subevent_stream_established_get_remote_seid(packet)); 506 printf("A2DP Source: Start playing mod, a2dp cid 0x%02x.\n", media_tracker.a2dp_cid); 507 media_tracker.stream_opened = 1; 508 data_source = STREAM_MOD; 509 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 510 break; 511 512 case A2DP_SUBEVENT_STREAM_STARTED: 513 play_info.status = AVRCP_PLAYBACK_STATUS_PLAYING; 514 if (media_tracker.avrcp_cid){ 515 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 516 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PLAYING); 517 } 518 a2dp_demo_timer_start(&media_tracker); 519 printf("A2DP Source: Stream started.\n"); 520 break; 521 522 case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW: 523 a2dp_demo_send_media_packet(); 524 break; 525 526 case A2DP_SUBEVENT_STREAM_SUSPENDED: 527 play_info.status = AVRCP_PLAYBACK_STATUS_PAUSED; 528 if (media_tracker.avrcp_cid){ 529 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PAUSED); 530 } 531 printf("A2DP Source: Stream paused.\n"); 532 a2dp_demo_timer_stop(&media_tracker); 533 break; 534 535 case A2DP_SUBEVENT_STREAM_RELEASED: 536 play_info.status = AVRCP_PLAYBACK_STATUS_STOPPED; 537 cid = a2dp_subevent_stream_released_get_a2dp_cid(packet); 538 if (cid == media_tracker.a2dp_cid) { 539 media_tracker.stream_opened = 0; 540 printf("A2DP Source: Stream released.\n"); 541 } 542 if (media_tracker.avrcp_cid){ 543 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); 544 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_STOPPED); 545 } 546 a2dp_demo_timer_stop(&media_tracker); 547 break; 548 case A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED: 549 cid = a2dp_subevent_signaling_connection_released_get_a2dp_cid(packet); 550 if (cid == media_tracker.a2dp_cid) { 551 media_tracker.avrcp_cid = 0; 552 media_tracker.a2dp_cid = 0; 553 printf("A2DP Source: Signaling released.\n\n"); 554 } 555 break; 556 default: 557 break; 558 } 559 } 560 561 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 562 UNUSED(channel); 563 UNUSED(size); 564 bd_addr_t event_addr; 565 uint16_t local_cid; 566 uint8_t status = ERROR_CODE_SUCCESS; 567 568 if (packet_type != HCI_EVENT_PACKET) return; 569 if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; 570 571 switch (packet[2]){ 572 case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: { 573 local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet); 574 // if (avrcp_cid != 0 && avrcp_cid != local_cid) { 575 // printf("AVRCP Target: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_cid, local_cid); 576 // return; 577 // } 578 // if (avrcp_cid != local_cid) break; 579 580 status = avrcp_subevent_connection_established_get_status(packet); 581 if (status != ERROR_CODE_SUCCESS){ 582 printf("AVRCP Target: Connection failed, status 0x%02x\n", status); 583 return; 584 } 585 media_tracker.avrcp_cid = local_cid; 586 avrcp_subevent_connection_established_get_bd_addr(packet, event_addr); 587 printf("AVRCP Target: Connected to %s, avrcp_cid 0x%02x\n", bd_addr_to_str(event_addr), local_cid); 588 589 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); 590 avrcp_target_set_unit_info(media_tracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, company_id); 591 avrcp_target_set_subunit_info(media_tracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, (uint8_t *)subunit_info, sizeof(subunit_info)); 592 return; 593 } 594 595 case AVRCP_SUBEVENT_EVENT_IDS_QUERY: 596 status = avrcp_target_supported_events(media_tracker.avrcp_cid, events_num, events, sizeof(events)); 597 break; 598 case AVRCP_SUBEVENT_COMPANY_IDS_QUERY: 599 status = avrcp_target_supported_companies(media_tracker.avrcp_cid, companies_num, companies, sizeof(companies)); 600 break; 601 case AVRCP_SUBEVENT_PLAY_STATUS_QUERY: 602 status = avrcp_target_play_status(media_tracker.avrcp_cid, play_info.song_length_ms, play_info.song_position_ms, play_info.status); 603 break; 604 // case AVRCP_SUBEVENT_NOW_PLAYING_INFO_QUERY: 605 // status = avrcp_target_now_playing_info(avrcp_cid); 606 // break; 607 case AVRCP_SUBEVENT_OPERATION:{ 608 avrcp_operation_id_t operation_id = avrcp_subevent_operation_get_operation_id(packet); 609 switch (operation_id){ 610 case AVRCP_OPERATION_ID_PLAY: 611 printf("AVRCP Target: PLAY\n"); 612 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 613 break; 614 case AVRCP_OPERATION_ID_PAUSE: 615 printf("AVRCP Target: PAUSE\n"); 616 status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 617 break; 618 case AVRCP_OPERATION_ID_STOP: 619 printf("AVRCP Target: STOP\n"); 620 status = a2dp_source_disconnect(media_tracker.a2dp_cid); 621 break; 622 default: 623 printf("AVRCP Target: operation 0x%2x is not handled\n", operation_id); 624 return; 625 } 626 break; 627 } 628 case AVRCP_SUBEVENT_CONNECTION_RELEASED: 629 printf("AVRCP Target: Disconnected, avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); 630 media_tracker.avrcp_cid = 0; 631 return; 632 default: 633 break; 634 } 635 636 if (status != ERROR_CODE_SUCCESS){ 637 printf("Responding to event 0x%02x failed with status 0x%02x\n", packet[2], status); 638 } 639 } 640 641 #ifdef HAVE_BTSTACK_STDIN 642 static void show_usage(void){ 643 bd_addr_t iut_address; 644 gap_local_bd_addr(iut_address); 645 printf("\n--- Bluetooth A2DP Source/AVRCP Target Demo %s ---\n", bd_addr_to_str(iut_address)); 646 printf("b - AVDTP Source create connection to addr %s\n", device_addr_string); 647 printf("B - AVDTP Source disconnect\n"); 648 printf("c - AVRCP Target create connection to addr %s\n", device_addr_string); 649 printf("C - AVRCP Target disconnect\n"); 650 651 printf("x - start streaming sine\n"); 652 if (hxcmod_initialized){ 653 printf("z - start streaming '%s'\n", mod_name); 654 } 655 printf("p - pause streaming\n"); 656 657 printf("\n--- Bluetooth AVRCP Target Commands %s ---\n", bd_addr_to_str(iut_address)); 658 printf("---\n"); 659 } 660 661 static void stdin_process(char cmd){ 662 uint8_t status = ERROR_CODE_SUCCESS; 663 switch (cmd){ 664 case 'b': 665 status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid); 666 printf("%c - Create AVDTP Source connection to addr %s, cid 0x%02x.\n", cmd, bd_addr_to_str(device_addr), media_tracker.a2dp_cid); 667 break; 668 case 'B': 669 printf("%c - AVDTP Source Disconnect from cid 0x%2x\n", cmd, media_tracker.a2dp_cid); 670 status = a2dp_source_disconnect(media_tracker.a2dp_cid); 671 break; 672 case 'c': 673 printf("%c - Create AVRCP Target connection to addr %s.\n", cmd, bd_addr_to_str(device_addr)); 674 status = avrcp_target_connect(device_addr, &media_tracker.avrcp_cid); 675 break; 676 case 'C': 677 printf("%c - AVRCP Target disconnect\n", cmd); 678 status = avrcp_target_disconnect(media_tracker.avrcp_cid); 679 break; 680 681 case '\n': 682 case '\r': 683 break; 684 685 case 'x': 686 if (media_tracker.avrcp_cid){ 687 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 688 } 689 printf("%c - Play sine.\n", cmd); 690 data_source = STREAM_SINE; 691 if (!media_tracker.stream_opened) break; 692 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 693 break; 694 case 'z': 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 mod.\n", cmd); 699 data_source = STREAM_MOD; 700 if (!media_tracker.stream_opened) break; 701 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 702 break; 703 704 case 'p': 705 if (!media_tracker.stream_opened) break; 706 printf("%c - Pause stream.\n", cmd); 707 status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 708 break; 709 710 default: 711 show_usage(); 712 return; 713 } 714 if (status != ERROR_CODE_SUCCESS){ 715 printf("Could not perform command \'%c\', status 0x%2x\n", cmd, status); 716 } 717 } 718 #endif 719 720 721 int btstack_main(int argc, const char * argv[]); 722 int btstack_main(int argc, const char * argv[]){ 723 (void)argc; 724 (void)argv; 725 726 int err = a2dp_source_and_avrcp_services_init(); 727 if (err) return err; 728 // turn on! 729 hci_power_control(HCI_POWER_ON); 730 return 0; 731 } 732 /* EXAMPLE_END */ 733