Bluetooth: Update advertising API

Update the advertising API according to what has recently been
discussed and agreed upon.

Naming-wise the most important change is the removal of "EIR" which
was confusing since this is mainly used with LE at the moment. The
Core Specification Supplement consistently uses the generic terms data
and data type to describe what we're dealing with here, so the new
names are bt_data and BT_DATA.

Another change is to detach the actual data from the struct by
converting it from an array to a pointer. This is not only essential
for supporting BR/EDR (which has a different length) but to also
minimize memory usage.

Another change is to require the caller of bt_le_adv_start() to
provide the array lengths of the ad and sd paramters. This way we
don't have to have the empty (8-byte) element at the end of each
array.

Lastly, the bt_le_adv_start() logic is slightly modified so that it
will always clear the respective data if necessary. Previously the
user might have been left with a previous callers data if it passed
NULL to the API.

Change-Id: I318026ceb1b52bb688edf4dcfed82613bd15c3e1
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
Johan Hedberg 2016-01-13 12:53:54 +02:00 committed by Anas Nashif
commit 3c47e9515c
13 changed files with 174 additions and 224 deletions

View file

@ -24,7 +24,8 @@ int bt_enable(bt_ready_cb_t cb)
} }
int bt_le_adv_start(const struct bt_le_adv_param *param, int bt_le_adv_start(const struct bt_le_adv_param *param,
const struct bt_eir *ad, const struct bt_eir *sd) const struct bt_data *ad, size_t ad_len,
const struct bt_data *sd, size_t sd_len)
{ {
return -ENOSYS; return -ENOSYS;
} }

View file

@ -47,11 +47,26 @@ int bt_enable(bt_ready_cb_t cb);
/* Advertising API */ /* Advertising API */
struct bt_eir { /** Description of different data types that can be encoded into
uint8_t len; * advertising data. Used to form arrays that are passed to the
* bt_le_adv_start() function.
*/
struct bt_data {
uint8_t type; uint8_t type;
uint8_t data[29]; uint8_t data_len;
} __packed; const uint8_t *data;
};
/** Helper to declare inline byte arrays */
#define BT_BYTES(bytes...) ((uint8_t []) { bytes })
/** Helper to declare elements of bt_data arrays */
#define BT_DATA(_type, _data, _data_len) \
{ \
.type = _type, \
.data_len = _data_len, \
.data = _data, \
}
/** Local advertising address type */ /** Local advertising address type */
enum { enum {
@ -103,12 +118,15 @@ struct bt_le_adv_param {
* *
* @param param Advertising parameters. * @param param Advertising parameters.
* @param ad Data to be used in advertisement packets. * @param ad Data to be used in advertisement packets.
* @param ad_len Number of elements in ad
* @param sd Data to be used in scan response packets. * @param sd Data to be used in scan response packets.
* @param sd_len Number of elements in sd
* *
* @return Zero on success or (negative) error code otherwise. * @return Zero on success or (negative) error code otherwise.
*/ */
int bt_le_adv_start(const struct bt_le_adv_param *param, int bt_le_adv_start(const struct bt_le_adv_param *param,
const struct bt_eir *ad, const struct bt_eir *sd); const struct bt_data *ad, size_t ad_len,
const struct bt_data *sd, size_t sd_len);
/** @brief Stop advertising /** @brief Stop advertising
* *

View file

@ -46,24 +46,25 @@ typedef struct {
#define BT_HCI_ERR_PAIRING_NOT_SUPPORTED 0x29 #define BT_HCI_ERR_PAIRING_NOT_SUPPORTED 0x29
#define BT_HCI_ERR_UNACCEPT_CONN_PARAMS 0x3b #define BT_HCI_ERR_UNACCEPT_CONN_PARAMS 0x3b
/* EIR/AD definitions */ /* EIR/AD data type definitions */
#define BT_EIR_FLAGS 0x01 /* AD flags */ #define BT_DATA_FLAGS 0x01 /* AD flags */
#define BT_EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */ #define BT_DATA_UUID16_SOME 0x02 /* 16-bit UUID, more available */
#define BT_EIR_UUID16_ALL 0x03 /* 16-bit UUID, all listed */ #define BT_DATA_UUID16_ALL 0x03 /* 16-bit UUID, all listed */
#define BT_EIR_UUID32_SOME 0x04 /* 32-bit UUID, more available */ #define BT_DATA_UUID32_SOME 0x04 /* 32-bit UUID, more available */
#define BT_EIR_UUID32_ALL 0x05 /* 32-bit UUID, all listed */ #define BT_DATA_UUID32_ALL 0x05 /* 32-bit UUID, all listed */
#define BT_EIR_UUID128_SOME 0x06 /* 128-bit UUID, more available */ #define BT_DATA_UUID128_SOME 0x06 /* 128-bit UUID, more available */
#define BT_EIR_UUID128_ALL 0x07 /* 128-bit UUID, all listed */ #define BT_DATA_UUID128_ALL 0x07 /* 128-bit UUID, all listed */
#define BT_EIR_NAME_COMPLETE 0x09 /* Complete name */ #define BT_DATA_NAME_SHORTENED 0x08 /* Shortened name */
#define BT_EIR_TX_POWER 0x0a /* Tx Power */ #define BT_DATA_NAME_COMPLETE 0x09 /* Complete name */
#define BT_EIR_SOLICIT16 0x14 /* Solicit UUIDs, 16-bit */ #define BT_DATA_TX_POWER 0x0a /* Tx Power */
#define BT_EIR_SOLICIT128 0x15 /* Solicit UUIDs, 128-bit */ #define BT_DATA_SOLICIT16 0x14 /* Solicit UUIDs, 16-bit */
#define BT_EIR_SVC_DATA16 0x16 /* Service data, 16-bit UUID */ #define BT_DATA_SOLICIT128 0x15 /* Solicit UUIDs, 128-bit */
#define BT_EIR_GAP_APPEARANCE 0x19 /* GAP appearance */ #define BT_DATA_SVC_DATA16 0x16 /* Service data, 16-bit UUID */
#define BT_EIR_SOLICIT32 0x1f /* Solicit UUIDs, 32-bit */ #define BT_DATA_GAP_APPEARANCE 0x19 /* GAP appearance */
#define BT_EIR_SVC_DATA32 0x20 /* Service data, 32-bit UUID */ #define BT_DATA_SOLICIT32 0x1f /* Solicit UUIDs, 32-bit */
#define BT_EIR_SVC_DATA128 0x21 /* Service data, 128-bit UUID */ #define BT_DATA_SVC_DATA32 0x20 /* Service data, 32-bit UUID */
#define BT_EIR_MANUFACTURER_DATA 0xff /* Manufacturer Specific Data */ #define BT_DATA_SVC_DATA128 0x21 /* Service data, 128-bit UUID */
#define BT_DATA_MANUFACTURER_DATA 0xff /* Manufacturer Specific Data */
#define BT_LE_AD_LIMITED 0x01 /* Limited Discoverable */ #define BT_LE_AD_LIMITED 0x01 /* Limited Discoverable */
#define BT_LE_AD_GENERAL 0x02 /* General Discoverable */ #define BT_LE_AD_GENERAL 0x02 /* General Discoverable */

View file

@ -2336,11 +2336,11 @@ static bool valid_adv_param(const struct bt_le_adv_param *param)
} }
int bt_le_adv_start(const struct bt_le_adv_param *param, int bt_le_adv_start(const struct bt_le_adv_param *param,
const struct bt_eir *ad, const struct bt_eir *sd) const struct bt_data *ad, size_t ad_len,
const struct bt_data *sd, size_t sd_len)
{ {
struct net_buf *buf; struct net_buf *buf;
struct bt_hci_cp_le_set_adv_data *set_data; struct bt_hci_cp_le_set_adv_data *set_data;
struct bt_hci_cp_le_set_adv_data *scan_rsp;
struct bt_hci_cp_le_set_adv_parameters *set_param; struct bt_hci_cp_le_set_adv_parameters *set_param;
uint8_t adv_enable; uint8_t adv_enable;
int i, err; int i, err;
@ -2353,10 +2353,6 @@ int bt_le_adv_start(const struct bt_le_adv_param *param,
return -EALREADY; return -EALREADY;
} }
if (!ad) {
goto send_scan_rsp;
}
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_DATA, sizeof(*set_data)); buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_DATA, sizeof(*set_data));
if (!buf) { if (!buf) {
return -ENOBUFS; return -ENOBUFS;
@ -2366,41 +2362,52 @@ int bt_le_adv_start(const struct bt_le_adv_param *param,
memset(set_data, 0, sizeof(*set_data)); memset(set_data, 0, sizeof(*set_data));
for (i = 0; ad[i].len; i++) { for (i = 0; i < ad_len; i++) {
/* Check if ad fit in the remaining buffer */ /* Check if ad fit in the remaining buffer */
if (set_data->len + ad[i].len + 1 > 29) { if (set_data->len + ad[i].data_len + 2 > 31) {
break; break;
} }
memcpy(&set_data->data[set_data->len], &ad[i], ad[i].len + 1); set_data->data[set_data->len++] = ad[i].data_len + 1;
set_data->len += ad[i].len + 1; set_data->data[set_data->len++] = ad[i].type;
memcpy(&set_data->data[set_data->len], ad[i].data,
ad[i].data_len);
set_data->len += ad[i].data_len;
} }
bt_hci_cmd_send(BT_HCI_OP_LE_SET_ADV_DATA, buf); bt_hci_cmd_send(BT_HCI_OP_LE_SET_ADV_DATA, buf);
send_scan_rsp: /*
if (!sd) { * Don't bother with scan response if the advertising type isn't
* a scannable one.
*/
if (param->type != BT_LE_ADV_IND && param->type != BT_LE_ADV_SCAN_IND) {
goto send_set_param; goto send_set_param;
} }
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_SCAN_RSP_DATA, buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_SCAN_RSP_DATA,
sizeof(*scan_rsp)); sizeof(*set_data));
if (!buf) { if (!buf) {
return -ENOBUFS; return -ENOBUFS;
} }
scan_rsp = net_buf_add(buf, sizeof(*scan_rsp)); set_data = net_buf_add(buf, sizeof(*set_data));
memset(scan_rsp, 0, sizeof(*scan_rsp)); memset(set_data, 0, sizeof(*set_data));
for (i = 0; sd[i].len; i++) { for (i = 0; i < sd_len; i++) {
/* Check if ad fit in the remaining buffer */ /* Check if ad fit in the remaining buffer */
if (scan_rsp->len + sd[i].len + 1 > 29) { if (set_data->len + sd[i].data_len + 2 > 31) {
break; break;
} }
memcpy(&scan_rsp->data[scan_rsp->len], &sd[i], sd[i].len + 1); set_data->data[set_data->len++] = sd[i].data_len + 1;
scan_rsp->len += sd[i].len + 1; set_data->data[set_data->len++] = sd[i].type;
memcpy(&set_data->data[set_data->len], sd[i].data,
sd[i].data_len);
set_data->len += sd[i].data_len;
} }
bt_hci_cmd_send(BT_HCI_OP_LE_SET_SCAN_RSP_DATA, buf); bt_hci_cmd_send(BT_HCI_OP_LE_SET_SCAN_RSP_DATA, buf);

View file

@ -19,34 +19,21 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <misc/printk.h> #include <misc/printk.h>
#include <misc/util.h>
#include <bluetooth/bluetooth.h> #include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h> #include <bluetooth/hci.h>
/* Set Advertisement data */ /* Set Advertisement data */
static const struct bt_eir ad[] = { static const struct bt_data ad[] = {
{ BT_DATA(BT_DATA_UUID16_ALL, BT_BYTES(0xd8, 0xfe), 2),
.len = 3, BT_DATA(BT_DATA_SVC_DATA16,
.type = BT_EIR_UUID16_ALL, BT_BYTES(0xd8, 0xfe, 0x00, 0x20, 0x02, '0', '1', 0x08), 8)
.data = { 0xd8, 0xfe },
},
{
.len = 9,
.type = BT_EIR_SVC_DATA16,
.data = { 0xd8, 0xfe, 0x00, 0x20, 0x02, '0', '1',
0x08 },
},
{ }
}; };
/* Set Scan Response data */ /* Set Scan Response data */
static const struct bt_eir sd[] = { static const struct bt_data sd[] = {
{ BT_DATA(BT_DATA_NAME_COMPLETE, "Test beacon", 11),
.len = 12,
.type = BT_EIR_NAME_COMPLETE,
.data = "Test beacon",
},
{ }
}; };
#ifdef CONFIG_MICROKERNEL #ifdef CONFIG_MICROKERNEL
@ -71,7 +58,7 @@ void main(void)
BT_LE_ADV_ADDR_NRPA, BT_LE_ADV_ADDR_NRPA,
BT_GAP_ADV_FAST_INT_MIN_2, BT_GAP_ADV_FAST_INT_MIN_2,
BT_GAP_ADV_FAST_INT_MAX_2), BT_GAP_ADV_FAST_INT_MAX_2),
ad, sd); ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
if (err) { if (err) {
printk("Advertising failed to start (err %d)\n", err); printk("Advertising failed to start (err %d)\n", err);
return; return;

View file

@ -119,26 +119,27 @@ static void connected(struct bt_conn *conn)
} }
} }
static bool eir_found(const struct bt_eir *eir, void *user_data) static bool eir_found(uint8_t type, const uint8_t *data, uint8_t data_len,
void *user_data)
{ {
bt_addr_le_t *addr = user_data; bt_addr_le_t *addr = user_data;
int i; int i;
printk("[AD]: %u len %u\n", eir->type, eir->len); printk("[AD]: %u data_len %u\n", type, data_len);
switch (eir->type) { switch (type) {
case BT_EIR_UUID16_SOME: case BT_DATA_UUID16_SOME:
case BT_EIR_UUID16_ALL: case BT_DATA_UUID16_ALL:
if ((eir->len - sizeof(eir->type)) % sizeof(uint16_t) != 0) { if (data_len % sizeof(uint16_t) != 0) {
printk("AD malformed\n"); printk("AD malformed\n");
return true; return true;
} }
for (i = 0; i < eir->len; i += sizeof(uint16_t)) { for (i = 0; i < data_len; i += sizeof(uint16_t)) {
uint16_t u16; uint16_t u16;
int err; int err;
memcpy(&u16, &eir->data[i], sizeof(u16)); memcpy(&u16, &data[i], sizeof(u16));
if (sys_le16_to_cpu(u16) != BT_UUID_HRS->u16) { if (sys_le16_to_cpu(u16) != BT_UUID_HRS->u16) {
continue; continue;
} }
@ -158,32 +159,30 @@ static bool eir_found(const struct bt_eir *eir, void *user_data)
return true; return true;
} }
static void ad_parse(const uint8_t *data, uint8_t len, static void ad_parse(const uint8_t *data, uint8_t data_len,
bool (*func)(const struct bt_eir *eir, void *user_data), bool (*func)(uint8_t type, const uint8_t *data,
uint8_t data_len, void *user_data),
void *user_data) void *user_data)
{ {
const void *p; while (data_len > 1) {
uint8_t len = data[0];
for (p = data; len > 0;) {
const struct bt_eir *eir = p;
/* Check for early termination */ /* Check for early termination */
if (eir->len == 0) { if (len == 0) {
return; return;
} }
if ((eir->len + sizeof(eir->len) > len) || if ((len + 1 > data_len) || (data_len < 2)) {
(len < sizeof(eir->len) + sizeof(eir->type))) {
printk("AD malformed\n"); printk("AD malformed\n");
return; return;
} }
if (!func(eir, user_data)) { if (!func(data[1], &data[2], len - 1, user_data)) {
return; return;
} }
p += sizeof(eir->len) + eir->len; data_len -= len + 1;
len -= sizeof(eir->len) + eir->len; data += len + 1;
} }
} }

View file

@ -35,6 +35,7 @@
#include <net/net_socket.h> #include <net/net_socket.h>
#define DEVICE_NAME "Test IPSP node" #define DEVICE_NAME "Test IPSP node"
#define DEVICE_NAME_LEN 14
#define UNKNOWN_APPEARANCE 0x0000 #define UNKNOWN_APPEARANCE 0x0000
/* The 2001:db8::/32 is the private address space for documentation RFC 3849 */ /* The 2001:db8::/32 is the private address space for documentation RFC 3849 */
@ -103,27 +104,14 @@ static struct bt_gatt_attr attrs[] = {
read_manuf, NULL, "Manufacturer"), read_manuf, NULL, "Manufacturer"),
}; };
static const struct bt_eir ad[] = { static const struct bt_data ad[] = {
{ BT_DATA(BT_DATA_FLAGS,
.len = 2, BT_BYTES(BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR), 1),
.type = BT_EIR_FLAGS, BT_DATA(BT_DATA_UUID16_ALL, BT_BYTES(0x20, 0x18), 3),
.data = { BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR },
},
{
.len = 3,
.type = BT_EIR_UUID16_ALL,
.data = { 0x20, 0x18 },
},
{ }
}; };
static const struct bt_eir sd[] = { static const struct bt_data sd[] = {
{ BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
.len = 15,
.type = BT_EIR_NAME_COMPLETE,
.data = DEVICE_NAME,
},
{ }
}; };
static void connected(struct bt_conn *conn) static void connected(struct bt_conn *conn)
@ -270,7 +258,8 @@ void main(void)
net_init(); net_init();
err = bt_le_adv_start(BT_LE_ADV(BT_LE_ADV_IND), ad, sd); err = bt_le_adv_start(BT_LE_ADV(BT_LE_ADV_IND), ad, ARRAY_SIZE(ad),
sd, ARRAY_SIZE(sd));
if (err) { if (err) {
printk("Advertising failed to start (err %d)\n", err); printk("Advertising failed to start (err %d)\n", err);
return; return;

View file

@ -33,6 +33,7 @@
#define CONFIG_BLUETOOTH_MAX_PAIRED 1 #define CONFIG_BLUETOOTH_MAX_PAIRED 1
#define DEVICE_NAME "Test peripheral" #define DEVICE_NAME "Test peripheral"
#define DEVICE_NAME_LEN 15
#define HEART_RATE_APPEARANCE 0x0341 #define HEART_RATE_APPEARANCE 0x0341
static int read_name(struct bt_conn *conn, const struct bt_gatt_attr *attr, static int read_name(struct bt_conn *conn, const struct bt_gatt_attr *attr,
@ -381,33 +382,18 @@ static struct bt_gatt_attr attrs[] = {
read_signed, write_signed, &signed_value), read_signed, write_signed, &signed_value),
}; };
static const struct bt_eir ad[] = { static const struct bt_data ad[] = {
{ BT_DATA(BT_DATA_FLAGS,
.len = 2, BT_BYTES(BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR), 1),
.type = BT_EIR_FLAGS, BT_DATA(BT_DATA_UUID16_ALL,
.data = { BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR }, BT_BYTES(0x0d, 0x18, 0x0f, 0x18, 0x05, 0x18), 6),
}, BT_DATA(BT_DATA_UUID128_ALL,
{ BT_BYTES(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
.len = 7, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12), 16),
.type = BT_EIR_UUID16_ALL,
.data = { 0x0d, 0x18, 0x0f, 0x18, 0x05, 0x18 },
},
{
.len = 17,
.type = BT_EIR_UUID128_ALL,
.data = { 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12 },
},
{ }
}; };
static const struct bt_eir sd[] = { static const struct bt_data sd[] = {
{ BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
.len = 16,
.type = BT_EIR_NAME_COMPLETE,
.data = DEVICE_NAME,
},
{ }
}; };
static void connected(struct bt_conn *conn) static void connected(struct bt_conn *conn)
@ -434,7 +420,8 @@ static void bt_ready(int err)
printk("Bluetooth initialized\n"); printk("Bluetooth initialized\n");
err = bt_le_adv_start(BT_LE_ADV(BT_LE_ADV_IND), ad, sd); err = bt_le_adv_start(BT_LE_ADV(BT_LE_ADV_IND), ad, ARRAY_SIZE(ad),
sd, ARRAY_SIZE(sd));
if (err) { if (err) {
printk("Advertising failed to start (err %d)\n", err); printk("Advertising failed to start (err %d)\n", err);
return; return;

View file

@ -31,6 +31,7 @@
#include <bluetooth/gatt.h> #include <bluetooth/gatt.h>
#define DEVICE_NAME "Test peripheral" #define DEVICE_NAME "Test peripheral"
#define DEVICE_NAME_LEN 15
#define HEART_RATE_APPEARANCE 0x0341 #define HEART_RATE_APPEARANCE 0x0341
static int read_name(struct bt_conn *conn, const struct bt_gatt_attr *attr, static int read_name(struct bt_conn *conn, const struct bt_gatt_attr *attr,
@ -379,33 +380,18 @@ static struct bt_gatt_attr attrs[] = {
read_signed, write_signed, &signed_value), read_signed, write_signed, &signed_value),
}; };
static const struct bt_eir ad[] = { static const struct bt_data ad[] = {
{ BT_DATA(BT_DATA_FLAGS,
.len = 2, BT_BYTES(BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR), 1),
.type = BT_EIR_FLAGS, BT_DATA(BT_DATA_UUID16_ALL,
.data = { BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR }, BT_BYTES(0x0d, 0x18, 0x0f, 0x18, 0x05, 0x18), 6),
}, BT_DATA(BT_DATA_UUID128_ALL,
{ BT_BYTES(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
.len = 7, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12), 16),
.type = BT_EIR_UUID16_ALL,
.data = { 0x0d, 0x18, 0x0f, 0x18, 0x05, 0x18 },
},
{
.len = 17,
.type = BT_EIR_UUID128_ALL,
.data = { 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12 },
},
{ }
}; };
static const struct bt_eir sd[] = { static const struct bt_data sd[] = {
{ BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
.len = 16,
.type = BT_EIR_NAME_COMPLETE,
.data = DEVICE_NAME,
},
{ }
}; };
static void connected(struct bt_conn *conn) static void connected(struct bt_conn *conn)
@ -432,7 +418,8 @@ static void bt_ready(int err)
printk("Bluetooth initialized\n"); printk("Bluetooth initialized\n");
err = bt_le_adv_start(BT_LE_ADV(BT_LE_ADV_IND), ad, sd); err = bt_le_adv_start(BT_LE_ADV(BT_LE_ADV_IND), ad, ARRAY_SIZE(ad),
sd, ARRAY_SIZE(sd));
if (err) { if (err) {
printk("Advertising failed to start (err %d)\n", err); printk("Advertising failed to start (err %d)\n", err);
return; return;

View file

@ -31,6 +31,7 @@
#include <bluetooth/gatt.h> #include <bluetooth/gatt.h>
#define DEVICE_NAME "DIS peripheral" #define DEVICE_NAME "DIS peripheral"
#define DEVICE_NAME_LEN 14
#define APPEARANCE 0x0000 #define APPEARANCE 0x0000
static int read_appearance(struct bt_conn *conn, static int read_appearance(struct bt_conn *conn,
@ -71,27 +72,14 @@ static struct bt_gatt_attr attrs[] = {
read_string, NULL, "Manufacturer"), read_string, NULL, "Manufacturer"),
}; };
static const struct bt_eir ad[] = { static const struct bt_data ad[] = {
{ BT_DATA(BT_DATA_FLAGS,
.len = 2, BT_BYTES(BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR), 1),
.type = BT_EIR_FLAGS, BT_DATA(BT_DATA_UUID16_ALL, BT_BYTES(0x0a, 0x18), 2),
.data = { BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR },
},
{
.len = 3,
.type = BT_EIR_UUID16_ALL,
.data = { 0x0a, 0x18 },
},
{ }
}; };
static const struct bt_eir sd[] = { static const struct bt_data sd[] = {
{ BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
.len = 15,
.type = BT_EIR_NAME_COMPLETE,
.data = DEVICE_NAME,
},
{ }
}; };
static void connected(struct bt_conn *conn) static void connected(struct bt_conn *conn)
@ -129,7 +117,8 @@ void main(void)
bt_conn_cb_register(&conn_callbacks); bt_conn_cb_register(&conn_callbacks);
err = bt_le_adv_start(BT_LE_ADV(BT_LE_ADV_IND), ad, sd); err = bt_le_adv_start(BT_LE_ADV(BT_LE_ADV_IND), ad, ARRAY_SIZE(ad),
sd, ARRAY_SIZE(sd));
if (err) { if (err) {
printk("Advertising failed to start (err %d)\n", err); printk("Advertising failed to start (err %d)\n", err);
return; return;

View file

@ -31,6 +31,7 @@
#include <bluetooth/gatt.h> #include <bluetooth/gatt.h>
#define DEVICE_NAME "SC only peripheral" #define DEVICE_NAME "SC only peripheral"
#define DEVICE_NAME_LEN 18
#define APPEARANCE 0x0000 #define APPEARANCE 0x0000
static int read_appearance(struct bt_conn *conn, static int read_appearance(struct bt_conn *conn,
@ -62,22 +63,13 @@ static struct bt_gatt_attr attrs[] = {
read_appearance, NULL, NULL), read_appearance, NULL, NULL),
}; };
static const struct bt_eir ad[] = { static const struct bt_data ad[] = {
{ BT_DATA(BT_DATA_FLAGS,
.len = 2, BT_BYTES(BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR), 1)
.type = BT_EIR_FLAGS,
.data = { BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR },
},
{ }
}; };
static const struct bt_eir sd[] = { static const struct bt_data sd[] = {
{ BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
.len = 18,
.type = BT_EIR_NAME_COMPLETE,
.data = DEVICE_NAME,
},
{ }
}; };
static void connected(struct bt_conn *conn) static void connected(struct bt_conn *conn)
@ -175,7 +167,8 @@ void main(void)
bt_auth_cb_register(&auth_cb_display); bt_auth_cb_register(&auth_cb_display);
bt_conn_cb_register(&conn_callbacks); bt_conn_cb_register(&conn_callbacks);
err = bt_le_adv_start(BT_LE_ADV(BT_LE_ADV_IND), ad, sd); err = bt_le_adv_start(BT_LE_ADV(BT_LE_ADV_IND), ad, ARRAY_SIZE(ad),
sd, ARRAY_SIZE(sd));
if (err) { if (err) {
printk("Advertising failed to start (err %d)\n", err); printk("Advertising failed to start (err %d)\n", err);
return; return;

View file

@ -37,7 +37,8 @@
#include <misc/shell.h> #include <misc/shell.h>
#define DEVICE_NAME "test shell" #define DEVICE_NAME "test shell"
#define DEVICE_NAME_LEN 10
#define AD_SHORT_NAME 0x08 #define AD_SHORT_NAME 0x08
#define AD_COMPLETE_NAME 0x09 #define AD_COMPLETE_NAME 0x09
#define CREDITS 10 #define CREDITS 10
@ -489,30 +490,20 @@ static void cmd_gatt_exchange_mtu(int argc, char *argv[])
} }
} }
static const struct bt_eir ad_discov[] = { static const struct bt_data ad_discov[] = {
{ BT_DATA(BT_DATA_FLAGS,
.len = 2, BT_BYTES(BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR), 1),
.type = BT_EIR_FLAGS,
.data = { BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR },
},
{ }
}; };
static const struct bt_eir ad_non_discov[] = { { 0 } }; static const struct bt_data sd[] = {
BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
static const struct bt_eir sd[] = {
{
.len = sizeof(DEVICE_NAME),
.type = BT_EIR_NAME_COMPLETE,
.data = DEVICE_NAME,
},
{ }
}; };
static void cmd_advertise(int argc, char *argv[]) static void cmd_advertise(int argc, char *argv[])
{ {
struct bt_le_adv_param param; struct bt_le_adv_param param;
const struct bt_eir *ad, *scan_rsp; const struct bt_data *ad, *scan_rsp;
size_t ad_len, scan_rsp_len;
if (argc < 2) { if (argc < 2) {
goto fail; goto fail;
@ -535,14 +526,17 @@ static void cmd_advertise(int argc, char *argv[])
param.type = BT_LE_ADV_IND; param.type = BT_LE_ADV_IND;
param.addr_type = BT_LE_ADV_ADDR_PUBLIC; param.addr_type = BT_LE_ADV_ADDR_PUBLIC;
scan_rsp = sd; scan_rsp = sd;
scan_rsp_len = ARRAY_SIZE(sd);
} else if (!strcmp(argv[1], "scan")) { } else if (!strcmp(argv[1], "scan")) {
param.type = BT_LE_ADV_SCAN_IND; param.type = BT_LE_ADV_SCAN_IND;
param.addr_type = BT_LE_ADV_ADDR_PUBLIC; param.addr_type = BT_LE_ADV_ADDR_PUBLIC;
scan_rsp = sd; scan_rsp = sd;
scan_rsp_len = ARRAY_SIZE(sd);
} else if (!strcmp(argv[1], "nconn")) { } else if (!strcmp(argv[1], "nconn")) {
param.type = BT_LE_ADV_NONCONN_IND; param.type = BT_LE_ADV_NONCONN_IND;
param.addr_type = BT_LE_ADV_ADDR_NRPA; param.addr_type = BT_LE_ADV_ADDR_NRPA;
scan_rsp = NULL; scan_rsp = NULL;
scan_rsp_len = 0;
} else { } else {
goto fail; goto fail;
} }
@ -553,16 +547,19 @@ static void cmd_advertise(int argc, char *argv[])
if (!strcmp(mode, "discov")) { if (!strcmp(mode, "discov")) {
ad = ad_discov; ad = ad_discov;
ad_len = ARRAY_SIZE(ad_discov);
} else if (!strcmp(mode, "non_discov")) { } else if (!strcmp(mode, "non_discov")) {
ad = ad_non_discov; ad = NULL;
ad_len = 0;
} else { } else {
goto fail; goto fail;
} }
} else { } else {
ad = ad_discov; ad = ad_discov;
ad_len = ARRAY_SIZE(ad_discov);
} }
if (bt_le_adv_start(&param, ad, scan_rsp) < 0) { if (bt_le_adv_start(&param, ad, ad_len, scan_rsp, scan_rsp_len) < 0) {
printk("Failed to start advertising\n"); printk("Failed to start advertising\n");
} else { } else {
printk("Advertising started\n"); printk("Advertising started\n");

View file

@ -143,31 +143,27 @@ static void set_connectable(uint8_t *data, uint16_t len)
(uint8_t *) &rp, sizeof(rp)); (uint8_t *) &rp, sizeof(rp));
} }
static struct bt_eir ad_flags = { static uint8_t ad_flags = BT_LE_AD_NO_BREDR;
.len = 2, static struct bt_data ad = BT_DATA(BT_DATA_FLAGS, &ad_flags, sizeof(ad_flags));
.type = BT_EIR_FLAGS,
.data = { BT_LE_AD_NO_BREDR },
};
static void set_discoverable(uint8_t *data, uint16_t len) static void set_discoverable(uint8_t *data, uint16_t len)
{ {
const struct gap_set_discoverable_cmd *cmd = (void *) data; const struct gap_set_discoverable_cmd *cmd = (void *) data;
struct gap_set_discoverable_rp rp; struct gap_set_discoverable_rp rp;
uint8_t *flags = &ad_flags.data[0];
switch (cmd->discoverable) { switch (cmd->discoverable) {
case GAP_NON_DISCOVERABLE: case GAP_NON_DISCOVERABLE:
*flags &= ~(BT_LE_AD_GENERAL | BT_LE_AD_LIMITED); ad_flags &= ~(BT_LE_AD_GENERAL | BT_LE_AD_LIMITED);
atomic_clear_bit(&current_settings, GAP_SETTINGS_DISCOVERABLE); atomic_clear_bit(&current_settings, GAP_SETTINGS_DISCOVERABLE);
break; break;
case GAP_GENERAL_DISCOVERABLE: case GAP_GENERAL_DISCOVERABLE:
*flags &= ~BT_LE_AD_LIMITED; ad_flags &= ~BT_LE_AD_LIMITED;
*flags |= BT_LE_AD_GENERAL; ad_flags |= BT_LE_AD_GENERAL;
atomic_set_bit(&current_settings, GAP_SETTINGS_DISCOVERABLE); atomic_set_bit(&current_settings, GAP_SETTINGS_DISCOVERABLE);
break; break;
case GAP_LIMITED_DISCOVERABLE: case GAP_LIMITED_DISCOVERABLE:
*flags &= ~BT_LE_AD_GENERAL; ad_flags &= ~BT_LE_AD_GENERAL;
*flags |= BT_LE_AD_LIMITED; ad_flags |= BT_LE_AD_LIMITED;
atomic_set_bit(&current_settings, GAP_SETTINGS_DISCOVERABLE); atomic_set_bit(&current_settings, GAP_SETTINGS_DISCOVERABLE);
break; break;
default: default:
@ -187,7 +183,6 @@ static void start_advertising(const uint8_t *data, uint16_t len)
const struct gap_start_advertising_cmd *cmd = (void *) data; const struct gap_start_advertising_cmd *cmd = (void *) data;
struct gap_start_advertising_rp rp; struct gap_start_advertising_rp rp;
uint8_t adv_type; uint8_t adv_type;
struct bt_eir ad_data[] = { ad_flags };
/* TODO /* TODO
* convert adv_data and scan_rsp and pass them * convert adv_data and scan_rsp and pass them
@ -200,7 +195,7 @@ static void start_advertising(const uint8_t *data, uint16_t len)
adv_type = BT_LE_ADV_NONCONN_IND; adv_type = BT_LE_ADV_NONCONN_IND;
} }
if (bt_le_adv_start(BT_LE_ADV(adv_type), ad_data, NULL) < 0) { if (bt_le_adv_start(BT_LE_ADV(adv_type), &ad, 1, NULL, 0) < 0) {
tester_rsp(BTP_SERVICE_ID_GAP, GAP_START_ADVERTISING, tester_rsp(BTP_SERVICE_ID_GAP, GAP_START_ADVERTISING,
CONTROLLER_INDEX, BTP_STATUS_FAILED); CONTROLLER_INDEX, BTP_STATUS_FAILED);
return; return;