1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

net/ble: add generic BLE helper module (bluetil)

So far, the helper module only contains functions for AD
(advertising data) processing
This commit is contained in:
Hauke Petersen 2018-12-07 18:02:47 +01:00
parent 3f93485eab
commit 23abc89675
5 changed files with 294 additions and 0 deletions

View File

@ -133,6 +133,9 @@ endif
ifneq (,$(filter cord_ep,$(USEMODULE)))
DIRS += net/application_layer/cord/ep
endif
ifneq (,$(filter bluetil_%,$(USEMODULE)))
DIRS += net/ble/bluetil
endif
DIRS += $(dir $(wildcard $(addsuffix /Makefile, $(USEMODULE))))

View File

@ -0,0 +1,195 @@
/*
* Copyright (C) 2018 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup net_bluetil_ad BLE Advertising Data (AD) Processing
* @ingroup net
* @brief Generic BLE advertising and scan request data processing
*
* This module provides functionality for user friendly reading and writing of
* BLE advertising and scan request buffers.
*
* This module is independent from any BLE stack.
*
* @{
*
* @file
* @brief Interface for the generic BLE advertising data processing module
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*/
#ifndef NET_BLUETIL_AD_H
#define NET_BLUETIL_AD_H
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "net/ble.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Static initializer for the advertising data structure
*/
#define BLUETIL_AD_INIT(b,p,s) { .buf = b, .pos = p, .size = s }
/**
* @brief Default flags to set when advertising BLE devices
*/
#define BLUETIL_AD_FLAGS_DEFAULT (BLE_GAP_DISCOVERABLE | \
BLE_GAP_FLAG_BREDR_NOTSUP)
/**
* @brief Return values used by the bluetil_ad module
*/
enum {
BLUETIL_AD_OK = 0, /**< everything went as expected */
BLUETIL_AD_NOTFOUND = -1, /**< entry not found */
BLUETIL_AD_NOMEM = -2, /**< insufficient memory to write field */
};
/**
* @brief Struct used for returning the contents of a selected field
*/
typedef struct {
uint8_t *data; /**< pointer a field's payload */
size_t len; /**< length of the payload */
} bluetil_ad_data_t;
/**
* @brief Descriptor for a buffer containing advertising data
*/
typedef struct {
uint8_t *buf; /**< buffer containing the advertising data */
size_t pos; /**< current write position in the buffer */
size_t size; /**< overall length of the buffer */
} bluetil_ad_t;
/**
* @brief Initialize the given advertising data descriptor
*
* @param[out] ad advertising data descriptor
* @param[in] buf buffer to point to
* @param[in] pos current fill position of @p buf
* @param[in] size size of @p buf
*/
void bluetil_ad_init(bluetil_ad_t *ad, void *buf, size_t pos, size_t size);
/**
* @brief Find a specific field in the given advertising data
*
* @param[in] ad advertising data descriptor
* @param[in] type field type to look for
* @param[out] data position and length of the field's payload
*
* @return BLUETIL_AD_OK if field was found
* @return BLUETIL_AD_NOTFOUND if field was not found
*/
int bluetil_ad_find(const bluetil_ad_t *ad,
uint8_t type, bluetil_ad_data_t *data);
/**
* @brief Find the given field and copy its payload into a string
*
* The resulting string is `\0` terminated. If the resulting string is too large
* to fit into the given buffer, it will be truncated to the maximum possible
* size (but still including the `\0` at the end).
*
* @param[in] ad advertising data descriptor
* @param[in] type field type to look for
* @param[out] str resulting string is written to this buffer
* @param[in] str_len maximum number of bytes to write to @p str, including
* the `\0` character
*
* @return BLUETIL_AD_OK if the field was found and copied
* @return BLUETIL_AD_NOTFOUND if the given field was not found
*/
int bluetil_ad_find_str(const bluetil_ad_t *ad, uint8_t type,
char *str, size_t str_len);
/**
* @brief Add a new field to the given advertising data
*
* @param[out] ad advertising data descriptor
* @param[in] type field type to add
* @param[in] data payload for the field
* @param[in] data_len length of the payload in bytes
*
* @return BLUETIL_AD_OK if the new field was added
* @return BLUETIL_AD_NOMEM if there is not enough space to write add field
*/
int bluetil_ad_add(bluetil_ad_t *ad, uint8_t type,
const void *data, size_t data_len);
/**
* @brief Convenience function to add the "flags" field
*
* @param[out] ad advertising data descriptor
* @param[in] flags flags to set
*
* @return BLUETIL_AD_OK if the flags field was added
* @return BLUETIL_AD_NOMEM if there is not enough space to write add field
*/
static inline int bluetil_ad_add_flags(bluetil_ad_t *ad, uint8_t flags)
{
return bluetil_ad_add(ad, BLE_GAP_AD_FLAGS, &flags, 1);
}
/**
* @brief Convenience function to add the "full name" field
*
* While the given name must be `\0` terminated, the termination character is
* not written to the advertising data.
*
* @param[out] ad advertising data descriptor
* @param[in] name name to set
*
* @return BLUETIL_AD_OK if the name field was added
* @return BLUETIL_AD_NOMEM if there is not enough space to add the name field
*/
static inline int bluetil_ad_add_name(bluetil_ad_t *ad, const char *name)
{
return bluetil_ad_add(ad, BLE_GAP_AD_NAME, name, strlen(name));
}
/**
* @brief Convenience function for initializing the advertising data
* descriptor and directly adding the flags field
*
* Most users will want to set the (mandatory) flags field right after
* initializing the advertising context, so this function provides a small
* shortcut.
*
* @param[out] ad advertising data descriptor
* @param[out] buf buffer to write advertising data into
* @param[in] buf_len size of @p buf in bytes
* @param[in] flags flags to set, typically BLUETIL_AD_FLAGS_DEFAULT
*
* @return BLUETIL_AD_OK on successful initialization with flags field
* @return BLUETIL_AD_NOMEM if given buffer is too small
*/
static inline int bluetil_ad_init_with_flags(bluetil_ad_t *ad,
void *buf, size_t buf_len,
uint8_t flags)
{
bluetil_ad_init(ad, buf, 0, buf_len);
return bluetil_ad_add_flags(ad, flags);
}
/* add more convenience functions on demand... */
#ifdef __cplusplus
}
#endif
#endif /* NET_BLUETIL_AD_H */
/** @} */

View File

@ -0,0 +1,3 @@
DIRS += $(filter bluetil_%,$(USEMODULE))
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,92 @@
/*
* Copyright (C) 2018 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup net_bluetil_ad
* @{
*
* @file
* @brief Implementation of the generic BLE advertising data processing
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*
* @}
*/
#include <string.h>
#include "assert.h"
#include "net/bluetil/ad.h"
#define POS_TYPE (1U)
#define POS_DATA (2U)
void bluetil_ad_init(bluetil_ad_t *ad, void *buf, size_t pos, size_t size)
{
assert(ad);
assert(buf);
ad->buf = buf;
ad->pos = pos;
ad->size = size;
}
int bluetil_ad_find(const bluetil_ad_t *ad, uint8_t type,
bluetil_ad_data_t *data)
{
assert(ad);
assert(data);
unsigned pos = 0;
while ((pos + POS_TYPE) < ad->pos) {
uint8_t len = ad->buf[pos];
if (ad->buf[pos + POS_TYPE] == type) {
data->data = ad->buf + pos + POS_DATA;
data->len = len - 1; /* take away the type field */
return BLUETIL_AD_OK;
}
pos += (len + 1);
}
return BLUETIL_AD_NOTFOUND;
}
int bluetil_ad_find_str(const bluetil_ad_t *ad, uint8_t type,
char *str, size_t str_len)
{
bluetil_ad_data_t f;
int res = bluetil_ad_find(ad, type, &f);
if (res != BLUETIL_AD_OK) {
return res;
}
size_t len = (f.len >= str_len) ? (str_len - 1) : f.len;
memcpy(str, f.data, len);
str[len] = '\0';
return BLUETIL_AD_OK;
}
int bluetil_ad_add(bluetil_ad_t *ad, uint8_t field_type,
const void *data, size_t data_len)
{
assert(ad);
if ((ad->pos + 2 + data_len) > ad->size) {
return BLUETIL_AD_NOMEM;
}
ad->buf[ad->pos++] = data_len + 1;
ad->buf[ad->pos++] = field_type;
memcpy(&ad->buf[ad->pos], data, data_len);
ad->pos += data_len;
return BLUETIL_AD_OK;
}