xref: /btstack/example/a2dp_source_demo.c (revision 4dc98401beb70c7710beb82d9ce2303f1ae599d0)
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): A2DP Source Demo
46  *
47  * @text This A2DP Source example demonstrates how to send
48  * an audio to a remote A2DP Sink device, and, if HAVE_BTSTACK_STDIN is defined,
49  * how to switch between two audio data sources.
50  */
51 // *****************************************************************************
52 
53 
54 #include <stdint.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 
59 #include "btstack.h"
60 
61 #include "hxcmod.h"
62 #include "mods/mod.h"
63 
64 #define NUM_CHANNELS                2
65 #define A2DP_SAMPLE_RATE            44100
66 #define BYTES_PER_AUDIO_SAMPLE      (2*NUM_CHANNELS)
67 #define AUDIO_TIMEOUT_MS            10
68 #define TABLE_SIZE_441HZ            100
69 
70 typedef enum {
71     STREAM_SINE = 0,
72     STREAM_MOD,
73     STREAM_PTS_TEST
74 } stream_data_source_t;
75 
76 typedef struct {
77     uint16_t a2dp_cid;
78     uint8_t  local_seid;
79     uint8_t  connected;
80 
81     uint32_t time_audio_data_sent; // ms
82     uint32_t acc_num_missed_samples;
83     uint32_t samples_ready;
84     btstack_timer_source_t audio_timer;
85     uint8_t  streaming;
86     int      max_media_payload_size;
87 
88     uint8_t  sbc_storage[1030];
89     uint16_t sbc_storage_count;
90     uint8_t  sbc_ready_to_send;
91 } a2dp_media_sending_context_t;
92 
93 static  uint8_t media_sbc_codec_capabilities[] = {
94     (AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO,
95     0xFF,//(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS,
96     2, 53
97 };
98 
99 static const int16_t sine_int16[] = {
100      0,    2057,    4107,    6140,    8149,   10126,   12062,   13952,   15786,   17557,
101  19260,   20886,   22431,   23886,   25247,   26509,   27666,   28714,   29648,   30466,
102  31163,   31738,   32187,   32509,   32702,   32767,   32702,   32509,   32187,   31738,
103  31163,   30466,   29648,   28714,   27666,   26509,   25247,   23886,   22431,   20886,
104  19260,   17557,   15786,   13952,   12062,   10126,    8149,    6140,    4107,    2057,
105      0,   -2057,   -4107,   -6140,   -8149,  -10126,  -12062,  -13952,  -15786,  -17557,
106 -19260,  -20886,  -22431,  -23886,  -25247,  -26509,  -27666,  -28714,  -29648,  -30466,
107 -31163,  -31738,  -32187,  -32509,  -32702,  -32767,  -32702,  -32509,  -32187,  -31738,
108 -31163,  -30466,  -29648,  -28714,  -27666,  -26509,  -25247,  -23886,  -22431,  -20886,
109 -19260,  -17557,  -15786,  -13952,  -12062,  -10126,   -8149,   -6140,   -4107,   -2057,
110 };
111 
112 static const char * device_name = "A2DP Source Demo 00:00:00:00:00:00";
113 static btstack_packet_callback_registration_t hci_event_callback_registration;
114 
115 // mac 2011:    static const char * device_addr_string = "04:0C:CE:E4:85:D3";
116 // pts:         static const char * device_addr_string = "00:1B:DC:08:0A:A5";
117 // mac 2013:    static const char * device_addr_string = "84:38:35:65:d1:15";
118 // phone 2013:  static const char * device_addr_string = "D8:BB:2C:DF:F0:F2";
119 // minijambox:
120 static const char * device_addr_string = "00:21:3C:AC:F7:38";
121 // head phones: static const char * device_addr_string = "00:18:09:28:50:18";
122 // bt dongle:   static const char * device_addr_string = "00:15:83:5F:9D:46";
123 // RT-B6:       static const char * device_addr_string = "00:75:58:FF:C9:7D";
124 
125 static bd_addr_t device_addr;
126 static uint8_t sdp_a2dp_source_service_buffer[150];
127 static uint8_t media_sbc_codec_configuration[4];
128 static a2dp_media_sending_context_t media_tracker;
129 
130 static uint16_t avrcp_cid;
131 static uint8_t  avrcp_connected;
132 
133 static stream_data_source_t data_source;
134 
135 static int sine_phase;
136 
137 static int hxcmod_initialized;
138 static modcontext mod_context;
139 static tracker_buffer_state trkbuf;
140 
141 
142 /* AVRCP Target context START */
143 static const uint8_t subunit_info[] = {
144     0,0,0,0,
145     1,1,1,1,
146     2,2,2,2,
147     3,3,3,3,
148     4,4,4,4,
149     5,5,5,5,
150     6,6,6,6,
151     7,7,7,7
152 };
153 
154 static uint32_t company_id = 0x112233;
155 static uint8_t companies_num = 1;
156 static uint8_t companies[] = {
157     0x00, 0x19, 0x58 //BT SIG registered CompanyID
158 };
159 
160 static uint8_t events_num = 13;
161 static uint8_t events[] = {
162     AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED,
163     AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED,
164     AVRCP_NOTIFICATION_EVENT_TRACK_REACHED_END,
165     AVRCP_NOTIFICATION_EVENT_TRACK_REACHED_START,
166     AVRCP_NOTIFICATION_EVENT_PLAYBACK_POS_CHANGED,
167     AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED,
168     AVRCP_NOTIFICATION_EVENT_SYSTEM_STATUS_CHANGED,
169     AVRCP_NOTIFICATION_EVENT_PLAYER_APPLICATION_SETTING_CHANGED,
170     AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED,
171     AVRCP_NOTIFICATION_EVENT_AVAILABLE_PLAYERS_CHANGED,
172     AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED,
173     AVRCP_NOTIFICATION_EVENT_UIDS_CHANGED,
174     AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED
175 };
176 
177 typedef struct {
178     uint8_t track_id[8];
179     uint32_t song_length_ms;
180     avrcp_playback_status_t status;
181     uint32_t song_position_ms; // 0xFFFFFFFF if not supported
182 } avrcp_play_status_info_t;
183 
184 // python -c "print('a'*512)"
185 static const char title[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
186 
187 
188 avrcp_track_t tracks[] = {
189     {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, 1, "Sine", "Generated", "AVRCP Demo", "monotone", 12345},
190     {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 2, "Nao-deceased", "Decease", "AVRCP Demo", "vivid", 12345},
191     {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, 3, (char *)title, "Decease", "AVRCP Demo", "vivid", 12345},
192 };
193 int current_track_index;
194 avrcp_play_status_info_t play_info;
195 
196 /* AVRCP Target context END */
197 
198 static void a2dp_demo_send_media_packet(void){
199     int num_bytes_in_frame = btstack_sbc_encoder_sbc_buffer_length();
200     int bytes_in_storage = media_tracker.sbc_storage_count;
201     uint8_t num_frames = bytes_in_storage / num_bytes_in_frame;
202     a2dp_source_stream_send_media_payload(media_tracker.a2dp_cid, media_tracker.local_seid, media_tracker.sbc_storage, bytes_in_storage, num_frames, 0);
203     media_tracker.sbc_storage_count = 0;
204     media_tracker.sbc_ready_to_send = 0;
205 }
206 
207 static void produce_sine_audio(int16_t * pcm_buffer, int num_samples_to_write){
208     int count;
209     for (count = 0; count < num_samples_to_write ; count++){
210         pcm_buffer[count * 2]     = sine_int16[sine_phase];
211         pcm_buffer[count * 2 + 1] = sine_int16[sine_phase];
212         sine_phase++;
213         if (sine_phase >= TABLE_SIZE_441HZ){
214             sine_phase -= TABLE_SIZE_441HZ;
215         }
216     }
217 }
218 
219 static void produce_mod_audio(int16_t * pcm_buffer, int num_samples_to_write){
220     hxcmod_fillbuffer(&mod_context, (unsigned short *) &pcm_buffer[0], num_samples_to_write, &trkbuf);
221 }
222 
223 static void produce_audio(int16_t * pcm_buffer, int num_samples){
224     switch (data_source){
225         case STREAM_SINE:
226             produce_sine_audio(pcm_buffer, num_samples);
227             break;
228         case STREAM_MOD:
229             produce_mod_audio(pcm_buffer, num_samples);
230             break;
231         default:
232             break;
233     }
234 }
235 
236 static int a2dp_demo_fill_sbc_audio_buffer(a2dp_media_sending_context_t * context){
237     // perform sbc encodin
238     int total_num_bytes_read = 0;
239     unsigned int num_audio_samples_per_sbc_buffer = btstack_sbc_encoder_num_audio_frames();
240     while (context->samples_ready >= num_audio_samples_per_sbc_buffer
241         && (context->max_media_payload_size - context->sbc_storage_count) >= btstack_sbc_encoder_sbc_buffer_length()){
242 
243         int16_t pcm_frame[256*NUM_CHANNELS];
244 
245         produce_audio(pcm_frame, num_audio_samples_per_sbc_buffer);
246         btstack_sbc_encoder_process_data(pcm_frame);
247 
248         uint16_t sbc_frame_size = btstack_sbc_encoder_sbc_buffer_length();
249         uint8_t * sbc_frame = btstack_sbc_encoder_sbc_buffer();
250 
251         total_num_bytes_read += num_audio_samples_per_sbc_buffer;
252         memcpy(&context->sbc_storage[context->sbc_storage_count], sbc_frame, sbc_frame_size);
253         context->sbc_storage_count += sbc_frame_size;
254         context->samples_ready -= num_audio_samples_per_sbc_buffer;
255     }
256     return total_num_bytes_read;
257 }
258 
259 static void a2dp_demo_audio_timeout_handler(btstack_timer_source_t * timer){
260     a2dp_media_sending_context_t * context = (a2dp_media_sending_context_t *) btstack_run_loop_get_timer_context(timer);
261     btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS);
262     btstack_run_loop_add_timer(&context->audio_timer);
263     uint32_t now = btstack_run_loop_get_time_ms();
264 
265     uint32_t update_period_ms = AUDIO_TIMEOUT_MS;
266     if (context->time_audio_data_sent > 0){
267         update_period_ms = now - context->time_audio_data_sent;
268     }
269 
270     uint32_t num_samples = (update_period_ms * A2DP_SAMPLE_RATE) / 1000;
271     context->acc_num_missed_samples += (update_period_ms * A2DP_SAMPLE_RATE) % 1000;
272 
273     while (context->acc_num_missed_samples >= 1000){
274         num_samples++;
275         context->acc_num_missed_samples -= 1000;
276     }
277     context->time_audio_data_sent = now;
278     context->samples_ready += num_samples;
279 
280     if (context->sbc_ready_to_send) return;
281 
282     a2dp_demo_fill_sbc_audio_buffer(context);
283 
284     if ((context->sbc_storage_count + btstack_sbc_encoder_sbc_buffer_length()) > context->max_media_payload_size){
285         // schedule sending
286         context->sbc_ready_to_send = 1;
287         a2dp_source_stream_endpoint_request_can_send_now(context->a2dp_cid, context->local_seid);
288     }
289 }
290 
291 static void a2dp_demo_timer_start(a2dp_media_sending_context_t * context){
292     context->max_media_payload_size = a2dp_max_media_payload_size(context->a2dp_cid, context->local_seid);
293     context->sbc_storage_count = 0;
294     context->sbc_ready_to_send = 0;
295     context->streaming = 1;
296     btstack_run_loop_remove_timer(&context->audio_timer);
297     btstack_run_loop_set_timer_handler(&context->audio_timer, a2dp_demo_audio_timeout_handler);
298     btstack_run_loop_set_timer_context(&context->audio_timer, context);
299     btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS);
300     btstack_run_loop_add_timer(&context->audio_timer);
301 }
302 
303 static void a2dp_demo_timer_stop(a2dp_media_sending_context_t * context){
304     context->time_audio_data_sent = 0;
305     context->acc_num_missed_samples = 0;
306     context->samples_ready = 0;
307     context->streaming = 1;
308     context->sbc_storage_count = 0;
309     context->sbc_ready_to_send = 0;
310     btstack_run_loop_remove_timer(&context->audio_timer);
311 }
312 
313 static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
314     UNUSED(channel);
315     UNUSED(size);
316     uint8_t status;
317     uint8_t local_seid;
318     bd_addr_t address;
319     uint16_t cid;
320 
321     if (packet_type != HCI_EVENT_PACKET) return;
322 
323 #ifndef HAVE_BTSTACK_STDIN
324     if (hci_event_packet_get_type(packet) == BTSTACK_EVENT_STATE){
325         if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
326         printf("Create AVDTP Source connection to addr %s.\n", bd_addr_to_str(device_addr));
327         status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid);
328         if (status != ERROR_CODE_SUCCESS){
329             printf("Could not perform command, status 0x%2x\n", status);
330         }
331         return;
332     }
333 #endif
334 
335     if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return;
336     switch (packet[2]){
337         case A2DP_SUBEVENT_INCOMING_CONNECTION_ESTABLISHED:
338             // TODO: check incoming cid
339             a2dp_subevent_incoming_connection_established_get_bd_addr(packet, address);
340             cid = a2dp_subevent_incoming_connection_established_get_a2dp_cid(packet);
341             printf("A2DP_SUBEVENT_INCOMING_CONNECTION_ESTABLISHED, cid 0x%02x,  media_tracker.a2dp_cid 0x%02x\n", cid, media_tracker.a2dp_cid);
342             if (cid != media_tracker.a2dp_cid) break;
343 
344             media_tracker.connected = 1;
345             printf("A2DP: Incoming connection established: address %s, a2dp cid 0x%02x. Create stream on local seid %d.\n",
346                 bd_addr_to_str(address), media_tracker.a2dp_cid, media_tracker.local_seid);
347             status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid);
348             if (status != ERROR_CODE_SUCCESS){
349                 printf("Could not perform command, status 0x%2x\n", status);
350             }
351             break;
352         case A2DP_SUBEVENT_STREAM_ESTABLISHED:
353             media_tracker.connected = 1;
354             a2dp_subevent_stream_established_get_bd_addr(packet, address);
355             status = a2dp_subevent_stream_established_get_status(packet);
356             if (status){
357                 printf("A2DP: Stream establishment failed: status 0x%02x.\n", status);
358                 break;
359             }
360             local_seid = a2dp_subevent_stream_established_get_local_seid(packet);
361             if (local_seid != media_tracker.local_seid){
362                 printf("A2DP: Stream establishment failed: wrong local seid %d, expected %d.\n", local_seid, media_tracker.local_seid);
363                 break;
364             }
365             media_tracker.a2dp_cid = a2dp_subevent_stream_established_get_a2dp_cid(packet);
366             printf("A2DP: Stream established: address %s, a2dp cid 0x%02x, local seid %d, remote seid %d.\n", bd_addr_to_str(address),
367                 media_tracker.a2dp_cid, media_tracker.local_seid, a2dp_subevent_stream_established_get_remote_seid(packet));
368             printf("Start playing mod, cid 0x%02x.\n", media_tracker.a2dp_cid);
369             data_source = STREAM_MOD;
370             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
371             break;
372 
373         case A2DP_SUBEVENT_STREAM_STARTED:
374             play_info.status = AVRCP_PLAYBACK_STATUS_PLAYING;
375             avrcp_target_set_now_playing_info(avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t));
376             avrcp_target_set_playback_status(avrcp_cid, AVRCP_PLAYBACK_STATUS_PLAYING);
377             a2dp_demo_timer_start(&media_tracker);
378             printf("A2DP: Stream started.\n");
379             break;
380 
381         case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW:
382             a2dp_demo_send_media_packet();
383             break;
384 
385         case A2DP_SUBEVENT_STREAM_SUSPENDED:
386             play_info.status = AVRCP_PLAYBACK_STATUS_PAUSED;
387             avrcp_target_set_playback_status(avrcp_cid, AVRCP_PLAYBACK_STATUS_PAUSED);
388             printf("A2DP: Stream paused.\n");
389             a2dp_demo_timer_stop(&media_tracker);
390             break;
391 
392         case A2DP_SUBEVENT_STREAM_RELEASED:
393             avrcp_target_set_now_playing_info(avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t));
394             play_info.status = AVRCP_PLAYBACK_STATUS_STOPPED;
395             avrcp_target_set_playback_status(avrcp_cid, AVRCP_PLAYBACK_STATUS_STOPPED);
396             printf("A2DP: Stream released.\n");
397             a2dp_demo_timer_stop(&media_tracker);
398             break;
399         case A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED:
400             printf("A2DP: Signaling released.\n");
401             cid = a2dp_subevent_signaling_connection_released_get_a2dp_cid(packet);
402             if (cid == media_tracker.a2dp_cid) {
403                 media_tracker.connected = 0;
404                 media_tracker.a2dp_cid = 0;
405             }
406             break;
407         default:
408             printf("A2DP: event 0x%02x is not parsed\n", packet[2]);
409             break;
410     }
411 }
412 
413 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
414     UNUSED(channel);
415     UNUSED(size);
416     bd_addr_t event_addr;
417     uint16_t local_cid;
418     uint8_t  status = ERROR_CODE_SUCCESS;
419 
420     if (packet_type != HCI_EVENT_PACKET) return;
421     if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return;
422 
423     switch (packet[2]){
424         case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: {
425             local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet);
426             // if (avrcp_cid != 0 && avrcp_cid != local_cid) {
427             //     printf("AVRCP: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_cid, local_cid);
428             //     return;
429             // }
430             // if (avrcp_cid != local_cid) break;
431 
432             status = avrcp_subevent_connection_established_get_status(packet);
433             if (status != ERROR_CODE_SUCCESS){
434                 printf("AVRCP: Connection failed: status 0x%02x\n", status);
435                 return;
436             }
437             avrcp_connected = 1;
438             avrcp_cid = local_cid;
439             avrcp_subevent_connection_established_get_bd_addr(packet, event_addr);
440             printf("AVRCP: connected to %s, avrcp_cid 0x%02x\n", bd_addr_to_str(event_addr), local_cid);
441 
442             avrcp_target_set_now_playing_info(avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t));
443             avrcp_target_set_unit_info(avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, company_id);
444             avrcp_target_set_subunit_info(avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, (uint8_t *)subunit_info, sizeof(subunit_info));
445             return;
446         }
447 
448         case AVRCP_SUBEVENT_EVENT_IDS_QUERY:
449             status = avrcp_target_supported_events(avrcp_cid, events_num, events, sizeof(events));
450             break;
451         case AVRCP_SUBEVENT_COMPANY_IDS_QUERY:
452             status = avrcp_target_supported_companies(avrcp_cid, companies_num, companies, sizeof(companies));
453             break;
454         case AVRCP_SUBEVENT_PLAY_STATUS_QUERY:
455             status = avrcp_target_play_status(avrcp_cid, play_info.song_length_ms, play_info.song_position_ms, play_info.status);
456             break;
457         // case AVRCP_SUBEVENT_NOW_PLAYING_INFO_QUERY:
458         //     status = avrcp_target_now_playing_info(avrcp_cid);
459         //     break;
460         case AVRCP_SUBEVENT_OPERATION:{
461             avrcp_operation_id_t operation_id = avrcp_subevent_operation_get_operation_id(packet);
462             if (!media_tracker.connected) break;
463             switch (operation_id){
464                 case AVRCP_OPERATION_ID_PLAY:
465                     printf("AVRCP: PLAY\n");
466                     status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
467                     break;
468                 case AVRCP_OPERATION_ID_PAUSE:
469                     printf("AVRCP: PAUSE\n");
470                     status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
471                     break;
472                 case AVRCP_OPERATION_ID_STOP:
473                     printf("AVRCP: STOP\n");
474                     status = a2dp_source_disconnect(media_tracker.a2dp_cid);
475                     break;
476                 default:
477                     return;
478             }
479             break;
480         }
481         case AVRCP_SUBEVENT_CONNECTION_RELEASED:
482             printf("AVRCP: Channel released: avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet));
483             avrcp_cid = 0;
484             return;
485         default:
486             printf("AVRCP: event not parsed %02x\n", packet[2]);
487             break;
488     }
489 
490     if (status != ERROR_CODE_SUCCESS){
491         printf("Responding to event 0x%02x failed with status 0x%02x\n", packet[2], status);
492     }
493 }
494 
495 #ifdef HAVE_BTSTACK_STDIN
496 static void show_usage(void){
497     bd_addr_t      iut_address;
498     gap_local_bd_addr(iut_address);
499     printf("\n--- Bluetooth A2DP Source/AVRCP Target Demo %s ---\n", bd_addr_to_str(iut_address));
500     printf("b      - AVDTP Source create  connection to addr %s\n", device_addr_string);
501     printf("B      - AVDTP Source disconnect\n");
502     printf("c      - AVRCP Target create connection to addr %s\n", device_addr_string);
503     printf("C      - AVRCP Target disconnect\n");
504     printf("0      - AVRCP reset now playing info\n");
505 
506     printf("x      - start streaming sine\n");
507     if (hxcmod_initialized){
508         printf("z      - start streaming '%s'\n", mod_name);
509     }
510     printf("p      - pause streaming\n");
511 
512     printf("\n--- Bluetooth  AVRCP Target Commands %s ---\n", bd_addr_to_str(iut_address));
513     printf("---\n");
514 }
515 
516 static void stdin_process(char cmd){
517     uint8_t status = ERROR_CODE_SUCCESS;
518     switch (cmd){
519         case 'b':
520             status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid);
521             printf(" - Create AVDTP Source connection to addr %s, cid 0x%02x.\n", bd_addr_to_str(device_addr), media_tracker.a2dp_cid);
522             break;
523         case 'B':
524             printf(" - AVDTP Source Disconnect from cid 0x%2x\n", media_tracker.a2dp_cid);
525             status = a2dp_source_disconnect(media_tracker.a2dp_cid);
526             break;
527         case 'c':
528             printf(" - Create AVRCP Target connection to addr %s.\n", bd_addr_to_str(device_addr));
529             status = avrcp_target_connect(device_addr, &avrcp_cid);
530             break;
531         case 'C':
532             printf(" - AVRCP Target disconnect\n");
533             status = avrcp_target_disconnect(avrcp_cid);
534             break;
535 
536         case '\n':
537         case '\r':
538             break;
539 
540         case 't':
541             printf("STREAM_PTS_TEST.\n");
542             data_source = STREAM_PTS_TEST;
543             avrcp_target_set_now_playing_info(avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t));
544             if (!media_tracker.connected) break;
545             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
546             break;
547 
548         case 'x':
549             avrcp_target_set_now_playing_info(avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t));
550             printf("Playing sine.\n");
551             data_source = STREAM_SINE;
552             if (!media_tracker.connected) break;
553             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
554             break;
555         case 'z':
556             avrcp_target_set_now_playing_info(avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t));
557             printf("Playing mod.\n");
558             data_source = STREAM_MOD;
559             if (!media_tracker.connected) break;
560             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
561             break;
562         case 'p':
563             if (!media_tracker.connected) break;
564             printf("Pause stream.\n");
565             status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
566             break;
567         case '0':
568             avrcp_target_set_now_playing_info(avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t));
569             printf("Reset now playing info\n");
570             break;
571         default:
572             show_usage();
573             return;
574     }
575     if (status != ERROR_CODE_SUCCESS){
576         printf("Could not perform command, status 0x%2x\n", status);
577     }
578 }
579 #endif
580 
581 
582 int btstack_main(int argc, const char * argv[]);
583 int btstack_main(int argc, const char * argv[]){
584     (void)argc;
585     (void)argv;
586 
587     // register for HCI events
588     hci_event_callback_registration.callback = &packet_handler;
589     hci_add_event_handler(&hci_event_callback_registration);
590 
591     l2cap_init();
592     // Initialize AVDTP Source
593     a2dp_source_init();
594     a2dp_source_register_packet_handler(&packet_handler);
595 
596     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));
597     if (!local_stream_endpoint){
598         printf("A2DP source demo: not enough memory to create local stream endpoint\n");
599         return 1;
600     }
601     media_tracker.local_seid = avdtp_local_seid(local_stream_endpoint);
602 
603     // Initialize AVRCP Target
604     avrcp_target_init();
605     avrcp_target_register_packet_handler(&avrcp_target_packet_handler);
606     // Initialize SDP
607     sdp_init();
608     memset(sdp_a2dp_source_service_buffer, 0, sizeof(sdp_a2dp_source_service_buffer));
609     a2dp_source_create_sdp_record(sdp_a2dp_source_service_buffer, 0x10002, 1, NULL, NULL);
610     sdp_register_service(sdp_a2dp_source_service_buffer);
611 
612     gap_set_local_name(device_name);
613     gap_discoverable_control(1);
614     gap_set_class_of_device(0x200408);
615 
616     hxcmod_initialized = hxcmod_init(&mod_context);
617     if (hxcmod_initialized){
618         hxcmod_setcfg(&mod_context, A2DP_SAMPLE_RATE, 16, 1, 1, 1);
619         hxcmod_load(&mod_context, (void *) &mod_data, mod_len);
620         printf("loaded mod '%s', size %u\n", mod_name, mod_len);
621     }
622     // parse human readable Bluetooth address
623     sscanf_bd_addr(device_addr_string, device_addr);
624 
625 #ifdef HAVE_BTSTACK_STDIN
626     btstack_stdin_setup(stdin_process);
627 #endif
628     // turn on!
629     hci_power_control(HCI_POWER_ON);
630     return 0;
631 }
632 /* EXAMPLE_END */
633