test: fix build

This commit is contained in:
Matthias Ringwald 2023-02-07 17:59:39 +01:00
parent ba42772a65
commit eb5d730608
16 changed files with 0 additions and 2021 deletions

View File

@ -26,7 +26,6 @@ SUBDIRS = \
l2cap-ecbm \
le_device_db_tlv \
linked_list \
map_test \
mesh \
obex \
pts \

View File

@ -20,7 +20,6 @@ VPATH += ${BTSTACK_ROOT}/test/mock
COMMON = \
ad_parser.c \
att_db.c \
audio_input_control_service_server.c \
battery_service_server.c \
btstack_linked_list.c \
btstack_memory.c \
@ -32,7 +31,6 @@ COMMON = \
hci_dump.c \
heart_rate_service_server.c \
hids_device.c \
microphone_control_service_server.c \
mock_att_server.c \
nordic_spp_service_server.c \
tx_power_service_server.c \
@ -54,7 +52,6 @@ all: build-coverage/battery_service_server_test build-asan/battery_service_se
build-coverage/device_information_service_server_test build-asan/device_information_service_server_test \
build-coverage/tx_power_service_server_test build-asan/tx_power_service_server_test \
build-coverage/bond_management_service_server_test build-asan/bond_management_service_server_test \
build-coverage/microphone_control_service_server_test build-asan/microphone_control_service_server_test \
build-coverage/heart_rate_service_server_test build-asan/heart_rate_service_server_test \
build-%:
@ -72,9 +69,6 @@ build-%/tx_power_service_server_test.h: tx_power_service_server_test.gatt| build
build-%/bond_management_service_server_test.h: bond_management_service_server_test.gatt| build-%
python3 ${BTSTACK_ROOT}/tool/compile_gatt.py $< $@
build-%/microphone_control_service_server_test.h: microphone_control_service_server_test.gatt| build-%
python3 ${BTSTACK_ROOT}/tool/compile_gatt.py $< $@
build-%/heart_rate_service_server_test.h: heart_rate_service_server_test.gatt| build-%
python3 ${BTSTACK_ROOT}/tool/compile_gatt.py $< $@
@ -114,12 +108,6 @@ build-coverage/bond_management_service_server_test: build-coverage/bond_manageme
build-asan/bond_management_service_server_test: build-asan/bond_management_service_server_test.h ${COMMON_OBJ_ASAN} build-asan/bond_management_service_server.o build-asan/bond_management_service_server_test.o | build-asan
${CXX} $(filter-out build-asan/bond_management_service_server_test.h,$^) ${LDFLAGS_ASAN} -o $@
build-coverage/microphone_control_service_server_test: build-coverage/microphone_control_service_server_test.h ${COMMON_OBJ_COVERAGE} build-coverage/microphone_control_service_server.o build-coverage/microphone_control_service_server_test.o | build-coverage
${CXX} $(filter-out build-coverage/microphone_control_service_server_test.h,$^) ${LDFLAGS_COVERAGE} -o $@
build-asan/microphone_control_service_server_test: build-asan/microphone_control_service_server_test.h ${COMMON_OBJ_ASAN} build-asan/microphone_control_service_server.o build-asan/microphone_control_service_server_test.o | build-asan
${CXX} $(filter-out build-asan/microphone_control_service_server_test.h,$^) ${LDFLAGS_ASAN} -o $@
build-coverage/heart_rate_service_server_test: build-coverage/heart_rate_service_server_test.h ${COMMON_OBJ_COVERAGE} build-coverage/heart_rate_service_server.o build-coverage/heart_rate_service_server_test.o | build-coverage
${CXX} $(filter-out build-coverage/heart_rate_service_server_test.h,$^) ${LDFLAGS_COVERAGE} -o $@
@ -131,7 +119,6 @@ test: all
build-asan/device_information_service_server_test
build-asan/tx_power_service_server_test
build-asan/bond_management_service_server_test
build-asan/microphone_control_service_server_test
build-asan/heart_rate_service_server_test
coverage: all
@ -140,7 +127,6 @@ coverage: all
build-coverage/device_information_service_server_test
build-coverage/tx_power_service_server_test
build-coverage/bond_management_service_server_test
build-coverage/microphone_control_service_server_test
build-coverage/heart_rate_service_server_test
clean:

View File

@ -1 +0,0 @@
map_client_test

View File

@ -1,65 +0,0 @@
BTSTACK_ROOT = ../..
CORE += main.c btstack_stdin_posix.c btstack_tlv_posix.c
COMMON += hci_transport_h2_libusb.c btstack_run_loop_posix.c btstack_chipset_zephyr.c btstack_link_key_db_tlv.c le_device_db_tlv.c
include ${BTSTACK_ROOT}/example/Makefile.inc
CFLAGS += -g -std=c99 -Wall -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Wunused-parameter -Wredundant-decls -Wsign-compare
# CFLAGS += -Werror
# CFLAGS += -pedantic
# only LLVM
# CFLAGS += -Wnewline-eof
# CFLAGS += -Wc11-extensions
# CFLAGS += -Wgnu-empty-initializer
CFLAGS += -I${BTSTACK_ROOT}/platform/posix \
-I${BTSTACK_ROOT}/platform/embedded \
-I${BTSTACK_ROOT}/3rd-party/tinydir \
-I${BTSTACK_ROOT}/chipset/zephyr
VPATH += ${BTSTACK_ROOT}/platform/embedded
VPATH += ${BTSTACK_ROOT}/platform/posix
VPATH += ${BTSTACK_ROOT}/platform/libusb
VPATH += ${BTSTACK_ROOT}/port/libusb
VPATH += ${BTSTACK_ROOT}/chipset/zephyr
# use pkg-config
CFLAGS += $(shell pkg-config libusb-1.0 --cflags)
LDFLAGS += $(shell pkg-config libusb-1.0 --libs)
MAP = \
obex_iterator.c \
obex_message_builder.c \
goep_client.c \
yxml.c \
btstack_util.c \
hci_dump.c \
map_util.c \
map_client.c \
map_server.c \
COMMON_OBJ = $(addprefix build-coverage/,$(COMMON:.c=.o))
MAP_OBJ = $(addprefix build-coverage/,$(MAP:.c=.o))
CORE_OBJ = $(addprefix build-coverage/,$(CORE:.c=.o))
all: map_client_test
build-%:
mkdir -p $@
build-coverage/%.o: %.c | build-coverage
${CC} -c $(CFLAGS) ${CPPFLAGS} $< -o $@
map_client_test: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ${SDP_CLIENT} ${MAP_OBJ} map_client_test.c
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
test: all
./map_client_test
clean:
rm -f *.o
rm -rf *.dSYM build-coverage
rm -f *.gcno *.gcda

View File

@ -1,39 +0,0 @@
//
// btstack_config.h for libusb port
//
#ifndef BTSTACK_CONFIG_H
#define BTSTACK_CONFIG_H
// Port related features
#define HAVE_BTSTACK_STDIN
#define HAVE_MALLOC
#define HAVE_POSIX_FILE_IO
#define HAVE_POSIX_TIME
// BTstack features that can be enabled
#define ENABLE_ATT_DELAYED_RESPONSE
#define ENABLE_BLE
#define ENABLE_CLASSIC
#define ENABLE_HFP_WIDE_BAND_SPEECH
#define ENABLE_LE_CENTRAL
#define ENABLE_L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE
#define ENABLE_LE_DATA_LENGTH_EXTENSION
#define ENABLE_LE_PERIPHERAL
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_LOG_ERROR
#define ENABLE_LOG_INFO
#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
#define ENABLE_PRINTF_HEXDUMP
#define ENABLE_SCO_OVER_HCI
#define ENABLE_SDP_DES_DUMP
#define ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE
// BTstack configuration. buffers, sizes, ...
#define HCI_ACL_PAYLOAD_SIZE (1691 + 4)
#define HCI_INCOMING_PRE_BUFFER_SIZE 14 // sizeof BNEP header, avoid memcpy
#define NVM_NUM_DEVICE_DB_ENTRIES 20
#define NVM_NUM_LINK_KEYS 20
#endif

View File

@ -1,115 +0,0 @@
/*
* Copyright (C) 2019 BlueKitchen GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
#ifndef MAP_H
#define MAP_H
#if defined __cplusplus
extern "C" {
#endif
#include "btstack_config.h"
#include <stdint.h>
/* API_START */
#define MAP_MAX_VALUE_LEN 32
#define MAP_MESSAGE_HANDLE_SIZE 8
/**
* @brief MAP Message handle
*/
typedef uint8_t map_message_handle_t[MAP_MESSAGE_HANDLE_SIZE];
typedef enum {
MAP_MESSAGE_TYPE_EMAIL = 0,
MAP_MESSAGE_TYPE_SMS_GSM,
MAP_MESSAGE_TYPE_SMS_CDMA,
MAP_MESSAGE_TYPE_MMS,
MAP_MESSAGE_TYPE_IM
} map_message_type_t;
typedef enum {
MAP_RECEPTION_STATUS_COMPLETE, // Complete message has been received by the MSE
MAP_RECEPTION_STATUS_FRACTIONED, // Only a part of the message has been received by the MSE (e.g., fractioned email of push-service)
MAP_RECEPTION_STATUS_NOTIFICATION // Only a notification of the message has been received by the MSE
} map_reception_status_t;
typedef enum {
MAP_FEATURE_NOTIFICATION_REGISTRATION = 0,
MAP_FEATURE_NOTIFICATION,
MAP_FEATURE_BROWSING,
MAP_FEATURE_UPLOADING,
MAP_FEATURE_DELETE,
MAP_FEATURE_INSTANCE_INFORMATION,
MAP_FEATURE_EXTENDED_EVENT_REPORT_1_1,
MAP_FEATURE_EVENT_REPORT_VERSION_1_2,
MAP_FEATURE_MESSAGE_FORMAT_VERSION_1_1,
MAP_FEATURE_MESSAGES_LISTING_FORMAT_VERSION_1_1,
MAP_FEATURE_PERSISTENT_MESSAGE_HANDLES,
MAP_FEATURE_DATABASE_IDENTIFIER,
MAP_FEATURE_FOLDER_VERSION_COUNTER,
MAP_FEATURE_CONVERSATION_VERSION_COUNTERS,
MAP_FEATURE_PARTICIPANT_PRESENCE_CHANGE_NOTIFICATION,
MAP_FEATURE_PARTICIPANT_CHAT_STATE_CHANGE_NOTIFICATION,
MAP_FEATURE_PBAP_CONTACT_CROSS_REFERENCE,
MAP_FEATURE_NOTIFICATION_FILTERING,
MAP_FEATURE_UTC_OFFSET_TIMESTAMP_FORMAT,
MAP_FEATURE_MAPSUPPORTEDFEATURES_IN_CONNECT_REQUEST,
MAP_FEATURE_CONVERSATION_LISTING,
MAP_FEATURE_OWNER_STATUS_BIT,
MAP_FEATURE_MESSAGE_FORWARDING
} map_feature_t;
typedef struct {
char handle[MAP_MESSAGE_HANDLE_SIZE];
char datetime[MAP_MAX_VALUE_LEN];
char subject[MAP_MAX_VALUE_LEN];
char sender_name[MAP_MAX_VALUE_LEN];
char sender_addressing[MAP_MAX_VALUE_LEN];
map_message_type_t type;
uint16_t attachment_size;
uint8_t flags; // 0 - read, 1 - text
} map_message_t;
/* API_END */
#if defined __cplusplus
}
#endif
#endif

View File

@ -1,532 +0,0 @@
/*
* Copyright (C) 2019 BlueKitchen GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
#define __BTSTACK_FILE__ "map_client.c"
#include "btstack_config.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hci_cmd.h"
#include "btstack_run_loop.h"
#include "btstack_debug.h"
#include "hci.h"
#include "btstack_memory.h"
#include "hci_dump.h"
#include "l2cap.h"
#include "bluetooth_sdp.h"
#include "classic/sdp_client_rfcomm.h"
#include "btstack_event.h"
#include "classic/sdp_client.h"
#include "classic/sdp_util.h"
#include "classic/obex.h"
#include "classic/obex_iterator.h"
#include "classic/goep_client.h"
#include "map_client.h"
#define MAP_MAX_NUM_ENTRIES 1024
// map access service bb582b40-420c-11db-b0de-0800200c9a66
static const uint8_t map_client_access_service_uuid[] = {0xbb, 0x58, 0x2b, 0x40, 0x42, 0xc, 0x11, 0xdb, 0xb0, 0xde, 0x8, 0x0, 0x20, 0xc, 0x9a, 0x66};
static uint32_t map_supported_features = 0x1F;
typedef enum {
MAP_INIT = 0,
MAP_W4_GOEP_CONNECTION,
MAP_W2_SEND_CONNECT_REQUEST,
MAP_W4_CONNECT_RESPONSE,
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_SET_NOTIFICATION,
MAP_W4_SET_NOTIFICATION,
MAP_W2_SEND_DISCONNECT_REQUEST,
MAP_W4_DISCONNECT_RESPONSE,
} map_state_t;
typedef struct map_client {
map_state_t state;
uint16_t cid;
bd_addr_t bd_addr;
hci_con_handle_t con_handle;
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;
uint8_t notifications_enabled;
map_message_handle_t message_handle;
uint8_t get_message_attachment;
} map_client_t;
static map_client_t _map_client;
static map_client_t * map_client = &_map_client;
static void map_client_emit_connected_event(map_client_t * context, uint8_t status){
uint8_t event[15];
int pos = 0;
event[pos++] = HCI_EVENT_MAP_META;
pos++; // skip len
event[pos++] = MAP_SUBEVENT_CONNECTION_OPENED;
little_endian_store_16(event,pos,context->cid);
pos+=2;
event[pos++] = status;
memcpy(&event[pos], context->bd_addr, 6);
pos += 6;
little_endian_store_16(event,pos,context->con_handle);
pos += 2;
event[pos++] = context->incoming;
event[1] = pos - 2;
if (pos != sizeof(event)) log_error("map_client_emit_connected_event size %u", pos);
context->client_handler(HCI_EVENT_PACKET, context->cid, &event[0], pos);
}
static void map_client_emit_connection_closed_event(map_client_t * context){
uint8_t event[5];
int pos = 0;
event[pos++] = HCI_EVENT_MAP_META;
pos++; // skip len
event[pos++] = MAP_SUBEVENT_CONNECTION_CLOSED;
little_endian_store_16(event,pos,context->cid);
pos+=2;
event[1] = pos - 2;
if (pos != sizeof(event)) log_error("map_client_emit_connection_closed_event size %u", pos);
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:
goep_client_request_create_connect(map_client->goep_cid, OBEX_VERSION, 0, OBEX_MAX_PACKETLEN_DEFAULT);
goep_client_header_add_target(map_client->goep_cid, map_client_access_service_uuid, 16);
// 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_MAP_SUPPORTED_FEATURES;
application_parameters[1] = 4;
big_endian_store_32(application_parameters, 2, map_supported_features);
goep_client_header_add_application_parameters(map_client->goep_cid, &application_parameters[0], 6);
// }
map_client->state = MAP_W4_CONNECT_RESPONSE;
goep_client_execute(map_client->goep_cid);
break;
case MAP_W2_SEND_DISCONNECT_REQUEST:
goep_client_request_create_disconnect(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_request_create_set_path(map_client->goep_cid, 1 << 1); // Dont create directory
goep_client_header_add_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_request_create_set_path(map_client->goep_cid, 1 << 1); // Dont create directory
goep_client_header_add_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_request_create_get(map_client->goep_cid);
goep_client_header_add_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_request_create_get(map_client->goep_cid);
goep_client_header_add_type(map_client->goep_cid, "x-bt/MAP-msg-listing");
goep_client_header_add_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_request_create_get(map_client->goep_cid);
map_message_handle_to_str(map_message_handle_to_str_buffer, map_client->message_handle);
goep_client_header_add_name(map_client->goep_cid, map_message_handle_to_str_buffer);
goep_client_header_add_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
goep_client_header_add_application_parameters(map_client->goep_cid, &application_parameters[0], 6);
map_client->state = MAP_W4_MESSAGE;
goep_client_execute(map_client->goep_cid);
break;
case MAP_W2_SET_NOTIFICATION:
goep_client_request_create_put(map_client->goep_cid);
goep_client_header_add_type(map_client->goep_cid, "x-bt/MAP-NotificationRegistration");
application_parameters[pos++] = 0x0E; // NotificationStatus
application_parameters[pos++] = 1;
application_parameters[pos++] = map_client->notifications_enabled;
goep_client_header_add_application_parameters(map_client->goep_cid, &application_parameters[0], pos);
goep_client_body_add_static(map_client->goep_cid, (uint8_t *) "0", 1);
map_client->state = MAP_W4_MESSAGE;
goep_client_execute(map_client->goep_cid);
break;
default:
break;
}
}
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));
obex_iterator_t it;
uint8_t status;
// int i;
// int wait_for_user = 0;
switch (packet_type){
case HCI_EVENT_PACKET:
switch (hci_event_packet_get_type(packet)) {
case HCI_EVENT_GOEP_META:
switch (hci_event_goep_meta_get_subevent_code(packet)){
case GOEP_SUBEVENT_CONNECTION_OPENED:
status = goep_subevent_connection_opened_get_status(packet);
map_client->con_handle = goep_subevent_connection_opened_get_con_handle(packet);
map_client->incoming = goep_subevent_connection_opened_get_incoming(packet);
goep_subevent_connection_opened_get_bd_addr(packet, map_client->bd_addr);
if (status){
log_info("map: connection failed %u", status);
map_client->state = MAP_INIT;
map_client_emit_connected_event(map_client, status);
} else {
log_info("map: connection established");
map_client->goep_cid = goep_subevent_connection_opened_get_goep_cid(packet);
map_client->state = MAP_W2_SEND_CONNECT_REQUEST;
goep_client_request_can_send_now(map_client->goep_cid);
}
break;
case GOEP_SUBEVENT_CONNECTION_CLOSED:
if (map_client->state != MAP_CONNECTED){
// map_client_emit_operation_complete_event(map_client, OBEX_DISCONNECTED);
}
map_client->state = MAP_INIT;
map_client_emit_connection_closed_event(map_client);
break;
case GOEP_SUBEVENT_CAN_SEND_NOW:
map_handle_can_send_now();
break;
}
break;
default:
break;
}
break;
case GOEP_DATA_PACKET:
switch (map_client->state){
case MAP_W4_CONNECT_RESPONSE:
switch (packet[0]){
case OBEX_RESP_SUCCESS:
for (obex_iterator_init_with_response_packet(&it, goep_client_get_request_opcode(map_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_CONNECTION_ID){
goep_client_set_connection_id(map_client->goep_cid, obex_iterator_get_data_32(&it));
}
}
map_client->state = MAP_CONNECTED;
// map_client->vcard_selector_supported = map_supported_features & goep_client_get_map_supported_features(map_client->goep_cid) & MAP_SUPPORTED_FEATURES_VCARD_SELECTING;
map_client_emit_connected_event(map_client, 0);
break;
default:
log_info("map: obex connect failed, result 0x%02x", packet[0]);
map_client->state = MAP_INIT;
map_client_emit_connected_event(map_client, OBEX_CONNECT_FAILED);
break;
}
break;
case MAP_W4_DISCONNECT_RESPONSE:
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");
for (obex_iterator_init_with_response_packet(&it, goep_client_get_request_opcode(map_client->goep_cid), packet, size); obex_iterator_has_more(&it) ; obex_iterator_next(&it)){
uint8_t hi = obex_iterator_get_hi(&it);
// uint16_t data_len = obex_iterator_get_data_len(&it);
const uint8_t * data = obex_iterator_get_data(&it);
switch (hi){
case OBEX_HEADER_BODY:
case OBEX_HEADER_END_OF_BODY:
printf("%s\n", data);
break;
default:
break;
}
}
printf("\n");
break;
case MAP_W4_MESSAGES_IN_FOLDER:
map_client->state = MAP_CONNECTED;
printf("Messages:\n");
for (obex_iterator_init_with_response_packet(&it, goep_client_get_request_opcode(map_client->goep_cid), packet, size); obex_iterator_has_more(&it) ; obex_iterator_next(&it)){
uint8_t hi = obex_iterator_get_hi(&it);
// uint16_t data_len = obex_iterator_get_data_len(&it);
const uint8_t * data = obex_iterator_get_data(&it);
switch (hi){
case OBEX_HEADER_BODY:
case OBEX_HEADER_END_OF_BODY:
printf("%s\n", data);
break;
default:
break;
}
}
printf("\n");
break;
case MAP_W4_MESSAGE:
map_client->state = MAP_CONNECTED;
printf("Message :\n");
for (obex_iterator_init_with_response_packet(&it, goep_client_get_request_opcode(map_client->goep_cid), packet, size); obex_iterator_has_more(&it) ; obex_iterator_next(&it)){
uint8_t hi = obex_iterator_get_hi(&it);
// uint16_t data_len = obex_iterator_get_data_len(&it);
const uint8_t * data = obex_iterator_get_data(&it);
switch (hi){
case OBEX_HEADER_BODY:
case OBEX_HEADER_END_OF_BODY:
printf("%s\n", data);
break;
default:
break;
}
}
printf("\n");
break;
default:
break;
}
break;
default:
break;
}
}
void map_client_init(void){
memset(map_client, 0, sizeof(map_client_t));
map_client->state = MAP_INIT;
map_client->cid = 1;
}
uint8_t map_client_connect(btstack_packet_handler_t handler, bd_addr_t addr, uint16_t * out_cid){
if (map_client->state != MAP_INIT) return BTSTACK_MEMORY_ALLOC_FAILED;
map_client->state = MAP_W4_GOEP_CONNECTION;
map_client->client_handler = handler;
uint8_t err = goep_client_create_connection(&map_packet_handler, addr, BLUETOOTH_SERVICE_CLASS_MESSAGE_ACCESS_SERVER, &map_client->goep_cid);
*out_cid = map_client->cid;
if (err) return err;
return 0;
}
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 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, const 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;
}
uint8_t map_client_enable_notifications(uint16_t map_cid){
UNUSED(map_cid);
if (map_client->state != MAP_CONNECTED) return BTSTACK_BUSY;
map_client->state = MAP_W2_SET_NOTIFICATION;
map_client->notifications_enabled = 1;
goep_client_request_can_send_now(map_client->goep_cid);
return 0;
}
uint8_t map_client_disable_notifications(uint16_t map_cid){
UNUSED(map_cid);
if (map_client->state != MAP_CONNECTED) return BTSTACK_BUSY;
map_client->state = MAP_W2_SET_NOTIFICATION;
map_client->notifications_enabled = 0;
goep_client_request_can_send_now(map_client->goep_cid);
return 0;
}

View File

@ -1,122 +0,0 @@
/*
* Copyright (C) 2019 BlueKitchen GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
#ifndef MAP_CLIENT_H
#define MAP_CLIENT_H
#if defined __cplusplus
extern "C" {
#endif
#include "btstack_config.h"
#include "map.h"
#include <stdint.h>
/* API_START */
/**
*
*/
void map_client_init(void);
/**
* @brief Create MAP Client connection.
* @param handler
* @param addr
* @param out_cid to use for further commands
* @result status
*/
uint8_t map_client_connect(btstack_packet_handler_t handler, bd_addr_t addr, uint16_t * out_cid);
/**
* @brief Disconnects MAP connection with given identifier.
* @param map_cid
* @return status
*/
uint8_t map_client_disconnect(uint16_t map_cid);
/**
* @brief Get list of folders.
* @param map_cid
* @return status
*/
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, const 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);
/**
* @brief Enable notifications.
* @param map_cid
* @return status
*/
uint8_t map_client_enable_notifications(uint16_t map_cid);
/**
* @brief Disable notifications.
* @param map_cid
* @return status
*/
uint8_t map_client_disable_notifications(uint16_t map_cid);
/* API_END */
#if defined __cplusplus
}
#endif
#endif

View File

@ -1,338 +0,0 @@
/*
* Copyright (C) 2014 BlueKitchen GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
#define __BTSTACK_FILE__ "map_client_test.c"
// *****************************************************************************
/* EXAMPLE_START(pbap_client_demo): Connect to Phonebook Server and get contacts.
*
* @text Note: The Bluetooth address of the remote Phonbook server is hardcoded.
* Change it before running example, then use the UI to connect to it, to set and
* query contacts.
*/
// *****************************************************************************
#include "btstack_config.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bluetooth_sdp.h"
#include "btstack_event.h"
#include "btstack_run_loop.h"
#include "classic/goep_client.h"
#include "classic/obex.h"
#include "classic/rfcomm.h"
#include "classic/sdp_client.h"
#include "classic/sdp_server.h"
#include "classic/sdp_util.h"
#include "l2cap.h"
#include "map_client.h"
#include "map_server.h"
#ifdef HAVE_BTSTACK_STDIN
#include "btstack_stdin.h"
#endif
static const uint8_t map_client_notification_service_uuid[] = {0xbb, 0x58, 0x2b, 0x41, 0x42, 0xc, 0x11, 0xdb, 0xb0, 0xde, 0x8, 0x0, 0x20, 0xc, 0x9a, 0x66};
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
static bd_addr_t remote_addr;
static uint16_t rfcomm_channel_id;
// MBP2016 "F4-0F-24-3B-1B-E1"
// Nexus 7 "30-85-A9-54-2E-78"
// iPhone SE "BC:EC:5D:E6:15:03"
// PTS "001BDC080AA5"
// iPhone 5 static char * remote_addr_string = "6C:72:E7:10:22:EE";
// Android
static const char * remote_addr_string = "a0:28:ed:04:33:b0";
static const char * folder_name = "inbox";
static map_message_handle_t message_handle = {0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
static const char * path = "telecom/msg";
static btstack_packet_callback_registration_t hci_event_callback_registration;
static uint16_t map_cid;
#ifdef HAVE_BTSTACK_STDIN
// Testig User Interface
static void show_usage(void){
bd_addr_t iut_address;
gap_local_bd_addr(iut_address);
printf("\n--- Bluetooth MAP Client Test Console %s ---\n", bd_addr_to_str(iut_address));
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 - enable notifications\n");
printf("\n");
}
static void stdin_process(char c){
switch (c){
case 'a':
printf("[+] Connecting to %s...\n", bd_addr_to_str(remote_addr));
map_client_connect(&packet_handler, remote_addr, &map_cid);
break;
case 'A':
printf("[+] Disconnect from %s...\n", bd_addr_to_str(remote_addr));
map_client_disconnect(map_cid);
break;
case 'p':
printf("[+] Set path \'%s\'\n", path);
map_client_set_path(map_cid, path);
break;
case 'f':
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 hardcoded handle\n");
map_client_get_message_with_handle(map_cid, message_handle, 1);
break;
case 'n':
printf("[+] Enable notifications\n");
map_client_enable_notifications(map_cid);
break;
default:
show_usage();
break;
}
}
static void obex_server_success_response(uint16_t rfcomm_cid){
uint8_t event[30];
int pos = 0;
event[pos++] = OBEX_RESP_SUCCESS;
// store len
pos += 2;
// obex version num
event[pos++] = OBEX_VERSION;
// flags
// Bit 0 should be used by the receiving client to decide how to multiplex operations
// to the server (should it desire to do so). If the bit is 0 the client should serialize
// the operations over a single TTP connection. If the bit is set the client is free to
// establish multiple TTP connections to the server and concurrently exchange its objects.
event[pos++] = 0;
// Maximum OBEX packet length
big_endian_store_16(event, pos, 0x0400);
pos += 2;
event[pos++] = OBEX_HEADER_CONNECTION_ID;
big_endian_store_32(event, pos, 0x1234);
pos += 4;
event[pos++] = OBEX_HEADER_WHO;
big_endian_store_16(event, pos, 16 + 3);
pos += 2;
memcpy(event+pos, map_client_notification_service_uuid, 16);
pos += 16;
big_endian_store_16(event, 1, pos);
rfcomm_send(rfcomm_cid, event, pos);
}
// packet handler for interactive console
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
UNUSED(channel);
UNUSED(size);
int i;
uint8_t status;
uint16_t mtu;
int value_len;
char value[MAP_MAX_VALUE_LEN];
memset(value, 0, MAP_MAX_VALUE_LEN);
switch (packet_type){
case HCI_EVENT_PACKET:
switch (hci_event_packet_get_type(packet)) {
case BTSTACK_EVENT_STATE:
// BTstack activated, get started
if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){
show_usage();
}
break;
case RFCOMM_EVENT_INCOMING_CONNECTION:
rfcomm_channel_id = rfcomm_event_incoming_connection_get_rfcomm_cid(packet);
printf("RFCOMM connection opened\n");
rfcomm_accept_connection(rfcomm_channel_id);
break;
case RFCOMM_EVENT_CHANNEL_OPENED:
// data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16)
if (rfcomm_event_channel_opened_get_status(packet)) {
printf("RFCOMM channel open failed, status %u\n", rfcomm_event_channel_opened_get_status(packet));
} else {
rfcomm_channel_id = rfcomm_event_channel_opened_get_rfcomm_cid(packet);
mtu = rfcomm_event_channel_opened_get_max_frame_size(packet);
printf("RFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n", rfcomm_channel_id, mtu);
}
break;
case RFCOMM_EVENT_CHANNEL_CLOSED:
printf("RFCOMM channel closed\n");
rfcomm_channel_id = 0;
break;
case HCI_EVENT_MAP_META:
switch (hci_event_map_meta_get_subevent_code(packet)){
case MAP_SUBEVENT_CONNECTION_OPENED:
status = map_subevent_connection_opened_get_status(packet);
if (status){
printf("[!] Connection failed, status 0x%02x\n", status);
} else {
printf("[+] Connected\n");
}
break;
case MAP_SUBEVENT_CONNECTION_CLOSED:
printf("[+] Connection closed\n");
break;
case MAP_SUBEVENT_OPERATION_COMPLETED:
printf("[+] Operation complete\n");
break;
case MAP_SUBEVENT_FOLDER_LISTING_ITEM:
value_len = btstack_min(map_subevent_folder_listing_item_get_name_len(packet), MAP_MAX_VALUE_LEN);
memcpy(value, map_subevent_folder_listing_item_get_name(packet), value_len);
printf("Folder \'%s\'\n", value);
break;
case MAP_SUBEVENT_MESSAGE_LISTING_ITEM:
memcpy((uint8_t *) message_handle, map_subevent_message_listing_item_get_handle(packet), MAP_MESSAGE_HANDLE_SIZE);
printf("Message handle: ");
printf_hexdump((uint8_t *) message_handle, MAP_MESSAGE_HANDLE_SIZE);
printf("\n");
break;
case MAP_SUBEVENT_PARSING_DONE:
break;
default:
break;
}
break;
default:
break;
}
break;
case RFCOMM_DATA_PACKET:
printf("RFCOMM data packet: '");
for (i=0;i<size;i++){
printf("%02x ", packet[i]);
}
printf("'\n");
obex_server_success_response(rfcomm_channel_id);
break;
case MAP_DATA_PACKET:
for (i=0;i<size;i++){
printf("%c", packet[i]);
}
printf("\n");
break;
default:
break;
}
}
#endif
static uint8_t map_message_notification_service_buffer[150];
const char * name = "MAP Service";
int btstack_main(int argc, const char * argv[]);
int btstack_main(int argc, const char * argv[]){
(void)argc;
(void)argv;
// init L2CAP
l2cap_init();
// init RFCOM
rfcomm_init();
// init GOEP Client
goep_client_init();
// init MAP Client
map_client_init();
// init MAP Server
map_server_init();
sdp_init();
// setup AVDTP sink
map_message_type_t supported_message_types = MAP_MESSAGE_TYPE_SMS_GSM;
uint32_t supported_features = 0x1F;
int rfcomm_channel_nr = 1;
memset(map_message_notification_service_buffer, 0, sizeof(map_message_notification_service_buffer));
map_message_notification_service_create_sdp_record(map_message_notification_service_buffer, 0x10001,
1, rfcomm_channel_nr, 1, supported_message_types, supported_features, name);
sdp_register_service(map_message_notification_service_buffer);
rfcomm_register_service(&packet_handler, rfcomm_channel_nr, 0xFFFF);
// register for HCI events
hci_event_callback_registration.callback = &packet_handler;
hci_add_event_handler(&hci_event_callback_registration);
sscanf_bd_addr(remote_addr_string, remote_addr);
#ifdef HAVE_BTSTACK_STDIN
btstack_stdin_setup(stdin_process);
#endif
// turn on!
hci_power_control(HCI_POWER_ON);
return 0;
}
/* EXAMPLE_END */

View File

@ -1,204 +0,0 @@
/*
* Copyright (C) 2019 BlueKitchen GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
#define __BTSTACK_FILE__ "map_server.c"
#include "btstack_config.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hci_cmd.h"
#include "btstack_run_loop.h"
#include "btstack_debug.h"
#include "hci.h"
#include "btstack_memory.h"
#include "hci_dump.h"
#include "l2cap.h"
#include "bluetooth_sdp.h"
#include "classic/sdp_client_rfcomm.h"
#include "btstack_event.h"
#include "classic/sdp_client.h"
#include "classic/sdp_util.h"
#include "classic/obex.h"
#include "classic/obex_iterator.h"
#include "classic/goep_client.h"
#include "map_server.h"
#define MAP_MAX_NUM_ENTRIES 1024
// map access service bb582b40-420c-11db-b0de-0800200c9a66
typedef enum {
MAP_INIT = 0,
MAP_CONNECTED
} map_state_t;
typedef struct map_server {
map_state_t state;
uint16_t cid;
bd_addr_t bd_addr;
hci_con_handle_t con_handle;
uint16_t goep_cid;
} map_server_t;
static map_server_t _map_server;
static map_server_t * map_server = &_map_server;
static void map_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t service_uuid, uint8_t instance_id,
int rfcomm_channel_nr, uint16_t goep_l2cap_psm, map_message_type_t supported_message_types, uint32_t supported_features, const char * name){
UNUSED(goep_l2cap_psm);
uint8_t* attribute;
de_create_sequence(service);
// 0x0000 "Service Record Handle"
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_RECORD_HANDLE);
de_add_number(service, DE_UINT, DE_SIZE_32, service_record_handle);
// 0x0001 "Service Class ID List"
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_CLASS_ID_LIST);
attribute = de_push_sequence(service);
{
// "UUID for Service"
de_add_number(attribute, DE_UUID, DE_SIZE_16, service_uuid);
}
de_pop_sequence(service, attribute);
// 0x0004 "Protocol Descriptor List"
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST);
attribute = de_push_sequence(service);
{
uint8_t* l2cpProtocol = de_push_sequence(attribute);
{
de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_L2CAP);
}
de_pop_sequence(attribute, l2cpProtocol);
uint8_t* rfcomm = de_push_sequence(attribute);
{
de_add_number(rfcomm, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_RFCOMM); // rfcomm_service
de_add_number(rfcomm, DE_UINT, DE_SIZE_8, rfcomm_channel_nr); // rfcomm channel
}
de_pop_sequence(attribute, rfcomm);
uint8_t* obexProtocol = de_push_sequence(attribute);
{
de_add_number(obexProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_OBEX);
}
de_pop_sequence(attribute, obexProtocol);
}
de_pop_sequence(service, attribute);
// 0x0005 "Public Browse Group"
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BROWSE_GROUP_LIST); // public browse group
attribute = de_push_sequence(service);
{
de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PUBLIC_BROWSE_ROOT);
}
de_pop_sequence(service, attribute);
// 0x0009 "Bluetooth Profile Descriptor List"
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
attribute = de_push_sequence(service);
{
uint8_t *profile = de_push_sequence(attribute);
{
de_add_number(profile, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_MESSAGE_ACCESS_PROFILE);
de_add_number(profile, DE_UINT, DE_SIZE_16, 0x0103); // Verision 1.7
}
de_pop_sequence(attribute, profile);
}
de_pop_sequence(service, attribute);
// "Service Name"
de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100);
de_add_data(service, DE_STRING, strlen(name), (uint8_t *) name);
#ifdef ENABLE_GOEP_L2CAP
// 0x0200 "GoepL2CapPsm"
de_add_number(service, DE_UINT, DE_SIZE_16, 0x0200);
de_add_number(service, DE_UINT, DE_SIZE_16, goep_l2cap_psm);
#endif
// 0x0315 "MASInstanceID"
de_add_number(service, DE_UINT, DE_SIZE_16, 0x0315);
de_add_number(service, DE_UINT, DE_SIZE_8, instance_id);
// 0x0316 "SupportedMessageTypes"
de_add_number(service, DE_UINT, DE_SIZE_16, 0x0316);
de_add_number(service, DE_UINT, DE_SIZE_8, supported_message_types);
// 0x0317 "MapSupportedFeatures"
de_add_number(service, DE_UINT, DE_SIZE_16, 0x0317);
de_add_number(service, DE_UINT, DE_SIZE_32, supported_features);
}
void map_message_access_service_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint8_t instance_id,
int rfcomm_channel_nr, uint16_t goep_l2cap_psm, map_message_type_t supported_message_types, uint32_t supported_features, const char * name){
map_create_sdp_record(service, service_record_handle, BLUETOOTH_SERVICE_CLASS_MESSAGE_ACCESS_SERVER, instance_id, rfcomm_channel_nr,
goep_l2cap_psm, supported_message_types, supported_features, name);
}
void map_message_notification_service_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint8_t instance_id,
int rfcomm_channel_nr, uint16_t goep_l2cap_psm, map_message_type_t supported_message_types, uint32_t supported_features, const char * name){
map_create_sdp_record(service, service_record_handle, BLUETOOTH_SERVICE_CLASS_MESSAGE_NOTIFICATION_SERVER, instance_id, rfcomm_channel_nr,
goep_l2cap_psm, supported_message_types, supported_features, name);
}
#if 0
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));
}
#endif
void map_server_init(void){
memset(map_server, 0, sizeof(map_server_t));
map_server->state = MAP_INIT;
map_server->cid = 1;
}

View File

@ -1,92 +0,0 @@
/*
* Copyright (C) 2019 BlueKitchen GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
#ifndef MAP_SERVER_H
#define MAP_SERVER_H
#if defined __cplusplus
extern "C" {
#endif
#include "btstack_config.h"
#include <stdint.h>
#include "map.h"
/* API_START */
/**
* @brief Create SDP record for Message Access Service
* @param service
* @param service_record_handle
* @param instance_id
* @param rfcomm_channel_nr
* @param goep_l2cap_psm
* @param supported_message_types
* @param supported_features
* @param name
*/
void map_message_access_service_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint8_t instance_id,
int rfcomm_channel_nr, uint16_t goep_l2cap_psm, map_message_type_t supported_message_types, uint32_t supported_features, const char * name);
/**
* @brief Create SDP record for Message Notification Service
* @param service
* @param service_record_handle
* @param instance_id
* @param rfcomm_channel_nr
* @param goep_l2cap_psm
* @param supported_message_types
* @param supported_features
* @param name
*/
void map_message_notification_service_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint8_t instance_id,
int rfcomm_channel_nr, uint16_t goep_l2cap_psm, map_message_type_t supported_message_types, uint32_t supported_features, const char * name);
/**
*
*/
void map_server_init(void);
/* API_END */
#if defined __cplusplus
}
#endif
#endif

View File

@ -1,223 +0,0 @@
/*
* Copyright (C) 2019 BlueKitchen GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
#define __BTSTACK_FILE__ "map_util.c"
#include "btstack_config.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "btstack_util.h"
#include "map_util.h"
#include "yxml.h"
#include "map.h"
#include "btstack_defines.h"
#include "btstack_util.h"
#include "btstack_debug.h"
#include "btstack_event.h"
static yxml_t xml_parser;
static uint8_t xml_buffer[50];
void map_message_str_to_handle(const char * value, map_message_handle_t msg_handle){
int i;
for (i = 0; i < MAP_MESSAGE_HANDLE_SIZE; i++) {
uint8_t upper_nibble = nibble_for_char(*value++);
uint8_t lower_nibble = nibble_for_char(*value++);
msg_handle[i] = (upper_nibble << 4) | lower_nibble;
}
}
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_client_emit_folder_listing_item_event(btstack_packet_handler_t callback, uint16_t cid, uint8_t * folder_name, uint16_t folder_name_len){
uint8_t event[7 + MAP_MAX_VALUE_LEN];
uint16_t pos = 0;
event[pos++] = HCI_EVENT_MAP_META;
pos++; // skip len
event[pos++] = MAP_SUBEVENT_FOLDER_LISTING_ITEM;
little_endian_store_16(event,pos,cid);
pos+=2;
uint16_t value_len = btstack_min(folder_name_len, sizeof(event) - pos);
little_endian_store_16(event, pos, value_len);
pos += 2;
memcpy(event+pos, folder_name, value_len);
pos += value_len;
event[1] = pos - 2;
if (pos > sizeof(event)) log_error("map_client_emit_folder_listing_item_event size %u", pos);
(*callback)(HCI_EVENT_PACKET, cid, &event[0], pos);
}
static void map_client_emit_message_listing_item_event(btstack_packet_handler_t callback, uint16_t cid, map_message_handle_t message_handle){
uint8_t event[7 + MAP_MESSAGE_HANDLE_SIZE];
uint16_t pos = 0;
event[pos++] = HCI_EVENT_MAP_META;
pos++; // skip len
event[pos++] = MAP_SUBEVENT_MESSAGE_LISTING_ITEM;
little_endian_store_16(event,pos,cid);
pos+=2;
memcpy(event+pos, message_handle, MAP_MESSAGE_HANDLE_SIZE);
pos += MAP_MESSAGE_HANDLE_SIZE;
event[1] = pos - 2;
if (pos > sizeof(event)) log_error("map_client_emit_message_listing_item_event size %u", pos);
(*callback)(HCI_EVENT_PACKET, cid, &event[0], pos);
}
static void map_client_emit_parsing_done_event(btstack_packet_handler_t callback, uint16_t cid){
uint8_t event[5];
int pos = 0;
event[pos++] = HCI_EVENT_MAP_META;
pos++; // skip len
event[pos++] = MAP_SUBEVENT_PARSING_DONE;
little_endian_store_16(event,pos,cid);
pos += 2;
event[1] = pos - 2;
if (pos != sizeof(event)) log_error("map_client_emit_parsing_done_event size %u", pos);
(*callback)(HCI_EVENT_PACKET, cid, &event[0], pos);
}
void map_client_parse_folder_listing(btstack_packet_handler_t callback, uint16_t cid, const uint8_t * data, uint16_t data_len){
int folder_found = 0;
int name_found = 0;
char name[MAP_MAX_VALUE_LEN];
yxml_init(&xml_parser, xml_buffer, sizeof(xml_buffer));
while (data_len > 0){
data_len -= 1;
yxml_ret_t r = yxml_parse(&xml_parser, *data++);
switch (r){
case YXML_ELEMSTART:
folder_found = strcmp("folder", xml_parser.elem) == 0;
break;
case YXML_ELEMEND:
if (folder_found){
map_client_emit_folder_listing_item_event(callback, cid, (uint8_t *) name, strlen(name));
}
folder_found = 0;
break;
case YXML_ATTRSTART:
if (folder_found == 0) break;
if (strcmp("name", xml_parser.attr) == 0){
name_found = 1;
name[0] = 0;
break;
}
break;
case YXML_ATTRVAL:
if (name_found == 1) {
// "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, xml_parser.data);
break;
}
break;
case YXML_ATTREND:
name_found = 0;
break;
default:
break;
}
}
map_client_emit_parsing_done_event(callback, cid);
}
void map_client_parse_message_listing(btstack_packet_handler_t callback, uint16_t cid, const uint8_t * data, uint16_t data_len){
// now try parsing it
btstack_assert(data_len < 65535);
int message_found = 0;
int handle_found = 0;
char handle[MAP_MESSAGE_HANDLE_SIZE * 2 + 1];
map_message_handle_t msg_handle;
yxml_init(&xml_parser, xml_buffer, sizeof(xml_buffer));
while (data_len > 0){
data_len -= 1;
yxml_ret_t r = yxml_parse(&xml_parser, *data++);
switch (r){
case YXML_ELEMSTART:
message_found = strcmp("msg", xml_parser.elem) == 0;
break;
case YXML_ELEMEND:
if (message_found == 0) break;
message_found = 0;
if (strlen(handle) != MAP_MESSAGE_HANDLE_SIZE * 2){
log_info("message handle string length %u != %u", (unsigned int) strlen(handle), MAP_MESSAGE_HANDLE_SIZE*2);
break;
}
map_message_str_to_handle(handle, msg_handle);
map_client_emit_message_listing_item_event(callback, cid, msg_handle);
break;
case YXML_ATTRSTART:
if (message_found == 0) break;
if (strcmp("handle", xml_parser.attr) == 0){
handle_found = 1;
handle[0] = 0;
break;
}
break;
case YXML_ATTRVAL:
if (handle_found == 1) {
if (strlen(xml_parser.data) != 1) break;
if (strlen(handle) >= (MAP_MESSAGE_HANDLE_SIZE * 2)) break;
strcat(handle, xml_parser.data);
break;
}
break;
case YXML_ATTREND:
handle_found = 0;
break;
default:
break;
}
}
map_client_emit_parsing_done_event(callback, cid);
}

View File

@ -1,63 +0,0 @@
/*
* Copyright (C) 2019 BlueKitchen GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
#ifndef MAP_UTIL_H
#define MAP_UTIL_H
#if defined __cplusplus
extern "C" {
#endif
#include "btstack_config.h"
#include <stdint.h>
#include "map.h"
/* API_START */
/* API_END */
// only for testing
void map_message_str_to_handle(const char * value, map_message_handle_t msg_handle);
void map_message_handle_to_str(char * p, const map_message_handle_t msg_handle);
void map_client_parse_folder_listing(btstack_packet_handler_t callback, uint16_t cid, const uint8_t * data, uint16_t data_len);
void map_client_parse_message_listing(btstack_packet_handler_t callback, uint16_t cid, const uint8_t * data, uint16_t data_len);
#if defined __cplusplus
}
#endif
#endif

View File

@ -1 +0,0 @@
map_xml_test

View File

@ -1,74 +0,0 @@
# Requirements: cpputest.github.io
BTSTACK_ROOT = ../..
CPPUTEST_HOME = ${BTSTACK_ROOT}/test/cpputest
CFLAGS = -DUNIT_TEST -x c++ -g -Wall -Wnarrowing -Wconversion-null
CFLAGS += -I${BTSTACK_ROOT}/src
CFLAGS += -I..
LDFLAGS += -lCppUTest -lCppUTestExt
VPATH += ${BTSTACK_ROOT}/src/ble
VPATH += ${BTSTACK_ROOT}/src
VPATH += ${BTSTACK_ROOT}/platform/posix
VPATH += ${BTSTACK_ROOT}/3rd-party/yxml
CFLAGS += -I${BTSTACK_ROOT}/3rd-party/yxml
VPATH += ${BTSTACK_ROOT}/test/map_client
CFLAGS += -I${BTSTACK_ROOT}/test/map_client
COMMON = \
yxml.c \
btstack_util.c \
hci_dump.c \
map_util.c \
btstack_util.c \
CFLAGS_COVERAGE = ${CFLAGS} -fprofile-arcs -ftest-coverage
CFLAGS_ASAN = ${CFLAGS} -fsanitize=address -DHAVE_ASSERT
LDFLAGS += -lCppUTest -lCppUTestExt
LDFLAGS_COVERAGE = ${LDFLAGS} -fprofile-arcs -ftest-coverage
LDFLAGS_ASAN = ${LDFLAGS} -fsanitize=address
COMMON_OBJ_COVERAGE = $(addprefix build-coverage/,$(COMMON:.c=.o))
COMMON_OBJ_ASAN = $(addprefix build-asan/, $(COMMON:.c=.o))
all: build-coverage/map_xml_test build-asan/map_xml_test
build-%:
mkdir -p $@
build-coverage/%.o: %.c | build-coverage
${CC} -c $(CFLAGS_COVERAGE) $< -o $@
build-coverage/%.o: %.cpp | build-coverage
${CXX} -c $(CFLAGS_COVERAGE) $< -o $@
build-asan/%.o: %.c | build-asan
${CC} -c $(CFLAGS_ASAN) $< -o $@
build-asan/%.o: %.cpp | build-asan
${CXX} -c $(CFLAGS_ASAN) $< -o $@
build-coverage/map_xml_test: ${COMMON_OBJ_COVERAGE} build-coverage/map_xml_test.o | build-coverage
${CXX} $^ ${LDFLAGS_COVERAGE} -o $@
build-asan/map_xml_test: ${COMMON_OBJ_ASAN} build-asan/map_xml_test.o | build-asan
${CXX} $^ ${LDFLAGS_ASAN} -o $@
test: all
build-asan/map_xml_test
coverage: all
rm -f build-coverage/*.gcda
build-coverage/map_xml_test
clean:
rm -rf build-coverage build-asan

View File

@ -1,137 +0,0 @@
#include "CppUTest/TestHarness.h"
#include "CppUTest/CommandLineTestRunner.h"
#include "yxml.h"
#include "map.h"
#include "btstack_defines.h"
#include "btstack_util.h"
#include "btstack_debug.h"
#include "btstack_event.h"
#include "map_util.h"
const static char * folders =
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
"<folder-listing version=\"1.0\">"
" <folder name=\"deleted\" />"
" <folder name=\"draft\" />"
" <folder name=\"inbox\" />"
" <folder name=\"outbox\" />"
" <folder name=\"sent\" />"
"</folder-listing>";
const char * expected_folders[] = {
"deleted",
"draft",
"inbox",
"outbox",
"sent"
};
const int num_expected_folders = 5;
const static char * messages =
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
"<MAP-msg-listing version=\"1.0\">"
" <msg handle=\"0400000000000002\" subject=\"Ping\" datetime=\"20190319T223947\" sender_name=\"John Doe\" sender_addressing=\"+41786786211\" recipient_name=\"@@@@@@@@@@@@@@@@\" recipient_addressing=\"+41798155782\" type=\"SMS_GSM\" size=\"4\" text=\"yes\" reception_status=\"complete\" attachment_size=\"0\" priority=\"no\" read=\"no\" sent=\"no\" protected=\"no\" />"
" <msg handle=\"0400000000000001\" subject=\"Lieber Kunde. Information und Hilfe zur Inbetriebnahme Ihres Mobiltelefons haben wir unter www.swisscom.ch/handy-einrichten für Sie zusammengestellt.\" datetime=\"20190308T224830\" sender_name=\"\" sender_addressing=\"Swisscom\" recipient_name=\"@@@@@@@@@@@@@@@@\" recipient_addressing=\"+41798155782\" type=\"SMS_GSM\" size=\"149\" text=\"yes\" reception_status=\"complete\" attachment_size=\"0\" priority=\"no\" read=\"no\" sent=\"no\" protected=\"no\" />"
"</MAP-msg-listing>";
const map_message_handle_t expected_message_handles[] = {
{4,0,0,0,0,0,0,2},
{4,0,0,0,0,0,0,1}
};
const int num_expected_message_handles = 2;
#if 0
const static char * message =
"BEGIN:BMSG\n"
"VERSION:1.0\n"
"STATUS:UNREAD\n"
"TYPE:SMS_GSM\n"
"FOLDER:telecom/msg/INBOX\n"
"BEGIN:VCARD\n"
"VERSION:3.0\n"
"FN:\n"
"N:\n"
"TEL:Swisscom\n"
"END:VCARD\n"
"BEGIN:BENV\n"
"BEGIN:BBODY\n"
"CHARSET:UTF-8\n"
"LENGTH:172\n"
"BEGIN:MSG\n"
"Lieber Kunde. Information und Hilfe zur Inbetriebnahme Ihres Mobiltelefons haben wir unter www.swisscom.ch/handy-einrichten für Sie zusammengestellt.\n"
"END:MSG\n"
"END:BBODY\n"
"END:BENV\n"
"END:BMSG\n";
#endif
/* xml parser */
static int num_found_items;
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
static void CHECK_EQUAL_ARRAY(const uint8_t * expected, uint8_t * actual, int size){
for (int i=0; i<size; i++){
// printf("%03u: %02x - %02x\n", i, expected[i], actual[i]);
BYTES_EQUAL(expected[i], actual[i]);
}
}
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
if (packet_type != HCI_EVENT_PACKET) return;
if (hci_event_packet_get_type(packet) != HCI_EVENT_MAP_META) return;
int value_len;
char value[MAP_MAX_VALUE_LEN];
memset(value, 0, MAP_MAX_VALUE_LEN);
switch (hci_event_goep_meta_get_subevent_code(packet)){
case MAP_SUBEVENT_FOLDER_LISTING_ITEM:
value_len = btstack_min(map_subevent_folder_listing_item_get_name_len(packet), MAP_MAX_VALUE_LEN);
memcpy(value, map_subevent_folder_listing_item_get_name(packet), value_len);
STRCMP_EQUAL(value, expected_folders[num_found_items]);
num_found_items++;
break;
case MAP_SUBEVENT_MESSAGE_LISTING_ITEM:
memcpy(value, map_subevent_message_listing_item_get_handle(packet), MAP_MESSAGE_HANDLE_SIZE);
CHECK_EQUAL_ARRAY((uint8_t *) value, (uint8_t *) expected_message_handles[num_found_items], MAP_MESSAGE_HANDLE_SIZE);
num_found_items++;
break;
default:
break;
}
}
TEST_GROUP(MAP_XML){
btstack_packet_handler_t map_callback;
uint16_t map_cid;
void setup(void){
map_callback = &packet_handler;
num_found_items = 0;
map_cid = 1;
}
};
TEST(MAP_XML, Folders){
map_client_parse_folder_listing(map_callback, map_cid, (const uint8_t *) folders, strlen(folders));
CHECK_EQUAL(num_found_items, num_expected_folders);
}
TEST(MAP_XML, Messages){
map_client_parse_message_listing(map_callback, map_cid, (const uint8_t *) messages, strlen(messages));
CHECK_EQUAL(num_found_items, num_expected_message_handles);
}
TEST(MAP_XML, Msg2Handle){
uint8_t expected_handle[] = {4,0,0,0,0,0,0,2};
map_message_handle_t msg_handle;
char handle[] = "0400000000000002";
map_message_str_to_handle(handle, msg_handle);
CHECK_EQUAL_ARRAY((uint8_t *) msg_handle, (uint8_t *) expected_handle, MAP_MESSAGE_HANDLE_SIZE);
}
int main (int argc, const char * argv[]){
return CommandLineTestRunner::RunAllTests(argc, argv);
}