/* * 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 ble_skald_eddystone * @{ * * @file * @brief Skald's Eddystone implementation * * @author Hauke Petersen * * @} */ #include #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); }