1 /* 2 * Copyright (C) 2014 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__ "pbap_client_demo.c" 39 40 // ***************************************************************************** 41 /* EXAMPLE_START(pbap_client_demo): Connect to Phonebook Server and get contacts. 42 * 43 * @text Note: The Bluetooth address of the remote Phonbook server is hardcoded. 44 * Change it before running example, then use the UI to connect to it, to set and 45 * query contacts. 46 */ 47 // ***************************************************************************** 48 49 50 #include "btstack_config.h" 51 52 #include <stdint.h> 53 #include <stdio.h> 54 #include <stdlib.h> 55 #include <string.h> 56 57 #include "btstack_run_loop.h" 58 #include "l2cap.h" 59 #include "classic/rfcomm.h" 60 #include "btstack_event.h" 61 #include "classic/goep_client.h" 62 #include "classic/pbap_client.h" 63 64 #ifdef HAVE_BTSTACK_STDIN 65 #include "btstack_stdin.h" 66 #endif 67 68 static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 69 70 static bd_addr_t remote_addr; 71 // MBP2016 "F4-0F-24-3B-1B-E1" 72 // Nexus 7 "30-85-A9-54-2E-78" 73 // iPhone SE "BC:EC:5D:E6:15:03" 74 // PTS "001BDC080AA5" 75 static char * remote_addr_string = "001BDC080AA5"; 76 77 static char * phone_number = "911"; 78 79 static const char * t_pb_path = "telecom/pb.vcf"; 80 static const char * t_fav_path = "telecom/fav.vcf"; 81 static const char * t_ich_path = "telecom/ich.vcf"; 82 static const char * t_och_path = "telecom/och.vcf"; 83 static const char * t_mch_path = "telecom/mch.vcf"; 84 static const char * t_cch_path = "telecom/cch.vcf"; 85 static const char * t_spd_path = "telecom/spd.vcf"; 86 87 static const char * st_pb_path = "SIM1/telecom/pb.vcf"; 88 static const char * st_ich_path = "SIM1/telecom/ich.vcf"; 89 static const char * st_och_path = "SIM1/telecom/och.vcf"; 90 static const char * st_mch_path = "SIM1/telecom/mch.vcf"; 91 static const char * st_cch_path = "SIM1/telecom/cch.vcf"; 92 93 static btstack_packet_callback_registration_t hci_event_callback_registration; 94 static uint16_t pbap_cid; 95 96 #ifdef HAVE_BTSTACK_STDIN 97 98 // Testig User Interface 99 static void show_usage(void){ 100 bd_addr_t iut_address; 101 gap_local_bd_addr(iut_address); 102 103 printf("\n--- Bluetooth PBAP Client (HF) Test Console %s ---\n", bd_addr_to_str(iut_address)); 104 printf("\n"); 105 printf("a - establish PBAP connection to %s\n", bd_addr_to_str(remote_addr)); 106 printf("b - set phonebook '/telecom/pb'\n"); 107 // printf("c - set phonebook '/SIM1/telecom/pb'\n"); 108 printf("r - set path to '/root/telecom'\n"); 109 printf("v - set vCardSelector to FN\n"); 110 printf("V - set vCardSelectorOperator to AND\n"); 111 printf("d - get size of '%s'\n", t_pb_path); 112 113 printf("e - pull phonebook '%s'\n", t_pb_path); 114 printf("f - pull phonebook '%s'\n", t_fav_path); 115 printf("i - pull phonebook '%s'\n", t_ich_path); 116 printf("o - pull phonebook '%s'\n", t_och_path); 117 printf("m - pull phonebook '%s'\n", t_mch_path); 118 printf("c - pull phonebook '%s'\n", t_cch_path); 119 printf("s - pull phonebook '%s'\n", t_spd_path); 120 121 printf("E - pull phonebook '%s'\n", st_pb_path); 122 printf("I - pull phonebook '%s'\n", st_ich_path); 123 printf("O - pull phonebook '%s'\n", st_och_path); 124 printf("M - pull phonebook '%s'\n", st_mch_path); 125 printf("C - pull phonebook '%s'\n", st_cch_path); 126 127 printf("t - disconnnect\n"); 128 printf("g - Lookup contact with number '%s'\n", phone_number); 129 printf("p - authenticate using password '0000'\n"); 130 printf("r - set path to 'telecom'\n"); 131 printf("x - abort operation\n"); 132 printf("\n"); 133 } 134 135 static void stdin_process(char c){ 136 switch (c){ 137 case 'a': 138 printf("[+] Connecting to %s...\n", bd_addr_to_str(remote_addr)); 139 pbap_connect(&packet_handler, remote_addr, &pbap_cid); 140 break; 141 case 'b': 142 printf("[+] Set phonebook 'telecom/pb'\n"); 143 pbap_set_phonebook(pbap_cid, "telecom/pb"); 144 break; 145 // case 'c': 146 // printf("[+] Set phonebook 'SIM1/telecom/pb'\n"); 147 // pbap_set_phonebook(pbap_cid, "SIM1/telecom/pb"); 148 // break; 149 case 'd': 150 printf("[+] Get size of phonebook '%s'\n", t_pb_path); 151 pbap_get_phonebook_size(pbap_cid, t_pb_path); 152 break; 153 case 'g': 154 pbap_lookup_by_number(pbap_cid, phone_number); 155 break; 156 157 case 'c': 158 printf("[+] Get phonebook '%s'\n", t_cch_path); 159 pbap_pull_phonebook(pbap_cid, t_cch_path); 160 break; 161 case 'e': 162 printf("[+] Get phonebook '%s'\n", t_pb_path); 163 pbap_pull_phonebook(pbap_cid, t_pb_path); 164 break; 165 case 'f': 166 printf("[+] Get phonebook '%s'\n", t_fav_path); 167 pbap_pull_phonebook(pbap_cid, t_fav_path); 168 break; 169 case 'i': 170 printf("[+] Get phonebook '%s'\n", t_ich_path); 171 pbap_pull_phonebook(pbap_cid, t_ich_path); 172 break; 173 case 'm': 174 printf("[+] Get phonebook '%s'\n", t_mch_path); 175 pbap_pull_phonebook(pbap_cid, t_mch_path); 176 break; 177 case 'o': 178 printf("[+] Get phonebook '%s'\n", t_och_path); 179 pbap_pull_phonebook(pbap_cid, t_och_path); 180 break; 181 case 's': 182 printf("[+] Get phonebook '%s'\n", t_spd_path); 183 pbap_pull_phonebook(pbap_cid, t_spd_path); 184 break; 185 186 case 'C': 187 printf("[+] Get phonebook '%s'\n", st_cch_path); 188 pbap_pull_phonebook(pbap_cid, st_cch_path); 189 break; 190 case 'E': 191 printf("[+] Get phonebook '%s'\n", st_pb_path); 192 pbap_pull_phonebook(pbap_cid, st_pb_path); 193 break; 194 case 'I': 195 printf("[+] Get phonebook '%s'\n", st_ich_path); 196 pbap_pull_phonebook(pbap_cid, st_ich_path); 197 break; 198 case 'M': 199 printf("[+] Get phonebook '%s'\n", st_mch_path); 200 pbap_pull_phonebook(pbap_cid, st_mch_path); 201 break; 202 case 'O': 203 printf("[+] Get phonebook '%s'\n", st_och_path); 204 pbap_pull_phonebook(pbap_cid, st_och_path); 205 break; 206 207 case 'p': 208 pbap_authentication_password(pbap_cid, "0000"); 209 break; 210 case 'v': 211 printf("[+] Set vCardSelector 'FN'\n"); 212 pbap_set_vcard_selector(pbap_cid, PBAP_PROPERTY_MASK_FN); 213 break; 214 case 'V': 215 printf("[+] Set vCardSelectorOperator 'AND'\n"); 216 pbap_set_vcard_selector_operator(pbap_cid, PBAP_VCARD_SELECTOR_OPERATOR_AND); 217 break; 218 case 'r': 219 printf("[+] Set path to 'telecom'\n"); 220 pbap_set_phonebook(pbap_cid, "telecom"); 221 break; 222 case 'x': 223 printf("[+] Abort'\n"); 224 pbap_abort(pbap_cid); 225 break; 226 case 't': 227 pbap_disconnect(pbap_cid); 228 break; 229 default: 230 show_usage(); 231 break; 232 } 233 } 234 235 // packet handler for interactive console 236 static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 237 UNUSED(channel); 238 UNUSED(size); 239 int i; 240 uint8_t status; 241 char buffer[32]; 242 switch (packet_type){ 243 case HCI_EVENT_PACKET: 244 switch (hci_event_packet_get_type(packet)) { 245 case BTSTACK_EVENT_STATE: 246 // BTstack activated, get started 247 if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){ 248 show_usage(); 249 } 250 break; 251 case HCI_EVENT_PBAP_META: 252 switch (hci_event_pbap_meta_get_subevent_code(packet)){ 253 case PBAP_SUBEVENT_CONNECTION_OPENED: 254 status = pbap_subevent_connection_opened_get_status(packet); 255 if (status){ 256 printf("[!] Connection failed, status 0x%02x\n", status); 257 } else { 258 printf("[+] Connected\n"); 259 } 260 break; 261 case PBAP_SUBEVENT_CONNECTION_CLOSED: 262 printf("[+] Connection closed\n"); 263 break; 264 case PBAP_SUBEVENT_OPERATION_COMPLETED: 265 printf("[+] Operation complete\n"); 266 break; 267 case PBAP_SUBEVENT_AUTHENTICATION_REQUEST: 268 printf("[?] Authentication requested\n"); 269 break; 270 case PBAP_SUBEVENT_PHONEBOOK_SIZE: 271 status = pbap_subevent_phonebook_size_get_status(packet); 272 if (status){ 273 printf("[!] Get Phonebook size error: 0x%x\n", status); 274 } else { 275 printf("[+] Phonebook size: %u\n", pbap_subevent_phonebook_size_get_phoneboook_size(packet)); 276 } 277 break; 278 case PBAP_SUBEVENT_CARD_RESULT: 279 memcpy(buffer, pbap_subevent_card_result_get_name(packet), pbap_subevent_card_result_get_name_len(packet)); 280 buffer[pbap_subevent_card_result_get_name_len(packet)] = 0; 281 printf("[-] Name: '%s'\n", buffer); 282 memcpy(buffer, pbap_subevent_card_result_get_handle(packet), pbap_subevent_card_result_get_handle_len(packet)); 283 buffer[pbap_subevent_card_result_get_handle_len(packet)] = 0; 284 printf("[-] Handle: '%s'\n", buffer); 285 break; 286 default: 287 break; 288 } 289 break; 290 default: 291 break; 292 } 293 break; 294 case PBAP_DATA_PACKET: 295 for (i=0;i<size;i++){ 296 printf("%c", packet[i]); 297 } 298 break; 299 default: 300 break; 301 } 302 } 303 #else 304 305 // packet handler for emdded system with fixed operation sequence 306 static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 307 UNUSED(channel); 308 UNUSED(size); 309 int i; 310 switch (packet_type){ 311 case HCI_EVENT_PACKET: 312 switch (hci_event_packet_get_type(packet)) { 313 case BTSTACK_EVENT_STATE: 314 // BTstack activated, get started 315 if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){ 316 printf("[+] Connect to Phone Book Server on %s\n", bd_addr_to_str(remote_addr)); 317 pbap_connect(&packet_handler, remote_addr, &pbap_cid); 318 } 319 break; 320 case HCI_EVENT_PBAP_META: 321 switch (hci_event_pbap_meta_get_subevent_code(packet)){ 322 case PBAP_SUBEVENT_CONNECTION_OPENED: 323 printf("[+] Connected\n"); 324 printf("[+] Pull phonebook\n"); 325 pbap_pull_phonebook(pbap_cid); 326 break; 327 case PBAP_SUBEVENT_CONNECTION_CLOSED: 328 printf("[+] Connection closed\n"); 329 break; 330 case PBAP_SUBEVENT_OPERATION_COMPLETED: 331 printf("[+] Operation complete\n"); 332 printf("[+] Pull Phonebook complete\n"); 333 pbap_disconnect(pbap_cid); 334 break; 335 default: 336 break; 337 } 338 break; 339 default: 340 break; 341 } 342 break; 343 case PBAP_DATA_PACKET: 344 for (i=0;i<size;i++){ 345 printf("%c", packet[i]); 346 } 347 break; 348 default: 349 break; 350 } 351 } 352 #endif 353 354 int btstack_main(int argc, const char * argv[]); 355 int btstack_main(int argc, const char * argv[]){ 356 357 (void)argc; 358 (void)argv; 359 360 // init L2CAP 361 l2cap_init(); 362 363 // init RFCOM 364 rfcomm_init(); 365 366 // init GOEP Client 367 goep_client_init(); 368 369 // init PBAP Client 370 pbap_client_init(); 371 372 // register for HCI events 373 hci_event_callback_registration.callback = &packet_handler; 374 hci_add_event_handler(&hci_event_callback_registration); 375 376 sscanf_bd_addr(remote_addr_string, remote_addr); 377 378 #ifdef HAVE_BTSTACK_STDIN 379 btstack_stdin_setup(stdin_process); 380 #endif 381 382 // turn on! 383 hci_power_control(HCI_POWER_ON); 384 385 return 0; 386 } 387 /* EXAMPLE_END */ 388