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