mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-17 05:12:57 +01:00
sys/net: added Skald
Skald is a very small and simple, TX-only BLE stack that supports sending advertisements only. It is useful for building all kinds of BLE beacons with very minimal memory footprints.
This commit is contained in:
parent
77499905e4
commit
49bd85d00a
@ -698,6 +698,15 @@ ifneq (,$(filter benchmark,$(USEMODULE)))
|
||||
USEMODULE += xtimer
|
||||
endif
|
||||
|
||||
ifneq (,$(filter skald_%,$(USEMODULE)))
|
||||
USEMODULE += skald
|
||||
endif
|
||||
|
||||
ifneq (,$(filter skald,$(USEMODULE)))
|
||||
FEATURES_REQUIRED += radio_ble
|
||||
USEMODULE += xtimer
|
||||
USEMODULE += random
|
||||
endif
|
||||
# always select gpio (until explicit dependencies are sorted out)
|
||||
FEATURES_OPTIONAL += periph_gpio
|
||||
|
||||
|
@ -117,3 +117,8 @@ PSEUDOMODULES += stm32_periph_%
|
||||
# declare periph submodules as pseudomodules, but exclude periph_common
|
||||
PSEUDOMODULES += periph_%
|
||||
NO_PSEUDOMODULES += periph_common
|
||||
|
||||
# Submodules and auto-init code provided by Skald
|
||||
PSEUDOMODULES += auto_init_skald
|
||||
PSEUDOMODULES += skald_ibeacon
|
||||
PSEUDOMODULES += skald_eddystone
|
||||
|
@ -124,6 +124,9 @@ endif
|
||||
ifneq (,$(filter nanocoap,$(USEMODULE)))
|
||||
DIRS += net/application_layer/nanocoap
|
||||
endif
|
||||
ifneq (,$(filter skald,$(USEMODULE)))
|
||||
DIRS += net/skald
|
||||
endif
|
||||
|
||||
DIRS += $(dir $(wildcard $(addsuffix /Makefile, $(USEMODULE))))
|
||||
|
||||
|
124
sys/include/net/skald.h
Normal file
124
sys/include/net/skald.h
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* 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_skald Skald, who advertises to the world
|
||||
* @ingroup net
|
||||
* @brief Skald, a minimalistic BLE advertising stack
|
||||
*
|
||||
* # About
|
||||
*
|
||||
* Skald is a very minimalistic BLE implementation, implementing the
|
||||
* `broadcaster` role only. With this focus, the stack allows for setting up
|
||||
* different kind of beacons using an extremely low memory footprint.
|
||||
*
|
||||
* # Design Decisions and Limitations
|
||||
* - support for local addresses only (using `luid` to generate them)
|
||||
* - advertising interval is configured during compile time, override by setting
|
||||
* `CFLAGS+=-DSKALD_INTERVAL=xxx`
|
||||
* - advertising channels are configured during compile time, override by
|
||||
* setting `CFLAGS+=-DSKALD_ADV_CHAN={37,39}`
|
||||
*
|
||||
* # Implementation state
|
||||
* Supported:
|
||||
* - advertising of custom GAP payloads
|
||||
* - iBeacon (full support)
|
||||
* - Eddystone (partly supported)
|
||||
*
|
||||
* Limitations:
|
||||
* - currently Skald supports random static addresses only (generated using
|
||||
* the `luid` module)
|
||||
*
|
||||
* @{
|
||||
* @file
|
||||
* @brief Skald's basic interface
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef NET_SKALD_H
|
||||
#define NET_SKALD_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "xtimer.h"
|
||||
#include "net/ble.h"
|
||||
#include "net/netdev/ble.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Static advertising interval
|
||||
*/
|
||||
#ifndef SKALD_INTERVAL
|
||||
#define SKALD_INTERVAL (1 * US_PER_SEC)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Static list of used advertising channels
|
||||
*/
|
||||
#ifndef SKALD_ADV_CHAN
|
||||
#define SKALD_ADV_CHAN { 37, 38, 39 }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UUID representation format used by Skald
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t u8[16]; /**< UUID with byte-wise access */
|
||||
} skald_uuid_t;
|
||||
|
||||
/**
|
||||
* @brief Advertising context holding the advertising data and state
|
||||
*/
|
||||
typedef struct {
|
||||
netdev_ble_pkt_t pkt; /**< packet holding the advertisement (GAP) data */
|
||||
xtimer_t timer; /**< timer for scheduling advertising events */
|
||||
uint32_t last; /**< last timer trigger (for offset compensation) */
|
||||
uint8_t cur_chan; /**< keep track of advertising channels */
|
||||
} skald_ctx_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize Skald and the underlying radio
|
||||
*/
|
||||
void skald_init(void);
|
||||
|
||||
/**
|
||||
* @brief Start advertising the given packet
|
||||
*
|
||||
* The packet will be send out each advertising interval (see SKALD_INTERVAL) on
|
||||
* each of the defined advertising channels (see SKALD_ADV_CHAN).
|
||||
*
|
||||
* @param[in,out] ctx start advertising this context
|
||||
*/
|
||||
void skald_adv_start(skald_ctx_t *ctx);
|
||||
|
||||
/**
|
||||
* @brief Stop the ongoing advertisement
|
||||
*
|
||||
* @param[in,out] ctx stop advertising this context
|
||||
*/
|
||||
void skald_adv_stop(skald_ctx_t *ctx);
|
||||
|
||||
/**
|
||||
* @brief Generate a random public address
|
||||
*
|
||||
* @note @p buf must be able to hold BLE_ADDR_LEN (6) bytes
|
||||
*
|
||||
* @param[out] buf the generated address is written to this buffer
|
||||
*/
|
||||
void skald_generate_random_addr(uint8_t *buf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NET_SKALD_H */
|
||||
/** @} */
|
83
sys/include/net/skald/eddystone.h
Normal file
83
sys/include/net/skald/eddystone.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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_skald_eddystone Skald meets Eddy
|
||||
* @ingroup net_skald
|
||||
* @brief Skald's Eddystone implementation
|
||||
*
|
||||
* # About
|
||||
* This module allows for creation and advertisement of Eddystone beacons (see
|
||||
* https://github.com/google/eddystone).
|
||||
*
|
||||
*
|
||||
* # Implementation state
|
||||
* supported:
|
||||
* - Eddystone-UID
|
||||
* - Eddystone-URL
|
||||
*
|
||||
* not (yet) supported:
|
||||
* - Eddystone-TLM
|
||||
* - Eddystone-EID
|
||||
*
|
||||
* @{
|
||||
* @file
|
||||
* @brief Skald's basic interface
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef NET_SKALD_EDDYSTONE_H
|
||||
#define NET_SKALD_EDDYSTONE_H
|
||||
|
||||
#include "net/eddystone.h"
|
||||
#include "net/skald.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Unique and opaque 16-byte beacon id format used by Eddystone
|
||||
*/
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t namespace[EDDYSTONE_NAMESPACE_LEN]; /**< 10-byte namespace */
|
||||
uint8_t instance[EDDYSTONE_INSTANCE_LEN]; /**< 6-byte instance */
|
||||
} skald_eddystone_uid_t;
|
||||
|
||||
/**
|
||||
* @brief Advertise Eddystone-UID data
|
||||
*
|
||||
* @see https://github.com/google/eddystone/tree/master/eddystone-uid
|
||||
*
|
||||
* @param[out] ctx advertising context
|
||||
* @param[in] uid UID to advertise
|
||||
* @param[in] tx_pwr calibrated TX power to be advertised by the beacon
|
||||
*/
|
||||
void skald_eddystone_uid_adv(skald_ctx_t *ctx,
|
||||
const skald_eddystone_uid_t *uid, uint8_t tx_pwr);
|
||||
|
||||
/**
|
||||
* @brief Advertise Eddystone-URL data
|
||||
*
|
||||
* @see https://github.com/google/eddystone/tree/master/eddystone-url
|
||||
*
|
||||
* @param[out] ctx advertising context
|
||||
* @param[in] scheme encoded URL scheme prefix
|
||||
* @param[in] url (short) url as \0 terminated string
|
||||
* @param[in] tx_pwr calibrated TX power to be advertised by the beacon
|
||||
*/
|
||||
void skald_eddystone_url_adv(skald_ctx_t *ctx,
|
||||
uint8_t scheme, const char *url, uint8_t tx_pwr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NET_SKALD_EDDYSTONE_H */
|
||||
/** @} */
|
54
sys/include/net/skald/ibeacon.h
Normal file
54
sys/include/net/skald/ibeacon.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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_skald_ibeacon Skald about iBeacon
|
||||
* @ingroup net_skald
|
||||
* @brief Skald's simple iBeacon abstraction
|
||||
*
|
||||
* # About
|
||||
* This Skald module supports the creation and advertisement of BLE iBeacons as
|
||||
* defined by Apple (see https://developer.apple.com/ibeacon/).
|
||||
*
|
||||
* # Implementation state
|
||||
* - all known iBeacon properties are supported
|
||||
*
|
||||
* @{
|
||||
* @file
|
||||
* @brief Skald's basic interface
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef NET_SKALD_IBEACON_H
|
||||
#define NET_SKALD_IBEACON_H
|
||||
|
||||
#include "net/skald.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Configure the IBeacon payload and start advertising
|
||||
*
|
||||
* @param[out] ctx advertising context
|
||||
* @param[in] uuid UUID advertised by the iBeacon
|
||||
* @param[in] major the iBeacon's major number
|
||||
* @param[in] minor the iBeacon's minor number
|
||||
* @param[in] txpower calibrated TX power to be advertised by the beacon
|
||||
*/
|
||||
void skald_ibeacon_advertise(skald_ctx_t *ctx, const skald_uuid_t *uuid,
|
||||
uint16_t major, uint16_t minor, uint8_t txpower);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NET_SKALD_IBEACON_H */
|
||||
/** @} */
|
11
sys/net/skald/Makefile
Normal file
11
sys/net/skald/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
SRC = skald.c
|
||||
|
||||
ifneq (,$(filter skald_ibeacon,$(USEMODULE)))
|
||||
SRC += skald_ibeacon.c
|
||||
endif
|
||||
|
||||
ifneq (,$(filter skald_eddystone,$(USEMODULE)))
|
||||
SRC += skald_eddystone.c
|
||||
endif
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
158
sys/net/skald/skald.c
Normal file
158
sys/net/skald/skald.c
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* 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_skald
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Skald's link layer implementation
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "assert.h"
|
||||
#include "random.h"
|
||||
#include "luid.h"
|
||||
|
||||
#include "net/netdev/ble.h"
|
||||
#include "net/skald.h"
|
||||
|
||||
/* include fitting radio driver */
|
||||
#if defined(MODULE_NRFBLE)
|
||||
#include "nrfble.h"
|
||||
/* add other BLE radio drivers once implemented - and potentially move to
|
||||
* auto-init at some point */
|
||||
#else
|
||||
#error "[skald] error: unable to find any netdev-ble capable radio"
|
||||
#endif
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
#define JITTER_MIN (0U) /* 0ms */
|
||||
#define JITTER_MAX (10000U) /* 10ms */
|
||||
|
||||
#define ADV_CHAN_NUMOF sizeof(_adv_chan)
|
||||
#define ADV_AA (0x8e89bed6) /* access address */
|
||||
#define ADV_CRC (0x00555555) /* CRC initializer */
|
||||
|
||||
static const uint8_t _adv_chan[] = SKALD_ADV_CHAN;
|
||||
|
||||
static netdev_ble_ctx_t _ble_ctx = {
|
||||
.aa.u32 = ADV_AA,
|
||||
.crc = ADV_CRC,
|
||||
};
|
||||
|
||||
static netdev_t *_radio;
|
||||
|
||||
static void _stop_radio(void)
|
||||
{
|
||||
netdev_ble_stop(_radio);
|
||||
_radio->context = NULL;
|
||||
}
|
||||
|
||||
static void _sched_next(skald_ctx_t *ctx)
|
||||
{
|
||||
ctx->last += SKALD_INTERVAL;
|
||||
/* schedule next advertising event, adding a random jitter between
|
||||
* 0ms and 10ms (see spec v5.0-vol6-b-4.4.2.2.1) */
|
||||
ctx->last += random_uint32_range(JITTER_MIN, JITTER_MAX);
|
||||
/* compensate the time passed since the timer triggered last by using the
|
||||
* current value of the timer */
|
||||
xtimer_set(&ctx->timer, (ctx->last - xtimer_now_usec()));
|
||||
}
|
||||
|
||||
static void _on_adv_evt(void *arg)
|
||||
{
|
||||
skald_ctx_t *ctx = (skald_ctx_t *)arg;
|
||||
|
||||
/* advertise on the next adv channel - or skip this event if the radio is
|
||||
* busy */
|
||||
if ((ctx->cur_chan < ADV_CHAN_NUMOF) && (_radio->context == NULL)) {
|
||||
_radio->context = ctx;
|
||||
_ble_ctx.chan = _adv_chan[ctx->cur_chan];
|
||||
netdev_ble_set_ctx(_radio, &_ble_ctx);
|
||||
netdev_ble_send(_radio, &ctx->pkt);
|
||||
++ctx->cur_chan;
|
||||
}
|
||||
else {
|
||||
ctx->cur_chan = 0;
|
||||
_sched_next(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void _on_radio_evt(netdev_t *netdev, netdev_event_t event)
|
||||
{
|
||||
(void)netdev;
|
||||
|
||||
if (event == NETDEV_EVENT_TX_COMPLETE) {
|
||||
skald_ctx_t *ctx = _radio->context;
|
||||
_stop_radio();
|
||||
xtimer_set(&ctx->timer, 150);
|
||||
}
|
||||
}
|
||||
|
||||
void skald_init(void)
|
||||
{
|
||||
assert(dev);
|
||||
|
||||
/* setup and a fitting radio driver - potentially move to auto-init at some
|
||||
* point */
|
||||
#if defined(MODULE_NRFBLE)
|
||||
_radio = nrfble_setup();
|
||||
#endif
|
||||
|
||||
_radio->event_callback = _on_radio_evt;
|
||||
_radio->driver->init(_radio);
|
||||
}
|
||||
|
||||
void skald_adv_start(skald_ctx_t *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
|
||||
/* make sure the given context is not advertising at the moment */
|
||||
skald_adv_stop(ctx);
|
||||
|
||||
/* initialize advertising context */
|
||||
ctx->timer.callback = _on_adv_evt;
|
||||
ctx->timer.arg = ctx;
|
||||
ctx->last = xtimer_now_usec();
|
||||
ctx->cur_chan = 0;
|
||||
ctx->pkt.flags = (BLE_ADV_NONCON_IND | BLE_LL_FLAG_TXADD);
|
||||
|
||||
/* start advertising */
|
||||
_sched_next(ctx);
|
||||
}
|
||||
|
||||
void skald_adv_stop(skald_ctx_t *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
|
||||
xtimer_remove(&ctx->timer);
|
||||
if (_radio->context == (void *)ctx) {
|
||||
_stop_radio();
|
||||
}
|
||||
}
|
||||
|
||||
void skald_generate_random_addr(uint8_t *buf)
|
||||
{
|
||||
assert(buf);
|
||||
|
||||
luid_get(buf, BLE_ADDR_LEN);
|
||||
/* swap byte 0 and 5, so that the unique byte given by luid does not clash
|
||||
* with universal/local and individual/group bits of address */
|
||||
uint8_t tmp = buf[5];
|
||||
buf[5] = buf[0];
|
||||
/* make address individual and local */
|
||||
buf[0] = ((tmp & 0xfc) | 0x02);
|
||||
}
|
109
sys/net/skald/skald_eddystone.c
Normal file
109
sys/net/skald/skald_eddystone.c
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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_skald_eddystone
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Skald's Eddystone implementation
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "assert.h"
|
||||
#include "net/skald/eddystone.h"
|
||||
|
||||
#define PREAMBLE_LEN (11U)
|
||||
#define PA_LEN (7U)
|
||||
#define PB_LEN (3U)
|
||||
|
||||
#define URL_HDR_LEN (6U)
|
||||
|
||||
#define UID_LEN (23U)
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t txadd[BLE_ADDR_LEN];
|
||||
uint8_t pa[PA_LEN];
|
||||
uint8_t service_data_len;
|
||||
uint8_t pb[PB_LEN];
|
||||
uint8_t type;
|
||||
} pre_t;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
pre_t pre;
|
||||
uint8_t tx_pwr;
|
||||
uint8_t namespace[EDDYSTONE_NAMESPACE_LEN];
|
||||
uint8_t instance[EDDYSTONE_INSTANCE_LEN];
|
||||
uint8_t reserved[2];
|
||||
} eddy_uid_t;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
pre_t pre;
|
||||
uint8_t tx_pwr;
|
||||
uint8_t scheme;
|
||||
uint8_t url[];
|
||||
} eddy_url_t;
|
||||
|
||||
/* ćonstant GAP data preamble parts, containing the following GAP fields:
|
||||
* - flags: BR/EDR not support set
|
||||
* - complete list of 16-bit UUIDs: holding the Eddystone UUID only (0xfeaa)
|
||||
* - service data of type 0xfeaa (Eddystone) */
|
||||
static const uint8_t _pa[PA_LEN] = { 0x02, 0x01, 0x04, 0x03, 0x03, 0xaa, 0xfe };
|
||||
static const uint8_t _pb[PB_LEN] = { 0x16, 0xaa, 0xfe };
|
||||
|
||||
static void _init_pre(pre_t *data, uint8_t type, uint8_t len)
|
||||
{
|
||||
skald_generate_random_addr(data->txadd);
|
||||
memcpy(data->pa, _pa, PA_LEN);
|
||||
memcpy(data->pb, _pb, PB_LEN);
|
||||
data->service_data_len = len;
|
||||
data->type = type;
|
||||
}
|
||||
|
||||
void skald_eddystone_uid_adv(skald_ctx_t *ctx,
|
||||
const skald_eddystone_uid_t *uid, uint8_t tx_pwr)
|
||||
{
|
||||
assert(ctx && uid);
|
||||
|
||||
eddy_uid_t *pdu = (eddy_uid_t *)ctx->pkt.pdu;
|
||||
_init_pre(&pdu->pre, EDDYSTONE_UID, UID_LEN);
|
||||
|
||||
pdu->tx_pwr = tx_pwr;
|
||||
memcpy(pdu->namespace, uid->namespace, EDDYSTONE_NAMESPACE_LEN);
|
||||
memcpy(pdu->instance, uid->instance, EDDYSTONE_INSTANCE_LEN);
|
||||
memset(pdu->reserved, 0, 2);
|
||||
|
||||
/* start advertising */
|
||||
ctx->pkt.len = sizeof(eddy_uid_t);
|
||||
skald_adv_start(ctx);
|
||||
}
|
||||
|
||||
void skald_eddystone_url_adv(skald_ctx_t *ctx,
|
||||
uint8_t scheme, const char *url, uint8_t tx_pwr)
|
||||
{
|
||||
assert(url && ctx);
|
||||
size_t len = strlen(url);
|
||||
assert(len <= (NETDEV_BLE_PDU_MAXLEN - (URL_HDR_LEN + PREAMBLE_LEN)));
|
||||
|
||||
eddy_url_t *pdu = (eddy_url_t *)ctx->pkt.pdu;
|
||||
_init_pre(&pdu->pre, EDDYSTONE_URL, (URL_HDR_LEN + len));
|
||||
|
||||
/* set remaining service data fields */
|
||||
pdu->tx_pwr = tx_pwr;
|
||||
pdu->scheme = scheme;
|
||||
memcpy(pdu->url, url, len);
|
||||
|
||||
/* start advertising */
|
||||
ctx->pkt.len = (sizeof(pre_t) + 2 + len);
|
||||
skald_adv_start(ctx);
|
||||
}
|
63
sys/net/skald/skald_ibeacon.c
Normal file
63
sys/net/skald/skald_ibeacon.c
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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_skald_ibeacon
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Skald's iBeacon implementation
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "byteorder.h"
|
||||
|
||||
#include "net/skald/ibeacon.h"
|
||||
|
||||
#define PREFIX_LEN (9U)
|
||||
|
||||
/**
|
||||
* @brief PDU format for iBeacon packets
|
||||
*/
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t txadd[BLE_ADDR_LEN];
|
||||
uint8_t prefix[PREFIX_LEN];
|
||||
skald_uuid_t uuid;
|
||||
be_uint16_t major;
|
||||
be_uint16_t minor;
|
||||
uint8_t txpower;
|
||||
} ibeacon_t;
|
||||
|
||||
/* constant GAP type value fields, fixed for the iBeacon format */
|
||||
static const uint8_t prefix[PREFIX_LEN] = { 0x02, 0x01, 0x06, 0x1a, 0xff,
|
||||
0x4c, 0x00, 0x02, 0x15 };
|
||||
|
||||
void skald_ibeacon_advertise(skald_ctx_t *ctx, const skald_uuid_t *uuid,
|
||||
uint16_t major, uint16_t minor, uint8_t txpower)
|
||||
{
|
||||
/* configure the iBeacon PDU */
|
||||
ibeacon_t *pdu = (ibeacon_t *)ctx->pkt.pdu;
|
||||
|
||||
ctx->pkt.len = (uint8_t)sizeof(ibeacon_t);
|
||||
|
||||
skald_generate_random_addr(pdu->txadd);
|
||||
memcpy(pdu->prefix, prefix, PREFIX_LEN);
|
||||
memcpy(&pdu->uuid, uuid, sizeof(skald_uuid_t));
|
||||
be_uint16_t tmp = byteorder_htons(major);
|
||||
memcpy(&pdu->major, &tmp, sizeof(uint16_t));
|
||||
tmp = byteorder_htons(minor);
|
||||
memcpy(&pdu->minor, &tmp, sizeof(uint16_t));
|
||||
pdu->txpower = txpower;
|
||||
|
||||
skald_adv_start(ctx);
|
||||
}
|
Loading…
Reference in New Issue
Block a user