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