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