1 /*
2 * Copyright (C) 2017 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 #include <stdint.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42
43 #include "btstack.h"
44
45 //#define AVRCP_BROWSING_ENABLED
46
47 static btstack_packet_callback_registration_t hci_event_callback_registration;
48
49 static bd_addr_t device_addr;
50 static uint8_t value[100];
51 // iPhone SE: static const char * device_addr_string = "BC:EC:5D:E6:15:03";
52 // iPhone 6: static const char * device_addr_string = "D8:BB:2C:DF:F1:08";
53 // iPhone 5S:
54 static const char * device_addr_string = "54:E4:3A:26:A2:39";
55 // Wiko Sunny: static const char * device_addr_string = "A0-4C-5B-0F-B2-42";
56 // pts: static const char * device_addr_string = "00:1B:DC:08:0A:A5";
57
58 static uint16_t avrcp_cid = 0;
59 static uint8_t sdp_avrcp_controller_service_buffer[200];
60
packet_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)61 static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
62 UNUSED(channel);
63 UNUSED(size);
64 bd_addr_t event_addr;
65 uint16_t local_cid;
66 uint8_t status = 0xFF;
67 switch (packet_type) {
68 case HCI_EVENT_PACKET:
69 switch (hci_event_packet_get_type(packet)) {
70 case HCI_EVENT_DISCONNECTION_COMPLETE:
71 // connection closed -> quit test app
72 printf("AVRCP: HCI_EVENT_DISCONNECTION_COMPLETE\n");
73 break;
74 case HCI_EVENT_AVRCP_META:
75 switch (packet[2]){
76 case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: {
77 local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet);
78 if (avrcp_cid != local_cid) {
79 printf("Connection is not established, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_cid, local_cid);
80 return;
81 }
82
83 status = avrcp_subevent_connection_established_get_status(packet);
84 avrcp_subevent_connection_established_get_bd_addr(packet, event_addr);
85 if (status != ERROR_CODE_SUCCESS){
86 printf("AVRCP Connection failed: status 0x%02x\n", status);
87 avrcp_cid = 0;
88 return;
89 }
90 printf("Channel successfully opened: %s, avrcp_cid 0x%02x\n", bd_addr_to_str(event_addr), avrcp_cid);
91 // automatically enable notifications
92 avrcp_controller_enable_notification(avrcp_cid, AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED);
93 avrcp_controller_enable_notification(avrcp_cid, AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED);
94 return;
95 }
96 case AVRCP_SUBEVENT_CONNECTION_RELEASED:
97 printf("Channel released: avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet));
98 avrcp_cid = 0;
99 return;
100 default:
101 break;
102 }
103
104 status = packet[5];
105 local_cid = little_endian_read_16(packet, 3);
106 if (avrcp_cid != local_cid) return;
107
108 printf("AVRCP: command status: %s, ", avrcp_ctype2str(status));
109 switch (packet[2]){
110 case AVRCP_SUBEVENT_NOTIFICATION_PLAYBACK_STATUS_CHANGED:
111 printf("notification, playback status changed %s\n", avrcp_play_status2str(avrcp_subevent_notification_playback_status_changed_get_play_status(packet)));
112 return;
113 case AVRCP_SUBEVENT_NOTIFICATION_NOW_PLAYING_CONTENT_CHANGED:
114 printf("notification, playing content changed\n");
115 return;
116 case AVRCP_SUBEVENT_NOTIFICATION_TRACK_CHANGED:
117 printf("notification track changed\n");
118 return;
119 case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED:
120 printf("notification absolute volume changed %d\n", avrcp_subevent_notification_volume_changed_get_absolute_volume(packet));
121 return;
122 case AVRCP_SUBEVENT_NOTIFICATION_AVAILABLE_PLAYERS_CHANGED:
123 printf("notification changed\n");
124 return;
125 case AVRCP_SUBEVENT_SHUFFLE_AND_REPEAT_MODE:{
126 uint8_t shuffle_mode = avrcp_subevent_shuffle_and_repeat_mode_get_shuffle_mode(packet);
127 uint8_t repeat_mode = avrcp_subevent_shuffle_and_repeat_mode_get_repeat_mode(packet);
128 printf("%s, %s\n", avrcp_shuffle2str(shuffle_mode), avrcp_repeat2str(repeat_mode));
129 break;
130 }
131
132 case AVRCP_SUBEVENT_NOW_PLAYING_TITLE_INFO:
133 printf("AVRCP_SUBEVENT_NOW_PLAYING_TITLE_INFO len %d \n", avrcp_subevent_now_playing_title_info_get_value_len(packet));
134 if (avrcp_subevent_now_playing_title_info_get_value_len(packet) > 0){
135 memcpy(value, avrcp_subevent_now_playing_title_info_get_value(packet), avrcp_subevent_now_playing_title_info_get_value_len(packet));
136 printf(" Title: %s\n", value);
137 }
138 break;
139
140 case AVRCP_SUBEVENT_NOW_PLAYING_ARTIST_INFO:
141 if (avrcp_subevent_now_playing_artist_info_get_value_len(packet) > 0){
142 memcpy(value, avrcp_subevent_now_playing_artist_info_get_value(packet), avrcp_subevent_now_playing_artist_info_get_value_len(packet));
143 printf(" Title: %s\n", value);
144 }
145 break;
146
147 case AVRCP_SUBEVENT_NOW_PLAYING_ALBUM_INFO:
148 if (avrcp_subevent_now_playing_album_info_get_value_len(packet) > 0){
149 memcpy(value, avrcp_subevent_now_playing_album_info_get_value(packet), avrcp_subevent_now_playing_album_info_get_value_len(packet));
150 printf(" Title: %s\n", value);
151 }
152 break;
153
154 case AVRCP_SUBEVENT_NOW_PLAYING_GENRE_INFO:
155 if (avrcp_subevent_now_playing_genre_info_get_value_len(packet) > 0){
156 memcpy(value, avrcp_subevent_now_playing_genre_info_get_value(packet), avrcp_subevent_now_playing_genre_info_get_value_len(packet));
157 printf(" Title: %s\n", value);
158 }
159 break;
160 case AVRCP_SUBEVENT_PLAY_STATUS:
161 printf("song length: %d ms, song position: %d ms, play status: %s\n",
162 avrcp_subevent_play_status_get_song_length(packet),
163 avrcp_subevent_play_status_get_song_position(packet),
164 avrcp_play_status2str(avrcp_subevent_play_status_get_play_status(packet)));
165 break;
166 case AVRCP_SUBEVENT_OPERATION_COMPLETE:
167 printf("operation done %s\n", avrcp_operation2str(avrcp_subevent_operation_complete_get_operation_id(packet)));
168 break;
169 case AVRCP_SUBEVENT_OPERATION_START:
170 printf("operation start %s\n", avrcp_operation2str(avrcp_subevent_operation_complete_get_operation_id(packet)));
171 break;
172 case AVRCP_SUBEVENT_PLAYER_APPLICATION_VALUE_RESPONSE:
173 // response to set shuffle and repeat mode
174 printf("\n");
175 break;
176 default:
177 printf("Not implemented\n");
178 break;
179 }
180 break;
181 default:
182 break;
183 }
184 break;
185 default:
186 // other packet type
187 break;
188 }
189
190 }
191
192 #ifdef HAVE_BTSTACK_STDIN
show_usage(void)193 static void show_usage(void){
194 bd_addr_t iut_address;
195 gap_local_bd_addr(iut_address);
196 printf("\n--- Bluetooth AVRCP Test Console %s ---\n", bd_addr_to_str(iut_address));
197 printf("c - create connection to addr %s\n", bd_addr_to_str(device_addr));
198 printf("D - disconnect\n");
199 printf("\n--- Bluetooth AVRCP Commands ---\n");
200 printf("i - get play status\n");
201 printf("j - get now playing info\n");
202 printf("k - play\n");
203 printf("K - stop\n");
204 printf("L - pause\n");
205 printf("m - start fast forward\n");
206 printf("M - stop fast forward\n");
207 printf("n - start rewind\n");
208 printf("N - stop rewind\n");
209 printf("o - forward\n");
210 printf("O - backward\n");
211 printf("p - volume up\n");
212 printf("P - volume down\n");
213 printf("r - absolute volume of 50 percent\n");
214 printf("s - mute\n");
215 printf("t - skip\n");
216 printf("u - query repeat and shuffle mode\n");
217 printf("v - repeat single track\n");
218 printf("x - repeat all tracks\n");
219 printf("X - disable repeat mode\n");
220 printf("z - shuffle all tracks\n");
221 printf("Z - disable shuffle mode\n");
222
223 printf("Ctrl-c - exit\n");
224 printf("---\n");
225 }
226
stdin_process(char cmd)227 static void stdin_process(char cmd){
228 uint8_t status = ERROR_CODE_SUCCESS;
229 switch (cmd){
230 case 'c':
231 printf(" - Create AVRCP connection to addr %s.\n", bd_addr_to_str(device_addr));
232 status = avrcp_connect(device_addr, &avrcp_cid);
233 break;
234 case 'B':
235 printf(" - Disconnect\n");
236 status = avrcp_disconnect(avrcp_cid);
237 break;
238 case 'i':
239 printf(" - get play status\n");
240 status = avrcp_controller_get_play_status(avrcp_cid);
241 break;
242 case 'j':
243 printf(" - get now playing info\n");
244 status = avrcp_controller_get_now_playing_info(avrcp_cid);
245 break;
246 case 'k':
247 printf(" - play\n");
248 status = avrcp_controller_play(avrcp_cid);
249 break;
250 case 'K':
251 printf(" - stop\n");
252 status = avrcp_controller_stop(avrcp_cid);
253 break;
254 case 'L':
255 printf(" - pause\n");
256 status = avrcp_controller_pause(avrcp_cid);
257 break;
258 case 'm':
259 printf(" - start fast forward\n");
260 status = avrcp_controller_press_and_hold_fast_forward(avrcp_cid);
261 break;
262 case 'M':
263 printf(" - stop fast forward\n");
264 status = avrcp_controller_release_press_and_hold_cmd(avrcp_cid);
265 break;
266 case 'n':
267 printf(" - start rewind\n");
268 status = avrcp_controller_press_and_hold_rewind(avrcp_cid);
269 break;
270 case 'N':
271 printf(" - stop rewind\n");
272 status = avrcp_controller_release_press_and_hold_cmd(avrcp_cid);
273 break;
274 case 'o':
275 printf(" - forward\n");
276 status = avrcp_controller_forward(avrcp_cid);
277 break;
278 case 'O':
279 printf(" - backward\n");
280 status = avrcp_controller_backward(avrcp_cid);
281 break;
282 case 'p':
283 printf(" - volume up\n");
284 status = avrcp_controller_volume_up(avrcp_cid);
285 break;
286 case 'P':
287 printf(" - volume down\n");
288 status = avrcp_controller_volume_down(avrcp_cid);
289 break;
290 case 'r':
291 printf(" - absolute volume of 50 percent\n");
292 status = avrcp_controller_set_absolute_volume(avrcp_cid, 50);
293 break;
294 case 's':
295 printf(" - mute\n");
296 status = avrcp_controller_mute(avrcp_cid);
297 break;
298 case 't':
299 printf(" - skip\n");
300 status = avrcp_controller_skip(avrcp_cid);
301 break;
302 case 'u':
303 printf(" - query repeat and shuffle mode\n");
304 status = avrcp_controller_query_shuffle_and_repeat_modes(avrcp_cid);
305 break;
306 case 'v':
307 printf(" - repeat single track\n");
308 status = avrcp_controller_set_repeat_mode(avrcp_cid, AVRCP_REPEAT_MODE_SINGLE_TRACK);
309 break;
310 case 'x':
311 printf(" - repeat all tracks\n");
312 status = avrcp_controller_set_repeat_mode(avrcp_cid, AVRCP_REPEAT_MODE_ALL_TRACKS);
313 break;
314 case 'X':
315 printf(" - disable repeat mode\n");
316 status = avrcp_controller_set_repeat_mode(avrcp_cid, AVRCP_REPEAT_MODE_OFF);
317 break;
318 case 'z':
319 printf(" - shuffle all tracks\n");
320 status = avrcp_controller_set_shuffle_mode(avrcp_cid, AVRCP_SHUFFLE_MODE_ALL_TRACKS);
321 break;
322 case 'Z':
323 printf(" - disable shuffle mode\n");
324 status = avrcp_controller_set_shuffle_mode(avrcp_cid, AVRCP_SHUFFLE_MODE_OFF);
325 break;
326 default:
327 show_usage();
328 return;
329 }
330 if (status != ERROR_CODE_SUCCESS){
331 printf("Could not perform command, status 0x%02x\n", status);
332 }
333 }
334 #endif
335
336 int btstack_main(int argc, const char * argv[]);
btstack_main(int argc,const char * argv[])337 int btstack_main(int argc, const char * argv[]){
338 UNUSED(argc);
339 (void)argv;
340 /* Register for HCI events */
341 hci_event_callback_registration.callback = &packet_handler;
342 hci_add_event_handler(&hci_event_callback_registration);
343
344 l2cap_init();
345
346 // Initialize AVRCP service.
347 avrcp_init();
348 avrcp_register_packet_handler(&packet_handler);
349 // Initialize AVRCP COntroller
350 avrcp_controller_init();
351 avrcp_controller_register_packet_handler(&packet_handler);
352
353 // Initialize SDP
354 sdp_init();
355 memset(sdp_avrcp_controller_service_buffer, 0, sizeof(sdp_avrcp_controller_service_buffer));
356
357 uint16_t supported_features = AVRCP_FEATURE_MASK_CATEGORY_PLAYER_OR_RECORDER;
358 #ifdef AVRCP_BROWSING_ENABLED
359 supported_features |= AVRCP_FEATURE_MASK_BROWSING;
360 #endif
361 avrcp_controller_create_sdp_record(sdp_avrcp_controller_service_buffer, 0x10001, supported_features, NULL, NULL);
362 sdp_register_service(sdp_avrcp_controller_service_buffer);
363
364 gap_set_local_name("BTstack AVRCP Test");
365 gap_discoverable_control(1);
366 // gap_set_class_of_device(0x200408);
367
368 // parse human readable Bluetooth address
369 sscanf_bd_addr(device_addr_string, device_addr);
370
371 // turn on!
372 hci_power_control(HCI_POWER_ON);
373
374 #ifdef HAVE_BTSTACK_STDIN
375 btstack_stdin_setup(stdin_process);
376 #endif
377 return 0;
378 }
379