new files for SDP queries

This commit is contained in:
matthias.ringwald@gmail.com 2013-04-26 20:18:25 +00:00
parent 40943ff4e0
commit d3d614de49
8 changed files with 804 additions and 0 deletions

View File

@ -28,6 +28,9 @@ BTdaemon_SOURCES = $(libBTstack_SOURCES) \
$(remote_device_db_sources) \
rfcomm.c \
sdp.c \
sdp_client.c \
sdp_parser.c \
sdp_query_rfcomm.c \
$(springboard_access_sources)
# use $(CC) for Objective-C files

View File

@ -22,6 +22,9 @@ BTdaemon_FILES = $(libBTstack_FILES) \
remote_device_db_iphone.m \
rfcomm.c \
sdp.c \
sdp_client.c \
sdp_parser.c \
sdp_query_rfcomm.c \
../SpringBoardAccess/SpringBoardAccess.c
BTdaemon_CFLAGS = -I../include -I..
BTdaemon_FRAMEWORKS = IOKit

238
src/sdp_client.c Normal file
View File

@ -0,0 +1,238 @@
//*****************************************************************************
//
// minimal setup for SDP client over USB or UART
//
//*****************************************************************************
#include "config.h"
#include "sdp_client.h"
#include <btstack/hci_cmds.h>
#include "l2cap.h"
#include "sdp_parser.h"
#include "sdp.h"
#include "debug.h"
typedef enum {
INIT, W4_CONNECT, W2_SEND, W4_RESPONSE
} 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_sdp_request(uint8_t * data);
// SDP Client Query
static uint16_t mtu;
static uint16_t sdp_cid = 0x40;
static uint8_t * serviceSearchPattern;
static uint8_t * attributeIDList;
static uint16_t transactionID = 0;
static uint8_t continuationState[16];
static uint8_t continuationStateLen;
static sdp_client_state_t sdp_client_state;
void sdp_client_handle_done(uint8_t status){
if (status == 0){
l2cap_disconnect_internal(sdp_cid, 0);
}
sdp_parser_handle_done(status);
}
// TODO: inline if not needed
void parse_AttributeLists(uint8_t* packet, uint16_t length){
sdp_parser_handle_chunk(packet, length);
}
void hexdump2(void *data, int size){
int i;
for (i=0; i<size;i++){
printf("%02X ", ((uint8_t *)data)[i]);
}
printf("\n");
}
void sdp_client_query(bd_addr_t remote, uint8_t * des_serviceSearchPattern, uint8_t * des_attributeIDList){
serviceSearchPattern = des_serviceSearchPattern;
attributeIDList = des_attributeIDList;
continuationStateLen = 0;
sdp_client_state = W4_CONNECT;
l2cap_create_channel_internal(NULL, sdp_packet_handler, remote, PSM_SDP, l2cap_max_mtu());
}
void tryToSend(uint16_t channel){
if (sdp_client_state != W2_SEND) return;
if (!l2cap_can_send_packet_now(channel)) return;
uint8_t * data = l2cap_get_outgoing_buffer();
uint16_t request_len = setup_sdp_request(data);
printf("tryToSend channel %x, size %u\n", channel, request_len);
int err = l2cap_send_prepared(channel, request_len);
switch (err){
case 0:
// packet is sent prepare next one
printf("l2cap_send_internal() -> OK\n\r");
sdp_client_state = W4_RESPONSE;
break;
case BTSTACK_ACL_BUFFERS_FULL:
printf("l2cap_send_internal() ->BTSTACK_ACL_BUFFERS_FULL\n\r");
break;
default:
printf("l2cap_send_internal() -> err %d\n\r", err);
break;
}
}
void parse_ServiceSearchAttributeResponse(uint8_t* packet){
uint16_t offset = 3;
uint16_t parameterLength = READ_NET_16(packet,offset);
offset+=2;
// AttributeListByteCount <= mtu
uint16_t attributeListByteCount = READ_NET_16(packet,offset);
offset+=2;
if (attributeListByteCount > mtu){
log_error("Error parsing ServiceSearchAttributeResponse: Number of bytes in found attribute list is larger then MTU.\n");
return;
}
// AttributeLists
parse_AttributeLists(packet+offset, attributeListByteCount);
offset+=attributeListByteCount;
continuationStateLen = packet[offset];
offset++;
if (continuationStateLen > 16){
log_error("Error parsing ServiceSearchAttributeResponse: Number of bytes in continuation state exceedes 16.\n");
return;
}
memcpy(continuationState, packet+offset, continuationStateLen);
offset+=continuationStateLen;
if (parameterLength != offset - 5){
log_error("Error parsing ServiceSearchAttributeResponse: wrong size of parameters, number of expected bytes%u, actual number %u.\n", parameterLength, offset);
}
}
void sdp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
uint16_t handle;
printf("l2cap_packet_handler type %u, packet[0] %x\n", packet_type, packet[0]);
if (packet_type == L2CAP_DATA_PACKET){
uint16_t responseTransactionID = READ_NET_16(packet,1);
if ( responseTransactionID != transactionID){
printf("Missmatching transaction ID, expected %u, found %u.\n", transactionID, responseTransactionID);
return;
}
if (packet[0] == SDP_ServiceSearchAttributeResponse){
parse_ServiceSearchAttributeResponse(packet);
// continuation set or DONE?
if (continuationStateLen == 0){
printf("DONE! All clients already notified.\n");
sdp_client_handle_done(0);
sdp_client_state = INIT;
return;
}
// prepare next request and send
sdp_client_state = W2_SEND;
tryToSend(sdp_cid);
}
return;
}
if (packet_type != HCI_EVENT_PACKET) return;
switch(packet[0]){
case L2CAP_EVENT_CHANNEL_OPENED:
if (sdp_client_state != W4_CONNECT) break;
// data: event (8), len(8), status (8), address(48), handle (16), psm (16), local_cid(16), remote_cid (16), local_mtu(16), remote_mtu(16)
if (packet[2]) {
printf("Connection failed.\n\r");
sdp_client_handle_done(packet[2]);
break;
}
sdp_cid = channel;
mtu = READ_BT_16(packet, 17);
handle = READ_BT_16(packet, 9);
printf("Connected, cid %x, mtu %u.\n\r", sdp_cid, mtu);
sdp_client_state = W2_SEND;
tryToSend(sdp_cid);
break;
case L2CAP_EVENT_CREDITS:
case DAEMON_EVENT_HCI_PACKET_SENT:
tryToSend(sdp_cid);
break;
case L2CAP_EVENT_CHANNEL_CLOSED:
printf("Channel closed.\n\r");
if (sdp_client_state == INIT) break;
sdp_client_handle_done(SDP_QUERY_INCOMPLETE);
break;
default:
break;
}
}
static uint16_t setup_sdp_request(uint8_t * data){
uint16_t offset = 0;
transactionID++;
// uint8_t SDP_PDU_ID_t.SDP_ServiceSearchRequest;
data[offset++] = SDP_ServiceSearchAttributeRequest;
// uint16_t transactionID
net_store_16(data, offset, transactionID);
offset += 2;
// param legnth
offset += 2;
// parameters:
// ServiceSearchPattern - DES (min 1 UUID, max 12)
uint16_t serviceSearchPatternLen = de_get_len(serviceSearchPattern);
memcpy(data + offset, serviceSearchPattern, serviceSearchPatternLen);
offset += serviceSearchPatternLen;
// MaximumAttributeByteCount - uint16_t 0x0007 - 0xffff -> mtu
net_store_16(data, offset, mtu);
offset += 2;
// AttibuteIDList
uint16_t attributeIDListLen = de_get_len(attributeIDList);
memcpy(data + offset, attributeIDList, attributeIDListLen);
offset += attributeIDListLen;
// ContinuationState - uint8_t number of cont. bytes N<=16
data[offset++] = continuationStateLen;
// - N-bytes previous response from server
memcpy(data + offset, continuationState, continuationStateLen);
offset += continuationStateLen;
// uint16_t paramLength
net_store_16(data, 3, offset - 5);
return offset;
}

10
src/sdp_client.h Normal file
View File

@ -0,0 +1,10 @@
//*****************************************************************************
//
// minimal setup for SDP client over USB or UART
//
//*****************************************************************************
#include <btstack/utils.h>
void sdp_client_query(bd_addr_t remote, uint8_t * des_serviceSearchPattern, uint8_t * des_attributeIDList);

202
src/sdp_parser.c Normal file
View File

@ -0,0 +1,202 @@
#include "sdp_parser.h"
#include "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 uint32_t attribute_bytes_received = 0;
static uint32_t attribute_bytes_delivered = 0;
static int list_offset = 0;
static int list_size;
static int record_offset = 0;
static int record_size;
static int attribute_value_size;
static int record_counter = 0;
static void (*sdp_query_rfcomm_callback)(sdp_parser_event_t * event);
// Low level parser
static de_state_t de_header_state;
void de_state_init(de_state_t * state){
state->in_state_GET_DE_HEADER_LENGTH = 1;
state->addon_header_bytes = 0;
state->de_size = 0;
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\n\r");
}
// printf("Data element payload is %d bytes.\n", 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;
// printf("Data element payload is %d bytes.\n", de_state->de_size);
de_state->in_state_GET_DE_HEADER_LENGTH = 1;
return 1;
}
void dummy_notify(sdp_parser_event_t* event){}
void sdp_parser_register_callback(void (*sdp_callback)(sdp_parser_event_t* event)){
sdp_query_rfcomm_callback = dummy_notify;
if (sdp_callback != NULL){
sdp_query_rfcomm_callback = sdp_callback;
}
}
void parse(uint8_t eventByte){
// count all bytes
list_offset++;
record_offset++;
// printf("BYTE_RECEIVED %02x\n", 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;
// printf("parser: List offset %u, list size %u\n", 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;
// printf("parser: Record payload is %d bytes.\n", 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;
// printf("ID data is stored in %d bytes.\n", 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;
// printf("parser: Attribute ID: %04x.\n", 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_attribute_value_event_t attribute_value_event = {
.type = SDP_PARSER_ATTRIBUTE_VALUE,
.record_id = record_counter,
.attribute_id = attribute_id,
.attribute_length = attribute_value_size,
.data_offset = attribute_bytes_delivered++,
.data = eventByte
};
(*sdp_query_rfcomm_callback)((sdp_parser_event_t*)&attribute_value_event);
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_attribute_value_event_t attribute_value_event1 = {
.type = SDP_PARSER_ATTRIBUTE_VALUE,
.record_id = record_counter,
.attribute_id = attribute_id,
.attribute_length = attribute_value_size,
.data_offset = attribute_bytes_delivered++,
.data = eventByte
};
(*sdp_query_rfcomm_callback)((sdp_parser_event_t*)&attribute_value_event1);
// printf("paser: attribute_bytes_received %u, attribute_value_size %u\n", attribute_bytes_received, attribute_value_size);
if (attribute_bytes_received < attribute_value_size) break;
// printf("parser: Record offset %u, record size %u\n", record_offset, record_size);
if (record_offset != record_size){
state = GET_ATTRIBUTE_ID_HEADER_LENGTH;
// printf("Get next attribute\n");
break;
}
record_offset = 0;
// printf("parser: List offset %u, list size %u\n", list_offset, list_size);
if (list_offset != list_size){
record_counter++;
state = GET_RECORD_LENGTH;
// printf("parser: END_OF_RECORD\n\n");
break;
}
list_offset = 0;
de_state_init(&de_header_state);
state = GET_LIST_LENGTH;
record_counter = 0;
// printf("parser: END_OF_RECORD & DONE\n\n\n");
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]);
}
}
void sdp_parser_handle_done(uint8_t status){
sdp_parser_complete_event_t complete_event = {
.type = SDP_PARSER_COMPLETE,
.status = status
};
(*sdp_query_rfcomm_callback)((sdp_parser_event_t*)&complete_event);
}

50
src/sdp_parser.h Normal file
View File

@ -0,0 +1,50 @@
//*****************************************************************************
//
// minimal setup for SDP client over USB or UART
//
//*****************************************************************************
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <btstack/sdp_util.h>
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;
typedef enum sdp_parser_event_type {
SDP_PARSER_ATTRIBUTE_VALUE = 1,
SDP_PARSER_COMPLETE,
} sdp_parser_event_type_t;
typedef struct sdp_parser_event {
uint8_t type;
} sdp_parser_event_t;
typedef struct sdp_parser_attribute_value_event {
uint8_t type;
int record_id;
uint16_t attribute_id;
uint32_t attribute_length;
int data_offset;
uint8_t data;
} sdp_parser_attribute_value_event_t;
typedef struct sdp_parser_complete_event {
uint8_t type;
uint8_t status; // 0 == OK
} sdp_parser_complete_event_t;
void de_state_init(de_state_t * state);
int de_state_size(uint8_t eventByte, de_state_t *de_state);
void sdp_parser_init();
void sdp_parser_handle_chunk(uint8_t * data, uint16_t size);
void sdp_parser_handle_done(uint8_t status);
void sdp_parser_register_callback(void (*sdp_callback)(sdp_parser_event_t* event));

267
src/sdp_query_rfcomm.c Normal file
View File

@ -0,0 +1,267 @@
//*****************************************************************************
//
// minimal setup for SDP client over USB or UART
//
//*****************************************************************************
#include "sdp_query_rfcomm.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <btstack/hci_cmds.h>
#include <btstack/sdp_util.h>
#include "sdp_client.h"
static void dummy_notify_app(sdp_query_rfcomm_event_t* event, void * context);
typedef enum {
GET_PROTOCOL_LIST_LENGTH = 1,
GET_PROTOCOL_LENGTH,
GET_PROTOCOL_ID_HEADER_LENGTH,
GET_PROTOCOL_ID,
GET_PROTOCOL_VALUE_LENGTH,
GET_PROTOCOL_VALUE
} pdl_state_t;
// higher layer query - get rfcomm channel and name
#define SDP_SERVICE_NAME_LEN 20
const uint8_t des_attributeIDList[] = { 0x35, 0x05, 0x0A, 0x00, 0x01, 0x01, 0x00}; // Arribute: 0x0001 - 0x0100
static uint8_t des_serviceSearchPattern[5] = {0x35, 0x03, 0x19, 0x00, 0x00};
static uint8_t sdp_service_name[SDP_SERVICE_NAME_LEN+1];
static uint8_t sdp_rfcom_channel_nr = 0;
static uint8_t sdp_service_name_header_size;
static pdl_state_t pdl_state = GET_PROTOCOL_LIST_LENGTH;
static uint32_t protocol_value_bytes_received = 0;
static uint16_t protocol_id = 0;
static int protocol_offset;
static int protocol_size;
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_context;
static void (*sdp_app_callback)(sdp_query_rfcomm_event_t * event, void * context) = dummy_notify_app;
//
static void dummy_notify_app(sdp_query_rfcomm_event_t* event, void * context){}
void sdp_query_rfcomm_register_callback(void (*sdp_callback)(sdp_query_rfcomm_event_t* event, void * context), void * context){
sdp_app_callback = dummy_notify_app;
if (sdp_callback != NULL){
sdp_app_callback = sdp_callback;
}
sdp_app_context = context;
}
void handleProtocolDescriptorListData(uint32_t attribute_value_length, uint32_t data_offset, uint8_t data){
// init state on first byte
if (data_offset == 0){
pdl_state = GET_PROTOCOL_LIST_LENGTH;
}
// printf("handleProtocolDescriptorListData (%u,%u) %02x\n", attribute_value_length, data_offset, data);
switch(pdl_state){
case GET_PROTOCOL_LIST_LENGTH:
if (!de_state_size(data, &de_header_state)) break;
// printf(" query: PD List payload is %d bytes.\n", de_header_state.de_size);
// printf(" query: PD List offset %u, list size %u\n", de_header_state.de_offset, de_header_state.de_size);
pdl_state = GET_PROTOCOL_LENGTH;
break;
case GET_PROTOCOL_LENGTH:
// check size
if (!de_state_size(data, &de_header_state)) break;
// printf(" query: PD Record payload is %d bytes.\n", de_header_state.de_size);
// cache protocol info
protocol_offset = de_header_state.de_offset;
protocol_size = de_header_state.de_size;
pdl_state = GET_PROTOCOL_ID_HEADER_LENGTH;
break;
case GET_PROTOCOL_ID_HEADER_LENGTH:
protocol_offset++;
if (!de_state_size(data, &de_header_state)) break;
protocol_id = 0;
protocol_id_bytes_to_read = de_header_state.de_size;
// printf(" query: ID data is stored in %d bytes.\n", protocol_id_bytes_to_read);
pdl_state = GET_PROTOCOL_ID;
break;
case GET_PROTOCOL_ID:
protocol_offset++;
protocol_id = (protocol_id << 8) | data;
protocol_id_bytes_to_read--;
if (protocol_id_bytes_to_read > 0) break;
// printf(" query: Protocol ID: %04x.\n", protocol_id);
if (protocol_offset >= protocol_size){
pdl_state = GET_PROTOCOL_LENGTH;
// printf(" query: Get next protocol\n");
break;
}
pdl_state = GET_PROTOCOL_VALUE_LENGTH;
protocol_value_bytes_received = 0;
break;
case GET_PROTOCOL_VALUE_LENGTH:
protocol_offset++;
if (!de_state_size(data, &de_header_state)) break;
protocol_value_size = de_header_state.de_size;
pdl_state = GET_PROTOCOL_VALUE;
sdp_rfcom_channel_nr = 0;
break;
case GET_PROTOCOL_VALUE:
protocol_offset++;
protocol_value_bytes_received++;
// printf(" query: protocol_value_bytes_received %u, protocol_value_size %u\n", protocol_value_bytes_received, protocol_value_size);
if (protocol_value_bytes_received < protocol_value_size) break;
if (protocol_id == 0x0003){
// printf("\n\n ******* Data ***** %02x\n\n", data);
sdp_rfcom_channel_nr = data;
}
// printf(" query: protocol done\n");
// printf(" query: Protocol offset %u, protocol size %u\n", protocol_offset, protocol_size);
if (protocol_offset >= protocol_size) {
pdl_state = GET_PROTOCOL_LENGTH;
break;
}
pdl_state = GET_PROTOCOL_ID_HEADER_LENGTH;
// printf(" query: Get next protocol\n");
break;
default:
break;
}
}
void handleServiceNameData(uint32_t attribute_value_length, uint32_t data_offset, uint8_t data){
// Get Header Len
if (data_offset == 0){
de_state_size(data, &sn_de_header_state);
sdp_service_name_header_size = sn_de_header_state.addon_header_bytes + 1;
return;
}
// Get Header
if (data_offset < sdp_service_name_header_size){
de_state_size(data, &sn_de_header_state);
return;
}
// Process payload
int name_len = attribute_value_length - sdp_service_name_header_size;
int name_pos = data_offset - sdp_service_name_header_size;
if (name_pos < SDP_SERVICE_NAME_LEN){
sdp_service_name[name_pos] = data;
name_pos++;
}
// sdp_rfcom_channel_nr is stored in Attribute 0x0004 which is received before this 0x0100
if (name_pos >= SDP_SERVICE_NAME_LEN || name_pos >= name_len){
sdp_service_name[name_pos] = 0;
}
// notify on last char
if (data_offset == attribute_value_length - 1 && sdp_rfcom_channel_nr!=0){
sdp_query_rfcomm_service_event_t value_event = {
.type = SDP_QUERY_RFCOMM_SERVICE,
.service_name = (uint8_t *) sdp_service_name,
.rfcomm_channel_nr = sdp_rfcom_channel_nr
};
printf("Service found %s\n", sdp_service_name);
(*sdp_app_callback)((sdp_query_rfcomm_event_t*)&value_event, sdp_app_context);
sdp_rfcom_channel_nr = 0;
}
}
static void handle_sdp_parser_event(sdp_parser_event_t * event){
// printf(" CN - [ RID, AID, ALen, VOffset] : [%d, %04x, %u, %u, %u] BYTE %02x\n",
// record_id, attribute_id, attribute_length, data_offset, *src);
// return ;
sdp_parser_attribute_value_event_t * ve;
sdp_parser_complete_event_t * ce;
switch (event->type){
case SDP_PARSER_ATTRIBUTE_VALUE:
ve = (sdp_parser_attribute_value_event_t*) event;
switch (ve->attribute_id){
case SDP_ProtocolDescriptorList:
// find rfcomm channel
handleProtocolDescriptorListData(ve->attribute_length, ve->data_offset, ve->data);
break;
case 0x0100:
// get service name
handleServiceNameData(ve->attribute_length, ve->data_offset, ve->data);
break;
default:
// give up
return;
}
break;
case SDP_PARSER_COMPLETE:
ce = (sdp_parser_complete_event_t*) event;
sdp_query_rfcomm_complete_event_t c_event = {
.type = SDP_QUERY_COMPLETE,
.status = ce->status
};
(*sdp_app_callback)((sdp_query_rfcomm_event_t*)&c_event, sdp_app_context);
break;
}
// insert higher level code HERE
}
void sdp_query_rfcomm_init(){
// init
de_state_init(&de_header_state);
de_state_init(&sn_de_header_state);
pdl_state = GET_PROTOCOL_LIST_LENGTH;
protocol_offset = 0;
sdp_parser_register_callback(handle_sdp_parser_event);
}
void sdp_query_rfcomm_channel_and_name_for_service_with_service_search_pattern(bd_addr_t remote, uint8_t * serviceSearchPattern){
sdp_parser_init();
sdp_query_rfcomm_init();
sdp_client_query(remote, serviceSearchPattern, (uint8_t*)&des_attributeIDList[0]);
}
void sdp_query_rfcomm_channel_and_name_for_service_with_uuid(bd_addr_t remote, uint16_t uuid){
net_store_16(des_serviceSearchPattern, 3, uuid);
sdp_query_rfcomm_channel_and_name_for_service_with_service_search_pattern(remote, (uint8_t*)des_serviceSearchPattern);
}

31
src/sdp_query_rfcomm.h Normal file
View File

@ -0,0 +1,31 @@
//*****************************************************************************
//
// minimal setup for SDP client over USB or UART
//
//*****************************************************************************
#include <btstack/utils.h>
#include "sdp_parser.h"
typedef struct sdp_query_rfcomm_event {
uint8_t type;
} sdp_query_rfcomm_event_t;
typedef struct sdp_query_rfcomm_service_event {
uint8_t type;
uint8_t rfcomm_channel_nr;
uint8_t * service_name;
} sdp_query_rfcomm_service_event_t;
typedef struct sdp_query_rfcomm_complete_event {
uint8_t type;
uint8_t status; // 0 == OK
} sdp_query_rfcomm_complete_event_t;
void sdp_query_rfcomm_init(void);
void sdp_query_rfcomm_channel_and_name_for_service_with_uuid(bd_addr_t remote, uint16_t uuid);
void sdp_query_rfcomm_channel_and_name_for_service_with_service_search_pattern(bd_addr_t remote, uint8_t * des_serviceSearchPattern);
void sdp_query_rfcomm_register_callback(void(*sdp_app_callback)(sdp_query_rfcomm_event_t * event, void * context), void * context);