Skip to content
Snippets Groups Projects
Commit 23abc896 authored by Hauke Petersen's avatar Hauke Petersen
Browse files

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

So far, the helper module only contains functions for AD
(advertising data) processing
parent 3f93485e
No related branches found
No related tags found
No related merge requests found
...@@ -133,6 +133,9 @@ endif ...@@ -133,6 +133,9 @@ endif
ifneq (,$(filter cord_ep,$(USEMODULE))) ifneq (,$(filter cord_ep,$(USEMODULE)))
DIRS += net/application_layer/cord/ep DIRS += net/application_layer/cord/ep
endif endif
ifneq (,$(filter bluetil_%,$(USEMODULE)))
DIRS += net/ble/bluetil
endif
DIRS += $(dir $(wildcard $(addsuffix /Makefile, $(USEMODULE)))) DIRS += $(dir $(wildcard $(addsuffix /Makefile, $(USEMODULE))))
......
/*
* 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 */
/** @} */
DIRS += $(filter bluetil_%,$(USEMODULE))
include $(RIOTBASE)/Makefile.base
include $(RIOTBASE)/Makefile.base
/*
* 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;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment