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 #define AVRCP_BROWSING_ENABLED 0 70 71 #define NUM_CHANNELS 2 72 #define A2DP_SAMPLE_RATE 44100 73 #define BYTES_PER_AUDIO_SAMPLE (2*NUM_CHANNELS) 74 #define AUDIO_TIMEOUT_MS 10 75 #define TABLE_SIZE_441HZ 100 76 77 #define SBC_STORAGE_SIZE 1030 78 79 typedef enum { 80 STREAM_SINE = 0, 81 STREAM_MOD, 82 STREAM_PTS_TEST 83 } stream_data_source_t; 84 85 typedef struct { 86 uint16_t a2dp_cid; 87 uint8_t local_seid; 88 uint8_t connected; 89 uint8_t stream_opened; 90 91 uint32_t time_audio_data_sent; // ms 92 uint32_t acc_num_missed_samples; 93 uint32_t samples_ready; 94 btstack_timer_source_t audio_timer; 95 uint8_t streaming; 96 int max_media_payload_size; 97 98 uint8_t sbc_storage[SBC_STORAGE_SIZE]; 99 uint16_t sbc_storage_count; 100 uint8_t sbc_ready_to_send; 101 } a2dp_media_sending_context_t; 102 103 static uint8_t media_sbc_codec_capabilities[] = { 104 (AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO, 105 0xFF,//(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS, 106 2, 53 107 }; 108 109 static const int16_t sine_int16[] = { 110 0, 2057, 4107, 6140, 8149, 10126, 12062, 13952, 15786, 17557, 111 19260, 20886, 22431, 23886, 25247, 26509, 27666, 28714, 29648, 30466, 112 31163, 31738, 32187, 32509, 32702, 32767, 32702, 32509, 32187, 31738, 113 31163, 30466, 29648, 28714, 27666, 26509, 25247, 23886, 22431, 20886, 114 19260, 17557, 15786, 13952, 12062, 10126, 8149, 6140, 4107, 2057, 115 0, -2057, -4107, -6140, -8149, -10126, -12062, -13952, -15786, -17557, 116 -19260, -20886, -22431, -23886, -25247, -26509, -27666, -28714, -29648, -30466, 117 -31163, -31738, -32187, -32509, -32702, -32767, -32702, -32509, -32187, -31738, 118 -31163, -30466, -29648, -28714, -27666, -26509, -25247, -23886, -22431, -20886, 119 -19260, -17557, -15786, -13952, -12062, -10126, -8149, -6140, -4107, -2057, 120 }; 121 122 typedef struct { 123 int reconfigure; 124 int num_channels; 125 int sampling_frequency; 126 int channel_mode; 127 int block_length; 128 int subbands; 129 int allocation_method; 130 int min_bitpool_value; 131 int max_bitpool_value; 132 int frames_per_buffer; 133 } avdtp_media_codec_configuration_sbc_t; 134 135 static btstack_packet_callback_registration_t hci_event_callback_registration; 136 137 #ifdef HAVE_BTSTACK_STDIN 138 // pts: static const char * device_addr_string = "00:1B:DC:08:0A:A5"; 139 // mac 2013: static const char * device_addr_string = "84:38:35:65:d1:15"; 140 // phone 2013: static const char * device_addr_string = "D8:BB:2C:DF:F0:F2"; 141 // Minijambox: 142 // static const char * device_addr_string = "00:21:3C:AC:F7:38"; 143 // Philips SHB9100: static const char * device_addr_string = "00:22:37:05:FD:E8"; 144 // RT-B6: static const char * device_addr_string = "00:75:58:FF:C9:7D"; 145 // BT dongle: 146 static const char * device_addr_string = "00:1A:7D:DA:71:0A"; 147 // Sony MDR-ZX330BT static const char * device_addr_string = "00:18:09:28:50:18"; 148 #endif 149 150 static bd_addr_t device_addr; 151 static uint8_t sdp_a2dp_source_service_buffer[150]; 152 static uint8_t sdp_avrcp_target_service_buffer[200]; 153 static avdtp_media_codec_configuration_sbc_t sbc_configuration; 154 static btstack_sbc_encoder_state_t sbc_encoder_state; 155 156 static uint8_t media_sbc_codec_configuration[4]; 157 static a2dp_media_sending_context_t media_tracker; 158 159 static uint16_t avrcp_cid; 160 static uint8_t avrcp_connected; 161 162 static stream_data_source_t data_source; 163 164 static int sine_phase; 165 166 static int hxcmod_initialized; 167 static modcontext mod_context; 168 static tracker_buffer_state trkbuf; 169 170 171 /* AVRCP Target context START */ 172 static const uint8_t subunit_info[] = { 173 0,0,0,0, 174 1,1,1,1, 175 2,2,2,2, 176 3,3,3,3, 177 4,4,4,4, 178 5,5,5,5, 179 6,6,6,6, 180 7,7,7,7 181 }; 182 183 static uint32_t company_id = 0x112233; 184 static uint8_t companies_num = 1; 185 static uint8_t companies[] = { 186 0x00, 0x19, 0x58 //BT SIG registered CompanyID 187 }; 188 189 static uint8_t events_num = 13; 190 static uint8_t events[] = { 191 AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED, 192 AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED, 193 AVRCP_NOTIFICATION_EVENT_TRACK_REACHED_END, 194 AVRCP_NOTIFICATION_EVENT_TRACK_REACHED_START, 195 AVRCP_NOTIFICATION_EVENT_PLAYBACK_POS_CHANGED, 196 AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED, 197 AVRCP_NOTIFICATION_EVENT_SYSTEM_STATUS_CHANGED, 198 AVRCP_NOTIFICATION_EVENT_PLAYER_APPLICATION_SETTING_CHANGED, 199 AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED, 200 AVRCP_NOTIFICATION_EVENT_AVAILABLE_PLAYERS_CHANGED, 201 AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED, 202 AVRCP_NOTIFICATION_EVENT_UIDS_CHANGED, 203 AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED 204 }; 205 206 typedef struct { 207 uint8_t track_id[8]; 208 uint32_t song_length_ms; 209 avrcp_playback_status_t status; 210 uint32_t song_position_ms; // 0xFFFFFFFF if not supported 211 } avrcp_play_status_info_t; 212 213 // python -c "print('a'*512)" 214 static const char title[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 215 216 avrcp_track_t tracks[] = { 217 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, 1, "Sine", "Generated", "AVRCP Demo", "monotone", 12345}, 218 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 2, "Nao-deceased", "Decease", "AVRCP Demo", "vivid", 12345}, 219 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, 3, (char *)title, "Decease", "AVRCP Demo", "vivid", 12345}, 220 }; 221 int current_track_index; 222 avrcp_play_status_info_t play_info; 223 224 /* AVRCP Target context END */ 225 226 /* @section Main Application Setup 227 * 228 * @text The Listing MainConfiguration shows how to setup AD2P Source and AVRCP Target services. 229 */ 230 231 /* LISTING_START(MainConfiguration): Setup Audio Source and AVRCP Target services */ 232 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size); 233 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 234 #ifdef HAVE_BTSTACK_STDIN 235 static void stdin_process(char cmd); 236 #endif 237 238 static int a2dp_source_and_avrcp_services_init(void){ 239 // Register for HCI events. 240 hci_event_callback_registration.callback = &a2dp_source_packet_handler; 241 hci_add_event_handler(&hci_event_callback_registration); 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 demo: 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 260 // Initialize SDP, 261 sdp_init(); 262 263 // Create A2DP Source service record and register it with SDP. 264 memset(sdp_a2dp_source_service_buffer, 0, sizeof(sdp_a2dp_source_service_buffer)); 265 a2dp_source_create_sdp_record(sdp_a2dp_source_service_buffer, 0x10002, 1, NULL, NULL); 266 sdp_register_service(sdp_a2dp_source_service_buffer); 267 268 // Create AVRCP target service record and register it with SDP. 269 memset(sdp_avrcp_target_service_buffer, 0, sizeof(sdp_avrcp_target_service_buffer)); 270 avrcp_target_create_sdp_record(sdp_avrcp_target_service_buffer, 0x10001, AVRCP_BROWSING_ENABLED, 1, NULL, NULL); 271 sdp_register_service(sdp_avrcp_target_service_buffer); 272 273 // Set local name with a template Bluetooth address, that will be automatically 274 // replaced with a actual address once it is available, i.e. when BTstack boots 275 // up and starts talking to a Bluetooth module. 276 gap_set_local_name(" A2DP Source Demo 00:00:00:00:00:00"); 277 gap_discoverable_control(1); 278 gap_set_class_of_device(0x200408); 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 // Parse human readable Bluetooth address. 287 sscanf_bd_addr(device_addr_string, device_addr); 288 289 #ifdef HAVE_BTSTACK_STDIN 290 btstack_stdin_setup(stdin_process); 291 #endif 292 return 0; 293 } 294 /* LISTING_END */ 295 296 static void a2dp_demo_send_media_packet(void){ 297 int num_bytes_in_frame = btstack_sbc_encoder_sbc_buffer_length(); 298 int bytes_in_storage = media_tracker.sbc_storage_count; 299 uint8_t num_frames = bytes_in_storage / num_bytes_in_frame; 300 a2dp_source_stream_send_media_payload(media_tracker.a2dp_cid, media_tracker.local_seid, media_tracker.sbc_storage, bytes_in_storage, num_frames, 0); 301 media_tracker.sbc_storage_count = 0; 302 media_tracker.sbc_ready_to_send = 0; 303 } 304 305 static void produce_sine_audio(int16_t * pcm_buffer, int num_samples_to_write){ 306 int count; 307 for (count = 0; count < num_samples_to_write ; count++){ 308 pcm_buffer[count * 2] = sine_int16[sine_phase]; 309 pcm_buffer[count * 2 + 1] = sine_int16[sine_phase]; 310 sine_phase++; 311 if (sine_phase >= TABLE_SIZE_441HZ){ 312 sine_phase -= TABLE_SIZE_441HZ; 313 } 314 } 315 } 316 317 static void produce_mod_audio(int16_t * pcm_buffer, int num_samples_to_write){ 318 hxcmod_fillbuffer(&mod_context, (unsigned short *) &pcm_buffer[0], num_samples_to_write, &trkbuf); 319 } 320 321 static void produce_audio(int16_t * pcm_buffer, int num_samples){ 322 switch (data_source){ 323 case STREAM_SINE: 324 produce_sine_audio(pcm_buffer, num_samples); 325 break; 326 case STREAM_MOD: 327 produce_mod_audio(pcm_buffer, num_samples); 328 break; 329 default: 330 break; 331 } 332 } 333 334 static int a2dp_demo_fill_sbc_audio_buffer(a2dp_media_sending_context_t * context){ 335 // perform sbc encodin 336 int total_num_bytes_read = 0; 337 unsigned int num_audio_samples_per_sbc_buffer = btstack_sbc_encoder_num_audio_frames(); 338 while (context->samples_ready >= num_audio_samples_per_sbc_buffer 339 && (context->max_media_payload_size - context->sbc_storage_count) >= btstack_sbc_encoder_sbc_buffer_length()){ 340 341 int16_t pcm_frame[256*NUM_CHANNELS]; 342 343 produce_audio(pcm_frame, num_audio_samples_per_sbc_buffer); 344 btstack_sbc_encoder_process_data(pcm_frame); 345 346 uint16_t sbc_frame_size = btstack_sbc_encoder_sbc_buffer_length(); 347 uint8_t * sbc_frame = btstack_sbc_encoder_sbc_buffer(); 348 349 total_num_bytes_read += num_audio_samples_per_sbc_buffer; 350 memcpy(&context->sbc_storage[context->sbc_storage_count], sbc_frame, sbc_frame_size); 351 context->sbc_storage_count += sbc_frame_size; 352 context->samples_ready -= num_audio_samples_per_sbc_buffer; 353 } 354 return total_num_bytes_read; 355 } 356 357 static void a2dp_demo_audio_timeout_handler(btstack_timer_source_t * timer){ 358 a2dp_media_sending_context_t * context = (a2dp_media_sending_context_t *) btstack_run_loop_get_timer_context(timer); 359 btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS); 360 btstack_run_loop_add_timer(&context->audio_timer); 361 uint32_t now = btstack_run_loop_get_time_ms(); 362 363 uint32_t update_period_ms = AUDIO_TIMEOUT_MS; 364 if (context->time_audio_data_sent > 0){ 365 update_period_ms = now - context->time_audio_data_sent; 366 } 367 368 uint32_t num_samples = (update_period_ms * A2DP_SAMPLE_RATE) / 1000; 369 context->acc_num_missed_samples += (update_period_ms * A2DP_SAMPLE_RATE) % 1000; 370 371 while (context->acc_num_missed_samples >= 1000){ 372 num_samples++; 373 context->acc_num_missed_samples -= 1000; 374 } 375 context->time_audio_data_sent = now; 376 context->samples_ready += num_samples; 377 378 if (context->sbc_ready_to_send) return; 379 380 a2dp_demo_fill_sbc_audio_buffer(context); 381 382 if ((context->sbc_storage_count + btstack_sbc_encoder_sbc_buffer_length()) > context->max_media_payload_size){ 383 // schedule sending 384 context->sbc_ready_to_send = 1; 385 a2dp_source_stream_endpoint_request_can_send_now(context->a2dp_cid, context->local_seid); 386 } 387 } 388 389 static void a2dp_demo_timer_start(a2dp_media_sending_context_t * context){ 390 context->max_media_payload_size = btstack_min(a2dp_max_media_payload_size(context->a2dp_cid, context->local_seid), SBC_STORAGE_SIZE); 391 context->sbc_storage_count = 0; 392 context->sbc_ready_to_send = 0; 393 context->streaming = 1; 394 btstack_run_loop_remove_timer(&context->audio_timer); 395 btstack_run_loop_set_timer_handler(&context->audio_timer, a2dp_demo_audio_timeout_handler); 396 btstack_run_loop_set_timer_context(&context->audio_timer, context); 397 btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS); 398 btstack_run_loop_add_timer(&context->audio_timer); 399 } 400 401 static void a2dp_demo_timer_stop(a2dp_media_sending_context_t * context){ 402 context->time_audio_data_sent = 0; 403 context->acc_num_missed_samples = 0; 404 context->samples_ready = 0; 405 context->streaming = 1; 406 context->sbc_storage_count = 0; 407 context->sbc_ready_to_send = 0; 408 btstack_run_loop_remove_timer(&context->audio_timer); 409 } 410 411 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 412 UNUSED(channel); 413 UNUSED(size); 414 uint8_t status; 415 uint8_t local_seid; 416 bd_addr_t address; 417 uint16_t cid; 418 419 if (packet_type != HCI_EVENT_PACKET) return; 420 421 #ifndef HAVE_BTSTACK_STDIN 422 if (hci_event_packet_get_type(packet) == BTSTACK_EVENT_STATE){ 423 if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return; 424 printf("Create AVDTP Source connection to addr %s.\n", bd_addr_to_str(device_addr)); 425 status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid); 426 if (status != ERROR_CODE_SUCCESS){ 427 printf("Could not perform command, status 0x%2x\n", status); 428 } 429 return; 430 } 431 #endif 432 if (hci_event_packet_get_type(packet) == HCI_EVENT_PIN_CODE_REQUEST) { 433 printf("Pin code request - using '0000'\n"); 434 hci_event_pin_code_request_get_bd_addr(packet, address); 435 gap_pin_code_response(address, "0000"); 436 return; 437 } 438 439 if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return; 440 switch (packet[2]){ 441 case A2DP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED: 442 a2dp_subevent_signaling_connection_established_get_bd_addr(packet, address); 443 cid = a2dp_subevent_signaling_connection_established_get_a2dp_cid(packet); 444 445 if (!media_tracker.a2dp_cid){ 446 media_tracker.a2dp_cid = cid; 447 } else if (cid != media_tracker.a2dp_cid){ 448 printf(" A2DP Source demo: Connection failed, received cid 0x%02x, expected cid 0x%02x\n", cid, media_tracker.a2dp_cid); 449 break; 450 } 451 printf(" A2DP Source demo: Connected to address %s, a2dp cid 0x%02x.\n", bd_addr_to_str(address), media_tracker.a2dp_cid); 452 break; 453 454 case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{ 455 printf(" A2DP Source demo: Received SBC codec configuration.\n"); 456 sbc_configuration.reconfigure = a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet); 457 sbc_configuration.num_channels = a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet); 458 sbc_configuration.sampling_frequency = a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet); 459 sbc_configuration.channel_mode = a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet); 460 sbc_configuration.block_length = a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet); 461 sbc_configuration.subbands = a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet); 462 sbc_configuration.allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet); 463 sbc_configuration.min_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet); 464 sbc_configuration.max_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet); 465 sbc_configuration.frames_per_buffer = sbc_configuration.subbands * sbc_configuration.block_length; 466 467 btstack_sbc_encoder_init(&sbc_encoder_state, SBC_MODE_STANDARD, 468 sbc_configuration.block_length, sbc_configuration.subbands, 469 sbc_configuration.allocation_method, sbc_configuration.sampling_frequency, 470 sbc_configuration.max_bitpool_value, 471 sbc_configuration.channel_mode); 472 473 // status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid); 474 // if (status != ERROR_CODE_SUCCESS){ 475 // printf("Could not perform command, status 0x%2x\n", status); 476 // } 477 break; 478 } 479 480 case A2DP_SUBEVENT_STREAM_ESTABLISHED: 481 a2dp_subevent_stream_established_get_bd_addr(packet, address); 482 status = a2dp_subevent_stream_established_get_status(packet); 483 if (status){ 484 printf(" A2DP Source demo: Stream failed, status 0x%02x.\n", status); 485 break; 486 } 487 local_seid = a2dp_subevent_stream_established_get_local_seid(packet); 488 if (local_seid != media_tracker.local_seid){ 489 printf(" A2DP Source demo: Stream failed, wrong local seid %d, expected %d.\n", local_seid, media_tracker.local_seid); 490 break; 491 } 492 printf(" A2DP Source demo: Stream established, address %s, a2dp cid 0x%02x, local seid %d, remote seid %d.\n", bd_addr_to_str(address), 493 media_tracker.a2dp_cid, media_tracker.local_seid, a2dp_subevent_stream_established_get_remote_seid(packet)); 494 printf(" A2DP Source demo: Start playing mod, a2dp cid 0x%02x.\n", media_tracker.a2dp_cid); 495 media_tracker.stream_opened = 1; 496 data_source = STREAM_MOD; 497 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 498 break; 499 500 case A2DP_SUBEVENT_STREAM_STARTED: 501 play_info.status = AVRCP_PLAYBACK_STATUS_PLAYING; 502 if (avrcp_connected){ 503 avrcp_target_set_now_playing_info(avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 504 avrcp_target_set_playback_status(avrcp_cid, AVRCP_PLAYBACK_STATUS_PLAYING); 505 } 506 a2dp_demo_timer_start(&media_tracker); 507 printf(" A2DP Source demo: Stream started.\n"); 508 break; 509 510 case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW: 511 a2dp_demo_send_media_packet(); 512 break; 513 514 case A2DP_SUBEVENT_STREAM_SUSPENDED: 515 play_info.status = AVRCP_PLAYBACK_STATUS_PAUSED; 516 if (avrcp_connected){ 517 avrcp_target_set_playback_status(avrcp_cid, AVRCP_PLAYBACK_STATUS_PAUSED); 518 } 519 printf(" A2DP Source demo: Stream paused.\n"); 520 a2dp_demo_timer_stop(&media_tracker); 521 break; 522 523 case A2DP_SUBEVENT_STREAM_RELEASED: 524 play_info.status = AVRCP_PLAYBACK_STATUS_STOPPED; 525 cid = a2dp_subevent_stream_released_get_a2dp_cid(packet); 526 if (cid == media_tracker.a2dp_cid) { 527 media_tracker.stream_opened = 0; 528 printf(" A2DP Source demo: Stream released.\n"); 529 } 530 if (avrcp_connected){ 531 avrcp_target_set_now_playing_info(avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); 532 avrcp_target_set_playback_status(avrcp_cid, AVRCP_PLAYBACK_STATUS_STOPPED); 533 } 534 a2dp_demo_timer_stop(&media_tracker); 535 break; 536 case A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED: 537 cid = a2dp_subevent_signaling_connection_released_get_a2dp_cid(packet); 538 if (cid == media_tracker.a2dp_cid) { 539 media_tracker.connected = 0; 540 media_tracker.a2dp_cid = 0; 541 printf(" A2DP Source demo: Signaling released.\n\n"); 542 } 543 break; 544 default: 545 break; 546 } 547 } 548 549 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 550 UNUSED(channel); 551 UNUSED(size); 552 bd_addr_t event_addr; 553 uint16_t local_cid; 554 uint8_t status = ERROR_CODE_SUCCESS; 555 556 if (packet_type != HCI_EVENT_PACKET) return; 557 if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; 558 559 switch (packet[2]){ 560 case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: { 561 local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet); 562 // if (avrcp_cid != 0 && avrcp_cid != local_cid) { 563 // printf("AVRCP Source demo: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_cid, local_cid); 564 // return; 565 // } 566 // if (avrcp_cid != local_cid) break; 567 568 status = avrcp_subevent_connection_established_get_status(packet); 569 if (status != ERROR_CODE_SUCCESS){ 570 printf("AVRCP Source demo: Connection failed, status 0x%02x\n", status); 571 return; 572 } 573 avrcp_connected = 1; 574 avrcp_cid = local_cid; 575 avrcp_subevent_connection_established_get_bd_addr(packet, event_addr); 576 printf("AVRCP Source demo: Connected to %s, avrcp_cid 0x%02x\n", bd_addr_to_str(event_addr), local_cid); 577 578 avrcp_target_set_now_playing_info(avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); 579 avrcp_target_set_unit_info(avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, company_id); 580 avrcp_target_set_subunit_info(avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, (uint8_t *)subunit_info, sizeof(subunit_info)); 581 return; 582 } 583 584 case AVRCP_SUBEVENT_EVENT_IDS_QUERY: 585 status = avrcp_target_supported_events(avrcp_cid, events_num, events, sizeof(events)); 586 break; 587 case AVRCP_SUBEVENT_COMPANY_IDS_QUERY: 588 status = avrcp_target_supported_companies(avrcp_cid, companies_num, companies, sizeof(companies)); 589 break; 590 case AVRCP_SUBEVENT_PLAY_STATUS_QUERY: 591 status = avrcp_target_play_status(avrcp_cid, play_info.song_length_ms, play_info.song_position_ms, play_info.status); 592 break; 593 // case AVRCP_SUBEVENT_NOW_PLAYING_INFO_QUERY: 594 // status = avrcp_target_now_playing_info(avrcp_cid); 595 // break; 596 case AVRCP_SUBEVENT_OPERATION:{ 597 avrcp_operation_id_t operation_id = avrcp_subevent_operation_get_operation_id(packet); 598 if (!media_tracker.connected) break; 599 switch (operation_id){ 600 case AVRCP_OPERATION_ID_PLAY: 601 printf("AVRCP Source demo: PLAY\n"); 602 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 603 break; 604 case AVRCP_OPERATION_ID_PAUSE: 605 printf("AVRCP Source demo: PAUSE\n"); 606 status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 607 break; 608 case AVRCP_OPERATION_ID_STOP: 609 printf("AVRCP Source demo: STOP\n"); 610 status = a2dp_source_disconnect(media_tracker.a2dp_cid); 611 break; 612 default: 613 return; 614 } 615 break; 616 } 617 case AVRCP_SUBEVENT_CONNECTION_RELEASED: 618 printf("AVRCP Source demo: Disconnected, avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); 619 avrcp_cid = 0; 620 avrcp_connected = 0; 621 return; 622 default: 623 break; 624 } 625 626 if (status != ERROR_CODE_SUCCESS){ 627 printf("Responding to event 0x%02x failed with status 0x%02x\n", packet[2], status); 628 } 629 } 630 631 #ifdef HAVE_BTSTACK_STDIN 632 static void show_usage(void){ 633 bd_addr_t iut_address; 634 gap_local_bd_addr(iut_address); 635 printf("\n--- Bluetooth A2DP Source/AVRCP Target Demo %s ---\n", bd_addr_to_str(iut_address)); 636 printf("b - AVDTP Source create connection to addr %s\n", device_addr_string); 637 printf("B - AVDTP Source disconnect\n"); 638 printf("c - AVRCP Target create connection to addr %s\n", device_addr_string); 639 printf("C - AVRCP Target disconnect\n"); 640 printf("0 - AVRCP reset now playing info\n"); 641 642 printf("x - start streaming sine\n"); 643 if (hxcmod_initialized){ 644 printf("z - start streaming '%s'\n", mod_name); 645 } 646 printf("p - pause streaming\n"); 647 648 printf("\n--- Bluetooth AVRCP Target Commands %s ---\n", bd_addr_to_str(iut_address)); 649 printf("---\n"); 650 } 651 652 static void stdin_process(char cmd){ 653 uint8_t status = ERROR_CODE_SUCCESS; 654 switch (cmd){ 655 case 'b': 656 status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid); 657 printf(" - Create AVDTP Source connection to addr %s, cid 0x%02x.\n", bd_addr_to_str(device_addr), media_tracker.a2dp_cid); 658 break; 659 case 'B': 660 printf(" - AVDTP Source Disconnect from cid 0x%2x\n", media_tracker.a2dp_cid); 661 status = a2dp_source_disconnect(media_tracker.a2dp_cid); 662 break; 663 case 'c': 664 printf(" - Create AVRCP Target connection to addr %s.\n", bd_addr_to_str(device_addr)); 665 status = avrcp_target_connect(device_addr, &avrcp_cid); 666 break; 667 case 'C': 668 printf(" - AVRCP Target disconnect\n"); 669 status = avrcp_target_disconnect(avrcp_cid); 670 break; 671 672 case '\n': 673 case '\r': 674 break; 675 676 case 't': 677 printf("STREAM_PTS_TEST.\n"); 678 data_source = STREAM_PTS_TEST; 679 if (avrcp_connected){ 680 avrcp_target_set_now_playing_info(avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 681 } 682 if (!media_tracker.stream_opened) break; 683 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 684 break; 685 686 case 'x': 687 if (avrcp_connected){ 688 avrcp_target_set_now_playing_info(avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 689 } 690 printf("Playing sine.\n"); 691 data_source = STREAM_SINE; 692 if (!media_tracker.stream_opened) break; 693 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 694 break; 695 case 'z': 696 if (avrcp_connected){ 697 avrcp_target_set_now_playing_info(avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 698 } 699 printf("Playing mod.\n"); 700 data_source = STREAM_MOD; 701 if (!media_tracker.stream_opened) break; 702 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 703 break; 704 case 'p': 705 if (!media_tracker.connected) break; 706 printf("Pause stream.\n"); 707 status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 708 break; 709 case '0': 710 if (avrcp_connected){ 711 avrcp_target_set_now_playing_info(avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); 712 printf("Reset now playing info\n"); 713 } 714 break; 715 default: 716 show_usage(); 717 return; 718 } 719 if (status != ERROR_CODE_SUCCESS){ 720 printf("Could not perform command, status 0x%2x\n", status); 721 } 722 } 723 #endif 724 725 726 int btstack_main(int argc, const char * argv[]); 727 int btstack_main(int argc, const char * argv[]){ 728 (void)argc; 729 (void)argv; 730 731 int err = a2dp_source_and_avrcp_services_init(); 732 if (err) return err; 733 // turn on! 734 hci_power_control(HCI_POWER_ON); 735 return 0; 736 } 737 /* EXAMPLE_END */ 738