1 /* 2 * Copyright (C) 2016 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 #define __BTSTACK_FILE__ "a2dp_source_demo.c" 39 40 /* 41 * a2dp_source_demo.c 42 */ 43 44 // ***************************************************************************** 45 /* EXAMPLE_START(a2dp_source_demo): Serve audio stream and handle remote playback control and queries. 46 * 47 * @text This A2DP Source example demonstrates how to send an audio data stream 48 * to a remote A2DP Sink device and how to switch between two audio data sources. 49 * In addition, the AVRCP Target is used to answer queries on currently played media, 50 * as well as to handle remote playback control, i.e. play, stop, repeat, etc. 51 * 52 * @test To test with a remote device, e.g. a Bluetooth speaker, 53 * set the device_addr_string to the Bluetooth address of your 54 * remote device in the code, and use the UI to connect and start playback. 55 * Tap SPACE on the console to show the available commands. 56 */ 57 // ***************************************************************************** 58 59 60 #include <stdint.h> 61 #include <stdio.h> 62 #include <stdlib.h> 63 #include <string.h> 64 65 #include "btstack.h" 66 67 #include "classic/btstack_sbc.h" 68 69 #include "hxcmod.h" 70 #include "mods/mod.h" 71 72 73 #define AVRCP_BROWSING_ENABLED 0 74 75 #define NUM_CHANNELS 2 76 #define A2DP_SAMPLE_RATE 44100 77 #define BYTES_PER_AUDIO_SAMPLE (2*NUM_CHANNELS) 78 #define AUDIO_TIMEOUT_MS 10 79 #define TABLE_SIZE_441HZ 100 80 81 #define SBC_STORAGE_SIZE 1030 82 83 typedef enum { 84 STREAM_SINE = 0, 85 STREAM_MOD, 86 STREAM_PTS_TEST 87 } stream_data_source_t; 88 89 typedef struct { 90 uint16_t a2dp_cid; 91 uint8_t local_seid; 92 uint8_t connected; 93 94 uint32_t time_audio_data_sent; // ms 95 uint32_t acc_num_missed_samples; 96 uint32_t samples_ready; 97 btstack_timer_source_t audio_timer; 98 uint8_t streaming; 99 int max_media_payload_size; 100 101 uint8_t sbc_storage[SBC_STORAGE_SIZE]; 102 uint16_t sbc_storage_count; 103 uint8_t sbc_ready_to_send; 104 } a2dp_media_sending_context_t; 105 106 static uint8_t media_sbc_codec_capabilities[] = { 107 (AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO, 108 0xFF,//(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS, 109 2, 53 110 }; 111 112 static const int16_t sine_int16[] = { 113 0, 2057, 4107, 6140, 8149, 10126, 12062, 13952, 15786, 17557, 114 19260, 20886, 22431, 23886, 25247, 26509, 27666, 28714, 29648, 30466, 115 31163, 31738, 32187, 32509, 32702, 32767, 32702, 32509, 32187, 31738, 116 31163, 30466, 29648, 28714, 27666, 26509, 25247, 23886, 22431, 20886, 117 19260, 17557, 15786, 13952, 12062, 10126, 8149, 6140, 4107, 2057, 118 0, -2057, -4107, -6140, -8149, -10126, -12062, -13952, -15786, -17557, 119 -19260, -20886, -22431, -23886, -25247, -26509, -27666, -28714, -29648, -30466, 120 -31163, -31738, -32187, -32509, -32702, -32767, -32702, -32509, -32187, -31738, 121 -31163, -30466, -29648, -28714, -27666, -26509, -25247, -23886, -22431, -20886, 122 -19260, -17557, -15786, -13952, -12062, -10126, -8149, -6140, -4107, -2057, 123 }; 124 125 typedef struct { 126 int reconfigure; 127 int num_channels; 128 int sampling_frequency; 129 int channel_mode; 130 int block_length; 131 int subbands; 132 int allocation_method; 133 int min_bitpool_value; 134 int max_bitpool_value; 135 int frames_per_buffer; 136 } avdtp_media_codec_configuration_sbc_t; 137 138 static btstack_packet_callback_registration_t hci_event_callback_registration; 139 140 #ifdef HAVE_BTSTACK_STDIN 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 #endif 150 151 static bd_addr_t device_addr; 152 static uint8_t sdp_a2dp_source_service_buffer[150]; 153 static uint8_t sdp_avrcp_target_service_buffer[200]; 154 static avdtp_media_codec_configuration_sbc_t sbc_configuration; 155 static btstack_sbc_encoder_state_t sbc_encoder_state; 156 157 static uint8_t media_sbc_codec_configuration[4]; 158 static a2dp_media_sending_context_t media_tracker; 159 160 static uint16_t avrcp_cid; 161 static uint8_t avrcp_connected; 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 172 /* AVRCP Target context START */ 173 static const uint8_t subunit_info[] = { 174 0,0,0,0, 175 1,1,1,1, 176 2,2,2,2, 177 3,3,3,3, 178 4,4,4,4, 179 5,5,5,5, 180 6,6,6,6, 181 7,7,7,7 182 }; 183 184 static uint32_t company_id = 0x112233; 185 static uint8_t companies_num = 1; 186 static uint8_t companies[] = { 187 0x00, 0x19, 0x58 //BT SIG registered CompanyID 188 }; 189 190 static uint8_t events_num = 13; 191 static uint8_t events[] = { 192 AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED, 193 AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED, 194 AVRCP_NOTIFICATION_EVENT_TRACK_REACHED_END, 195 AVRCP_NOTIFICATION_EVENT_TRACK_REACHED_START, 196 AVRCP_NOTIFICATION_EVENT_PLAYBACK_POS_CHANGED, 197 AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED, 198 AVRCP_NOTIFICATION_EVENT_SYSTEM_STATUS_CHANGED, 199 AVRCP_NOTIFICATION_EVENT_PLAYER_APPLICATION_SETTING_CHANGED, 200 AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED, 201 AVRCP_NOTIFICATION_EVENT_AVAILABLE_PLAYERS_CHANGED, 202 AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED, 203 AVRCP_NOTIFICATION_EVENT_UIDS_CHANGED, 204 AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED 205 }; 206 207 typedef struct { 208 uint8_t track_id[8]; 209 uint32_t song_length_ms; 210 avrcp_playback_status_t status; 211 uint32_t song_position_ms; // 0xFFFFFFFF if not supported 212 } avrcp_play_status_info_t; 213 214 // python -c "print('a'*512)" 215 static const char title[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 216 217 avrcp_track_t tracks[] = { 218 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, 1, "Sine", "Generated", "AVRCP Demo", "monotone", 12345}, 219 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 2, "Nao-deceased", "Decease", "AVRCP Demo", "vivid", 12345}, 220 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, 3, (char *)title, "Decease", "AVRCP Demo", "vivid", 12345}, 221 }; 222 int current_track_index; 223 avrcp_play_status_info_t play_info; 224 225 /* AVRCP Target context END */ 226 227 /* @section Main Application Setup 228 * 229 * @text The Listing MainConfiguration shows how to setup AD2P Source and AVRCP Target services. 230 */ 231 232 /* LISTING_START(MainConfiguration): Setup Audio Source and AVRCP Target services */ 233 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size); 234 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 235 #ifdef HAVE_BTSTACK_STDIN 236 static void stdin_process(char cmd); 237 #endif 238 239 static int a2dp_source_and_avrcp_services_init(void){ 240 // Register for HCI events. 241 hci_event_callback_registration.callback = &a2dp_source_packet_handler; 242 hci_add_event_handler(&hci_event_callback_registration); 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 demo: 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 257 // Initialize AVRCP Target. 258 avrcp_target_init(); 259 avrcp_target_register_packet_handler(&avrcp_target_packet_handler); 260 261 // Initialize SDP, 262 sdp_init(); 263 264 // Create A2DP source service record and register it with SDP. 265 memset(sdp_a2dp_source_service_buffer, 0, sizeof(sdp_a2dp_source_service_buffer)); 266 a2dp_source_create_sdp_record(sdp_a2dp_source_service_buffer, 0x10002, 1, NULL, NULL); 267 sdp_register_service(sdp_a2dp_source_service_buffer); 268 269 // Create AVRCP target service record and register it with SDP. 270 memset(sdp_avrcp_target_service_buffer, 0, sizeof(sdp_avrcp_target_service_buffer)); 271 avrcp_target_create_sdp_record(sdp_avrcp_target_service_buffer, 0x10001, AVRCP_BROWSING_ENABLED, 1, NULL, NULL); 272 sdp_register_service(sdp_avrcp_target_service_buffer); 273 274 // Set local name with a template Bluetooth address, that will be automatically 275 // replaced with a actual address once it is available, i.e. when BTstack boots 276 // up and starts talking to a Bluetooth module. 277 gap_set_local_name("A2DP Source Demo 00:00:00:00:00:00"); 278 gap_discoverable_control(1); 279 gap_set_class_of_device(0x200408); 280 281 hxcmod_initialized = hxcmod_init(&mod_context); 282 if (hxcmod_initialized){ 283 hxcmod_setcfg(&mod_context, A2DP_SAMPLE_RATE, 16, 1, 1, 1); 284 hxcmod_load(&mod_context, (void *) &mod_data, mod_len); 285 printf("loaded mod '%s', size %u\n", mod_name, mod_len); 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 } 334 335 static int a2dp_demo_fill_sbc_audio_buffer(a2dp_media_sending_context_t * context){ 336 // perform sbc encodin 337 int total_num_bytes_read = 0; 338 unsigned int num_audio_samples_per_sbc_buffer = btstack_sbc_encoder_num_audio_frames(); 339 while (context->samples_ready >= num_audio_samples_per_sbc_buffer 340 && (context->max_media_payload_size - context->sbc_storage_count) >= btstack_sbc_encoder_sbc_buffer_length()){ 341 342 int16_t pcm_frame[256*NUM_CHANNELS]; 343 344 produce_audio(pcm_frame, num_audio_samples_per_sbc_buffer); 345 btstack_sbc_encoder_process_data(pcm_frame); 346 347 uint16_t sbc_frame_size = btstack_sbc_encoder_sbc_buffer_length(); 348 uint8_t * sbc_frame = btstack_sbc_encoder_sbc_buffer(); 349 350 total_num_bytes_read += num_audio_samples_per_sbc_buffer; 351 memcpy(&context->sbc_storage[context->sbc_storage_count], sbc_frame, sbc_frame_size); 352 context->sbc_storage_count += sbc_frame_size; 353 context->samples_ready -= num_audio_samples_per_sbc_buffer; 354 } 355 return total_num_bytes_read; 356 } 357 358 static void a2dp_demo_audio_timeout_handler(btstack_timer_source_t * timer){ 359 a2dp_media_sending_context_t * context = (a2dp_media_sending_context_t *) btstack_run_loop_get_timer_context(timer); 360 btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS); 361 btstack_run_loop_add_timer(&context->audio_timer); 362 uint32_t now = btstack_run_loop_get_time_ms(); 363 364 uint32_t update_period_ms = AUDIO_TIMEOUT_MS; 365 if (context->time_audio_data_sent > 0){ 366 update_period_ms = now - context->time_audio_data_sent; 367 } 368 369 uint32_t num_samples = (update_period_ms * A2DP_SAMPLE_RATE) / 1000; 370 context->acc_num_missed_samples += (update_period_ms * A2DP_SAMPLE_RATE) % 1000; 371 372 while (context->acc_num_missed_samples >= 1000){ 373 num_samples++; 374 context->acc_num_missed_samples -= 1000; 375 } 376 context->time_audio_data_sent = now; 377 context->samples_ready += num_samples; 378 379 if (context->sbc_ready_to_send) return; 380 381 a2dp_demo_fill_sbc_audio_buffer(context); 382 383 if ((context->sbc_storage_count + btstack_sbc_encoder_sbc_buffer_length()) > context->max_media_payload_size){ 384 // schedule sending 385 context->sbc_ready_to_send = 1; 386 a2dp_source_stream_endpoint_request_can_send_now(context->a2dp_cid, context->local_seid); 387 } 388 } 389 390 static void a2dp_demo_timer_start(a2dp_media_sending_context_t * context){ 391 context->max_media_payload_size = btstack_min(a2dp_max_media_payload_size(context->a2dp_cid, context->local_seid), SBC_STORAGE_SIZE); 392 context->sbc_storage_count = 0; 393 context->sbc_ready_to_send = 0; 394 context->streaming = 1; 395 btstack_run_loop_remove_timer(&context->audio_timer); 396 btstack_run_loop_set_timer_handler(&context->audio_timer, a2dp_demo_audio_timeout_handler); 397 btstack_run_loop_set_timer_context(&context->audio_timer, context); 398 btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS); 399 btstack_run_loop_add_timer(&context->audio_timer); 400 } 401 402 static void a2dp_demo_timer_stop(a2dp_media_sending_context_t * context){ 403 context->time_audio_data_sent = 0; 404 context->acc_num_missed_samples = 0; 405 context->samples_ready = 0; 406 context->streaming = 1; 407 context->sbc_storage_count = 0; 408 context->sbc_ready_to_send = 0; 409 btstack_run_loop_remove_timer(&context->audio_timer); 410 } 411 412 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 413 UNUSED(channel); 414 UNUSED(size); 415 uint8_t status; 416 uint8_t local_seid; 417 bd_addr_t address; 418 uint16_t cid; 419 420 if (packet_type != HCI_EVENT_PACKET) return; 421 422 #ifndef HAVE_BTSTACK_STDIN 423 if (hci_event_packet_get_type(packet) == BTSTACK_EVENT_STATE){ 424 if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return; 425 printf("Create AVDTP Source connection to addr %s.\n", bd_addr_to_str(device_addr)); 426 status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid); 427 if (status != ERROR_CODE_SUCCESS){ 428 printf("Could not perform command, status 0x%2x\n", status); 429 } 430 return; 431 } 432 #endif 433 434 if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return; 435 switch (packet[2]){ 436 case A2DP_SUBEVENT_INCOMING_CONNECTION_ESTABLISHED: 437 a2dp_subevent_incoming_connection_established_get_bd_addr(packet, address); 438 cid = a2dp_subevent_incoming_connection_established_get_a2dp_cid(packet); 439 440 if (!media_tracker.a2dp_cid){ 441 media_tracker.a2dp_cid = cid; 442 } else if (cid != media_tracker.a2dp_cid){ 443 printf("A2DP: Incoming connection failure, received cid 0x%02x, expected cid 0x%02x\n", cid, media_tracker.a2dp_cid); 444 break; 445 } 446 447 media_tracker.connected = 1; 448 printf("A2DP: Incoming connection established: address %s, a2dp cid 0x%02x. Create stream on local seid %d.\n", 449 bd_addr_to_str(address), media_tracker.a2dp_cid, media_tracker.local_seid); 450 status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid); 451 if (status != ERROR_CODE_SUCCESS){ 452 printf("Could not perform command, status 0x%2x\n", status); 453 } 454 break; 455 456 case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{ 457 printf("A2DP Sink demo: received SBC codec configuration.\n"); 458 sbc_configuration.reconfigure = a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet); 459 sbc_configuration.num_channels = a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet); 460 sbc_configuration.sampling_frequency = a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet); 461 sbc_configuration.channel_mode = a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet); 462 sbc_configuration.block_length = a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet); 463 sbc_configuration.subbands = a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet); 464 sbc_configuration.allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet); 465 sbc_configuration.min_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet); 466 sbc_configuration.max_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet); 467 sbc_configuration.frames_per_buffer = sbc_configuration.subbands * sbc_configuration.block_length; 468 469 btstack_sbc_encoder_init(&sbc_encoder_state, SBC_MODE_STANDARD, 470 sbc_configuration.block_length, sbc_configuration.subbands, 471 sbc_configuration.allocation_method, sbc_configuration.sampling_frequency, 472 sbc_configuration.max_bitpool_value, 473 sbc_configuration.channel_mode); 474 break; 475 } 476 477 case A2DP_SUBEVENT_STREAM_ESTABLISHED: 478 media_tracker.connected = 1; 479 a2dp_subevent_stream_established_get_bd_addr(packet, address); 480 status = a2dp_subevent_stream_established_get_status(packet); 481 if (status){ 482 printf("A2DP: Stream establishment failed: status 0x%02x.\n", status); 483 break; 484 } 485 local_seid = a2dp_subevent_stream_established_get_local_seid(packet); 486 if (local_seid != media_tracker.local_seid){ 487 printf("A2DP: Stream establishment failed: wrong local seid %d, expected %d.\n", local_seid, media_tracker.local_seid); 488 break; 489 } 490 media_tracker.a2dp_cid = a2dp_subevent_stream_established_get_a2dp_cid(packet); 491 printf("A2DP: Stream established: address %s, a2dp cid 0x%02x, local seid %d, remote seid %d.\n", bd_addr_to_str(address), 492 media_tracker.a2dp_cid, media_tracker.local_seid, a2dp_subevent_stream_established_get_remote_seid(packet)); 493 printf("Start playing mod, cid 0x%02x.\n", media_tracker.a2dp_cid); 494 data_source = STREAM_MOD; 495 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 496 break; 497 498 case A2DP_SUBEVENT_STREAM_STARTED: 499 play_info.status = AVRCP_PLAYBACK_STATUS_PLAYING; 500 avrcp_target_set_now_playing_info(avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 501 avrcp_target_set_playback_status(avrcp_cid, AVRCP_PLAYBACK_STATUS_PLAYING); 502 a2dp_demo_timer_start(&media_tracker); 503 printf("A2DP: Stream started.\n"); 504 break; 505 506 case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW: 507 a2dp_demo_send_media_packet(); 508 break; 509 510 case A2DP_SUBEVENT_STREAM_SUSPENDED: 511 play_info.status = AVRCP_PLAYBACK_STATUS_PAUSED; 512 avrcp_target_set_playback_status(avrcp_cid, AVRCP_PLAYBACK_STATUS_PAUSED); 513 printf("A2DP: Stream paused.\n"); 514 a2dp_demo_timer_stop(&media_tracker); 515 break; 516 517 case A2DP_SUBEVENT_STREAM_RELEASED: 518 avrcp_target_set_now_playing_info(avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); 519 play_info.status = AVRCP_PLAYBACK_STATUS_STOPPED; 520 avrcp_target_set_playback_status(avrcp_cid, AVRCP_PLAYBACK_STATUS_STOPPED); 521 printf("A2DP: Stream released.\n"); 522 a2dp_demo_timer_stop(&media_tracker); 523 break; 524 case A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED: 525 printf("A2DP: Signaling released.\n"); 526 cid = a2dp_subevent_signaling_connection_released_get_a2dp_cid(packet); 527 if (cid == media_tracker.a2dp_cid) { 528 media_tracker.connected = 0; 529 media_tracker.a2dp_cid = 0; 530 } 531 break; 532 default: 533 printf("A2DP: event 0x%02x is not parsed\n", packet[2]); 534 break; 535 } 536 } 537 538 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 539 UNUSED(channel); 540 UNUSED(size); 541 bd_addr_t event_addr; 542 uint16_t local_cid; 543 uint8_t status = ERROR_CODE_SUCCESS; 544 545 if (packet_type != HCI_EVENT_PACKET) return; 546 if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; 547 548 switch (packet[2]){ 549 case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: { 550 local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet); 551 // if (avrcp_cid != 0 && avrcp_cid != local_cid) { 552 // printf("AVRCP: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_cid, local_cid); 553 // return; 554 // } 555 // if (avrcp_cid != local_cid) break; 556 557 status = avrcp_subevent_connection_established_get_status(packet); 558 if (status != ERROR_CODE_SUCCESS){ 559 printf("AVRCP: Connection failed: status 0x%02x\n", status); 560 return; 561 } 562 avrcp_connected = 1; 563 avrcp_cid = local_cid; 564 avrcp_subevent_connection_established_get_bd_addr(packet, event_addr); 565 printf("AVRCP: connected to %s, avrcp_cid 0x%02x\n", bd_addr_to_str(event_addr), local_cid); 566 567 avrcp_target_set_now_playing_info(avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); 568 avrcp_target_set_unit_info(avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, company_id); 569 avrcp_target_set_subunit_info(avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, (uint8_t *)subunit_info, sizeof(subunit_info)); 570 return; 571 } 572 573 case AVRCP_SUBEVENT_EVENT_IDS_QUERY: 574 status = avrcp_target_supported_events(avrcp_cid, events_num, events, sizeof(events)); 575 break; 576 case AVRCP_SUBEVENT_COMPANY_IDS_QUERY: 577 status = avrcp_target_supported_companies(avrcp_cid, companies_num, companies, sizeof(companies)); 578 break; 579 case AVRCP_SUBEVENT_PLAY_STATUS_QUERY: 580 status = avrcp_target_play_status(avrcp_cid, play_info.song_length_ms, play_info.song_position_ms, play_info.status); 581 break; 582 // case AVRCP_SUBEVENT_NOW_PLAYING_INFO_QUERY: 583 // status = avrcp_target_now_playing_info(avrcp_cid); 584 // break; 585 case AVRCP_SUBEVENT_OPERATION:{ 586 avrcp_operation_id_t operation_id = avrcp_subevent_operation_get_operation_id(packet); 587 if (!media_tracker.connected) break; 588 switch (operation_id){ 589 case AVRCP_OPERATION_ID_PLAY: 590 printf("AVRCP: PLAY\n"); 591 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 592 break; 593 case AVRCP_OPERATION_ID_PAUSE: 594 printf("AVRCP: PAUSE\n"); 595 status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 596 break; 597 case AVRCP_OPERATION_ID_STOP: 598 printf("AVRCP: STOP\n"); 599 status = a2dp_source_disconnect(media_tracker.a2dp_cid); 600 break; 601 default: 602 return; 603 } 604 break; 605 } 606 case AVRCP_SUBEVENT_CONNECTION_RELEASED: 607 printf("AVRCP: Channel released: avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); 608 avrcp_cid = 0; 609 return; 610 default: 611 printf("AVRCP: event not parsed %02x\n", packet[2]); 612 break; 613 } 614 615 if (status != ERROR_CODE_SUCCESS){ 616 printf("Responding to event 0x%02x failed with status 0x%02x\n", packet[2], status); 617 } 618 } 619 620 #ifdef HAVE_BTSTACK_STDIN 621 static void show_usage(void){ 622 bd_addr_t iut_address; 623 gap_local_bd_addr(iut_address); 624 printf("\n--- Bluetooth A2DP Source/AVRCP Target Demo %s ---\n", bd_addr_to_str(iut_address)); 625 printf("b - AVDTP Source create connection to addr %s\n", device_addr_string); 626 printf("B - AVDTP Source disconnect\n"); 627 printf("c - AVRCP Target create connection to addr %s\n", device_addr_string); 628 printf("C - AVRCP Target disconnect\n"); 629 printf("0 - AVRCP reset now playing info\n"); 630 631 printf("x - start streaming sine\n"); 632 if (hxcmod_initialized){ 633 printf("z - start streaming '%s'\n", mod_name); 634 } 635 printf("p - pause streaming\n"); 636 637 printf("\n--- Bluetooth AVRCP Target Commands %s ---\n", bd_addr_to_str(iut_address)); 638 printf("---\n"); 639 } 640 641 static void stdin_process(char cmd){ 642 uint8_t status = ERROR_CODE_SUCCESS; 643 switch (cmd){ 644 case 'b': 645 status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid); 646 printf(" - Create AVDTP Source connection to addr %s, cid 0x%02x.\n", bd_addr_to_str(device_addr), media_tracker.a2dp_cid); 647 break; 648 case 'B': 649 printf(" - AVDTP Source Disconnect from cid 0x%2x\n", media_tracker.a2dp_cid); 650 status = a2dp_source_disconnect(media_tracker.a2dp_cid); 651 break; 652 case 'c': 653 printf(" - Create AVRCP Target connection to addr %s.\n", bd_addr_to_str(device_addr)); 654 status = avrcp_target_connect(device_addr, &avrcp_cid); 655 break; 656 case 'C': 657 printf(" - AVRCP Target disconnect\n"); 658 status = avrcp_target_disconnect(avrcp_cid); 659 break; 660 661 case '\n': 662 case '\r': 663 break; 664 665 case 't': 666 printf("STREAM_PTS_TEST.\n"); 667 data_source = STREAM_PTS_TEST; 668 avrcp_target_set_now_playing_info(avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 669 if (!media_tracker.connected) break; 670 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 671 break; 672 673 case 'x': 674 avrcp_target_set_now_playing_info(avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 675 printf("Playing sine.\n"); 676 data_source = STREAM_SINE; 677 if (!media_tracker.connected) break; 678 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 679 break; 680 case 'z': 681 avrcp_target_set_now_playing_info(avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 682 printf("Playing mod.\n"); 683 data_source = STREAM_MOD; 684 if (!media_tracker.connected) break; 685 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 686 break; 687 case 'p': 688 if (!media_tracker.connected) break; 689 printf("Pause stream.\n"); 690 status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 691 break; 692 case '0': 693 avrcp_target_set_now_playing_info(avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); 694 printf("Reset now playing info\n"); 695 break; 696 default: 697 show_usage(); 698 return; 699 } 700 if (status != ERROR_CODE_SUCCESS){ 701 printf("Could not perform command, status 0x%2x\n", status); 702 } 703 } 704 #endif 705 706 707 int btstack_main(int argc, const char * argv[]); 708 int btstack_main(int argc, const char * argv[]){ 709 (void)argc; 710 (void)argv; 711 712 int err = a2dp_source_and_avrcp_services_init(); 713 if (err) return err; 714 // turn on! 715 hci_power_control(HCI_POWER_ON); 716 return 0; 717 } 718 /* EXAMPLE_END */ 719