mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-23 19:20:51 +00:00
sdp_query: pass in packet handler on query instead of global registration. integrate sdp_parser into sdp_client
This commit is contained in:
parent
69a7c8111f
commit
6c927b22a9
@ -21,7 +21,6 @@ apis = [
|
||||
["src/classic/pan.h", "PAN", "pan"],
|
||||
["src/classic/rfcomm.h", "RFCOMM", "rfcomm"],
|
||||
["src/classic/sdp_client.h", "SDP Client", "sdpClient"],
|
||||
["src/classic/sdp_parser.h","SDP Parser","sdpParser"],
|
||||
["src/classic/sdp_query_rfcomm.h", "SDP RFCOMM Query", "sdpQueries"],
|
||||
["src/classic/sdp_query_util.h","SDP Query Utils","sdpQueryUtil"],
|
||||
["src/classic/sdp_server.h", "SDP Server", "sdpSrv"],
|
||||
|
@ -85,7 +85,6 @@
|
||||
#include "btstack_event.h"
|
||||
#include "btstack_run_loop.h"
|
||||
#include "classic/sdp_client.h"
|
||||
#include "classic/sdp_parser.h"
|
||||
#include "classic/sdp_query_util.h"
|
||||
#include "classic/sdp_util.h"
|
||||
#include "hci.h"
|
||||
@ -151,10 +150,6 @@ static void panu_setup(void){
|
||||
bnep_register_packet_handler(packet_handler);
|
||||
// Minimum L2CAP MTU for bnep is 1691 bytes
|
||||
bnep_register_service(SDP_PANU, 1691);
|
||||
|
||||
// Initialise SDP
|
||||
sdp_parser_init();
|
||||
sdp_parser_register_callback(handle_sdp_client_query_result);
|
||||
}
|
||||
/* LISTING_END */
|
||||
|
||||
|
@ -55,7 +55,6 @@
|
||||
#include "btstack_memory.h"
|
||||
#include "btstack_run_loop.h"
|
||||
#include "classic/sdp_client.h"
|
||||
#include "classic/sdp_parser.h"
|
||||
#include "classic/sdp_query_util.h"
|
||||
#include "classic/sdp_util.h"
|
||||
#include "hci.h"
|
||||
@ -90,7 +89,7 @@ static void assertBuffer(int size){
|
||||
|
||||
/* LISTING_START(SDPClientInit): SDP client setup */
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
static void handle_sdp_client_query_result(uint8_t packet_type, uint8_t *packet, uint16_t size);
|
||||
static void handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
|
||||
static void sdp_client_init(void){
|
||||
|
||||
@ -100,9 +99,6 @@ static void sdp_client_init(void){
|
||||
|
||||
// init L2CAP
|
||||
l2cap_init();
|
||||
|
||||
sdp_parser_init();
|
||||
sdp_parser_register_callback(handle_sdp_client_query_result);
|
||||
}
|
||||
/* LISTING_END */
|
||||
|
||||
@ -125,7 +121,7 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
||||
// BTstack activated, get started
|
||||
if (packet[2] == HCI_STATE_WORKING){
|
||||
printf("Start SDP BNEP query.\n");
|
||||
sdp_general_query_for_uuid(remote, SDP_BNEPProtocol);
|
||||
sdp_general_query_for_uuid(&handle_sdp_client_query_result, remote, SDP_BNEPProtocol);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -165,7 +161,7 @@ static char * get_string_from_data_element(uint8_t * element){
|
||||
*/
|
||||
|
||||
/* LISTING_START(HandleSDPQUeryResult): Extracting BNEP Protcol UUID and L2CAP PSM */
|
||||
static void handle_sdp_client_query_result(uint8_t packet_type, uint8_t *packet, uint16_t size){
|
||||
static void handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
/* LISTING_PAUSE */
|
||||
des_iterator_t des_list_it;
|
||||
des_iterator_t prot_it;
|
||||
|
@ -54,8 +54,6 @@
|
||||
#include "btstack_memory.h"
|
||||
#include "btstack_run_loop.h"
|
||||
#include "classic/sdp_client.h"
|
||||
#include "classic/sdp_parser.h"
|
||||
#include "classic/sdp_parser.h"
|
||||
#include "classic/sdp_query_util.h"
|
||||
#include "hci.h"
|
||||
#include "hci_cmd.h"
|
||||
@ -80,7 +78,7 @@ static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
|
||||
/* LISTING_START(SDPClientInit): SDP client setup */
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
static void handle_sdp_client_query_result(uint8_t packet_type, uint8_t *packet, uint16_t size);
|
||||
static void handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
|
||||
static void sdp_client_init(void){
|
||||
|
||||
@ -90,9 +88,6 @@ static void sdp_client_init(void){
|
||||
|
||||
// init L2CAP
|
||||
l2cap_init();
|
||||
|
||||
sdp_parser_init();
|
||||
sdp_parser_register_callback(handle_sdp_client_query_result);
|
||||
}
|
||||
/* LISTING_END */
|
||||
|
||||
@ -120,7 +115,7 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
||||
switch (event) {
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (packet[2] == HCI_STATE_WORKING){
|
||||
sdp_general_query_for_uuid(remote, SDP_PublicBrowseGroup);
|
||||
sdp_general_query_for_uuid(&handle_sdp_client_query_result, remote, SDP_PublicBrowseGroup);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -149,7 +144,7 @@ static void assertBuffer(int size){
|
||||
*/
|
||||
|
||||
/* LISTING_START(HandleSDPQUeryResult): Handling query result chunks. */
|
||||
static void handle_sdp_client_query_result(uint8_t packet_type, uint8_t *packet, uint16_t size){
|
||||
static void handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
switch (packet[0]){
|
||||
case SDP_EVENT_QUERY_ATTRIBUTE_VALUE:
|
||||
// handle new record
|
||||
|
@ -59,6 +59,8 @@
|
||||
#include "classic/sdp_query_rfcomm.h"
|
||||
#include "btstack_event.h"
|
||||
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
|
||||
// static bd_addr_t remote = {0x04,0x0C,0xCE,0xE4,0x85,0xD3};
|
||||
static bd_addr_t remote = {0x84, 0x38, 0x35, 0x65, 0xD1, 0x15};
|
||||
|
||||
@ -78,7 +80,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
|
||||
case BTSTACK_EVENT_STATE:
|
||||
// bt stack activated, get started
|
||||
if (packet[2] == HCI_STATE_WORKING){
|
||||
sdp_query_rfcomm_channel_and_name_for_uuid(remote, SDP_PublicBrowseGroup);
|
||||
sdp_query_rfcomm_channel_and_name_for_uuid(&handle_query_rfcomm_event, remote, SDP_PublicBrowseGroup);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -109,7 +111,7 @@ static void report_found_services(void){
|
||||
printf(" ***\n\n");
|
||||
}
|
||||
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint8_t *packet, uint16_t size){
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
switch (packet[0]){
|
||||
case SDP_EVENT_QUERY_RFCOMM_SERVICE:
|
||||
store_found_service(sdp_event_query_rfcomm_service_get_name(packet),
|
||||
@ -133,8 +135,6 @@ int btstack_main(int argc, const char * argv[]){
|
||||
// init L2CAP
|
||||
l2cap_init();
|
||||
|
||||
sdp_query_rfcomm_register_callback(handle_query_rfcomm_event);
|
||||
|
||||
// turn on!
|
||||
hci_power_control(HCI_POWER_ON);
|
||||
|
||||
|
@ -70,6 +70,8 @@ typedef enum {
|
||||
DONE
|
||||
} state_t;
|
||||
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
|
||||
#define DATA_VOLUME (1000 * 1000)
|
||||
|
||||
// configuration area {
|
||||
@ -124,7 +126,7 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
||||
case BTSTACK_EVENT_STATE:
|
||||
// bt stack activated, get started
|
||||
if (packet[2] == HCI_STATE_WORKING){
|
||||
sdp_query_rfcomm_channel_and_name_for_uuid(remote, SDP_PublicBrowseGroup);
|
||||
sdp_query_rfcomm_channel_and_name_for_uuid(&handle_query_rfcomm_event, remote, SDP_PublicBrowseGroup);
|
||||
}
|
||||
break;
|
||||
case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE:
|
||||
@ -161,7 +163,7 @@ static void handle_found_service(const char * name, uint8_t port){
|
||||
state = W4_SDP_COMPLETE;
|
||||
}
|
||||
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint8_t *packet, uint16_t size){
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
switch (packet[0]){
|
||||
case SDP_EVENT_QUERY_RFCOMM_SERVICE:
|
||||
handle_found_service(sdp_event_query_rfcomm_service_get_name(packet),
|
||||
@ -196,8 +198,6 @@ int btstack_main(int argc, const char * argv[]){
|
||||
// init L2CAP
|
||||
l2cap_init();
|
||||
|
||||
sdp_query_rfcomm_register_callback(handle_query_rfcomm_event);
|
||||
|
||||
// turn on!
|
||||
hci_power_control(HCI_POWER_ON);
|
||||
|
||||
|
@ -68,7 +68,6 @@
|
||||
#include "classic/rfcomm.h"
|
||||
#include "classic/sdp_server.h"
|
||||
#include "classic/sdp_client.h"
|
||||
#include "classic/sdp_parser.h"
|
||||
#include "classic/sdp_query_rfcomm.h"
|
||||
#include "classic/sdp_query_util.h"
|
||||
#include "hci.h"
|
||||
@ -1134,13 +1133,11 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui
|
||||
memcpy(serviceSearchPattern, &packet[9], serviceSearchPatternLen);
|
||||
|
||||
sdp_client_query_connection = connection;
|
||||
sdp_query_rfcomm_register_callback(handle_sdp_rfcomm_service_result);
|
||||
sdp_query_rfcomm_channel_and_name_for_search_pattern(addr, serviceSearchPattern);
|
||||
|
||||
break;
|
||||
case SDP_CLIENT_QUERY_SERVICES:
|
||||
bt_flip_addr(addr, &packet[3]);
|
||||
sdp_parser_init();
|
||||
sdp_client_query_connection = connection;
|
||||
sdp_parser_register_callback(handle_sdp_client_query_result);
|
||||
|
||||
|
@ -57,7 +57,6 @@
|
||||
<itemPath>../../../src/rfcomm.h</itemPath>
|
||||
<itemPath>../../../src/sdp_server.h</itemPath>
|
||||
<itemPath>../../../src/sdp_client.h</itemPath>
|
||||
<itemPath>../../../src/sdp_parser.h</itemPath>
|
||||
<itemPath>../../../src/sdp_query_rfcomm.h</itemPath>
|
||||
<itemPath>../../../src/sdp_query_util.h</itemPath>
|
||||
</logicalFolder>
|
||||
|
@ -88,7 +88,6 @@
|
||||
#include "classic/rfcomm.h"
|
||||
#include "classic/sdp_server.h"
|
||||
#include "classic/sdp_client.h"
|
||||
#include "classic/sdp_parser.h"
|
||||
#include "classic/sdp_query_rfcomm.h"
|
||||
#include "classic/sdp_query_util.h"
|
||||
#include "classic/sdp_util.h"
|
||||
|
@ -424,7 +424,7 @@ static void handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *pac
|
||||
hfp_handle_hci_event(packet_type, packet, size);
|
||||
}
|
||||
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint8_t *packet, uint16_t size){
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
hfp_connection_t * connection = connection_doing_sdp_query;
|
||||
|
||||
if ( connection->state != HFP_W4_SDP_EVENT_QUERY_COMPLETE) return;
|
||||
@ -1268,10 +1268,6 @@ static void parse_sequence(hfp_connection_t * context){
|
||||
}
|
||||
}
|
||||
|
||||
void hfp_init(void){
|
||||
sdp_query_rfcomm_register_callback(handle_query_rfcomm_event);
|
||||
}
|
||||
|
||||
void hfp_establish_service_level_connection(bd_addr_t bd_addr, uint16_t service_uuid){
|
||||
hfp_connection_t * context = provide_hfp_connection_context_for_bd_addr(bd_addr);
|
||||
log_info("hfp_connect %s, context %p", bd_addr_to_str(bd_addr), context);
|
||||
@ -1293,7 +1289,7 @@ void hfp_establish_service_level_connection(bd_addr_t bd_addr, uint16_t service_
|
||||
context->state = HFP_W4_SDP_EVENT_QUERY_COMPLETE;
|
||||
connection_doing_sdp_query = context;
|
||||
context->service_uuid = service_uuid;
|
||||
sdp_query_rfcomm_channel_and_name_for_uuid(context->remote_addr, service_uuid);
|
||||
sdp_query_rfcomm_channel_and_name_for_uuid(&handle_query_rfcomm_event, context->remote_addr, service_uuid);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -634,7 +634,6 @@ void set_hfp_generic_status_indicators(hfp_generic_status_indicator_t * indicato
|
||||
btstack_linked_list_t * hfp_get_connections(void);
|
||||
void hfp_parse(hfp_connection_t * context, uint8_t byte, int isHandsFree);
|
||||
|
||||
void hfp_init(void);
|
||||
void hfp_establish_service_level_connection(bd_addr_t bd_addr, uint16_t service_uuid);
|
||||
void hfp_release_service_level_connection(hfp_connection_t * connection);
|
||||
void hfp_reset_context_flags(hfp_connection_t * context);
|
||||
|
@ -1998,7 +1998,6 @@ void hfp_ag_init(uint16_t rfcomm_channel_nr, uint32_t supported_features,
|
||||
l2cap_init();
|
||||
|
||||
rfcomm_register_service(packet_handler, rfcomm_channel_nr, 0xffff);
|
||||
hfp_init();
|
||||
|
||||
hfp_supported_features = supported_features;
|
||||
hfp_codecs_nr = codecs_nr;
|
||||
|
@ -1058,8 +1058,7 @@ void hfp_hf_init(uint16_t rfcomm_channel_nr, uint32_t supported_features, uint16
|
||||
|
||||
l2cap_init();
|
||||
rfcomm_register_service(packet_handler, rfcomm_channel_nr, 0xffff);
|
||||
hfp_init();
|
||||
|
||||
|
||||
hfp_supported_features = supported_features;
|
||||
|
||||
hfp_indicators_nr = indicators_nr;
|
||||
|
@ -116,7 +116,7 @@ static hsp_ag_callback_t hsp_ag_callback;
|
||||
|
||||
static void hsp_run();
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint8_t *packet, uint16_t size);
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
|
||||
static void dummy_notify(uint8_t * event, uint16_t size){}
|
||||
|
||||
@ -263,8 +263,6 @@ void hsp_ag_init(uint8_t rfcomm_channel_nr){
|
||||
rfcomm_init();
|
||||
rfcomm_register_service(packet_handler, rfcomm_channel_nr, 0xffff); // reserved channel, mtu limited by l2cap
|
||||
|
||||
sdp_query_rfcomm_register_callback(handle_query_rfcomm_event);
|
||||
|
||||
hsp_ag_reset_state();
|
||||
}
|
||||
|
||||
@ -367,7 +365,7 @@ static void hsp_run(void){
|
||||
case HSP_SDP_QUERY_RFCOMM_CHANNEL:
|
||||
hsp_state = HSP_W4_SDP_EVENT_QUERY_COMPLETE;
|
||||
log_info("Start SDP query %s, 0x%02x", bd_addr_to_str(remote), SDP_HSP);
|
||||
sdp_query_rfcomm_channel_and_name_for_uuid(remote, SDP_HSP);
|
||||
sdp_query_rfcomm_channel_and_name_for_uuid(&handle_query_rfcomm_event, remote, SDP_HSP);
|
||||
break;
|
||||
|
||||
case HSP_W4_RING_ANSWER:
|
||||
@ -441,7 +439,7 @@ static void hsp_run(void){
|
||||
}
|
||||
|
||||
|
||||
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
// log_info("packet_handler type %u, packet[0] %x", packet_type, packet[0]);
|
||||
if (packet_type == RFCOMM_DATA_PACKET){
|
||||
while (size > 0 && (packet[0] == '\n' || packet[0] == '\r')){
|
||||
@ -601,7 +599,7 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha
|
||||
hsp_run();
|
||||
}
|
||||
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint8_t *packet, uint16_t size){
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
switch (packet[0]){
|
||||
case SDP_EVENT_QUERY_RFCOMM_SERVICE:
|
||||
channel_nr = sdp_event_query_rfcomm_service_get_rfcomm_channel(packet);
|
||||
|
@ -55,7 +55,7 @@ extern "C" {
|
||||
typedef void (*hsp_ag_callback_t)(uint8_t * event, uint16_t event_size);
|
||||
|
||||
|
||||
void hsp_ag_create_sdp_record(uint8_t * service, int rfcomm_channel_nr, const char * name);
|
||||
void hsp_ag_create_sdp_record(uint8_t * service, uint32_t service_record_handle, int rfcomm_channel_nr, const char * name);
|
||||
|
||||
|
||||
void hsp_ag_init(uint8_t rfcomm_channel_nr);
|
||||
|
@ -111,7 +111,7 @@ static hsp_state_t hsp_state = HSP_IDLE;
|
||||
|
||||
static void hsp_run(void);
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint8_t *packet, uint16_t size);
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
|
||||
static hsp_hs_callback_t hsp_hs_callback;
|
||||
static void dummy_notify(uint8_t * event, uint16_t size){}
|
||||
@ -263,8 +263,6 @@ void hsp_hs_init(uint8_t rfcomm_channel_nr){
|
||||
rfcomm_init();
|
||||
rfcomm_register_service(packet_handler, rfcomm_channel_nr, 0xffff); // reserved channel, mtu limited by l2cap
|
||||
|
||||
sdp_query_rfcomm_register_callback(handle_query_rfcomm_event);
|
||||
|
||||
hsp_hs_reset_state();
|
||||
}
|
||||
|
||||
@ -330,7 +328,7 @@ static void hsp_run(void){
|
||||
switch (hsp_state){
|
||||
case HSP_SDP_QUERY_RFCOMM_CHANNEL:
|
||||
hsp_state = HSP_W4_SDP_EVENT_QUERY_COMPLETE;
|
||||
sdp_query_rfcomm_channel_and_name_for_uuid(remote, SDP_Headset_AG);
|
||||
sdp_query_rfcomm_channel_and_name_for_uuid(&handle_query_rfcomm_event, remote, SDP_Headset_AG);
|
||||
break;
|
||||
|
||||
case HSP_W2_CONNECT_SCO:
|
||||
@ -565,7 +563,7 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
||||
hsp_run();
|
||||
}
|
||||
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint8_t *packet, uint16_t size){
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
switch (packet[0]){
|
||||
case SDP_EVENT_QUERY_RFCOMM_SERVICE:
|
||||
channel_nr = sdp_event_query_rfcomm_service_get_rfcomm_channel(packet);
|
||||
|
@ -45,64 +45,284 @@
|
||||
#include "hci_cmd.h"
|
||||
|
||||
#include "l2cap.h"
|
||||
#include "classic/sdp_parser.h"
|
||||
#include "classic/sdp_server.h"
|
||||
#include "btstack_debug.h"
|
||||
|
||||
// Types SDP Parser - Data Element stream helper
|
||||
typedef enum {
|
||||
GET_LIST_LENGTH = 1,
|
||||
GET_RECORD_LENGTH,
|
||||
GET_ATTRIBUTE_ID_HEADER_LENGTH,
|
||||
GET_ATTRIBUTE_ID,
|
||||
GET_ATTRIBUTE_VALUE_LENGTH,
|
||||
GET_ATTRIBUTE_VALUE
|
||||
} sdp_parser_state_t;
|
||||
|
||||
// Types SDP Client
|
||||
typedef enum {
|
||||
INIT, W4_CONNECT, W2_SEND, W4_RESPONSE, QUERY_COMPLETE
|
||||
} sdp_client_state_t;
|
||||
|
||||
|
||||
void sdp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
|
||||
static uint16_t setup_service_search_attribute_request(uint8_t * data);
|
||||
// Prototypes SDP Parser
|
||||
void sdp_parser_init(btstack_packet_handler_t callback);
|
||||
void sdp_parser_handle_chunk(uint8_t * data, uint16_t size);
|
||||
void sdp_parser_handle_done(uint8_t status);
|
||||
void sdp_parser_init_service_attribute_search(void);
|
||||
void sdp_parser_init_service_search(void);
|
||||
void sdp_parser_handle_service_search(uint8_t * data, uint16_t total_count, uint16_t record_handle_count);
|
||||
|
||||
// Prototypes SDP Client
|
||||
void sdp_client_reset(void);
|
||||
void sdp_client_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
static uint16_t sdp_client_setup_service_search_attribute_request(uint8_t * data);
|
||||
#ifdef ENABLE_SDP_EXTRA_QUERIES
|
||||
static uint16_t setup_service_search_request(uint8_t * data);
|
||||
static uint16_t setup_service_attribute_request(uint8_t * data);
|
||||
static void parse_service_search_response(uint8_t* packet);
|
||||
static void parse_service_attribute_response(uint8_t* packet);
|
||||
static uint16_t sdp_client_setup_service_search_request(uint8_t * data);
|
||||
static uint16_t sdp_client_setup_service_attribute_request(uint8_t * data);
|
||||
static void sdp_client_parse_service_search_response(uint8_t* packet);
|
||||
static void sdp_client_parse_service_attribute_response(uint8_t* packet);
|
||||
static uint32_t serviceRecordHandle;
|
||||
static uint32_t record_handle;
|
||||
#endif
|
||||
|
||||
// SDP Client Query
|
||||
// State DES Parser
|
||||
static de_state_t de_header_state;
|
||||
|
||||
// State SDP Parser
|
||||
static sdp_parser_state_t state = GET_LIST_LENGTH;
|
||||
static uint16_t attribute_id = 0;
|
||||
static uint16_t attribute_bytes_received = 0;
|
||||
static uint16_t attribute_bytes_delivered = 0;
|
||||
static uint16_t list_offset = 0;
|
||||
static uint16_t list_size;
|
||||
static uint16_t record_offset = 0;
|
||||
static uint16_t record_size;
|
||||
static uint16_t attribute_value_size;
|
||||
static int record_counter = 0;
|
||||
static btstack_packet_handler_t sdp_parser_callback;
|
||||
|
||||
// State SDP Client
|
||||
static uint16_t mtu;
|
||||
static uint16_t sdp_cid = 0x40;
|
||||
static uint8_t * serviceSearchPattern;
|
||||
static uint8_t * attributeIDList;
|
||||
static const uint8_t * service_search_pattern;
|
||||
static const uint8_t * attribute_id_list;
|
||||
static uint16_t transactionID = 0;
|
||||
static uint8_t continuationState[16];
|
||||
static uint8_t continuationStateLen;
|
||||
static sdp_client_state_t sdp_client_state = INIT;
|
||||
static SDP_PDU_ID_t PDU_ID = SDP_Invalid;
|
||||
|
||||
// DES Parser
|
||||
void de_state_init(de_state_t * de_state){
|
||||
de_state->in_state_GET_DE_HEADER_LENGTH = 1;
|
||||
de_state->addon_header_bytes = 0;
|
||||
de_state->de_size = 0;
|
||||
de_state->de_offset = 0;
|
||||
}
|
||||
|
||||
int de_state_size(uint8_t eventByte, de_state_t *de_state){
|
||||
if (de_state->in_state_GET_DE_HEADER_LENGTH){
|
||||
de_state->addon_header_bytes = de_get_header_size(&eventByte) - 1;
|
||||
de_state->de_size = 0;
|
||||
de_state->de_offset = 0;
|
||||
|
||||
if (de_state->addon_header_bytes == 0){
|
||||
de_state->de_size = de_get_data_size(&eventByte);
|
||||
if (de_state->de_size == 0) {
|
||||
log_error(" ERROR: ID size is zero");
|
||||
}
|
||||
// log_info("Data element payload is %d bytes.", de_state->de_size);
|
||||
return 1;
|
||||
}
|
||||
de_state->in_state_GET_DE_HEADER_LENGTH = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (de_state->addon_header_bytes > 0){
|
||||
de_state->de_size = (de_state->de_size << 8) | eventByte;
|
||||
de_state->addon_header_bytes--;
|
||||
}
|
||||
if (de_state->addon_header_bytes > 0) return 0;
|
||||
// log_info("Data element payload is %d bytes.", de_state->de_size);
|
||||
de_state->in_state_GET_DE_HEADER_LENGTH = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// SDP Parser
|
||||
static void sdp_parser_emit_value_byte(uint8_t event_byte){
|
||||
uint8_t event[11];
|
||||
event[0] = SDP_EVENT_QUERY_ATTRIBUTE_VALUE;
|
||||
event[1] = 9;
|
||||
little_endian_store_16(event, 2, record_counter);
|
||||
little_endian_store_16(event, 4, attribute_id);
|
||||
little_endian_store_16(event, 6, attribute_value_size);
|
||||
little_endian_store_16(event, 8, attribute_bytes_delivered);
|
||||
event[10] = event_byte;
|
||||
(*sdp_parser_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
static void sdp_parser_process_byte(uint8_t eventByte){
|
||||
// count all bytes
|
||||
list_offset++;
|
||||
record_offset++;
|
||||
|
||||
// log_info(" parse BYTE_RECEIVED %02x", eventByte);
|
||||
switch(state){
|
||||
case GET_LIST_LENGTH:
|
||||
if (!de_state_size(eventByte, &de_header_state)) break;
|
||||
list_offset = de_header_state.de_offset;
|
||||
list_size = de_header_state.de_size;
|
||||
// log_info("parser: List offset %u, list size %u", list_offset, list_size);
|
||||
|
||||
record_counter = 0;
|
||||
state = GET_RECORD_LENGTH;
|
||||
break;
|
||||
|
||||
case GET_RECORD_LENGTH:
|
||||
// check size
|
||||
if (!de_state_size(eventByte, &de_header_state)) break;
|
||||
// log_info("parser: Record payload is %d bytes.", de_header_state.de_size);
|
||||
record_offset = de_header_state.de_offset;
|
||||
record_size = de_header_state.de_size;
|
||||
state = GET_ATTRIBUTE_ID_HEADER_LENGTH;
|
||||
break;
|
||||
|
||||
case GET_ATTRIBUTE_ID_HEADER_LENGTH:
|
||||
if (!de_state_size(eventByte, &de_header_state)) break;
|
||||
attribute_id = 0;
|
||||
log_info("ID data is stored in %d bytes.", (int) de_header_state.de_size);
|
||||
state = GET_ATTRIBUTE_ID;
|
||||
break;
|
||||
|
||||
case GET_ATTRIBUTE_ID:
|
||||
attribute_id = (attribute_id << 8) | eventByte;
|
||||
de_header_state.de_size--;
|
||||
if (de_header_state.de_size > 0) break;
|
||||
log_info("parser: Attribute ID: %04x.", attribute_id);
|
||||
|
||||
state = GET_ATTRIBUTE_VALUE_LENGTH;
|
||||
attribute_bytes_received = 0;
|
||||
attribute_bytes_delivered = 0;
|
||||
attribute_value_size = 0;
|
||||
de_state_init(&de_header_state);
|
||||
break;
|
||||
|
||||
case GET_ATTRIBUTE_VALUE_LENGTH:
|
||||
attribute_bytes_received++;
|
||||
sdp_parser_emit_value_byte(eventByte);
|
||||
attribute_bytes_delivered++;
|
||||
if (!de_state_size(eventByte, &de_header_state)) break;
|
||||
|
||||
attribute_value_size = de_header_state.de_size + attribute_bytes_received;
|
||||
|
||||
state = GET_ATTRIBUTE_VALUE;
|
||||
break;
|
||||
|
||||
case GET_ATTRIBUTE_VALUE:
|
||||
attribute_bytes_received++;
|
||||
sdp_parser_emit_value_byte(eventByte);
|
||||
attribute_bytes_delivered++;
|
||||
// log_info("paser: attribute_bytes_received %u, attribute_value_size %u", attribute_bytes_received, attribute_value_size);
|
||||
|
||||
if (attribute_bytes_received < attribute_value_size) break;
|
||||
// log_info("parser: Record offset %u, record size %u", record_offset, record_size);
|
||||
if (record_offset != record_size){
|
||||
state = GET_ATTRIBUTE_ID_HEADER_LENGTH;
|
||||
// log_info("Get next attribute");
|
||||
break;
|
||||
}
|
||||
record_offset = 0;
|
||||
// log_info("parser: List offset %u, list size %u", list_offset, list_size);
|
||||
|
||||
if (list_size > 0 && list_offset != list_size){
|
||||
record_counter++;
|
||||
state = GET_RECORD_LENGTH;
|
||||
log_info("parser: END_OF_RECORD");
|
||||
break;
|
||||
}
|
||||
list_offset = 0;
|
||||
de_state_init(&de_header_state);
|
||||
state = GET_LIST_LENGTH;
|
||||
record_counter = 0;
|
||||
log_info("parser: END_OF_RECORD & DONE");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void sdp_parser_init(btstack_packet_handler_t callback){
|
||||
// init
|
||||
sdp_parser_callback = callback;
|
||||
de_state_init(&de_header_state);
|
||||
state = GET_LIST_LENGTH;
|
||||
list_offset = 0;
|
||||
record_offset = 0;
|
||||
record_counter = 0;
|
||||
}
|
||||
|
||||
void sdp_parser_handle_chunk(uint8_t * data, uint16_t size){
|
||||
int i;
|
||||
for (i=0;i<size;i++){
|
||||
sdp_parser_process_byte(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SDP_EXTRA_QUERIES
|
||||
void sdp_parser_init_service_attribute_search(void){
|
||||
// init
|
||||
de_state_init(&de_header_state);
|
||||
state = GET_RECORD_LENGTH;
|
||||
list_offset = 0;
|
||||
record_offset = 0;
|
||||
record_counter = 0;
|
||||
}
|
||||
|
||||
void sdp_parser_init_service_search(void){
|
||||
record_offset = 0;
|
||||
}
|
||||
|
||||
void sdp_parser_handle_service_search(uint8_t * data, uint16_t total_count, uint16_t record_handle_count){
|
||||
int i;
|
||||
for (i=0;i<record_handle_count;i++){
|
||||
record_handle = big_endian_read_32(data, i*4);
|
||||
record_counter++;
|
||||
uint8_t event[10];
|
||||
event[0] = SDP_EVENT_QUERY_SERVICE_RECORD_HANDLE;
|
||||
event[1] = 8;
|
||||
little_endian_store_16(event, 2, total_count);
|
||||
little_endian_store_16(event, 4, record_counter);
|
||||
little_endian_store_32(event, 6, record_handle);
|
||||
(*sdp_parser_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void sdp_parser_handle_done(uint8_t status){
|
||||
uint8_t event[3];
|
||||
event[0] = SDP_EVENT_QUERY_COMPLETE;
|
||||
event[1] = 1;
|
||||
event[2] = status;
|
||||
(*sdp_parser_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
|
||||
// SDP Client
|
||||
|
||||
// TODO: inline if not needed (des(des))
|
||||
static void parse_attribute_lists(uint8_t* packet, uint16_t length){
|
||||
sdp_parser_handle_chunk(packet, length);
|
||||
}
|
||||
|
||||
/* Queries the SDP service of the remote device given a service search pattern
|
||||
and a list of attribute IDs. The remote data is handled by the SDP parser. The
|
||||
SDP parser delivers attribute values and done event via a registered callback. */
|
||||
|
||||
void sdp_client_query(bd_addr_t remote, uint8_t * des_serviceSearchPattern, uint8_t * des_attributeIDList){
|
||||
serviceSearchPattern = des_serviceSearchPattern;
|
||||
attributeIDList = des_attributeIDList;
|
||||
continuationStateLen = 0;
|
||||
PDU_ID = SDP_ServiceSearchAttributeResponse;
|
||||
|
||||
sdp_client_state = W4_CONNECT;
|
||||
l2cap_create_channel(sdp_packet_handler, remote, PSM_SDP, l2cap_max_mtu(), NULL);
|
||||
}
|
||||
|
||||
static int can_send_now(uint16_t channel){
|
||||
static int sdp_client_can_send_now(uint16_t channel){
|
||||
if (sdp_client_state != W2_SEND) return 0;
|
||||
if (!l2cap_can_send_packet_now(channel)) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void send_request(uint16_t channel){
|
||||
static void sdp_client_parse_attribute_lists(uint8_t* packet, uint16_t length){
|
||||
sdp_parser_handle_chunk(packet, length);
|
||||
}
|
||||
|
||||
|
||||
static void sdp_client_send_request(uint16_t channel){
|
||||
l2cap_reserve_packet_buffer();
|
||||
uint8_t * data = l2cap_get_outgoing_buffer();
|
||||
uint16_t request_len = 0;
|
||||
@ -110,17 +330,17 @@ static void send_request(uint16_t channel){
|
||||
switch (PDU_ID){
|
||||
#ifdef ENABLE_SDP_EXTRA_QUERIES
|
||||
case SDP_ServiceSearchResponse:
|
||||
request_len = setup_service_search_request(data);
|
||||
request_len = sdp_client_setup_service_search_request(data);
|
||||
break;
|
||||
case SDP_ServiceAttributeResponse:
|
||||
request_len = setup_service_attribute_request(data);
|
||||
request_len = sdp_client_setup_service_attribute_request(data);
|
||||
break;
|
||||
#endif
|
||||
case SDP_ServiceSearchAttributeResponse:
|
||||
request_len = setup_service_search_attribute_request(data);
|
||||
request_len = sdp_client_setup_service_search_attribute_request(data);
|
||||
break;
|
||||
default:
|
||||
log_error("SDP Client send_request :: PDU ID invalid. %u", PDU_ID);
|
||||
log_error("SDP Client sdp_client_send_request :: PDU ID invalid. %u", PDU_ID);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -145,7 +365,7 @@ static void send_request(uint16_t channel){
|
||||
}
|
||||
|
||||
|
||||
static void parse_service_search_attribute_response(uint8_t* packet){
|
||||
static void sdp_client_parse_service_search_attribute_response(uint8_t* packet){
|
||||
uint16_t offset = 3;
|
||||
uint16_t parameterLength = big_endian_read_16(packet,offset);
|
||||
offset+=2;
|
||||
@ -159,7 +379,7 @@ static void parse_service_search_attribute_response(uint8_t* packet){
|
||||
}
|
||||
|
||||
// AttributeLists
|
||||
parse_attribute_lists(packet+offset, attributeListByteCount);
|
||||
sdp_client_parse_attribute_lists(packet+offset, attributeListByteCount);
|
||||
offset+=attributeListByteCount;
|
||||
|
||||
continuationStateLen = packet[offset];
|
||||
@ -177,7 +397,7 @@ static void parse_service_search_attribute_response(uint8_t* packet){
|
||||
}
|
||||
}
|
||||
|
||||
void sdp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
void sdp_client_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
// uint16_t handle;
|
||||
if (packet_type == L2CAP_DATA_PACKET){
|
||||
uint16_t responseTransactionID = big_endian_read_16(packet,1);
|
||||
@ -199,14 +419,14 @@ void sdp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet,
|
||||
switch (PDU_ID){
|
||||
#ifdef ENABLE_SDP_EXTRA_QUERIES
|
||||
case SDP_ServiceSearchResponse:
|
||||
parse_service_search_response(packet);
|
||||
sdp_client_parse_service_search_response(packet);
|
||||
break;
|
||||
case SDP_ServiceAttributeResponse:
|
||||
parse_service_attribute_response(packet);
|
||||
sdp_client_parse_service_attribute_response(packet);
|
||||
break;
|
||||
#endif
|
||||
case SDP_ServiceSearchAttributeResponse:
|
||||
parse_service_search_attribute_response(packet);
|
||||
sdp_client_parse_service_search_attribute_response(packet);
|
||||
break;
|
||||
default:
|
||||
log_error("SDP Client :: PDU ID invalid. %u ,%u", PDU_ID, packet[0]);
|
||||
@ -223,7 +443,7 @@ void sdp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet,
|
||||
}
|
||||
// prepare next request and send
|
||||
sdp_client_state = W2_SEND;
|
||||
if (can_send_now(sdp_cid)) send_request(sdp_cid);
|
||||
if (sdp_client_can_send_now(sdp_cid)) sdp_client_send_request(sdp_cid);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -247,11 +467,11 @@ void sdp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet,
|
||||
log_info("SDP Client Connected, cid %x, mtu %u.", sdp_cid, mtu);
|
||||
|
||||
sdp_client_state = W2_SEND;
|
||||
if (can_send_now(sdp_cid)) send_request(sdp_cid);
|
||||
if (sdp_client_can_send_now(sdp_cid)) sdp_client_send_request(sdp_cid);
|
||||
|
||||
break;
|
||||
case L2CAP_EVENT_CAN_SEND_NOW:
|
||||
if (can_send_now(sdp_cid)) send_request(sdp_cid);
|
||||
if (sdp_client_can_send_now(sdp_cid)) sdp_client_send_request(sdp_cid);
|
||||
break;
|
||||
case L2CAP_EVENT_CHANNEL_CLOSED: {
|
||||
if (sdp_cid != little_endian_read_16(packet, 2)) {
|
||||
@ -270,7 +490,7 @@ void sdp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet,
|
||||
}
|
||||
|
||||
|
||||
static uint16_t setup_service_search_attribute_request(uint8_t * data){
|
||||
static uint16_t sdp_client_setup_service_search_attribute_request(uint8_t * data){
|
||||
|
||||
uint16_t offset = 0;
|
||||
transactionID++;
|
||||
@ -284,19 +504,19 @@ static uint16_t setup_service_search_attribute_request(uint8_t * data){
|
||||
offset += 2;
|
||||
|
||||
// parameters:
|
||||
// ServiceSearchPattern - DES (min 1 UUID, max 12)
|
||||
uint16_t serviceSearchPatternLen = de_get_len(serviceSearchPattern);
|
||||
memcpy(data + offset, serviceSearchPattern, serviceSearchPatternLen);
|
||||
offset += serviceSearchPatternLen;
|
||||
// Service_search_pattern - DES (min 1 UUID, max 12)
|
||||
uint16_t service_search_pattern_len = de_get_len(service_search_pattern);
|
||||
memcpy(data + offset, service_search_pattern, service_search_pattern_len);
|
||||
offset += service_search_pattern_len;
|
||||
|
||||
// MaximumAttributeByteCount - uint16_t 0x0007 - 0xffff -> mtu
|
||||
big_endian_store_16(data, offset, mtu);
|
||||
offset += 2;
|
||||
|
||||
// AttibuteIDList
|
||||
uint16_t attributeIDListLen = de_get_len(attributeIDList);
|
||||
memcpy(data + offset, attributeIDList, attributeIDListLen);
|
||||
offset += attributeIDListLen;
|
||||
uint16_t attribute_id_list_len = de_get_len(attribute_id_list);
|
||||
memcpy(data + offset, attribute_id_list, attribute_id_list_len);
|
||||
offset += attribute_id_list_len;
|
||||
|
||||
// ContinuationState - uint8_t number of cont. bytes N<=16
|
||||
data[offset++] = continuationStateLen;
|
||||
@ -311,11 +531,11 @@ static uint16_t setup_service_search_attribute_request(uint8_t * data){
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SDP_EXTRA_QUERIES
|
||||
void parse_service_record_handle_list(uint8_t* packet, uint16_t total_count, uint16_t current_count){
|
||||
void sdp_client_parse_service_record_handle_list(uint8_t* packet, uint16_t total_count, uint16_t current_count){
|
||||
sdp_parser_handle_service_search(packet, total_count, current_count);
|
||||
}
|
||||
|
||||
static uint16_t setup_service_search_request(uint8_t * data){
|
||||
static uint16_t sdp_client_setup_service_search_request(uint8_t * data){
|
||||
uint16_t offset = 0;
|
||||
transactionID++;
|
||||
// uint8_t SDP_PDU_ID_t.SDP_ServiceSearchRequest;
|
||||
@ -328,10 +548,10 @@ static uint16_t setup_service_search_request(uint8_t * data){
|
||||
offset += 2;
|
||||
|
||||
// parameters:
|
||||
// ServiceSearchPattern - DES (min 1 UUID, max 12)
|
||||
uint16_t serviceSearchPatternLen = de_get_len(serviceSearchPattern);
|
||||
memcpy(data + offset, serviceSearchPattern, serviceSearchPatternLen);
|
||||
offset += serviceSearchPatternLen;
|
||||
// Service_search_pattern - DES (min 1 UUID, max 12)
|
||||
uint16_t service_search_pattern_len = de_get_len(service_search_pattern);
|
||||
memcpy(data + offset, service_search_pattern, service_search_pattern_len);
|
||||
offset += service_search_pattern_len;
|
||||
|
||||
// MaximumAttributeByteCount - uint16_t 0x0007 - 0xffff -> mtu
|
||||
big_endian_store_16(data, offset, mtu);
|
||||
@ -350,7 +570,7 @@ static uint16_t setup_service_search_request(uint8_t * data){
|
||||
}
|
||||
|
||||
|
||||
static uint16_t setup_service_attribute_request(uint8_t * data){
|
||||
static uint16_t sdp_client_setup_service_attribute_request(uint8_t * data){
|
||||
|
||||
uint16_t offset = 0;
|
||||
transactionID++;
|
||||
@ -373,9 +593,9 @@ static uint16_t setup_service_attribute_request(uint8_t * data){
|
||||
offset += 2;
|
||||
|
||||
// AttibuteIDList
|
||||
uint16_t attributeIDListLen = de_get_len(attributeIDList);
|
||||
memcpy(data + offset, attributeIDList, attributeIDListLen);
|
||||
offset += attributeIDListLen;
|
||||
uint16_t attribute_id_list_len = de_get_len(attribute_id_list);
|
||||
memcpy(data + offset, attribute_id_list, attribute_id_list_len);
|
||||
offset += attribute_id_list_len;
|
||||
|
||||
// ContinuationState - uint8_t number of cont. bytes N<=16
|
||||
data[offset++] = continuationStateLen;
|
||||
@ -389,7 +609,7 @@ static uint16_t setup_service_attribute_request(uint8_t * data){
|
||||
return offset;
|
||||
}
|
||||
|
||||
static void parse_service_search_response(uint8_t* packet){
|
||||
static void sdp_client_parse_service_search_response(uint8_t* packet){
|
||||
uint16_t offset = 3;
|
||||
uint16_t parameterLength = big_endian_read_16(packet,offset);
|
||||
offset+=2;
|
||||
@ -404,7 +624,7 @@ static void parse_service_search_response(uint8_t* packet){
|
||||
return;
|
||||
}
|
||||
|
||||
parse_service_record_handle_list(packet+offset, totalServiceRecordCount, currentServiceRecordCount);
|
||||
sdp_client_parse_service_record_handle_list(packet+offset, totalServiceRecordCount, currentServiceRecordCount);
|
||||
offset+=(currentServiceRecordCount * 4);
|
||||
|
||||
continuationStateLen = packet[offset];
|
||||
@ -421,7 +641,7 @@ static void parse_service_search_response(uint8_t* packet){
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_service_attribute_response(uint8_t* packet){
|
||||
static void sdp_client_parse_service_attribute_response(uint8_t* packet){
|
||||
uint16_t offset = 3;
|
||||
uint16_t parameterLength = big_endian_read_16(packet,offset);
|
||||
offset+=2;
|
||||
@ -436,7 +656,7 @@ static void parse_service_attribute_response(uint8_t* packet){
|
||||
}
|
||||
|
||||
// AttributeLists
|
||||
parse_attribute_lists(packet+offset, attributeListByteCount);
|
||||
sdp_client_parse_attribute_lists(packet+offset, attributeListByteCount);
|
||||
offset+=attributeListByteCount;
|
||||
|
||||
continuationStateLen = packet[offset];
|
||||
@ -453,24 +673,62 @@ static void parse_service_attribute_response(uint8_t* packet){
|
||||
log_error("Error parsing ServiceAttributeResponse: wrong size of parameters, number of expected bytes%u, actual number %u.", parameterLength, offset);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void sdp_client_service_attribute_search(bd_addr_t remote, uint32_t search_serviceRecordHandle, uint8_t * des_attributeIDList){
|
||||
serviceRecordHandle = search_serviceRecordHandle;
|
||||
attributeIDList = des_attributeIDList;
|
||||
// for testing only
|
||||
void sdp_client_reset(void){
|
||||
sdp_client_state = INIT;
|
||||
}
|
||||
|
||||
// Public API
|
||||
|
||||
int sdp_client_ready(void){
|
||||
return sdp_client_state == INIT;
|
||||
}
|
||||
|
||||
void sdp_client_query(btstack_packet_handler_t callback, bd_addr_t remote, const uint8_t * des_service_search_pattern, const uint8_t * des_attribute_id_list){
|
||||
if (!sdp_client_ready()) {
|
||||
log_error("sdp_client_query called when not ready");
|
||||
return;
|
||||
}
|
||||
sdp_parser_init(callback);
|
||||
service_search_pattern = des_service_search_pattern;
|
||||
attribute_id_list = des_attribute_id_list;
|
||||
continuationStateLen = 0;
|
||||
PDU_ID = SDP_ServiceSearchAttributeResponse;
|
||||
|
||||
sdp_client_state = W4_CONNECT;
|
||||
l2cap_create_channel(sdp_client_packet_handler, remote, PSM_SDP, l2cap_max_mtu(), NULL);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SDP_EXTRA_QUERIES
|
||||
void sdp_client_service_attribute_search(btstack_packet_handler_t callback, bd_addr_t remote, uint32_t search_service_record_handle, uint8_t * des_attribute_id_list){
|
||||
if (!sdp_client_ready()) {
|
||||
log_error("sdp_client_query called when not ready");
|
||||
return;
|
||||
}
|
||||
sdp_parser_init(callback);
|
||||
serviceRecordHandle = search_service_record_handle;
|
||||
attribute_id_list = des_attribute_id_list;
|
||||
continuationStateLen = 0;
|
||||
PDU_ID = SDP_ServiceAttributeResponse;
|
||||
|
||||
sdp_client_state = W4_CONNECT;
|
||||
l2cap_create_channel(sdp_packet_handler, remote, PSM_SDP, l2cap_max_mtu(), NULL);
|
||||
l2cap_create_channel(sdp_client_packet_handler, remote, PSM_SDP, l2cap_max_mtu(), NULL);
|
||||
}
|
||||
|
||||
void sdp_client_service_search(bd_addr_t remote, uint8_t * des_serviceSearchPattern){
|
||||
serviceSearchPattern = des_serviceSearchPattern;
|
||||
void sdp_client_service_search(btstack_packet_handler_t callback, bd_addr_t remote, uint8_t * des_service_search_pattern){
|
||||
if (!sdp_client_ready()) {
|
||||
log_error("sdp_client_query called when not ready");
|
||||
return;
|
||||
}
|
||||
sdp_parser_init(callback);
|
||||
service_search_pattern = des_service_search_pattern;
|
||||
continuationStateLen = 0;
|
||||
PDU_ID = SDP_ServiceSearchResponse;
|
||||
|
||||
sdp_client_state = W4_CONNECT;
|
||||
l2cap_create_channel(sdp_packet_handler, remote, PSM_SDP, l2cap_max_mtu(), NULL);
|
||||
l2cap_create_channel(sdp_client_packet_handler, remote, PSM_SDP, l2cap_max_mtu(), NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -51,17 +51,55 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* API_START */
|
||||
|
||||
|
||||
typedef struct de_state {
|
||||
uint8_t in_state_GET_DE_HEADER_LENGTH ;
|
||||
uint32_t addon_header_bytes;
|
||||
uint32_t de_size;
|
||||
uint32_t de_offset;
|
||||
} de_state_t;
|
||||
|
||||
void de_state_init(de_state_t * state);
|
||||
int de_state_size(uint8_t eventByte, de_state_t *de_state);
|
||||
|
||||
/**
|
||||
* @brief Checks if the SDP Client is ready
|
||||
* @return 1 when no query is active
|
||||
*/
|
||||
int sdp_client_ready(void);
|
||||
|
||||
/**
|
||||
* @brief Queries the SDP service of the remote device given a service search pattern and a list of attribute IDs.
|
||||
* The remote data is handled by the SDP parser. The SDP parser delivers attribute values and done event via a registered callback.
|
||||
* The remote data is handled by the SDP parser. The SDP parser delivers attribute values and done event via the callback.
|
||||
* @param callback for attributes values and done event
|
||||
* @param remote address
|
||||
* @param des_service_search_pattern
|
||||
* @param des_attribute_id_list
|
||||
*/
|
||||
void sdp_client_query(bd_addr_t remote, uint8_t * des_serviceSearchPattern, uint8_t * des_attributeIDList);
|
||||
void sdp_client_query(btstack_packet_handler_t callback, bd_addr_t remote, const uint8_t * des_service_search_pattern, const uint8_t * des_attribute_id_list);
|
||||
|
||||
/**
|
||||
* @brief Retrieves all attribute IDs of a SDP record specified by its service record handle and a list of attribute IDs.
|
||||
* The remote data is handled by the SDP parser. The SDP parser delivers attribute values and done event via the callback.
|
||||
* @note only provided if ENABLE_SDP_EXTRA_QUERIES is defined
|
||||
* @param callback for attributes values and done event
|
||||
* @param remote address
|
||||
* @param search_service_record_handle
|
||||
* @param des_attributeIDList
|
||||
*/
|
||||
void sdp_client_service_attribute_search(btstack_packet_handler_t callback, bd_addr_t remote, uint32_t search_service_record_handle, const uint8_t * des_attributeIDList);
|
||||
|
||||
/**
|
||||
* @brief Query the list of SDP records that match a given service search pattern.
|
||||
* The remote data is handled by the SDP parser. The SDP parser delivers attribute values and done event via the callback.
|
||||
* @note only provided if ENABLE_SDP_EXTRA_QUERIES is defined
|
||||
* @param callback for attributes values and done event
|
||||
* @param remote address
|
||||
* @param des_service_search_pattern
|
||||
*/
|
||||
void sdp_client_service_search(btstack_packet_handler_t callback, bd_addr_t remote, const uint8_t * des_service_search_pattern);
|
||||
|
||||
|
||||
#ifdef ENABLE_SDP_EXTRA_QUERIES
|
||||
void sdp_client_service_attribute_search(bd_addr_t remote, uint32_t search_serviceRecordHandle, uint8_t * des_attributeIDList);
|
||||
void sdp_client_service_search(bd_addr_t remote, uint8_t * des_serviceSearchPattern);
|
||||
#endif
|
||||
/* API_END */
|
||||
|
||||
#if defined __cplusplus
|
||||
|
@ -1,273 +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
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* sdp_parser.c
|
||||
*/
|
||||
#include "hci_cmd.h"
|
||||
#include "classic/sdp_parser.h"
|
||||
#include "btstack_debug.h"
|
||||
|
||||
typedef enum {
|
||||
GET_LIST_LENGTH = 1,
|
||||
GET_RECORD_LENGTH,
|
||||
GET_ATTRIBUTE_ID_HEADER_LENGTH,
|
||||
GET_ATTRIBUTE_ID,
|
||||
GET_ATTRIBUTE_VALUE_LENGTH,
|
||||
GET_ATTRIBUTE_VALUE
|
||||
} state_t;
|
||||
|
||||
static state_t state = GET_LIST_LENGTH;
|
||||
static uint16_t attribute_id = 0;
|
||||
static uint16_t attribute_bytes_received = 0;
|
||||
static uint16_t attribute_bytes_delivered = 0;
|
||||
static uint16_t list_offset = 0;
|
||||
static uint16_t list_size;
|
||||
static uint16_t record_offset = 0;
|
||||
static uint16_t record_size;
|
||||
static uint16_t attribute_value_size;
|
||||
static int record_counter = 0;
|
||||
|
||||
#ifdef ENABLE_SDP_EXTRA_QUERIES
|
||||
static uint32_t record_handle;
|
||||
#endif
|
||||
|
||||
static void (*sdp_query_callback)(uint8_t packet_type, uint8_t *packet, uint16_t size);
|
||||
|
||||
// Low level parser
|
||||
static de_state_t de_header_state;
|
||||
|
||||
|
||||
void de_state_init(de_state_t * de_state){
|
||||
de_state->in_state_GET_DE_HEADER_LENGTH = 1;
|
||||
de_state->addon_header_bytes = 0;
|
||||
de_state->de_size = 0;
|
||||
de_state->de_offset = 0;
|
||||
}
|
||||
|
||||
int de_state_size(uint8_t eventByte, de_state_t *de_state){
|
||||
if (de_state->in_state_GET_DE_HEADER_LENGTH){
|
||||
de_state->addon_header_bytes = de_get_header_size(&eventByte) - 1;
|
||||
de_state->de_size = 0;
|
||||
de_state->de_offset = 0;
|
||||
|
||||
if (de_state->addon_header_bytes == 0){
|
||||
de_state->de_size = de_get_data_size(&eventByte);
|
||||
if (de_state->de_size == 0) {
|
||||
log_error(" ERROR: ID size is zero");
|
||||
}
|
||||
// log_info("Data element payload is %d bytes.", de_state->de_size);
|
||||
return 1;
|
||||
}
|
||||
de_state->in_state_GET_DE_HEADER_LENGTH = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (de_state->addon_header_bytes > 0){
|
||||
de_state->de_size = (de_state->de_size << 8) | eventByte;
|
||||
de_state->addon_header_bytes--;
|
||||
}
|
||||
if (de_state->addon_header_bytes > 0) return 0;
|
||||
// log_info("Data element payload is %d bytes.", de_state->de_size);
|
||||
de_state->in_state_GET_DE_HEADER_LENGTH = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void dummy_notify(uint8_t packet_type, uint8_t *packet, uint16_t size){}
|
||||
|
||||
void sdp_parser_register_callback(void (*sdp_callback)(uint8_t packet_type, uint8_t *packet, uint16_t size)){
|
||||
sdp_query_callback = dummy_notify;
|
||||
if (sdp_callback != NULL){
|
||||
sdp_query_callback = sdp_callback;
|
||||
}
|
||||
}
|
||||
|
||||
static void emit_value_byte(uint8_t event_byte){
|
||||
uint8_t event[11];
|
||||
event[0] = SDP_EVENT_QUERY_ATTRIBUTE_VALUE;
|
||||
event[1] = 9;
|
||||
little_endian_store_16(event, 2, record_counter);
|
||||
little_endian_store_16(event, 4, attribute_id);
|
||||
little_endian_store_16(event, 6, attribute_value_size);
|
||||
little_endian_store_16(event, 8, attribute_bytes_delivered);
|
||||
event[10] = event_byte;
|
||||
(*sdp_query_callback)(HCI_EVENT_PACKET, event, sizeof(event));
|
||||
}
|
||||
|
||||
static void parse(uint8_t eventByte){
|
||||
// count all bytes
|
||||
list_offset++;
|
||||
record_offset++;
|
||||
|
||||
// log_info(" parse BYTE_RECEIVED %02x", eventByte);
|
||||
switch(state){
|
||||
case GET_LIST_LENGTH:
|
||||
if (!de_state_size(eventByte, &de_header_state)) break;
|
||||
list_offset = de_header_state.de_offset;
|
||||
list_size = de_header_state.de_size;
|
||||
// log_info("parser: List offset %u, list size %u", list_offset, list_size);
|
||||
|
||||
record_counter = 0;
|
||||
state = GET_RECORD_LENGTH;
|
||||
break;
|
||||
|
||||
case GET_RECORD_LENGTH:
|
||||
// check size
|
||||
if (!de_state_size(eventByte, &de_header_state)) break;
|
||||
// log_info("parser: Record payload is %d bytes.", de_header_state.de_size);
|
||||
record_offset = de_header_state.de_offset;
|
||||
record_size = de_header_state.de_size;
|
||||
state = GET_ATTRIBUTE_ID_HEADER_LENGTH;
|
||||
break;
|
||||
|
||||
case GET_ATTRIBUTE_ID_HEADER_LENGTH:
|
||||
if (!de_state_size(eventByte, &de_header_state)) break;
|
||||
attribute_id = 0;
|
||||
log_info("ID data is stored in %d bytes.", (int) de_header_state.de_size);
|
||||
state = GET_ATTRIBUTE_ID;
|
||||
break;
|
||||
|
||||
case GET_ATTRIBUTE_ID:
|
||||
attribute_id = (attribute_id << 8) | eventByte;
|
||||
de_header_state.de_size--;
|
||||
if (de_header_state.de_size > 0) break;
|
||||
log_info("parser: Attribute ID: %04x.", attribute_id);
|
||||
|
||||
state = GET_ATTRIBUTE_VALUE_LENGTH;
|
||||
attribute_bytes_received = 0;
|
||||
attribute_bytes_delivered = 0;
|
||||
attribute_value_size = 0;
|
||||
de_state_init(&de_header_state);
|
||||
break;
|
||||
|
||||
case GET_ATTRIBUTE_VALUE_LENGTH:
|
||||
attribute_bytes_received++;
|
||||
emit_value_byte(eventByte);
|
||||
attribute_bytes_delivered++;
|
||||
if (!de_state_size(eventByte, &de_header_state)) break;
|
||||
|
||||
attribute_value_size = de_header_state.de_size + attribute_bytes_received;
|
||||
|
||||
state = GET_ATTRIBUTE_VALUE;
|
||||
break;
|
||||
|
||||
case GET_ATTRIBUTE_VALUE:
|
||||
attribute_bytes_received++;
|
||||
emit_value_byte(eventByte);
|
||||
attribute_bytes_delivered++;
|
||||
// log_info("paser: attribute_bytes_received %u, attribute_value_size %u", attribute_bytes_received, attribute_value_size);
|
||||
|
||||
if (attribute_bytes_received < attribute_value_size) break;
|
||||
// log_info("parser: Record offset %u, record size %u", record_offset, record_size);
|
||||
if (record_offset != record_size){
|
||||
state = GET_ATTRIBUTE_ID_HEADER_LENGTH;
|
||||
// log_info("Get next attribute");
|
||||
break;
|
||||
}
|
||||
record_offset = 0;
|
||||
// log_info("parser: List offset %u, list size %u", list_offset, list_size);
|
||||
|
||||
if (list_size > 0 && list_offset != list_size){
|
||||
record_counter++;
|
||||
state = GET_RECORD_LENGTH;
|
||||
log_info("parser: END_OF_RECORD");
|
||||
break;
|
||||
}
|
||||
list_offset = 0;
|
||||
de_state_init(&de_header_state);
|
||||
state = GET_LIST_LENGTH;
|
||||
record_counter = 0;
|
||||
log_info("parser: END_OF_RECORD & DONE");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void sdp_parser_init(void){
|
||||
// init
|
||||
de_state_init(&de_header_state);
|
||||
state = GET_LIST_LENGTH;
|
||||
list_offset = 0;
|
||||
record_offset = 0;
|
||||
record_counter = 0;
|
||||
}
|
||||
|
||||
void sdp_parser_handle_chunk(uint8_t * data, uint16_t size){
|
||||
int i;
|
||||
for (i=0;i<size;i++){
|
||||
parse(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SDP_EXTRA_QUERIES
|
||||
void sdp_parser_init_service_attribute_search(void){
|
||||
// init
|
||||
de_state_init(&de_header_state);
|
||||
state = GET_RECORD_LENGTH;
|
||||
list_offset = 0;
|
||||
record_offset = 0;
|
||||
record_counter = 0;
|
||||
}
|
||||
|
||||
void sdp_parser_init_service_search(void){
|
||||
record_offset = 0;
|
||||
}
|
||||
|
||||
void sdp_parser_handle_service_search(uint8_t * data, uint16_t total_count, uint16_t record_handle_count){
|
||||
int i;
|
||||
for (i=0;i<record_handle_count;i++){
|
||||
record_handle = big_endian_read_32(data, i*4);
|
||||
record_counter++;
|
||||
uint8_t event[10];
|
||||
event[0] = SDP_EVENT_QUERY_SERVICE_RECORD_HANDLE;
|
||||
event[1] = 8;
|
||||
little_endian_store_16(event, 2, total_count);
|
||||
little_endian_store_16(event, 4, record_counter);
|
||||
little_endian_store_32(event, 6, record_handle);
|
||||
(*sdp_query_callback)(HCI_EVENT_PACKET, event, sizeof(event));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void sdp_parser_handle_done(uint8_t status){
|
||||
uint8_t event[3];
|
||||
event[0] = SDP_EVENT_QUERY_COMPLETE;
|
||||
event[1] = 1;
|
||||
event[2] = status;
|
||||
(*sdp_query_callback)(HCI_EVENT_PACKET, event, sizeof(event));
|
||||
}
|
@ -1,118 +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
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* sdp_parser.h
|
||||
*/
|
||||
|
||||
#ifndef __SDP_PARSER_H
|
||||
#define __SDP_PARSER_H
|
||||
|
||||
#include "btstack_config.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "classic/sdp_util.h"
|
||||
#include "btstack_util.h"
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* SDP Parser */
|
||||
|
||||
// Data Element stream parser helper
|
||||
typedef struct de_state {
|
||||
uint8_t in_state_GET_DE_HEADER_LENGTH ;
|
||||
uint32_t addon_header_bytes;
|
||||
uint32_t de_size;
|
||||
uint32_t de_offset;
|
||||
} de_state_t;
|
||||
void de_state_init(de_state_t * state);
|
||||
int de_state_size(uint8_t eventByte, de_state_t *de_state);
|
||||
|
||||
/* API_START */
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
void sdp_parser_init(void);
|
||||
|
||||
/*
|
||||
* @brief Registers a callback to receive attribute value data and parse complete event.
|
||||
*/
|
||||
void sdp_parser_register_callback(void (*sdp_callback)(uint8_t packet_type, uint8_t *packet, uint16_t size));
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
void sdp_parser_handle_chunk(uint8_t * data, uint16_t size);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
void sdp_parser_handle_done(uint8_t status);
|
||||
|
||||
|
||||
#ifdef ENABLE_SDP_EXTRA_QUERIES
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
void sdp_parser_init_service_attribute_search(void);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
void sdp_parser_init_service_search(void);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
void sdp_parser_handle_service_search(uint8_t * data, uint16_t total_count, uint16_t record_handle_count);
|
||||
#endif
|
||||
|
||||
|
||||
/* API_END */
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __SDP_PARSER_H
|
@ -44,6 +44,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "btstack_debug.h"
|
||||
#include "btstack_event.h"
|
||||
#include "classic/sdp_client.h"
|
||||
#include "classic/sdp_query_rfcomm.h"
|
||||
@ -53,11 +54,6 @@
|
||||
// called by test/sdp_client
|
||||
void sdp_query_rfcomm_init(void);
|
||||
|
||||
// called by test/sdp_client
|
||||
void sdp_query_rfcomm_init(void);
|
||||
|
||||
static void dummy_notify_app(uint8_t packet_type, uint8_t *packet, uint16_t size);
|
||||
|
||||
typedef enum {
|
||||
GET_PROTOCOL_LIST_LENGTH = 1,
|
||||
GET_PROTOCOL_LENGTH,
|
||||
@ -88,12 +84,9 @@ static int protocol_id_bytes_to_read;
|
||||
static int protocol_value_size;
|
||||
static de_state_t de_header_state;
|
||||
static de_state_t sn_de_header_state;
|
||||
static void (*sdp_app_callback)(uint8_t packet_type, uint8_t *packet, uint16_t size) = dummy_notify_app;
|
||||
|
||||
static btstack_packet_handler_t sdp_app_callback;
|
||||
//
|
||||
|
||||
static void dummy_notify_app(uint8_t packet_type, uint8_t *packet, uint16_t size){}
|
||||
|
||||
static void emit_service(void){
|
||||
uint8_t event[3+SDP_SERVICE_NAME_LEN+1];
|
||||
event[0] = SDP_EVENT_QUERY_RFCOMM_SERVICE;
|
||||
@ -101,17 +94,10 @@ static void emit_service(void){
|
||||
event[2] = sdp_rfcomm_channel_nr;
|
||||
memcpy(&event[3], sdp_service_name, sdp_service_name_len);
|
||||
event[3+sdp_service_name_len] = 0;
|
||||
(*sdp_app_callback)(HCI_EVENT_PACKET, event, sizeof(event));
|
||||
(*sdp_app_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
sdp_rfcomm_channel_nr = 0;
|
||||
}
|
||||
|
||||
void sdp_query_rfcomm_register_callback(void (*sdp_callback)(uint8_t packet_type, uint8_t *packet, uint16_t size)){
|
||||
sdp_app_callback = dummy_notify_app;
|
||||
if (sdp_callback != NULL){
|
||||
sdp_app_callback = sdp_callback;
|
||||
}
|
||||
}
|
||||
|
||||
static void handleProtocolDescriptorListData(uint32_t attribute_value_length, uint32_t data_offset, uint8_t data){
|
||||
// init state on first byte
|
||||
if (data_offset == 0){
|
||||
@ -253,7 +239,7 @@ static void handleServiceNameData(uint32_t attribute_value_length, uint32_t data
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_sdp_parser_event(uint8_t packet_type, uint8_t *packet, uint16_t size){
|
||||
static void handle_sdp_parser_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
switch (packet[0]){
|
||||
case SDP_EVENT_QUERY_SERVICE_RECORD_HANDLE:
|
||||
// handle service without a name
|
||||
@ -292,7 +278,7 @@ static void handle_sdp_parser_event(uint8_t packet_type, uint8_t *packet, uint16
|
||||
if (sdp_rfcomm_channel_nr){
|
||||
emit_service();
|
||||
}
|
||||
(*sdp_app_callback)(HCI_EVENT_PACKET, packet, size);
|
||||
(*sdp_app_callback)(HCI_EVENT_PACKET, 0, packet, size);
|
||||
break;
|
||||
}
|
||||
// insert higher level code HERE
|
||||
@ -304,19 +290,31 @@ void sdp_query_rfcomm_init(void){
|
||||
de_state_init(&sn_de_header_state);
|
||||
pdl_state = GET_PROTOCOL_LIST_LENGTH;
|
||||
protocol_offset = 0;
|
||||
sdp_parser_register_callback(handle_sdp_parser_event);
|
||||
sdp_rfcomm_channel_nr = 0;
|
||||
sdp_service_name[0] = 0;
|
||||
}
|
||||
|
||||
// Public API
|
||||
|
||||
void sdp_query_rfcomm_channel_and_name_for_search_pattern(bd_addr_t remote, uint8_t * serviceSearchPattern){
|
||||
sdp_parser_init();
|
||||
int sdp_query_rfcomm_ready(void){
|
||||
return sdp_client_ready();
|
||||
}
|
||||
|
||||
void sdp_query_rfcomm_channel_and_name_for_search_pattern(btstack_packet_handler_t callback, bd_addr_t remote, uint8_t * serviceSearchPattern){
|
||||
if (!sdp_query_rfcomm_ready()){
|
||||
log_error("sdp_query_rfcomm_channel_and_name_for_search_pattern called when not readdy");
|
||||
return;
|
||||
}
|
||||
sdp_app_callback = callback;
|
||||
sdp_query_rfcomm_init();
|
||||
sdp_client_query(remote, serviceSearchPattern, (uint8_t*)&des_attributeIDList[0]);
|
||||
sdp_client_query(&handle_sdp_parser_event, remote, serviceSearchPattern, (uint8_t*)&des_attributeIDList[0]);
|
||||
}
|
||||
|
||||
void sdp_query_rfcomm_channel_and_name_for_uuid(bd_addr_t remote, uint16_t uuid){
|
||||
void sdp_query_rfcomm_channel_and_name_for_uuid(btstack_packet_handler_t callback, bd_addr_t remote, uint16_t uuid){
|
||||
if (!sdp_query_rfcomm_ready()){
|
||||
log_error("sdp_query_rfcomm_channel_and_name_for_uuid called when not readdy");
|
||||
return;
|
||||
}
|
||||
big_endian_store_16(des_serviceSearchPattern, 3, uuid);
|
||||
sdp_query_rfcomm_channel_and_name_for_search_pattern(remote, (uint8_t*)des_serviceSearchPattern);
|
||||
sdp_query_rfcomm_channel_and_name_for_search_pattern(callback, remote, (uint8_t*)des_serviceSearchPattern);
|
||||
}
|
||||
|
@ -43,7 +43,6 @@
|
||||
#define __SDP_QUERY_RFCOMM_H
|
||||
|
||||
#include "btstack_util.h"
|
||||
#include "classic/sdp_parser.h"
|
||||
#include "classic/sdp_query_util.h"
|
||||
|
||||
#define SDP_SERVICE_NAME_LEN 20
|
||||
@ -55,19 +54,20 @@ extern "C" {
|
||||
/* API_START */
|
||||
|
||||
/**
|
||||
* @brief Registers a callback to receive RFCOMM service and query complete event.
|
||||
* @brief Checks if the SDP Client is ready
|
||||
* @return 1 when no query is active
|
||||
*/
|
||||
void sdp_query_rfcomm_register_callback(void(*sdp_app_callback)(uint8_t packet_type, uint8_t *packet, uint16_t size));
|
||||
int sdp_query_rfcomm_ready(void);
|
||||
|
||||
/**
|
||||
* @brief Searches SDP records on a remote device for RFCOMM services with a given UUID.
|
||||
*/
|
||||
void sdp_query_rfcomm_channel_and_name_for_uuid(bd_addr_t remote, uint16_t uuid);
|
||||
void sdp_query_rfcomm_channel_and_name_for_uuid(btstack_packet_handler_t callback, bd_addr_t remote, uint16_t uuid);
|
||||
|
||||
/**
|
||||
* @brief Searches SDP records on a remote device for RFCOMM services with a given service search pattern.
|
||||
*/
|
||||
void sdp_query_rfcomm_channel_and_name_for_search_pattern(bd_addr_t remote, uint8_t * des_serviceSearchPattern);
|
||||
void sdp_query_rfcomm_channel_and_name_for_search_pattern(btstack_packet_handler_t callback, bd_addr_t remote, uint8_t * des_serviceSearchPattern);
|
||||
/* API_END */
|
||||
|
||||
#if defined __cplusplus
|
||||
|
@ -38,7 +38,7 @@
|
||||
/*
|
||||
* sdp_query_util.c
|
||||
*/
|
||||
#include "classic/sdp_parser.h"
|
||||
#include "btstack_debug.h"
|
||||
#include "classic/sdp_client.h"
|
||||
#include "classic/sdp_query_util.h"
|
||||
|
||||
@ -54,21 +54,35 @@ static uint8_t* create_service_search_pattern_for_uuid128(uint8_t* uuid){
|
||||
return (uint8_t*)des_serviceSearchPatternUUID128;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if the SDP Client is ready
|
||||
* @return 1 when no query is active
|
||||
*/
|
||||
int sdp_general_query_ready(void){
|
||||
return sdp_client_ready();
|
||||
}
|
||||
|
||||
uint8_t* create_service_search_pattern_for_uuid(uint16_t uuid){
|
||||
big_endian_store_16(des_serviceSearchPattern, 3, uuid);
|
||||
return (uint8_t*)des_serviceSearchPattern;
|
||||
}
|
||||
|
||||
void sdp_general_query_for_uuid(bd_addr_t remote, uint16_t uuid){
|
||||
void sdp_general_query_for_uuid(btstack_packet_handler_t callback, bd_addr_t remote, uint16_t uuid){
|
||||
if (!sdp_client_ready()){
|
||||
log_error("sdp_general_query_for_uuid called when not readdy");
|
||||
return;
|
||||
}
|
||||
create_service_search_pattern_for_uuid(uuid);
|
||||
sdp_parser_init();
|
||||
sdp_client_query(remote, (uint8_t*)&des_serviceSearchPattern[0], (uint8_t*)&des_attributeIDList[0]);
|
||||
sdp_client_query(callback, remote, (uint8_t*)&des_serviceSearchPattern[0], (uint8_t*)&des_attributeIDList[0]);
|
||||
}
|
||||
|
||||
void sdp_general_query_for_uuid128(bd_addr_t remote, uint8_t* uuid){
|
||||
void sdp_general_query_for_uuid128(btstack_packet_handler_t callback, bd_addr_t remote, uint8_t* uuid){
|
||||
if (!sdp_client_ready()){
|
||||
log_error("sdp_general_query_for_uuid called when not readdy");
|
||||
return;
|
||||
}
|
||||
create_service_search_pattern_for_uuid128(uuid);
|
||||
sdp_parser_init();
|
||||
sdp_client_query(remote, (uint8_t*)&des_serviceSearchPatternUUID128[0], (uint8_t*)&des_attributeIDList[0]);
|
||||
sdp_client_query(callback, remote, (uint8_t*)&des_serviceSearchPatternUUID128[0], (uint8_t*)&des_attributeIDList[0]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -54,15 +54,21 @@ extern "C" {
|
||||
*/
|
||||
uint8_t* create_service_search_pattern_for_uuid(uint16_t uuid);
|
||||
|
||||
/**
|
||||
* @brief Checks if the SDP Client is ready
|
||||
* @return 1 when no query is active
|
||||
*/
|
||||
int sdp_general_query_ready(void);
|
||||
|
||||
/*
|
||||
* @brief Searches SDP records on a remote device for all services with a given UUID.
|
||||
*/
|
||||
void sdp_general_query_for_uuid(bd_addr_t remote, uint16_t uuid16);
|
||||
void sdp_general_query_for_uuid(btstack_packet_handler_t callback, bd_addr_t remote, uint16_t uuid16);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
void sdp_general_query_for_uuid128(bd_addr_t remote, uint8_t* uuid128);
|
||||
void sdp_general_query_for_uuid128(btstack_packet_handler_t callback, bd_addr_t remote, uint8_t* uuid128);
|
||||
|
||||
/* API_END */
|
||||
|
||||
|
@ -61,15 +61,15 @@ const char * const type_names[] = { "NIL", "UINT", "INT", "UUID", "STRING", "BOO
|
||||
#endif
|
||||
|
||||
// MARK: DataElement getter
|
||||
de_size_t de_get_size_type(uint8_t *header){
|
||||
de_size_t de_get_size_type(const uint8_t *header){
|
||||
return (de_size_t) (header[0] & 7);
|
||||
}
|
||||
|
||||
de_type_t de_get_element_type(uint8_t *header){
|
||||
de_type_t de_get_element_type(const uint8_t *header){
|
||||
return (de_type_t) (header[0] >> 3);
|
||||
}
|
||||
|
||||
int de_get_header_size(uint8_t * header){
|
||||
int de_get_header_size(const uint8_t * header){
|
||||
de_size_t de_size = de_get_size_type(header);
|
||||
if (de_size <= DE_SIZE_128) {
|
||||
return 1;
|
||||
@ -77,7 +77,7 @@ int de_get_header_size(uint8_t * header){
|
||||
return 1 + (1 << (de_size-DE_SIZE_VAR_8));
|
||||
}
|
||||
|
||||
int de_get_data_size(uint8_t * header){
|
||||
int de_get_data_size(const uint8_t * header){
|
||||
uint32_t result = 0;
|
||||
de_type_t de_type = de_get_element_type(header);
|
||||
de_size_t de_size = de_get_size_type(header);
|
||||
@ -103,19 +103,19 @@ int de_get_data_size(uint8_t * header){
|
||||
return result;
|
||||
}
|
||||
|
||||
int de_get_len(uint8_t *header){
|
||||
int de_get_len(const uint8_t *header){
|
||||
return de_get_header_size(header) + de_get_data_size(header);
|
||||
}
|
||||
|
||||
// @returns OK, if UINT16 value was read
|
||||
int de_element_get_uint16(uint8_t * element, uint16_t * value){
|
||||
int de_element_get_uint16(const uint8_t * element, uint16_t * value){
|
||||
if (de_get_size_type(element) != DE_SIZE_16) return 0;
|
||||
*value = big_endian_read_16(element, de_get_header_size(element));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// @returns: element is valid UUID
|
||||
int de_get_normalized_uuid(uint8_t *uuid128, uint8_t *element){
|
||||
int de_get_normalized_uuid(uint8_t *uuid128, const uint8_t *element){
|
||||
de_type_t uuidType = de_get_element_type(element);
|
||||
de_size_t uuidSize = de_get_size_type(element);
|
||||
if (uuidType != DE_UUID) return 0;
|
||||
@ -138,7 +138,7 @@ int de_get_normalized_uuid(uint8_t *uuid128, uint8_t *element){
|
||||
}
|
||||
|
||||
// @returns 0 if no UUID16 or UUID32 is present, and UUID32 otherwise
|
||||
uint32_t de_get_uuid32(uint8_t * element){
|
||||
uint32_t de_get_uuid32(const uint8_t * element){
|
||||
uint8_t uuid128[16];
|
||||
int validUuid128 = de_get_normalized_uuid(uuid128, element);
|
||||
if (!validUuid128) return 0;
|
||||
@ -665,13 +665,13 @@ static int de_traversal_dump_data(uint8_t * element, de_type_t de_type, de_size_
|
||||
}
|
||||
#endif
|
||||
|
||||
void de_dump_data_element(uint8_t * record){
|
||||
void de_dump_data_element(const uint8_t * record){
|
||||
#ifdef ENABLE_SDP_DES_DUMP
|
||||
int indent = 0;
|
||||
// hack to get root DES, too.
|
||||
de_type_t type = de_get_element_type(record);
|
||||
de_size_t size = de_get_size_type(record);
|
||||
de_traversal_dump_data(record, type, size, (void*) &indent);
|
||||
de_traversal_dump_data((uint8_t *) record, type, size, (void*) &indent);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -74,23 +74,24 @@ typedef enum {
|
||||
} de_size_t;
|
||||
|
||||
// MARK: DateElement
|
||||
void de_dump_data_element(uint8_t * record);
|
||||
int de_get_len(uint8_t *header);
|
||||
de_size_t de_get_size_type(uint8_t *header);
|
||||
de_type_t de_get_element_type(uint8_t *header);
|
||||
int de_get_header_size(uint8_t * header);
|
||||
void de_create_sequence(uint8_t *header);
|
||||
void de_dump_data_element(const uint8_t * record);
|
||||
int de_get_len(const uint8_t * header);
|
||||
de_size_t de_get_size_type(const uint8_t * header);
|
||||
de_type_t de_get_element_type(const uint8_t * header);
|
||||
int de_get_header_size(const uint8_t * header);
|
||||
int de_element_get_uint16(const uint8_t * element, uint16_t * value);
|
||||
int de_get_data_size(const uint8_t * header);
|
||||
uint32_t de_get_uuid32(const uint8_t * element);
|
||||
int de_get_normalized_uuid(uint8_t *uuid128, const uint8_t *element);
|
||||
|
||||
void de_create_sequence(uint8_t * header);
|
||||
void de_store_descriptor_with_len(uint8_t * header, de_type_t type, de_size_t size, uint32_t len);
|
||||
uint8_t * de_push_sequence(uint8_t *header);
|
||||
void de_pop_sequence(uint8_t * parent, uint8_t * child);
|
||||
void de_add_number(uint8_t *seq, de_type_t type, de_size_t size, uint32_t value);
|
||||
void de_add_data( uint8_t *seq, de_type_t type, uint16_t size, uint8_t *data);
|
||||
int de_element_get_uint16(uint8_t * element, uint16_t * value);
|
||||
|
||||
int de_get_data_size(uint8_t * header);
|
||||
void de_add_uuid128(uint8_t * seq, uint8_t * uuid);
|
||||
uint32_t de_get_uuid32(uint8_t * element);
|
||||
int de_get_normalized_uuid(uint8_t *uuid128, uint8_t *element);
|
||||
|
||||
// MARK: DES iterator
|
||||
typedef struct {
|
||||
|
@ -59,7 +59,6 @@
|
||||
#include "l2cap.h"
|
||||
#include "classic/rfcomm.h"
|
||||
#include "classic/sdp_server.h"
|
||||
#include "classic/sdp_parser.h"
|
||||
#include "btstack_debug.h"
|
||||
#include "classic/hfp_ag.h"
|
||||
|
||||
|
@ -59,7 +59,6 @@
|
||||
#include "l2cap.h"
|
||||
#include "classic/rfcomm.h"
|
||||
#include "classic/sdp_server.h"
|
||||
#include "classic/sdp_parser.h"
|
||||
#include "btstack_debug.h"
|
||||
#include "classic/hfp_hf.h"
|
||||
|
||||
|
@ -70,7 +70,7 @@ static uint8_t rfcomm_reserved_buffer[1000];
|
||||
hfp_connection_t * hfp_context;
|
||||
|
||||
void (*registered_rfcomm_packet_handler)(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
void (*registered_sdp_app_callback)(uint8_t packet_type, uint8_t *packet, uint16_t size);
|
||||
void (*registered_sdp_app_callback)(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
|
||||
uint8_t * get_rfcomm_payload(){
|
||||
return &rfcomm_payload[0];
|
||||
@ -198,17 +198,12 @@ int hci_send_cmd(const hci_cmd_t *cmd, ...){
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void sdp_query_rfcomm_register_callback(void(*sdp_app_callback)(uint8_t packet_type, uint8_t *packet, uint16_t size)){
|
||||
registered_sdp_app_callback = sdp_app_callback;
|
||||
}
|
||||
|
||||
static void sdp_query_complete_response(uint8_t status){
|
||||
uint8_t event[3];
|
||||
event[0] = SDP_EVENT_QUERY_COMPLETE;
|
||||
event[1] = 1;
|
||||
event[2] = status;
|
||||
(*registered_sdp_app_callback)(HCI_EVENT_PACKET, event, sizeof(event));
|
||||
(*registered_sdp_app_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
static void sdp_query_rfcomm_service_response(uint8_t status){
|
||||
@ -219,11 +214,12 @@ static void sdp_query_rfcomm_service_response(uint8_t status){
|
||||
event[2] = sdp_rfcomm_channel_nr;
|
||||
memcpy(&event[3], sdp_rfcomm_service_name, sdp_service_name_len);
|
||||
event[3+sdp_service_name_len] = 0;
|
||||
(*registered_sdp_app_callback)(HCI_EVENT_PACKET, event, sizeof(event));
|
||||
(*registered_sdp_app_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
void sdp_query_rfcomm_channel_and_name_for_uuid(bd_addr_t remote, uint16_t uuid){
|
||||
void sdp_query_rfcomm_channel_and_name_for_uuid(btstack_packet_handler_t callback, bd_addr_t remote, uint16_t uuid){
|
||||
// printf("sdp_query_rfcomm_channel_and_name_for_uuid %p\n", registered_sdp_app_callback);
|
||||
registered_sdp_app_callback = callback;
|
||||
sdp_query_rfcomm_service_response(0);
|
||||
sdp_query_complete_response(0);
|
||||
}
|
||||
|
@ -398,7 +398,7 @@ static void handle_found_service(const char * name, uint8_t port){
|
||||
rfcomm_channel_nr = port;
|
||||
}
|
||||
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint8_t *packet, uint16_t size){
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
switch (packet[0]){
|
||||
case SDP_EVENT_QUERY_RFCOMM_SERVICE:
|
||||
handle_found_service(sdp_event_query_rfcomm_service_get_name(packet),
|
||||
@ -596,7 +596,7 @@ static int stdin_process(struct btstack_data_source *ds){
|
||||
|
||||
case 'k':
|
||||
printf("Start SDP query for SPP service\n");
|
||||
sdp_query_rfcomm_channel_and_name_for_uuid(remote_rfcomm, 0x1101);
|
||||
sdp_query_rfcomm_channel_and_name_for_uuid(&handle_query_rfcomm_event, remote_rfcomm, 0x1101);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
@ -790,8 +790,6 @@ int btstack_main(int argc, const char * argv[]){
|
||||
de_dump_data_element((uint8_t*)dummy_service_buffer);
|
||||
printf("Dummy service record size: %u\n\r", de_get_len((uint8_t*)dummy_service_buffer));
|
||||
sdp_register_service((uint8_t*)dummy_service_buffer);
|
||||
|
||||
sdp_query_rfcomm_register_callback(handle_query_rfcomm_event);
|
||||
|
||||
hci_discoverable_control(0);
|
||||
hci_connectable_control(0);
|
||||
|
@ -107,7 +107,7 @@ static void packet_handler(void * connection, uint8_t packet_type, uint16_t chan
|
||||
// bt stack activated, get started
|
||||
if (packet[2] == HCI_STATE_WORKING){
|
||||
printf("Start SDP RFCOMM Query for UUID 0x%02x\n", SDP_Handsfree);
|
||||
// sdp_query_rfcomm_channel_and_name_for_uuid(remote, SDP_Handsfree);
|
||||
sdp_query_rfcomm_channel_and_name_for_uuid(&handle_query_rfcomm_event, remote, SDP_Handsfree);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -146,7 +146,7 @@ static void hci_event_handler(uint8_t packet_type, uint8_t * packet, uint16_t si
|
||||
}
|
||||
|
||||
|
||||
void handle_query_rfcomm_event(uint8_t packet_type, uint8_t *packet, uint16_t size){
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
switch (event->type){
|
||||
case SDP_EVENT_QUERY_RFCOMM_SERVICE:
|
||||
channel_nr = sdp_event_query_rfcomm_service_get_name(packet);
|
||||
@ -177,8 +177,6 @@ int btstack_main(int argc, const char * argv[]){
|
||||
l2cap_init();
|
||||
rfcomm_init();
|
||||
|
||||
sdp_query_rfcomm_register_callback(handle_query_rfcomm_event);
|
||||
|
||||
// turn on!
|
||||
hci_power_control(HCI_POWER_ON);
|
||||
|
||||
|
@ -103,10 +103,10 @@ int btstack_main(int argc, const char * argv[]){
|
||||
pan_create_panu_service(pan_service_buffer, 0x10002, network_packet_types, NULL, NULL, BNEP_SECURITY_NONE);
|
||||
sdp_register_service((uint8_t*)pan_service_buffer);
|
||||
|
||||
hsp_ag_create_service((uint8_t *)hsp_ag_service_buffer, 0x10003, 2, "HSP AG");
|
||||
hsp_ag_create_sdp_record((uint8_t *)hsp_ag_service_buffer, 0x10003, 2, "HSP AG");
|
||||
sdp_register_service((uint8_t *)hsp_ag_service_buffer);
|
||||
|
||||
hsp_hs_create_service((uint8_t *)hsp_hs_service_buffer, 0x10004, 3, "HSP HS", 0);
|
||||
hsp_hs_create_sdp_record((uint8_t *)hsp_hs_service_buffer, 0x10004, 3, "HSP HS", 0);
|
||||
sdp_register_service((uint8_t *)hsp_hs_service_buffer);
|
||||
|
||||
hfp_ag_create_sdp_record((uint8_t *)hfp_ag_service_buffer, 0x10005, 4, "HFP AG", 0, 0);
|
||||
|
@ -15,7 +15,8 @@ VPATH += ${BTSTACK_ROOT}/platform/posix
|
||||
|
||||
COMMON = \
|
||||
sdp_util.c \
|
||||
sdp_parser.c \
|
||||
sdp_client.c \
|
||||
mock.c \
|
||||
hci_dump.c \
|
||||
btstack_util.c \
|
||||
|
||||
|
@ -15,11 +15,11 @@
|
||||
#include "btstack_event.h"
|
||||
#include "btstack_memory.h"
|
||||
#include "btstack_run_loop.h"
|
||||
#include "classic/sdp_parser.h"
|
||||
#include "hci.h"
|
||||
#include "hci_cmd.h"
|
||||
#include "hci_dump.h"
|
||||
#include "l2cap.h"
|
||||
#include "mock.h"
|
||||
|
||||
#include "CppUTest/TestHarness.h"
|
||||
#include "CppUTest/CommandLineTestRunner.h"
|
||||
@ -95,7 +95,6 @@ static uint8_t sdp_test_record_list[] = {
|
||||
0x09, 0x03, 0x0A, 0x09, 0x00, 0x01, 0x09, 0x03, 0x0B, 0x09, 0x00, 0x05
|
||||
};
|
||||
|
||||
|
||||
uint16_t attribute_id = -1;
|
||||
uint16_t record_id = -1;
|
||||
|
||||
@ -142,7 +141,7 @@ static void test_attribute_value_event(const uint8_t * event){
|
||||
}
|
||||
|
||||
|
||||
static void handle_sdp_parser_event(uint8_t packet_type, uint8_t *packet, uint16_t size){
|
||||
static void handle_sdp_parser_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
switch (packet[0]){
|
||||
case SDP_EVENT_QUERY_ATTRIBUTE_VALUE:
|
||||
test_attribute_value_event(packet);
|
||||
@ -168,8 +167,7 @@ TEST_GROUP(SDPClient){
|
||||
attribute_value_buffer_size = 1000;
|
||||
attribute_value = (uint8_t*) malloc(attribute_value_buffer_size);
|
||||
record_id = -1;
|
||||
sdp_parser_init();
|
||||
sdp_parser_register_callback(handle_sdp_parser_event);
|
||||
sdp_parser_init(&handle_sdp_parser_event);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "hci_dump.h"
|
||||
#include "l2cap.h"
|
||||
#include "btstack_event.h"
|
||||
#include "mock.h"
|
||||
|
||||
#include "CppUTest/TestHarness.h"
|
||||
#include "CppUTest/CommandLineTestRunner.h"
|
||||
@ -82,15 +83,8 @@ static uint8_t sdp_test_record_list[] = { 0x36, 0x02, 0xE7, 0x35, 0x48,
|
||||
0x6B, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65
|
||||
};
|
||||
|
||||
// dummy function to allow compile without the stack
|
||||
extern "C" void sdp_client_query(bd_addr_t remote, uint8_t * des_serviceSearchPattern, uint8_t * des_attributeIDList){
|
||||
}
|
||||
|
||||
// for test purposes
|
||||
void sdp_query_rfcomm_init();
|
||||
|
||||
|
||||
void handle_query_rfcomm_event(uint8_t packet_type, uint8_t *packet, uint16_t size){
|
||||
void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
switch (packet[0]){
|
||||
case SDP_EVENT_QUERY_RFCOMM_SERVICE:
|
||||
channel_nr[service_index] = sdp_event_query_rfcomm_service_get_rfcomm_channel(packet);
|
||||
@ -109,12 +103,13 @@ void handle_query_rfcomm_event(uint8_t packet_type, uint8_t *packet, uint16_t si
|
||||
|
||||
TEST_GROUP(SDPClient){
|
||||
uint8_t spp_buffer[sizeof(sdp_test_record_list)];
|
||||
bd_addr_t address;
|
||||
|
||||
void setup(void){
|
||||
service_index = 0;
|
||||
sdp_query_rfcomm_register_callback(handle_query_rfcomm_event);
|
||||
sdp_parser_init();
|
||||
sdp_query_rfcomm_init();
|
||||
sdp_client_reset(); // avoid "not ready" warning
|
||||
// start query using public API although data will be injected
|
||||
sdp_query_rfcomm_channel_and_name_for_uuid(&handle_query_rfcomm_event, address, 0x1234);
|
||||
}
|
||||
};
|
||||
|
||||
@ -148,7 +143,6 @@ TEST(SDPClient, QueryRFCOMMWithMacOSXData){
|
||||
"Bluetooth-PDA-Sync", "Headset Audio Gatewa"};
|
||||
uint8_t expected_channel[] = {10, 2, 15, 3, 4};
|
||||
// de_dump_data_element(sdp_test_record_list);
|
||||
|
||||
sdp_parser_handle_chunk(sdp_test_record_list, de_get_len(sdp_test_record_list));
|
||||
|
||||
CHECK_EQUAL(service_index, 5);
|
||||
|
@ -15,11 +15,11 @@
|
||||
#include "btstack_event.h"
|
||||
#include "btstack_memory.h"
|
||||
#include "btstack_run_loop.h"
|
||||
#include "classic/sdp_parser.h"
|
||||
#include "hci.h"
|
||||
#include "hci_cmd.h"
|
||||
#include "hci_dump.h"
|
||||
#include "l2cap.h"
|
||||
#include "mock.h"
|
||||
|
||||
#include "CppUTest/TestHarness.h"
|
||||
#include "CppUTest/CommandLineTestRunner.h"
|
||||
@ -87,7 +87,7 @@ static void test_attribute_value_event(const uint8_t * event){
|
||||
}
|
||||
|
||||
|
||||
static void handle_sdp_parser_event(uint8_t packet_type, uint8_t *packet, uint16_t size){
|
||||
static void handle_sdp_parser_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
switch (packet[0]){
|
||||
case SDP_EVENT_QUERY_ATTRIBUTE_VALUE:
|
||||
test_attribute_value_event(packet);
|
||||
@ -113,8 +113,8 @@ TEST_GROUP(SDPClient){
|
||||
attribute_value_buffer_size = 1000;
|
||||
attribute_value = (uint8_t*) malloc(attribute_value_buffer_size);
|
||||
record_id = -1;
|
||||
sdp_parser_init(&handle_sdp_parser_event);
|
||||
sdp_parser_init_service_attribute_search();
|
||||
sdp_parser_register_callback(handle_sdp_parser_event);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -15,11 +15,11 @@
|
||||
#include "btstack_event.h"
|
||||
#include "btstack_memory.h"
|
||||
#include "btstack_run_loop.h"
|
||||
#include "classic/sdp_parser.h"
|
||||
#include "hci.h"
|
||||
#include "hci_cmd.h"
|
||||
#include "hci_dump.h"
|
||||
#include "l2cap.h"
|
||||
#include "mock.h"
|
||||
|
||||
#include "CppUTest/TestHarness.h"
|
||||
#include "CppUTest/CommandLineTestRunner.h"
|
||||
@ -39,8 +39,7 @@ static uint8_t sdp_test_record_list[] = {
|
||||
0x00, 0x00, 0x00, 0x0A
|
||||
};
|
||||
|
||||
|
||||
static void handle_sdp_parser_event(uint8_t packet_type, uint8_t *packet, uint16_t size){
|
||||
static void handle_sdp_parser_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
static uint32_t record_handle = sdp_test_record_list[0];
|
||||
switch (packet[0]){
|
||||
case SDP_EVENT_QUERY_SERVICE_RECORD_HANDLE:
|
||||
@ -56,8 +55,8 @@ static void handle_sdp_parser_event(uint8_t packet_type, uint8_t *packet, uint16
|
||||
|
||||
TEST_GROUP(SDPClient){
|
||||
void setup(void){
|
||||
sdp_parser_init(&handle_sdp_parser_event);
|
||||
sdp_parser_init_service_search();
|
||||
sdp_parser_register_callback(handle_sdp_parser_event);
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user