mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-04-15 23:42:52 +00:00
map_client: set path, get folders and messages, draft impl
This commit is contained in:
parent
47e764c40c
commit
0cb4d92c9e
@ -74,9 +74,18 @@ typedef enum {
|
||||
MAP_CONNECT_RESPONSE_RECEIVED,
|
||||
MAP_CONNECTED,
|
||||
|
||||
MAP_W2_SET_PATH_ROOT,
|
||||
MAP_W4_SET_PATH_ROOT_COMPLETE,
|
||||
MAP_W2_SET_PATH_ELEMENT,
|
||||
MAP_W4_SET_PATH_ELEMENT_COMPLETE,
|
||||
|
||||
MAP_W2_SEND_GET_FOLDERS,
|
||||
MAP_W4_FOLDERS,
|
||||
|
||||
MAP_W2_SEND_GET_MESSAGES_FOR_FOLDER,
|
||||
MAP_W4_MESSAGES_IN_FOLDER,
|
||||
MAP_W2_SEND_GET_MESSAGE_WITH_HANDLE,
|
||||
MAP_W4_MESSAGE,
|
||||
|
||||
MAP_W2_SEND_DISCONNECT_REQUEST,
|
||||
MAP_W4_DISCONNECT_RESPONSE,
|
||||
} map_state_t;
|
||||
@ -89,6 +98,13 @@ typedef struct map_client {
|
||||
uint8_t incoming;
|
||||
uint16_t goep_cid;
|
||||
btstack_packet_handler_t client_handler;
|
||||
|
||||
const char * folder_name;
|
||||
const char * current_folder;
|
||||
uint16_t set_path_offset;
|
||||
|
||||
map_message_handle_t message_handle;
|
||||
uint8_t get_message_attachment;
|
||||
} map_client_t;
|
||||
|
||||
static map_client_t _map_client;
|
||||
@ -126,9 +142,38 @@ static void map_client_emit_connection_closed_event(map_client_t * context){
|
||||
context->client_handler(HCI_EVENT_PACKET, context->cid, &event[0], pos);
|
||||
}
|
||||
|
||||
static void map_client_emit_operation_complete_event(map_client_t * context, uint8_t status){
|
||||
uint8_t event[6];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_MAP_META;
|
||||
pos++; // skip len
|
||||
event[pos++] = MAP_SUBEVENT_OPERATION_COMPLETED;
|
||||
little_endian_store_16(event,pos,context->cid);
|
||||
pos+=2;
|
||||
event[pos++]= status;
|
||||
event[1] = pos - 2;
|
||||
if (pos != sizeof(event)) log_error("map_client_emit_can_send_now_event size %u", pos);
|
||||
context->client_handler(HCI_EVENT_PACKET, context->cid, &event[0], pos);
|
||||
}
|
||||
|
||||
static void map_message_handle_to_str(char * p, const map_message_handle_t msg_handle){
|
||||
int i;
|
||||
for (i = 0; i < MAP_MESSAGE_HANDLE_SIZE ; i++) {
|
||||
uint8_t byte = msg_handle[i];
|
||||
*p++ = char_for_nibble(byte >> 4);
|
||||
*p++ = char_for_nibble(byte & 0x0F);
|
||||
}
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
static void map_handle_can_send_now(void){
|
||||
uint8_t application_parameters[6];
|
||||
int pos = 0;
|
||||
char map_message_handle_to_str_buffer[MAP_MESSAGE_HANDLE_SIZE * 2 + 1];
|
||||
uint8_t path_element[20];
|
||||
uint16_t path_element_start;
|
||||
uint16_t path_element_len;
|
||||
int done;
|
||||
|
||||
switch (map_client->state){
|
||||
case MAP_W2_SEND_CONNECT_REQUEST:
|
||||
@ -136,7 +181,7 @@ static void map_handle_can_send_now(void){
|
||||
goep_client_add_header_target(map_client->goep_cid, 16, map_client_access_service_uuid);
|
||||
// Mandatory if the PSE advertises a PbapSupportedFeatures attribute in its SDP record, else excluded.
|
||||
// if (goep_client_get_map_supported_features(map_client->goep_cid) != MAP_FEATURES_NOT_PRESENT){
|
||||
application_parameters[0] = 0x29; // MAP_APPLICATION_PARAMETER_PBAP_SUPPORTED_FEATURES;
|
||||
application_parameters[0] = 0x29; // MAP_APPLICATION_PARAMETER_MAP_SUPPORTED_FEATURES;
|
||||
application_parameters[1] = 4;
|
||||
big_endian_store_32(application_parameters, 2, map_supported_features);
|
||||
goep_client_add_header_application_parameters(map_client->goep_cid, 6, &application_parameters[0]);
|
||||
@ -145,17 +190,85 @@ static void map_handle_can_send_now(void){
|
||||
map_client->state = MAP_W4_CONNECT_RESPONSE;
|
||||
goep_client_execute(map_client->goep_cid);
|
||||
break;
|
||||
|
||||
case MAP_W2_SEND_DISCONNECT_REQUEST:
|
||||
goep_client_create_disconnect_request(map_client->goep_cid);
|
||||
map_client->state = MAP_W4_DISCONNECT_RESPONSE;
|
||||
goep_client_execute(map_client->goep_cid);
|
||||
break;
|
||||
|
||||
case MAP_W2_SET_PATH_ROOT:
|
||||
goep_client_create_set_path_request(map_client->goep_cid, 1 << 1); // Don’t create directory
|
||||
goep_client_add_header_name(map_client->goep_cid, "");
|
||||
// state
|
||||
map_client->state = MAP_W4_SET_PATH_ROOT_COMPLETE;
|
||||
// send packet
|
||||
goep_client_execute(map_client->goep_cid);
|
||||
break;
|
||||
case MAP_W2_SET_PATH_ELEMENT:
|
||||
// find '/' or '\0'
|
||||
path_element_start = map_client->set_path_offset;
|
||||
while (map_client->current_folder[map_client->set_path_offset] != '\0' &&
|
||||
map_client->current_folder[map_client->set_path_offset] != '/'){
|
||||
map_client->set_path_offset++;
|
||||
}
|
||||
path_element_len = map_client->set_path_offset-path_element_start;
|
||||
memcpy(path_element, &map_client->current_folder[path_element_start], path_element_len);
|
||||
path_element[path_element_len] = 0;
|
||||
|
||||
// skip /
|
||||
if (map_client->current_folder[map_client->set_path_offset] == '/'){
|
||||
map_client->set_path_offset++;
|
||||
}
|
||||
|
||||
// done?
|
||||
done = map_client->current_folder[map_client->set_path_offset] == '\0';
|
||||
|
||||
// status
|
||||
log_info("Path element '%s', done %u", path_element, done);
|
||||
|
||||
goep_client_create_set_path_request(map_client->goep_cid, 1 << 1); // Don’t create directory
|
||||
goep_client_add_header_name(map_client->goep_cid, (const char *) path_element); // next element
|
||||
// state
|
||||
map_client->state = MAP_W4_SET_PATH_ELEMENT_COMPLETE;
|
||||
// send packet
|
||||
goep_client_execute(map_client->goep_cid);
|
||||
break;
|
||||
|
||||
case MAP_W2_SEND_GET_FOLDERS:
|
||||
goep_client_create_get_request(map_client->goep_cid);
|
||||
goep_client_add_header_type(map_client->goep_cid, "x-obex/folder-listing");
|
||||
map_client->state = MAP_W4_FOLDERS;
|
||||
goep_client_execute(map_client->goep_cid);
|
||||
break;
|
||||
|
||||
case MAP_W2_SEND_GET_MESSAGES_FOR_FOLDER:
|
||||
goep_client_create_get_request(map_client->goep_cid);
|
||||
goep_client_add_header_type(map_client->goep_cid, "x-bt/MAP-msg-listing");
|
||||
goep_client_add_header_name(map_client->goep_cid, map_client->folder_name);
|
||||
map_client->state = MAP_W4_MESSAGES_IN_FOLDER;
|
||||
goep_client_execute(map_client->goep_cid);
|
||||
break;
|
||||
|
||||
case MAP_W2_SEND_GET_MESSAGE_WITH_HANDLE:
|
||||
goep_client_create_get_request(map_client->goep_cid);
|
||||
|
||||
map_message_handle_to_str(map_message_handle_to_str_buffer, map_client->message_handle);
|
||||
goep_client_add_header_name(map_client->goep_cid, map_message_handle_to_str_buffer);
|
||||
|
||||
goep_client_add_header_type(map_client->goep_cid, "x-bt/message");
|
||||
|
||||
application_parameters[pos++] = 0x0A; // attachment
|
||||
application_parameters[pos++] = 1;
|
||||
application_parameters[pos++] = map_client->get_message_attachment;
|
||||
|
||||
application_parameters[pos++] = 0x14; // Charset
|
||||
application_parameters[pos++] = 1;
|
||||
application_parameters[pos++] = 1; // UTF-8
|
||||
|
||||
map_client->state = MAP_W4_MESSAGE;
|
||||
goep_client_execute(map_client->goep_cid);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -164,7 +277,7 @@ static void map_handle_can_send_now(void){
|
||||
static void map_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
printf("packet_type 0x%02x, event type 0x%02x, subevent 0x%02x\n", packet_type, hci_event_packet_get_type(packet), hci_event_goep_meta_get_subevent_code(packet));
|
||||
// printf("packet_type 0x%02x, event type 0x%02x, subevent 0x%02x\n", packet_type, hci_event_packet_get_type(packet), hci_event_goep_meta_get_subevent_code(packet));
|
||||
obex_iterator_t it;
|
||||
uint8_t status;
|
||||
// int i;
|
||||
@ -232,12 +345,46 @@ static void map_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *p
|
||||
map_client->state = MAP_INIT;
|
||||
goep_client_disconnect(map_client->goep_cid);
|
||||
break;
|
||||
|
||||
case MAP_W4_SET_PATH_ROOT_COMPLETE:
|
||||
case MAP_W4_SET_PATH_ELEMENT_COMPLETE:
|
||||
if (packet[0] == OBEX_RESP_SUCCESS){
|
||||
// more path?
|
||||
if (map_client->current_folder[map_client->set_path_offset]){
|
||||
map_client->state = MAP_W2_SET_PATH_ELEMENT;
|
||||
goep_client_request_can_send_now(map_client->goep_cid);
|
||||
} else {
|
||||
map_client->current_folder = NULL;
|
||||
map_client->state = MAP_CONNECTED;
|
||||
map_client_emit_operation_complete_event(map_client, 0);
|
||||
}
|
||||
} else if (packet[0] == OBEX_RESP_NOT_FOUND){
|
||||
map_client->state = MAP_CONNECTED;
|
||||
map_client_emit_operation_complete_event(map_client, OBEX_NOT_FOUND);
|
||||
} else {
|
||||
map_client->state = MAP_CONNECTED;
|
||||
map_client_emit_operation_complete_event(map_client, OBEX_UNKNOWN_ERROR);
|
||||
}
|
||||
break;
|
||||
|
||||
case MAP_W4_FOLDERS:
|
||||
map_client->state = MAP_CONNECTED;
|
||||
printf("Folders:\n");
|
||||
printf_hexdump(packet, size);
|
||||
printf("\n");
|
||||
break;
|
||||
case MAP_W4_MESSAGES_IN_FOLDER:
|
||||
map_client->state = MAP_CONNECTED;
|
||||
printf("Messages:\n");
|
||||
printf_hexdump(packet, size);
|
||||
printf("\n");
|
||||
break;
|
||||
case MAP_W4_MESSAGE:
|
||||
map_client->state = MAP_CONNECTED;
|
||||
printf("Message :\n");
|
||||
printf_hexdump(packet, size);
|
||||
printf("\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -265,18 +412,47 @@ uint8_t map_client_connect(btstack_packet_handler_t handler, bd_addr_t addr, uin
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t map_client_disconnect(uint16_t bip_cid){
|
||||
UNUSED(bip_cid);
|
||||
uint8_t map_client_disconnect(uint16_t map_cid){
|
||||
UNUSED(map_cid);
|
||||
if (map_client->state != MAP_CONNECTED) return BTSTACK_BUSY;
|
||||
map_client->state = MAP_W2_SEND_DISCONNECT_REQUEST;
|
||||
goep_client_request_can_send_now(map_client->goep_cid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t map_client_get_folder_listing(uint16_t bip_cid){
|
||||
UNUSED(bip_cid);
|
||||
uint8_t map_client_get_folder_listing(uint16_t map_cid){
|
||||
UNUSED(map_cid);
|
||||
if (map_client->state != MAP_CONNECTED) return BTSTACK_BUSY;
|
||||
map_client->state = MAP_W2_SEND_GET_FOLDERS;
|
||||
goep_client_request_can_send_now(map_client->goep_cid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t map_client_get_message_listing_for_folder(uint16_t map_cid, const char * folder_name){
|
||||
UNUSED(map_cid);
|
||||
if (map_client->state != MAP_CONNECTED) return BTSTACK_BUSY;
|
||||
map_client->state = MAP_W2_SEND_GET_MESSAGES_FOR_FOLDER;
|
||||
map_client->folder_name = folder_name;
|
||||
goep_client_request_can_send_now(map_client->goep_cid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t map_client_get_message_with_handle(uint16_t map_cid, const map_message_handle_t message_handle, uint8_t with_attachment){
|
||||
UNUSED(map_cid);
|
||||
if (map_client->state != MAP_CONNECTED) return BTSTACK_BUSY;
|
||||
map_client->state = MAP_W2_SEND_GET_MESSAGE_WITH_HANDLE;
|
||||
memcpy(map_client->message_handle, message_handle, MAP_MESSAGE_HANDLE_SIZE);
|
||||
map_client->get_message_attachment = with_attachment;
|
||||
goep_client_request_can_send_now(map_client->goep_cid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t map_client_set_path(uint16_t map_cid, char * path){
|
||||
UNUSED(map_cid);
|
||||
if (map_client->state != MAP_CONNECTED) return BTSTACK_BUSY;
|
||||
map_client->state = MAP_W2_SET_PATH_ROOT;
|
||||
map_client->current_folder = path;
|
||||
map_client->set_path_offset = 0;
|
||||
goep_client_request_can_send_now(map_client->goep_cid);
|
||||
return 0;
|
||||
}
|
@ -46,6 +46,12 @@ extern "C" {
|
||||
|
||||
/* API_START */
|
||||
|
||||
#define MAP_MESSAGE_HANDLE_SIZE 8
|
||||
/**
|
||||
* @brief MAP Message handle
|
||||
*/
|
||||
typedef uint8_t map_message_handle_t[MAP_MESSAGE_HANDLE_SIZE];
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ -65,14 +71,38 @@ uint8_t map_client_connect(btstack_packet_handler_t handler, bd_addr_t addr, uin
|
||||
* @param map_cid
|
||||
* @return status
|
||||
*/
|
||||
uint8_t map_client_disconnect(uint16_t bip_cid);
|
||||
uint8_t map_client_disconnect(uint16_t map_cid);
|
||||
|
||||
/**
|
||||
* @brief Get all folders.
|
||||
* @brief Get list of folders.
|
||||
* @param map_cid
|
||||
* @return status
|
||||
*/
|
||||
uint8_t map_client_get_folder_listing(uint16_t bip_cid);
|
||||
uint8_t map_client_get_folder_listing(uint16_t map_cid);
|
||||
|
||||
/**
|
||||
* @brief Set current folder
|
||||
* @param map_cid
|
||||
* @return status
|
||||
*/
|
||||
uint8_t map_client_set_path(uint16_t map_cid, char * path);
|
||||
|
||||
/**
|
||||
* @brief Get list of messages for particular folder.
|
||||
* @param map_cid
|
||||
* @param folder_name
|
||||
* @return status
|
||||
*/
|
||||
uint8_t map_client_get_message_listing_for_folder(uint16_t map_cid, const char * folder_name);
|
||||
|
||||
/**
|
||||
* @brief Get message with particular handle.
|
||||
* @param map_cid
|
||||
* @param map_message_handle
|
||||
* @param with_attachment
|
||||
* @return status
|
||||
*/
|
||||
uint8_t map_client_get_message_with_handle(uint16_t map_cid, const map_message_handle_t map_message_handle, uint8_t with_attachment);
|
||||
|
||||
/* API_END */
|
||||
|
||||
|
@ -75,6 +75,9 @@ static bd_addr_t remote_addr;
|
||||
// iPhone 5 static char * remote_addr_string = "6C:72:E7:10:22:EE";
|
||||
// Android
|
||||
static char * remote_addr_string = "a0:28:ed:04:33:b0";
|
||||
static const char * folder_name = "telecom";
|
||||
static map_message_handle_t message_handle;
|
||||
static char * path = "telecom/msg";
|
||||
|
||||
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
static uint16_t map_cid;
|
||||
@ -89,7 +92,10 @@ static void show_usage(void){
|
||||
printf("\n");
|
||||
printf("a - establish MAP connection to %s\n", bd_addr_to_str(remote_addr));
|
||||
printf("A - disconnect from %s\n", bd_addr_to_str(remote_addr));
|
||||
printf("p - set path \'%s\'\n", path);
|
||||
printf("f - get folder listing\n");
|
||||
printf("F - get message listing for folder \'%s\'\n", folder_name);
|
||||
printf("l - get message for last found handle'\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
@ -104,10 +110,22 @@ static void stdin_process(char c){
|
||||
map_client_disconnect(map_cid);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
printf("[+] Get folder listing\n");
|
||||
map_client_set_path(map_cid, path);
|
||||
break;
|
||||
case 'f':
|
||||
printf("[+] Get folder listing from %s...\n", bd_addr_to_str(remote_addr));
|
||||
printf("[+] Get folder listing\n");
|
||||
map_client_get_folder_listing(map_cid);
|
||||
break;
|
||||
case 'F':
|
||||
printf("[+] Get message listing for folder \'%s\'\n", folder_name);
|
||||
map_client_get_message_listing_for_folder(map_cid, folder_name);
|
||||
break;
|
||||
case 'l':
|
||||
printf("[+] Get message for last found handle\n");
|
||||
map_client_get_message_with_handle(map_cid, message_handle, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
show_usage();
|
||||
|
Loading…
x
Reference in New Issue
Block a user