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