pbap_client: implement pbap_lookup_by_number

This commit is contained in:
Matthias Ringwald 2018-09-26 16:45:03 +02:00
parent ed573b145a
commit e03b79ab68
4 changed files with 120 additions and 10 deletions

View File

@ -9,6 +9,7 @@ VPATH += ${BTSTACK_ROOT}/3rd-party/md5
VPATH += ${BTSTACK_ROOT}/3rd-party/micro-ecc
VPATH += ${BTSTACK_ROOT}/3rd-party/bluedroid/decoder/srce
VPATH += ${BTSTACK_ROOT}/3rd-party/bluedroid/encoder//srce
VPATH += ${BTSTACK_ROOT}/3rd-party/yxml
CFLAGS += -I.
CFLAGS += -I${BTSTACK_ROOT}/src/ble
@ -19,6 +20,7 @@ CFLAGS += -I${BTSTACK_ROOT}/3rd-party/md5
CFLAGS += -I${BTSTACK_ROOT}/3rd-party/micro-ecc
CFLAGS += -I${BTSTACK_ROOT}/3rd-party/bluedroid/decoder/include
CFLAGS += -I${BTSTACK_ROOT}/3rd-party/bluedroid/encoder/include
CFLAGS += -I${BTSTACK_ROOT}/3rd-party/yxml
# for CVSD/SBC PLC
LDFLAGS += -lm
@ -194,7 +196,7 @@ ant_test: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ant_test.c
sdp_rfcomm_query: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ${PAN_OBJ} ${SDP_CLIENT} sdp_rfcomm_query.c
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
pbap_client_demo: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ${SDP_CLIENT} md5.o obex_iterator.c goep_client.c pbap_client.c pbap_client_demo.c
pbap_client_demo: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ${SDP_CLIENT} md5.o obex_iterator.o goep_client.o yxml.o pbap_client.o pbap_client_demo.o
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
sdp_general_query: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ${SDP_CLIENT} sdp_general_query.c

View File

@ -72,7 +72,9 @@ static bd_addr_t remote_addr;
// Nexus 7 "30-85-A9-54-2E-78"
// iPhone SE "BC:EC:5D:E6:15:03"
// PTS "001BDC080AA5"
static char * remote_addr_string = "001BDC080AA5";
static char * remote_addr_string = "BC:EC:5D:E6:15:03";
static char * phone_number = "911";
static btstack_packet_callback_registration_t hci_event_callback_registration;
static uint16_t pbap_cid;
@ -92,6 +94,7 @@ static void show_usage(void){
printf("d - get phonebook size\n");
printf("e - pull phonebook\n");
printf("f - disconnnect\n");
printf("g - Lookup contact with number '%s'\n", phone_number);
printf("p - authenticate using password '0000'\n");
printf("\n");
}
@ -119,6 +122,9 @@ static void stdin_process(char c){
case 'f':
pbap_disconnect(pbap_cid);
break;
case 'g':
pbap_lookup_by_number(pbap_cid, phone_number);
break;
case 'p':
pbap_authentication_password(pbap_cid, "0000");
break;

View File

@ -75,16 +75,23 @@
#include "classic/sdp_client_rfcomm.h"
#include "btstack_event.h"
#include "md5.h"
#include "yxml.h"
#include "classic/obex.h"
#include "classic/obex_iterator.h"
#include "classic/goep_client.h"
#include "classic/pbap_client.h"
#define PBAP_MAX_PHONE_NUMBER_LEN 30
// 796135f0-f0c5-11d8-0966- 0800200c9a66
uint8_t pbap_uuid[] = { 0x79, 0x61, 0x35, 0xf0, 0xf0, 0xc5, 0x11, 0xd8, 0x09, 0x66, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66};
const char * pbap_type = "x-bt/phonebook";
const char * pbap_name = "pb.vcf";
const char * pbap_phonebook_type = "x-bt/phonebook";
const char * pbap_phonebook_name = "pb.vcf";
const char * pbap_vcard_listing_type = "x-bt/vcard-listing";
const char * pbap_vcard_listing_name = "pb";
typedef enum {
PBAP_INIT = 0,
@ -107,6 +114,10 @@ typedef enum {
PBAP_W4_SET_PATH_ELEMENT_COMPLETE,
PBAP_W2_GET_PHONEBOOK_SIZE,
PBAP_W4_GET_PHONEBOOK_SIZE_COMPLETE,
//
PBAP_W2_GET_CARD_LIST,
PBAP_W4_GET_CARD_LIST_COMPLETE,
} pbap_state_t;
typedef struct pbap_client {
@ -118,10 +129,13 @@ typedef struct pbap_client {
uint16_t goep_cid;
btstack_packet_handler_t client_handler;
const char * current_folder;
const char * phone_number;
uint16_t set_path_offset;
uint8_t authentication_options;
uint16_t authentication_nonce[16];
const char * authentication_password;
yxml_t xml_parser;
uint8_t xml_buffer[50];
} pbap_client_t;
static pbap_client_t _pbap_client;
@ -213,9 +227,10 @@ static void pbap_handle_can_send_now(void){
uint8_t path_element[20];
uint16_t path_element_start;
uint16_t path_element_len;
uint8_t application_parameters[20];
uint8_t application_parameters[PBAP_MAX_PHONE_NUMBER_LEN + 10];
uint8_t challenge_response[36];
int i;
uint16_t phone_number_len;
MD5_CTX md5_ctx;
@ -261,8 +276,8 @@ static void pbap_handle_can_send_now(void){
case PBAP_W2_PULL_PHONEBOOK:
case PBAP_W2_GET_PHONEBOOK_SIZE:
goep_client_create_get_request(pbap_client->goep_cid);
goep_client_add_header_type(pbap_client->goep_cid, pbap_type);
goep_client_add_header_name(pbap_client->goep_cid, pbap_name);
goep_client_add_header_type(pbap_client->goep_cid, pbap_phonebook_type);
goep_client_add_header_name(pbap_client->goep_cid, pbap_phonebook_name);
if (pbap_client->state == PBAP_W2_GET_PHONEBOOK_SIZE){
// Regular TLV wih 1-byte len
application_parameters[0] = PBAP_APPLICATION_PARAMETER_MAX_LIST_COUNT;
@ -278,6 +293,25 @@ static void pbap_handle_can_send_now(void){
// send packet
goep_client_execute(pbap_client->goep_cid);
break;
case PBAP_W2_GET_CARD_LIST:
goep_client_create_get_request(pbap_client->goep_cid);
goep_client_add_header_type(pbap_client->goep_cid, pbap_vcard_listing_type);
goep_client_add_header_name(pbap_client->goep_cid, pbap_vcard_listing_name);
// Regular TLV wih 1-byte len
i = 0;
phone_number_len = btstack_min(PBAP_MAX_PHONE_NUMBER_LEN, strlen(pbap_client->phone_number));
application_parameters[i++] = PBAP_APPLICATION_PARAMETER_SEARCH_VALUE;
application_parameters[i++] = phone_number_len;
memcpy(&application_parameters[i], pbap_client->phone_number, phone_number_len);
i += phone_number_len;
application_parameters[i++] = PBAP_APPLICATION_PARAMETER_SEARCH_PROPERTY;
application_parameters[i++] = 1;
application_parameters[i++] = 0x01; // Number
goep_client_add_header_application_parameters(pbap_client->goep_cid, i, &application_parameters[0]);
pbap_client->state = PBAP_W4_GET_CARD_LIST_COMPLETE;
// send packet
goep_client_execute(pbap_client->goep_cid);
break;
case PBAP_W2_SET_PATH_ROOT:
goep_client_create_set_path_request(pbap_client->goep_cid, 1 << 1); // Dont create directory
// On Android 4.2 Cyanogenmod, using "" as path fails
@ -392,9 +426,7 @@ static void pbap_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *
break;
case GOEP_DATA_PACKET:
// TODO: handle chunked data
#if 1
// obex_dump_packet(goep_client_get_request_opcode(pbap_client->goep_cid), packet, size);
#endif
switch (pbap_client->state){
case PBAP_W4_CONNECT_RESPONSE:
switch (packet[0]){
@ -495,6 +527,59 @@ static void pbap_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *
}
pbap_client_emit_phonebook_size_event(pbap_client, OBEX_UNKNOWN_ERROR, 0);
break;
case PBAP_W4_GET_CARD_LIST_COMPLETE:
printf("PBAP_W4_GET_CARD_LIST_COMPLETE\n");
if (packet[0] == OBEX_RESP_CONTINUE){
pbap_client->state = PBAP_W2_GET_CARD_LIST;
goep_client_request_can_send_now(pbap_client->goep_cid);
} else if (packet[0] == OBEX_RESP_SUCCESS){
for (obex_iterator_init_with_response_packet(&it, goep_client_get_request_opcode(pbap_client->goep_cid), packet, size); obex_iterator_has_more(&it) ; obex_iterator_next(&it)){
uint8_t hi = obex_iterator_get_hi(&it);
if (hi == OBEX_HEADER_END_OF_BODY){
uint16_t data_len = obex_iterator_get_data_len(&it);
const uint8_t * data = obex_iterator_get_data(&it);
// now try parsing it
yxml_init(&pbap_client->xml_parser, pbap_client->xml_buffer, sizeof(pbap_client->xml_buffer));
int card_found = 0;
int name_found = 0;
char name[32];
while (data_len--){
yxml_ret_t r = yxml_parse(&pbap_client->xml_parser, *data++);
switch (r){
case YXML_ELEMSTART:
card_found = strcmp("card", pbap_client->xml_parser.elem) == 0;
break;
case YXML_ELEMEND:
card_found = 0;
break;
case YXML_ATTRSTART:
if (!card_found) break;
name_found = strcmp("name", pbap_client->xml_parser.attr) == 0;
break;
case YXML_ATTRVAL:
if (!name_found) break;
// "In UTF-8, characters from the U+0000..U+10FFFF range (the UTF-16 accessible range) are encoded using sequences of 1 to 4 octets."
if (strlen(name) + 4 + 1 >= sizeof(name)) break;
strcat(name, pbap_client->xml_parser.data);
break;
case YXML_ATTREND:
if (!name_found) break;
printf("Name: '%s'\n", name);
name_found = 0;
break;
default:
break;
}
}
//
pbap_client->state = PBAP_CONNECTED;
}
}
} else {
// ?
}
break;
default:
break;
}
@ -562,3 +647,12 @@ uint8_t pbap_authentication_password(uint16_t pbap_cid, const char * password){
goep_client_request_can_send_now(pbap_client->goep_cid);
return 0;
}
uint8_t pbap_lookup_by_number(uint16_t pbap_cid, const char * phone_number){
UNUSED(pbap_cid);
if (pbap_client->state != PBAP_CONNECTED) return BTSTACK_BUSY;
pbap_client->state = PBAP_W2_GET_CARD_LIST;
pbap_client->phone_number = phone_number;
goep_client_request_can_send_now(pbap_client->goep_cid);
return 0;
}

View File

@ -94,7 +94,15 @@ uint8_t pbap_get_phonebook_size(uint16_t pbap_cid);
* @param pbap_cid
* @return status
*/
uint8_t pbap_pull_phonebook(uint16_t pbap_cid);
uint8_t pbap_pull_phonebook(uint16_t pbap_cid);
/**
* @brief Lookup contact(s) by phone number
* @param pbap_cid
* @param phone_number
* @return status
*/
uint8_t pbap_lookup_by_number(uint16_t pbap_cid, const char * phone_number);
/* API_END */