xref: /btstack/example/avrcp_browsing_client.c (revision 954cc391b7ff237c6d9460ea14cf8b96b1fbd1e4)
1462aa085SMilanka Ringwald /*
2462aa085SMilanka Ringwald  * Copyright (C) 2016 BlueKitchen GmbH
3462aa085SMilanka Ringwald  *
4462aa085SMilanka Ringwald  * Redistribution and use in source and binary forms, with or without
5462aa085SMilanka Ringwald  * modification, are permitted provided that the following conditions
6462aa085SMilanka Ringwald  * are met:
7462aa085SMilanka Ringwald  *
8462aa085SMilanka Ringwald  * 1. Redistributions of source code must retain the above copyright
9462aa085SMilanka Ringwald  *    notice, this list of conditions and the following disclaimer.
10462aa085SMilanka Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11462aa085SMilanka Ringwald  *    notice, this list of conditions and the following disclaimer in the
12462aa085SMilanka Ringwald  *    documentation and/or other materials provided with the distribution.
13462aa085SMilanka Ringwald  * 3. Neither the name of the copyright holders nor the names of
14462aa085SMilanka Ringwald  *    contributors may be used to endorse or promote products derived
15462aa085SMilanka Ringwald  *    from this software without specific prior written permission.
16462aa085SMilanka Ringwald  * 4. Any redistribution, use, or modification is done solely for
17462aa085SMilanka Ringwald  *    personal benefit and not for any commercial purpose or for
18462aa085SMilanka Ringwald  *    monetary gain.
19462aa085SMilanka Ringwald  *
20462aa085SMilanka Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21462aa085SMilanka Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22462aa085SMilanka Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23462aa085SMilanka Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24462aa085SMilanka Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25462aa085SMilanka Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26462aa085SMilanka Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27462aa085SMilanka Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28462aa085SMilanka Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29462aa085SMilanka Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30462aa085SMilanka Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31462aa085SMilanka Ringwald  * SUCH DAMAGE.
32462aa085SMilanka Ringwald  *
33462aa085SMilanka Ringwald  * Please inquire about commercial licensing options at
34462aa085SMilanka Ringwald  * [email protected]
35462aa085SMilanka Ringwald  *
36462aa085SMilanka Ringwald  */
37462aa085SMilanka Ringwald 
38462aa085SMilanka Ringwald #define __BTSTACK_FILE__ "avrcp_browsing_client.c"
39462aa085SMilanka Ringwald 
40462aa085SMilanka Ringwald /*
41462aa085SMilanka Ringwald  * avrcp_browsing_client.c
42462aa085SMilanka Ringwald  */
43462aa085SMilanka Ringwald 
44462aa085SMilanka Ringwald // *****************************************************************************
45462aa085SMilanka Ringwald /* EXAMPLE_START(avrcp_browsing_client): Browse media players and media information on a remote device.
46462aa085SMilanka Ringwald  *
47462aa085SMilanka Ringwald  * @text This example demonstrates how to use the AVRCP Controller Browsing service to
48462aa085SMilanka Ringwald  * browse madia players and media information on a remote AVRCP Source device.
49462aa085SMilanka Ringwald  *
50462aa085SMilanka Ringwald  * @test To test with a remote device, e.g. a mobile phone,
51462aa085SMilanka Ringwald  * pair from the remote device with the demo, then use the UI for browsing (tap
52462aa085SMilanka Ringwald  * SPACE on the console to show the available AVRCP commands).
53462aa085SMilanka Ringwald  *
54462aa085SMilanka Ringwald  */
55462aa085SMilanka Ringwald // *****************************************************************************
56462aa085SMilanka Ringwald 
57462aa085SMilanka Ringwald #include <stdint.h>
58*954cc391SMilanka Ringwald #include <inttypes.h>
59462aa085SMilanka Ringwald #include <stdio.h>
60462aa085SMilanka Ringwald #include <stdlib.h>
61462aa085SMilanka Ringwald #include <string.h>
62462aa085SMilanka Ringwald 
63462aa085SMilanka Ringwald #include "btstack.h"
64462aa085SMilanka Ringwald 
65462aa085SMilanka Ringwald #ifdef HAVE_BTSTACK_STDIN
66462aa085SMilanka Ringwald #include "btstack_stdin.h"
67462aa085SMilanka Ringwald #endif
68462aa085SMilanka Ringwald 
69462aa085SMilanka Ringwald #ifdef HAVE_BTSTACK_STDIN
70462aa085SMilanka Ringwald // mac 2011: static bd_addr_t remote = {0x04, 0x0C, 0xCE, 0xE4, 0x85, 0xD3};
71462aa085SMilanka Ringwald // pts: static bd_addr_t remote = {0x00, 0x1B, 0xDC, 0x08, 0x0A, 0xA5};
72462aa085SMilanka Ringwald // mac 2013:
73462aa085SMilanka Ringwald // static const char * device_addr_string = "84:38:35:65:d1:15";
74462aa085SMilanka Ringwald // iPhone 5S: static const char * device_addr_string = "54:E4:3A:26:A2:39";
75462aa085SMilanka Ringwald // phone 2013:
76462aa085SMilanka Ringwald static const char * device_addr_string = "D8:BB:2C:DF:F1:08";
77462aa085SMilanka Ringwald static bd_addr_t device_addr;
78462aa085SMilanka Ringwald #endif
79462aa085SMilanka Ringwald 
80462aa085SMilanka Ringwald static uint16_t avrcp_cid = 0;
81462aa085SMilanka Ringwald static uint8_t  avrcp_connected = 0;
82462aa085SMilanka Ringwald 
83462aa085SMilanka Ringwald static uint16_t browsing_cid = 0;
84462aa085SMilanka Ringwald static uint8_t  avrcp_browsing_connected = 0;
85462aa085SMilanka Ringwald static uint8_t  sdp_avrcp_browsing_controller_service_buffer[200];
86462aa085SMilanka Ringwald 
87*954cc391SMilanka Ringwald static uint8_t browsing_query_active = 0;
88*954cc391SMilanka Ringwald static avrcp_media_item_context_t media_item_context;
89*954cc391SMilanka Ringwald 
90462aa085SMilanka Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration;
91462aa085SMilanka Ringwald 
92462aa085SMilanka Ringwald static uint8_t ertm_buffer[10000];
93462aa085SMilanka Ringwald static l2cap_ertm_config_t ertm_config = {
94462aa085SMilanka Ringwald     1,  // ertm mandatory
95462aa085SMilanka Ringwald     2,  // max transmit, some tests require > 1
96462aa085SMilanka Ringwald     2000,
97462aa085SMilanka Ringwald     12000,
98462aa085SMilanka Ringwald     144,    // l2cap ertm mtu
99462aa085SMilanka Ringwald     4,
100462aa085SMilanka Ringwald     4,
101462aa085SMilanka Ringwald };
102462aa085SMilanka Ringwald 
103462aa085SMilanka Ringwald 
104462aa085SMilanka Ringwald /* @section Main Application Setup
105462aa085SMilanka Ringwald  *
106462aa085SMilanka Ringwald  * @text The Listing MainConfiguration shows how to setup AVRCP Controller Browsing service.
107462aa085SMilanka Ringwald  * To announce AVRCP Controller Browsing service, you need to create corresponding
108462aa085SMilanka Ringwald  * SDP record and register it with the SDP service.
109462aa085SMilanka Ringwald  * You'll also need to register several packet handlers:
110462aa085SMilanka Ringwald  * - stdin_process callback - used to trigger AVRCP commands, such are get media players, playlists, albums, etc. Requires HAVE_BTSTACK_STDIN.
111462aa085SMilanka Ringwald  * - avrcp_browsing_controller_packet_handler - used to receive answers for AVRCP commands.
112462aa085SMilanka Ringwald  *
113462aa085SMilanka Ringwald  */
114462aa085SMilanka Ringwald 
115462aa085SMilanka Ringwald /* LISTING_START(MainConfiguration): Setup Audio Sink and AVRCP Controller services */
116462aa085SMilanka Ringwald static void avrcp_browsing_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
117462aa085SMilanka Ringwald #ifdef HAVE_BTSTACK_STDIN
118462aa085SMilanka Ringwald static void stdin_process(char cmd);
119462aa085SMilanka Ringwald #endif
120462aa085SMilanka Ringwald 
121462aa085SMilanka Ringwald #define BROWSING_ENABLED 1
122462aa085SMilanka Ringwald 
123462aa085SMilanka Ringwald int btstack_main(int argc, const char * argv[]);
124462aa085SMilanka Ringwald int btstack_main(int argc, const char * argv[]){
125462aa085SMilanka Ringwald     (void)argc;
126462aa085SMilanka Ringwald     (void)argv;
127462aa085SMilanka Ringwald 
128462aa085SMilanka Ringwald     // Register for HCI events.
129462aa085SMilanka Ringwald     hci_event_callback_registration.callback = &avrcp_browsing_controller_packet_handler;
130462aa085SMilanka Ringwald     hci_add_event_handler(&hci_event_callback_registration);
131462aa085SMilanka Ringwald 
132462aa085SMilanka Ringwald     // Initialize L2CAP.
133462aa085SMilanka Ringwald     l2cap_init();
134462aa085SMilanka Ringwald 
135462aa085SMilanka Ringwald     // Initialize AVRCP Controller.
136462aa085SMilanka Ringwald     avrcp_controller_init();
137462aa085SMilanka Ringwald     // Register AVRCP for HCI events.
138462aa085SMilanka Ringwald     avrcp_controller_register_packet_handler(&avrcp_browsing_controller_packet_handler);
139462aa085SMilanka Ringwald 
140247956eaSMilanka Ringwald     // Initialize AVRCP Browsing Controller, HCI events will be sent to the AVRCP Controller callback.
141462aa085SMilanka Ringwald     avrcp_browsing_controller_init();
142e30788a3SMilanka Ringwald     // // Register AVRCP for HCI events.
143e30788a3SMilanka Ringwald     // avrcp_browsing_controller_register_packet_handler(&avrcp_browsing_controller_packet_handler);
144462aa085SMilanka Ringwald 
145462aa085SMilanka Ringwald     // Initialize SDP.
146462aa085SMilanka Ringwald     sdp_init();
147462aa085SMilanka Ringwald 
148462aa085SMilanka Ringwald     // Create AVRCP service record and register it with SDP.
149462aa085SMilanka Ringwald     memset(sdp_avrcp_browsing_controller_service_buffer, 0, sizeof(sdp_avrcp_browsing_controller_service_buffer));
150462aa085SMilanka Ringwald     avrcp_controller_create_sdp_record(sdp_avrcp_browsing_controller_service_buffer, 0x10001, BROWSING_ENABLED, 1, NULL, NULL);
151462aa085SMilanka Ringwald     sdp_register_service(sdp_avrcp_browsing_controller_service_buffer);
152462aa085SMilanka Ringwald 
153462aa085SMilanka Ringwald     // Set local name with a template Bluetooth address, that will be automatically
154462aa085SMilanka Ringwald     // replaced with a actual address once it is available, i.e. when BTstack boots
155462aa085SMilanka Ringwald     // up and starts talking to a Bluetooth module.
156462aa085SMilanka Ringwald     gap_set_local_name("AVRCP Browsing Client 00:00:00:00:00:00");
157462aa085SMilanka Ringwald     gap_discoverable_control(1);
158462aa085SMilanka Ringwald     gap_set_class_of_device(0x200408);
159462aa085SMilanka Ringwald 
160462aa085SMilanka Ringwald #ifdef HAVE_BTSTACK_STDIN
161462aa085SMilanka Ringwald     // Parse human readable Bluetooth address.
162462aa085SMilanka Ringwald     sscanf_bd_addr(device_addr_string, device_addr);
163462aa085SMilanka Ringwald     btstack_stdin_setup(stdin_process);
164462aa085SMilanka Ringwald #endif
165462aa085SMilanka Ringwald     printf("Starting BTstack ...\n");
166462aa085SMilanka Ringwald     hci_power_control(HCI_POWER_ON);
167462aa085SMilanka Ringwald     return 0;
168462aa085SMilanka Ringwald }
169462aa085SMilanka Ringwald /* LISTING_END */
170462aa085SMilanka Ringwald 
171462aa085SMilanka Ringwald static void avrcp_browsing_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
172462aa085SMilanka Ringwald     UNUSED(channel);
173*954cc391SMilanka Ringwald     int pos;
174462aa085SMilanka Ringwald 
175*954cc391SMilanka Ringwald     switch(packet_type){
176*954cc391SMilanka Ringwald         case AVRCP_BROWSING_DATA_PACKET:
177*954cc391SMilanka Ringwald             pos = 0;
178*954cc391SMilanka Ringwald             browsing_query_active = 1;
179*954cc391SMilanka Ringwald             avrcp_browsing_item_type_t data_type = (avrcp_browsing_item_type_t)packet[pos++];
180*954cc391SMilanka Ringwald             pos += 2; // length
181*954cc391SMilanka Ringwald 
182*954cc391SMilanka Ringwald             switch (data_type){
183*954cc391SMilanka Ringwald                 case AVRCP_BROWSING_MEDIA_PLAYER_ITEM:{
184*954cc391SMilanka Ringwald                     printf("AVRCP Browsing Client: Received media player item \n");
185*954cc391SMilanka Ringwald 
186*954cc391SMilanka Ringwald                     uint16_t player_id = big_endian_read_16(packet, pos);
187*954cc391SMilanka Ringwald                     pos += 2;
188*954cc391SMilanka Ringwald                     avrcp_browsing_media_player_major_type_t major_type = packet[pos++];
189*954cc391SMilanka Ringwald                     avrcp_browsing_media_player_subtype_t subtype = big_endian_read_32(packet, pos);
190*954cc391SMilanka Ringwald                     pos += 4;
191*954cc391SMilanka Ringwald                     uint8_t status = packet[pos++];
192*954cc391SMilanka Ringwald                     uint8_t feature_bitmask[16];
193*954cc391SMilanka Ringwald                     memcpy(feature_bitmask, packet, 16);
194*954cc391SMilanka Ringwald                     pos += 16;
195*954cc391SMilanka Ringwald                     printf("player ID 0x%04x\n, major_type %d, subtype %d, status %d\n", player_id, major_type, subtype, status);
196*954cc391SMilanka Ringwald                     printf_hexdump(feature_bitmask, 16);
197*954cc391SMilanka Ringwald                     break;
198*954cc391SMilanka Ringwald                 }
199*954cc391SMilanka Ringwald                 case AVRCP_BROWSING_FOLDER_ITEM:{
200*954cc391SMilanka Ringwald                     printf("AVRCP Browsing Client: Received folder item \n");
201*954cc391SMilanka Ringwald 
202*954cc391SMilanka Ringwald                     uint32_t folder_uid_high = big_endian_read_32(packet, pos);
203*954cc391SMilanka Ringwald                     pos += 4;
204*954cc391SMilanka Ringwald                     uint32_t folder_uid_low  = big_endian_read_32(packet, pos+4);
205*954cc391SMilanka Ringwald                     pos += 4;
206*954cc391SMilanka Ringwald                     avrcp_browsing_folder_type_t folder_type = packet[pos++];
207*954cc391SMilanka Ringwald                     uint8_t  is_playable = packet[pos++];
208*954cc391SMilanka Ringwald                     uint16_t charset = big_endian_read_16(packet, pos);
209*954cc391SMilanka Ringwald                     pos += 2;
210*954cc391SMilanka Ringwald                     uint16_t displayable_name_length = big_endian_read_16(packet, pos);
211*954cc391SMilanka Ringwald                     pos += 2;
212*954cc391SMilanka Ringwald                     char value[20];
213*954cc391SMilanka Ringwald                     uint16_t value_len = sizeof(value) > displayable_name_length ? displayable_name_length:sizeof(value)-1;
214*954cc391SMilanka Ringwald                     memcpy(value, packet+pos, value_len);
215*954cc391SMilanka Ringwald                     value[value_len] = 0;
216*954cc391SMilanka Ringwald                     printf("Folder UID: 0x%08" PRIx32 "%08" PRIx32 ", folder_type 0x%02x, is_playable %d, charset 0x%02x, displayable_name_length %d, value %s\n",
217*954cc391SMilanka Ringwald                         folder_uid_high, folder_uid_low, folder_type, is_playable, charset, displayable_name_length, value);
218*954cc391SMilanka Ringwald                     break;
219*954cc391SMilanka Ringwald                 }
220*954cc391SMilanka Ringwald                 case AVRCP_BROWSING_MEDIA_ELEMENT_ITEM:{
221*954cc391SMilanka Ringwald                     printf("AVRCP Browsing Client: Received media item \n");
222*954cc391SMilanka Ringwald 
223*954cc391SMilanka Ringwald                     uint32_t media_uid_high = big_endian_read_32(packet, pos);
224*954cc391SMilanka Ringwald                     pos += 4;
225*954cc391SMilanka Ringwald                     uint32_t media_uid_low  = big_endian_read_32(packet, pos+4);
226*954cc391SMilanka Ringwald                     pos += 4;
227*954cc391SMilanka Ringwald                     avrcp_browsing_media_type_t media_type = packet[pos++];
228*954cc391SMilanka Ringwald                     uint16_t charset = big_endian_read_16(packet, pos);
229*954cc391SMilanka Ringwald                     pos += 2;
230*954cc391SMilanka Ringwald                     uint16_t displayable_name_length = big_endian_read_16(packet, pos);
231*954cc391SMilanka Ringwald                     pos += 2;
232*954cc391SMilanka Ringwald                     pos += displayable_name_length;
233*954cc391SMilanka Ringwald                     printf("Media UID: 0x%08" PRIx32 "%08" PRIx32 ", media_type 0x%02x, charset 0x%02x, displayable_name_length %d\n", media_uid_high, media_uid_low, media_type, charset, displayable_name_length);
234*954cc391SMilanka Ringwald 
235*954cc391SMilanka Ringwald                     uint8_t num_attributes = packet[pos++];
236*954cc391SMilanka Ringwald                     printf("Num media attributes %d\n", num_attributes);
237*954cc391SMilanka Ringwald 
238*954cc391SMilanka Ringwald                     for (avrcp_media_item_iterator_init(&media_item_context, size-pos, packet+pos); avrcp_media_item_iterator_has_more(&media_item_context); avrcp_media_item_iterator_next(&media_item_context)){
239*954cc391SMilanka Ringwald                         uint32_t attr_id            = avrcp_media_item_iterator_get_attr_id(&media_item_context);
240*954cc391SMilanka Ringwald                         uint16_t attr_charset       = avrcp_media_item_iterator_get_attr_charset(&media_item_context);
241*954cc391SMilanka Ringwald                         uint16_t attr_value_length  = avrcp_media_item_iterator_get_attr_value_len(&media_item_context);
242*954cc391SMilanka Ringwald                         const uint8_t * attr_value  = avrcp_media_item_iterator_get_attr_value(&media_item_context);
243*954cc391SMilanka Ringwald 
244*954cc391SMilanka Ringwald                         printf("Attr ID 0x%08" PRIx32 ", charset %d, attr_value_length %d, value %s", attr_id, attr_charset, attr_value_length, attr_value);
245*954cc391SMilanka Ringwald                     }
246*954cc391SMilanka Ringwald                     break;
247*954cc391SMilanka Ringwald                 }
248*954cc391SMilanka Ringwald 
249*954cc391SMilanka Ringwald                 default:
250*954cc391SMilanka Ringwald                     log_error("AVRCP browsing: unknown browsable item type 0%02x", data_type);
251*954cc391SMilanka Ringwald                     break;
252*954cc391SMilanka Ringwald             }
253*954cc391SMilanka Ringwald             break;
254*954cc391SMilanka Ringwald 
255*954cc391SMilanka Ringwald         case HCI_EVENT_PACKET:
256*954cc391SMilanka Ringwald             if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return;
257462aa085SMilanka Ringwald             uint16_t local_cid;
258462aa085SMilanka Ringwald             uint8_t  status = 0xFF;
259*954cc391SMilanka Ringwald             bd_addr_t address;
260462aa085SMilanka Ringwald 
261462aa085SMilanka Ringwald             switch (packet[2]){
262462aa085SMilanka Ringwald                 case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: {
263462aa085SMilanka Ringwald                     local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet);
264462aa085SMilanka Ringwald                     if (browsing_cid != 0 && browsing_cid != local_cid) {
265247956eaSMilanka Ringwald                         printf("AVRCP Browsing Client: AVRCP Controller connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", browsing_cid, local_cid);
266462aa085SMilanka Ringwald                         return;
267462aa085SMilanka Ringwald                     }
268462aa085SMilanka Ringwald 
269462aa085SMilanka Ringwald                     status = avrcp_subevent_connection_established_get_status(packet);
270462aa085SMilanka Ringwald                     if (status != ERROR_CODE_SUCCESS){
271247956eaSMilanka Ringwald                         printf("AVRCP Browsing Client: AVRCP Controller connection failed: status 0x%02x\n", status);
272462aa085SMilanka Ringwald                         browsing_cid = 0;
273462aa085SMilanka Ringwald                         return;
274462aa085SMilanka Ringwald                     }
275462aa085SMilanka Ringwald 
276462aa085SMilanka Ringwald                     avrcp_cid = local_cid;
277462aa085SMilanka Ringwald                     avrcp_connected = 1;
278*954cc391SMilanka Ringwald                     avrcp_subevent_connection_established_get_bd_addr(packet, address);
279*954cc391SMilanka Ringwald                     printf("AVRCP Browsing Client: AVRCP Controller Channel successfully opened: %s, avrcp_cid 0x%02x\n", bd_addr_to_str(address), avrcp_cid);
280462aa085SMilanka Ringwald                     return;
281462aa085SMilanka Ringwald                 }
282462aa085SMilanka Ringwald                 case AVRCP_SUBEVENT_CONNECTION_RELEASED:
283247956eaSMilanka Ringwald                     printf("AVRCP Browsing Client: AVRCP Controller Channel released: avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet));
284462aa085SMilanka Ringwald                     browsing_cid = 0;
285462aa085SMilanka Ringwald                     avrcp_browsing_connected = 0;
286462aa085SMilanka Ringwald                     return;
287462aa085SMilanka Ringwald 
288462aa085SMilanka Ringwald                 case AVRCP_SUBEVENT_BROWSING_CONNECTION_ESTABLISHED: {
289462aa085SMilanka Ringwald                     local_cid = avrcp_subevent_browsing_connection_established_get_browsing_cid(packet);
290462aa085SMilanka Ringwald                     if (browsing_cid != 0 && browsing_cid != local_cid) {
291247956eaSMilanka Ringwald                         printf("AVRCP Browsing Client: AVRCP Browsing Controller Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", browsing_cid, local_cid);
292462aa085SMilanka Ringwald                         return;
293462aa085SMilanka Ringwald                     }
294462aa085SMilanka Ringwald 
295462aa085SMilanka Ringwald                     status = avrcp_subevent_browsing_connection_established_get_status(packet);
296462aa085SMilanka Ringwald                     if (status != ERROR_CODE_SUCCESS){
297247956eaSMilanka Ringwald                         printf("AVRCP Browsing Client: AVRCP Browsing Controller Connection failed: status 0x%02x\n", status);
298462aa085SMilanka Ringwald                         browsing_cid = 0;
299462aa085SMilanka Ringwald                         return;
300462aa085SMilanka Ringwald                     }
301462aa085SMilanka Ringwald 
302462aa085SMilanka Ringwald                     browsing_cid = local_cid;
303462aa085SMilanka Ringwald                     avrcp_browsing_connected = 1;
304*954cc391SMilanka Ringwald                     avrcp_subevent_browsing_connection_established_get_bd_addr(packet, address);
305*954cc391SMilanka Ringwald                     printf("AVRCP Browsing Client: AVRCP Browsing Controller Channel successfully opened: %s, browsing_cid 0x%02x\n", bd_addr_to_str(address), browsing_cid);
306462aa085SMilanka Ringwald                     return;
307462aa085SMilanka Ringwald                 }
308462aa085SMilanka Ringwald                 case AVRCP_SUBEVENT_BROWSING_CONNECTION_RELEASED:
309247956eaSMilanka Ringwald                     printf("AVRCP Browsing Client: AVRCP Browsing Controller Channel released: browsing_cid 0x%02x\n", avrcp_subevent_browsing_connection_released_get_browsing_cid(packet));
310462aa085SMilanka Ringwald                     browsing_cid = 0;
311462aa085SMilanka Ringwald                     avrcp_browsing_connected = 0;
312462aa085SMilanka Ringwald                     return;
313*954cc391SMilanka Ringwald 
314*954cc391SMilanka Ringwald                 case AVRCP_SUBEVENT_BROWSING_MEDIA_ITEM_DONE:
315*954cc391SMilanka Ringwald                     printf("AVRCP Browsing Client: query done with browsing status 0x%02x, bluetooth status 0x%02x.\n",
316*954cc391SMilanka Ringwald                         avrcp_subevent_browsing_media_item_done_get_browsing_status(packet),
317*954cc391SMilanka Ringwald                         avrcp_subevent_browsing_media_item_done_get_bluetooth_status(packet));
318*954cc391SMilanka Ringwald                     browsing_query_active = 0;
319*954cc391SMilanka Ringwald                     break;
320*954cc391SMilanka Ringwald 
321462aa085SMilanka Ringwald                 default:
322462aa085SMilanka Ringwald                     printf("AVRCP Browsing Client: event is not parsed\n");
323462aa085SMilanka Ringwald                     break;
324462aa085SMilanka Ringwald             }
325*954cc391SMilanka Ringwald             break;
326*954cc391SMilanka Ringwald 
327*954cc391SMilanka Ringwald         default:
328*954cc391SMilanka Ringwald             break;
329*954cc391SMilanka Ringwald     }
330*954cc391SMilanka Ringwald 
331462aa085SMilanka Ringwald }
332462aa085SMilanka Ringwald 
333462aa085SMilanka Ringwald #ifdef HAVE_BTSTACK_STDIN
334462aa085SMilanka Ringwald static void show_usage(void){
335462aa085SMilanka Ringwald     bd_addr_t      iut_address;
336462aa085SMilanka Ringwald     gap_local_bd_addr(iut_address);
337462aa085SMilanka Ringwald     printf("\n--- Bluetooth AVRCP Controller Connection Test Console %s ---\n", bd_addr_to_str(iut_address));
338247956eaSMilanka Ringwald     printf("a      - AVRCP Controller create connection to addr %s\n", bd_addr_to_str(device_addr));
339247956eaSMilanka Ringwald     printf("c      - AVRCP Browsing Controller create connection to addr %s\n", bd_addr_to_str(device_addr));
340247956eaSMilanka Ringwald     printf("C      - AVRCP Browsing Controller disconnect\n");
341247956eaSMilanka Ringwald     printf("A      - AVRCP Controller disconnect\n");
342ed0df7b2SMilanka Ringwald     printf("p      - Get player list\n");
343462aa085SMilanka Ringwald     printf("---\n");
344462aa085SMilanka Ringwald }
345462aa085SMilanka Ringwald #endif
346462aa085SMilanka Ringwald 
347ed0df7b2SMilanka Ringwald 
348462aa085SMilanka Ringwald #ifdef HAVE_BTSTACK_STDIN
349462aa085SMilanka Ringwald static void stdin_process(char cmd){
350462aa085SMilanka Ringwald     uint8_t status = ERROR_CODE_SUCCESS;
351462aa085SMilanka Ringwald 
352*954cc391SMilanka Ringwald     if (cmd != 'a' && cmd != 'A' && cmd != 'c' && cmd != 'C'){
353*954cc391SMilanka Ringwald         if (browsing_query_active){
354*954cc391SMilanka Ringwald             printf("Query active, try later!\n");
355*954cc391SMilanka Ringwald             return;
356*954cc391SMilanka Ringwald         }
357*954cc391SMilanka Ringwald     }
358*954cc391SMilanka Ringwald 
359462aa085SMilanka Ringwald     switch (cmd){
360462aa085SMilanka Ringwald         case 'a':
361247956eaSMilanka Ringwald             printf(" - Create AVRCP connection for control to addr %s.\n", bd_addr_to_str(device_addr));
362462aa085SMilanka Ringwald             status = avrcp_controller_connect(device_addr, &avrcp_cid);
363462aa085SMilanka Ringwald             break;
364247956eaSMilanka Ringwald         case 'A':
365247956eaSMilanka Ringwald             if (avrcp_connected){
366247956eaSMilanka Ringwald                 printf(" - AVRCP Controller disconnect from addr %s.\n", bd_addr_to_str(device_addr));
367247956eaSMilanka Ringwald                 status = avrcp_controller_disconnect(avrcp_cid);
368247956eaSMilanka Ringwald                 break;
369247956eaSMilanka Ringwald             }
370247956eaSMilanka Ringwald             printf("AVRCP Controller already disconnected\n");
371247956eaSMilanka Ringwald             break;
372247956eaSMilanka Ringwald 
373462aa085SMilanka Ringwald         case 'c':
374462aa085SMilanka Ringwald             if (!avrcp_connected) {
375247956eaSMilanka Ringwald                 printf(" You must first create AVRCP connection for control to addr %s.\n", bd_addr_to_str(device_addr));
376462aa085SMilanka Ringwald                 break;
377462aa085SMilanka Ringwald             }
378462aa085SMilanka Ringwald             printf(" - Create AVRCP connection for browsing to addr %s.\n", bd_addr_to_str(device_addr));
379462aa085SMilanka Ringwald             status = avrcp_browsing_controller_connect(device_addr, ertm_buffer, sizeof(ertm_buffer), &ertm_config, &browsing_cid);
380462aa085SMilanka Ringwald             break;
381462aa085SMilanka Ringwald         case 'C':
382247956eaSMilanka Ringwald             if (avrcp_browsing_connected){
383247956eaSMilanka Ringwald                 printf(" - AVRCP Browsing Controller disconnect from addr %s.\n", bd_addr_to_str(device_addr));
384462aa085SMilanka Ringwald                 status = avrcp_browsing_controller_disconnect(browsing_cid);
385462aa085SMilanka Ringwald                 break;
386247956eaSMilanka Ringwald             }
387247956eaSMilanka Ringwald             printf("AVRCP Browsing Controller already disconnected\n");
388247956eaSMilanka Ringwald             break;
389ed0df7b2SMilanka Ringwald 
390ed0df7b2SMilanka Ringwald         case 'p':
391ed0df7b2SMilanka Ringwald             printf("AVRCP Browsing: get player list\n");
392ed0df7b2SMilanka Ringwald             avrcp_browsing_controller_get_player_list(browsing_cid);
393ed0df7b2SMilanka Ringwald             break;
394ed0df7b2SMilanka Ringwald 
395462aa085SMilanka Ringwald         case '\n':
396462aa085SMilanka Ringwald         case '\r':
397462aa085SMilanka Ringwald             break;
398462aa085SMilanka Ringwald         default:
399462aa085SMilanka Ringwald             show_usage();
400462aa085SMilanka Ringwald             return;
401462aa085SMilanka Ringwald     }
402ed0df7b2SMilanka Ringwald 
403462aa085SMilanka Ringwald     if (status != ERROR_CODE_SUCCESS){
404462aa085SMilanka Ringwald         printf("Could not perform command, status 0x%2x\n", status);
405462aa085SMilanka Ringwald     }
406462aa085SMilanka Ringwald }
407462aa085SMilanka Ringwald #endif
408462aa085SMilanka Ringwald /* EXAMPLE_END */
409