mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-21 12:40:42 +00:00
implement advertising or scan data parser
This commit is contained in:
parent
45c3b63f47
commit
60c84a4425
73
example/libusb/ad_parser.c
Normal file
73
example/libusb/ad_parser.c
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2013 by Matthias Ringwald
|
||||
*
|
||||
* 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. This software may not be used in a commercial product
|
||||
* without an explicit license granted by the copyright holder.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD 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.
|
||||
*
|
||||
*/
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Advertising Data Parser
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ad_parser.h"
|
||||
|
||||
void ad_iterator_init(ad_context_t *context, uint8_t ad_len, uint8_t * ad_data){
|
||||
context->data = ad_data;
|
||||
context->length = ad_len;
|
||||
context->offset = 0;
|
||||
}
|
||||
|
||||
int ad_iterator_has_more(ad_context_t * context){
|
||||
return context->offset < context->length;
|
||||
}
|
||||
|
||||
void ad_iterator_next(ad_context_t * context){
|
||||
uint8_t chunk_len = context->data[context->offset];
|
||||
context->offset += 1 + chunk_len;
|
||||
}
|
||||
|
||||
uint8_t ad_iterator_get_data_len(ad_context_t * context){
|
||||
return context->data[context->offset] - 1;
|
||||
}
|
||||
|
||||
uint8_t ad_iterator_get_data_type(ad_context_t * context){
|
||||
return context->data[context->offset + 1];
|
||||
}
|
||||
|
||||
uint8_t * ad_iterator_get_data(ad_context_t * context){
|
||||
return &context->data[context->offset + 2];
|
||||
}
|
||||
|
73
example/libusb/ad_parser.h
Normal file
73
example/libusb/ad_parser.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2013 by Matthias Ringwald
|
||||
*
|
||||
* 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. This software may not be used in a commercial product
|
||||
* without an explicit license granted by the copyright holder.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD 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.
|
||||
*
|
||||
*/
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Advertising Data Parser
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <btstack/utils.h>
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct ad_context {
|
||||
uint8_t * data;
|
||||
uint8_t offset;
|
||||
uint8_t length;
|
||||
} ad_context_t;
|
||||
|
||||
// Advertising or Scan Response data iterator
|
||||
void ad_iterator_init(ad_context_t *context, uint8_t ad_len, uint8_t * ad_data);
|
||||
int ad_iterator_has_more(ad_context_t * context);
|
||||
void ad_iterator_next(ad_context_t * context);
|
||||
|
||||
// Access functions
|
||||
uint8_t ad_iterator_get_data_type(ad_context_t * context);
|
||||
uint8_t ad_iterator_get_data_len(ad_context_t * context);
|
||||
uint8_t * ad_iterator_get_data(ad_context_t * context);
|
||||
|
||||
// convenience function on complete advertisements
|
||||
int ad_data_contains_uuid16(uint8_t ad_len, uint8_t * ad_data, uint16_t uuid);
|
||||
int ad_data_contains_uuid128(uint8_t ad_len, uint8_t * ad_data, uint8_t * uuid128);
|
||||
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
@ -46,7 +46,7 @@
|
||||
#include <string.h>
|
||||
#include <btstack/run_loop.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "ble_client.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "btstack_memory.h"
|
||||
@ -56,90 +56,17 @@
|
||||
#include "l2cap.h"
|
||||
|
||||
#include "att.h"
|
||||
|
||||
// API
|
||||
|
||||
typedef struct gatt_client_event {
|
||||
uint8_t type;
|
||||
} gatt_client_event_t;
|
||||
|
||||
typedef struct ad_event {
|
||||
uint8_t type;
|
||||
uint8_t event_type;
|
||||
uint8_t address_type;
|
||||
bd_addr_t address;
|
||||
uint8_t rssi;
|
||||
uint8_t length;
|
||||
uint8_t * data;
|
||||
} ad_event_t;
|
||||
#include "ad_parser.h"
|
||||
|
||||
|
||||
void (*gatt_client_callback)(gatt_client_event_t * event);
|
||||
|
||||
void gatt_client_init();
|
||||
void gatt_client_start_scan();
|
||||
// creates one event per found peripheral device
|
||||
// EVENT: type (8), addr_type (8), addr(48), rssi(8), ad_len(8), ad_data(ad_len*8)
|
||||
void gatt_client_stop_scan();
|
||||
|
||||
/*
|
||||
|
||||
typedef struct service_uuid{
|
||||
uint8_t lenght;
|
||||
uint8_t * uuid;
|
||||
} service_uuid_t;
|
||||
|
||||
typedef struct peripheral{
|
||||
|
||||
} peripheral_t;
|
||||
|
||||
// Advertising Data Parser
|
||||
|
||||
typedef struct ad_context {
|
||||
uint8_t * data;
|
||||
uint8_t offset;
|
||||
uint8_t length;
|
||||
} ad_context_t;
|
||||
|
||||
// iterator
|
||||
void ad_init(ad_context_t *context, uint8_t ad_len, uint8_t * ad_data);
|
||||
int ad_has_more(ad_context_t * context);
|
||||
void ad_next(ad_context_t * context);
|
||||
|
||||
// access functions
|
||||
uint8_t ad_get_data_type(ad_context_t * context);
|
||||
uint8_t ad_get_data_len(ad_context_t * context);
|
||||
uint8_t * ad_get_data(ad_context_t * context);
|
||||
|
||||
// convenience function on complete advertisements
|
||||
int ad_data_contains_uuid16(uint8_t ad_len, uint8_t * ad_data, uint16_t uuid);
|
||||
int ad_data_contains_uuid128(uint8_t ad_len, uint8_t * ad_data, uint8_t * uuid128);
|
||||
|
||||
// example use of Advertisment Data Parser
|
||||
void test_ad_parser(){
|
||||
ad_context_t context;
|
||||
for (ad_init(&context, len, data) ; ad_has_more(&context) ; ad_next(&context)){
|
||||
uint8_t data_type = ad_get_data_type(&context);
|
||||
uint8_t data_len = ad_get_data_len(&context);
|
||||
uint8_t * data = ad_get_data(&context);
|
||||
static void hexdump2(void *data, int size){
|
||||
int i;
|
||||
for (i=0; i<size;i++){
|
||||
printf("%02X ", ((uint8_t *)data)[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// GATT Client API
|
||||
|
||||
void gatt_client_register_handler( btstack_packet_handler_t handler);
|
||||
|
||||
uint16_t gatt_client_connect(bt_addr_t *dev);
|
||||
void gatt_client_cancel_connect(peripheral_id peripheral);
|
||||
|
||||
void get_services_for_peripheral(peripheral_id peripheral);
|
||||
// EVENT: type (8), peripheral_id (16), service_id
|
||||
|
||||
void get_characteristics_for_service(peripheral_id, service_id);
|
||||
// EVENT: type (8), peripheral_id (16), service_id (16), ...
|
||||
*/
|
||||
// END API
|
||||
|
||||
// gatt client state
|
||||
static uint8_t requested_scan_state = 0;
|
||||
static uint8_t scan_state = 0;
|
||||
@ -174,14 +101,6 @@ void gatt_client_stop_scan(){
|
||||
}
|
||||
|
||||
|
||||
static void hexdump2(void *data, int size){
|
||||
int i;
|
||||
for (i=0; i<size;i++){
|
||||
printf("%02X ", ((uint8_t *)data)[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void dump_ad_event(ad_event_t e){
|
||||
printf("evt-type %u, addr-type %u, addr %s, rssi %u, length adv %u, data: ", e.event_type,
|
||||
e.address_type, bd_addr_to_str(e.address), e.rssi, e.length);
|
||||
|
108
example/libusb/ble_client.h
Normal file
108
example/libusb/ble_client.h
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2013 by Matthias Ringwald
|
||||
*
|
||||
* 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. This software may not be used in a commercial product
|
||||
* without an explicit license granted by the copyright holder.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD 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.
|
||||
*
|
||||
*/
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// BLE Client
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
|
||||
// NOTE: Supports only a single connection
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <btstack/utils.h>
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct gatt_client_event {
|
||||
uint8_t type;
|
||||
} gatt_client_event_t;
|
||||
|
||||
typedef struct ad_event {
|
||||
uint8_t type;
|
||||
uint8_t event_type;
|
||||
uint8_t address_type;
|
||||
bd_addr_t address;
|
||||
uint8_t rssi;
|
||||
uint8_t length;
|
||||
uint8_t * data;
|
||||
} ad_event_t;
|
||||
|
||||
|
||||
void (*gatt_client_callback)(gatt_client_event_t * event);
|
||||
|
||||
void gatt_client_init();
|
||||
void gatt_client_start_scan();
|
||||
// creates one event per found peripheral device
|
||||
// EVENT: type (8), addr_type (8), addr(48), rssi(8), ad_len(8), ad_data(ad_len*8)
|
||||
void gatt_client_stop_scan();
|
||||
|
||||
|
||||
/*
|
||||
|
||||
typedef struct service_uuid{
|
||||
uint8_t lenght;
|
||||
uint8_t * uuid;
|
||||
} service_uuid_t;
|
||||
|
||||
typedef struct peripheral{
|
||||
|
||||
} peripheral_t;
|
||||
|
||||
|
||||
|
||||
// GATT Client API
|
||||
|
||||
void gatt_client_register_handler( btstack_packet_handler_t handler);
|
||||
|
||||
uint16_t gatt_client_connect(bt_addr_t *dev);
|
||||
void gatt_client_cancel_connect(peripheral_id peripheral);
|
||||
|
||||
void get_services_for_peripheral(peripheral_id peripheral);
|
||||
// EVENT: type (8), peripheral_id (16), service_id
|
||||
|
||||
void get_characteristics_for_service(peripheral_id, service_id);
|
||||
// EVENT: type (8), peripheral_id (16), service_id (16), ...
|
||||
*/
|
||||
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
25
test/ble_client/Makefile
Normal file
25
test/ble_client/Makefile
Normal file
@ -0,0 +1,25 @@
|
||||
CC = g++
|
||||
|
||||
# Requirements: http://www.cpputest.org/ should be placed in btstack/test
|
||||
|
||||
BTSTACK_ROOT = ../..
|
||||
CPPUTEST_HOME = ${BTSTACK_ROOT}/test/cpputest
|
||||
|
||||
CFLAGS = -g -Wall -I. -I${BTSTACK_ROOT}/example/libusb -I${BTSTACK_ROOT}/include -I$(CPPUTEST_HOME)/include
|
||||
LDFLAGS += -L$(CPPUTEST_HOME) -lCppUTest -lCppUTestExt
|
||||
|
||||
COMMON = \
|
||||
${BTSTACK_ROOT}/example/libusb/ad_parser.c \
|
||||
|
||||
COMMON_OBJ = $(COMMON:.c=.o)
|
||||
|
||||
all: ad_parser
|
||||
|
||||
ad_parser: ${CORE_OBJ} ${COMMON_OBJ} advertising_data_parser.c
|
||||
${CC} ${CORE_OBJ} ${COMMON_OBJ} advertising_data_parser.c ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
clean:
|
||||
rm -f ad_parser
|
||||
rm -f *.o ${BTSTACK_ROOT}/src/*.o
|
||||
rm -rf *.dSYM
|
||||
|
53
test/ble_client/advertising_data_parser.c
Normal file
53
test/ble_client/advertising_data_parser.c
Normal file
@ -0,0 +1,53 @@
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// test rfcomm query tests
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ad_parser.h"
|
||||
|
||||
#include "CppUTest/TestHarness.h"
|
||||
#include "CppUTest/CommandLineTestRunner.h"
|
||||
|
||||
static uint8_t ad_data[] = {0x02, 0x01, 0x05, 0x03, 0x02, 0xF0, 0xFF};
|
||||
|
||||
TEST_GROUP(ADParser){
|
||||
};
|
||||
|
||||
|
||||
TEST(ADParser, Test){
|
||||
ad_context_t context;
|
||||
uint8_t expected_len[] = {1, 2};
|
||||
uint8_t expected_type[] = {0x01, 0x02};
|
||||
uint8_t expected_data[][2] = {{0x05, 0x00}, {0xF0, 0xFF}};
|
||||
|
||||
int i = 0;
|
||||
uint8_t ad_len = sizeof(ad_data);
|
||||
|
||||
for (ad_iterator_init(&context, ad_len, ad_data) ; ad_iterator_has_more(&context) ; ad_iterator_next(&context)){
|
||||
uint8_t data_type = ad_iterator_get_data_type(&context);
|
||||
uint8_t data_len = ad_iterator_get_data_len(&context);
|
||||
uint8_t * data = ad_iterator_get_data(&context);
|
||||
|
||||
CHECK_EQUAL(expected_len[i], data_len);
|
||||
CHECK_EQUAL(expected_type[i], data_type);
|
||||
|
||||
int j;
|
||||
for (j = 0; j < data_len; j++){
|
||||
CHECK_EQUAL(expected_data[i][j], data[j]);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, const char * argv[]){
|
||||
return CommandLineTestRunner::RunAllTests(argc, argv);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user