summaryrefslogtreecommitdiff
path: root/samples
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2016-02-05 14:24:57 +0200
committerAnas Nashif <anas.nashif@intel.com>2016-02-10 19:12:55 -0500
commit2b7a5229f2fa2d7403e1be38edde461b3eab507c (patch)
treedfc9c86378d251b17dc52b3060d96774891fd350 /samples
parent843268d78dd1a6d9597a3072fd42242b94c51d07 (diff)
Bluetooth: samples: Add dedicated Heartrate peripheral sample app
This can be used to focus on demonstrating a simple heartrate service. Change-Id: Ib59c653ebe356784592c8468767b45c5240ec67a Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Anas Nashif <anas.nashif@intel.com>
Diffstat (limited to 'samples')
-rw-r--r--samples/bluetooth/peripheral_hr/Makefile7
-rw-r--r--samples/bluetooth/peripheral_hr/README4
-rw-r--r--samples/bluetooth/peripheral_hr/prj.conf9
-rw-r--r--samples/bluetooth/peripheral_hr/prj.mdef5
-rw-r--r--samples/bluetooth/peripheral_hr/prj_nble.conf4
-rw-r--r--samples/bluetooth/peripheral_hr/src/Makefile1
-rw-r--r--samples/bluetooth/peripheral_hr/src/main.c268
-rw-r--r--samples/bluetooth/peripheral_hr/testcase.ini20
8 files changed, 318 insertions, 0 deletions
diff --git a/samples/bluetooth/peripheral_hr/Makefile b/samples/bluetooth/peripheral_hr/Makefile
new file mode 100644
index 000000000..fdc0101e3
--- /dev/null
+++ b/samples/bluetooth/peripheral_hr/Makefile
@@ -0,0 +1,7 @@
+BOARD ?= qemu_x86
+MDEF_FILE = prj.mdef
+KERNEL_TYPE = micro
+CONF_FILE ?= prj.conf
+QEMU_EXTRA_FLAGS = -serial unix:/tmp/bt-server-bredr
+
+include $(ZEPHYR_BASE)/Makefile.inc
diff --git a/samples/bluetooth/peripheral_hr/README b/samples/bluetooth/peripheral_hr/README
new file mode 100644
index 000000000..a09758188
--- /dev/null
+++ b/samples/bluetooth/peripheral_hr/README
@@ -0,0 +1,4 @@
+For building shell with Nordic Bluetooth Low Energy stack (NBLE)
+use prj_nble.conf:
+
+$ make CONF_FILE=prj_nble.conf BOARD=arduino_101
diff --git a/samples/bluetooth/peripheral_hr/prj.conf b/samples/bluetooth/peripheral_hr/prj.conf
new file mode 100644
index 000000000..f86a01fd7
--- /dev/null
+++ b/samples/bluetooth/peripheral_hr/prj.conf
@@ -0,0 +1,9 @@
+CONFIG_TEST_RANDOM_GENERATOR=y
+CONFIG_BLUETOOTH=y
+CONFIG_BLUETOOTH_LE=y
+CONFIG_BLUETOOTH_DEBUG=y
+CONFIG_BLUETOOTH_SMP=y
+CONFIG_TINYCRYPT=y
+CONFIG_TINYCRYPT_AES=y
+CONFIG_BLUETOOTH_PERIPHERAL=y
+CONFIG_BLUETOOTH_GATT_DYNAMIC_DB=y
diff --git a/samples/bluetooth/peripheral_hr/prj.mdef b/samples/bluetooth/peripheral_hr/prj.mdef
new file mode 100644
index 000000000..a1bef7a2d
--- /dev/null
+++ b/samples/bluetooth/peripheral_hr/prj.mdef
@@ -0,0 +1,5 @@
+% Application : Bluetooth heartrate peripheral sample
+
+% TASK NAME PRIO ENTRY STACK GROUPS
+% ===================================================
+ TASK MAIN 7 mainloop 2048 [EXE]
diff --git a/samples/bluetooth/peripheral_hr/prj_nble.conf b/samples/bluetooth/peripheral_hr/prj_nble.conf
new file mode 100644
index 000000000..ef0af4e30
--- /dev/null
+++ b/samples/bluetooth/peripheral_hr/prj_nble.conf
@@ -0,0 +1,4 @@
+CONFIG_TEST_RANDOM_GENERATOR=y
+CONFIG_NBLE=y
+CONFIG_ARC_INIT=n
+CONFIG_BLUETOOTH_DEBUG=y
diff --git a/samples/bluetooth/peripheral_hr/src/Makefile b/samples/bluetooth/peripheral_hr/src/Makefile
new file mode 100644
index 000000000..00066e156
--- /dev/null
+++ b/samples/bluetooth/peripheral_hr/src/Makefile
@@ -0,0 +1 @@
+obj-y = main.o
diff --git a/samples/bluetooth/peripheral_hr/src/main.c b/samples/bluetooth/peripheral_hr/src/main.c
new file mode 100644
index 000000000..0e08e8fce
--- /dev/null
+++ b/samples/bluetooth/peripheral_hr/src/main.c
@@ -0,0 +1,268 @@
+/* main.c - Application main entry point */
+
+/*
+ * Copyright (c) 2015 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+#include <errno.h>
+#include <misc/printk.h>
+#include <misc/byteorder.h>
+#include <zephyr.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/uuid.h>
+#include <bluetooth/gatt.h>
+
+#define DEVICE_NAME "Heartrate Monitor"
+#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
+#define HEART_RATE_APPEARANCE 0x0341
+
+static int read_name(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+ void *buf, uint16_t len, uint16_t offset)
+{
+ const char *name = attr->user_data;
+
+ return bt_gatt_attr_read(conn, attr, buf, len, offset, name,
+ strlen(name));
+}
+
+static int read_appearance(struct bt_conn *conn,
+ const struct bt_gatt_attr *attr, void *buf,
+ uint16_t len, uint16_t offset)
+{
+ uint16_t appearance = sys_cpu_to_le16(HEART_RATE_APPEARANCE);
+
+ return bt_gatt_attr_read(conn, attr, buf, len, offset, &appearance,
+ sizeof(appearance));
+}
+
+static struct bt_gatt_ccc_cfg hrmc_ccc_cfg[CONFIG_BLUETOOTH_MAX_PAIRED] = {};
+static uint8_t simulate_hrm;
+
+static void hrmc_ccc_cfg_changed(uint16_t value)
+{
+ simulate_hrm = (value == BT_GATT_CCC_NOTIFY) ? 1 : 0;
+}
+
+static int read_blsc(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+ void *buf, uint16_t len, uint16_t offset)
+{
+ uint8_t value = 0x01;
+
+ return bt_gatt_attr_read(conn, attr, buf, len, offset, &value,
+ sizeof(value));
+}
+
+static struct bt_gatt_ccc_cfg blvl_ccc_cfg[CONFIG_BLUETOOTH_MAX_PAIRED] = {};
+static uint8_t simulate_blvl;
+static uint8_t battery = 100;
+
+static void blvl_ccc_cfg_changed(uint16_t value)
+{
+ simulate_blvl = (value == BT_GATT_CCC_NOTIFY) ? 1 : 0;
+}
+
+static int read_blvl(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+ void *buf, uint16_t len, uint16_t offset)
+{
+ const char *value = attr->user_data;
+
+ return bt_gatt_attr_read(conn, attr, buf, len, offset, value,
+ sizeof(*value));
+}
+
+static int read_model(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+ void *buf, uint16_t len, uint16_t offset)
+{
+ const char *value = attr->user_data;
+
+ return bt_gatt_attr_read(conn, attr, buf, len, offset, value,
+ strlen(value));
+}
+
+static int read_manuf(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+ void *buf, uint16_t len, uint16_t offset)
+{
+ const char *value = attr->user_data;
+
+ return bt_gatt_attr_read(conn, attr, buf, len, offset, value,
+ strlen(value));
+}
+
+static struct bt_gatt_attr gap_attrs[] = {
+ BT_GATT_PRIMARY_SERVICE(BT_UUID_GAP),
+ BT_GATT_CHARACTERISTIC(BT_UUID_GAP_DEVICE_NAME, BT_GATT_CHRC_READ),
+ BT_GATT_DESCRIPTOR(BT_UUID_GAP_DEVICE_NAME, BT_GATT_PERM_READ,
+ read_name, NULL, DEVICE_NAME),
+ BT_GATT_CHARACTERISTIC(BT_UUID_GAP_APPEARANCE, BT_GATT_CHRC_READ),
+ BT_GATT_DESCRIPTOR(BT_UUID_GAP_APPEARANCE, BT_GATT_PERM_READ,
+ read_appearance, NULL, NULL),
+};
+
+/* Heart Rate Service Declaration */
+static struct bt_gatt_attr hrs_attrs[] = {
+ BT_GATT_PRIMARY_SERVICE(BT_UUID_HRS),
+ BT_GATT_CHARACTERISTIC(BT_UUID_HRS_MEASUREMENT, BT_GATT_CHRC_NOTIFY),
+ BT_GATT_DESCRIPTOR(BT_UUID_HRS_MEASUREMENT, BT_GATT_PERM_READ, NULL,
+ NULL, NULL),
+ BT_GATT_CCC(hrmc_ccc_cfg, hrmc_ccc_cfg_changed),
+ BT_GATT_CHARACTERISTIC(BT_UUID_HRS_BODY_SENSOR, BT_GATT_CHRC_READ),
+ BT_GATT_DESCRIPTOR(BT_UUID_HRS_BODY_SENSOR, BT_GATT_PERM_READ,
+ read_blsc, NULL, NULL),
+ BT_GATT_CHARACTERISTIC(BT_UUID_HRS_CONTROL_POINT, BT_GATT_CHRC_WRITE),
+ /* TODO: Add write permission and callback */
+ BT_GATT_DESCRIPTOR(BT_UUID_HRS_CONTROL_POINT, BT_GATT_PERM_READ, NULL,
+ NULL, NULL),
+};
+
+/* Battery Service Declaration */
+static struct bt_gatt_attr bas_attrs[] = {
+ BT_GATT_PRIMARY_SERVICE(BT_UUID_BAS),
+ BT_GATT_CHARACTERISTIC(BT_UUID_BAS_BATTERY_LEVEL,
+ BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY),
+ BT_GATT_DESCRIPTOR(BT_UUID_BAS_BATTERY_LEVEL, BT_GATT_PERM_READ,
+ read_blvl, NULL, &battery),
+ BT_GATT_CCC(blvl_ccc_cfg, blvl_ccc_cfg_changed),
+};
+
+/* Device Information Service Declaration */
+static struct bt_gatt_attr dis_attrs[] = {
+ BT_GATT_PRIMARY_SERVICE(BT_UUID_DIS),
+ BT_GATT_CHARACTERISTIC(BT_UUID_DIS_MODEL_NUMBER, BT_GATT_CHRC_READ),
+ BT_GATT_DESCRIPTOR(BT_UUID_DIS_MODEL_NUMBER, BT_GATT_PERM_READ,
+ read_model, NULL, CONFIG_SOC),
+ BT_GATT_CHARACTERISTIC(BT_UUID_DIS_MANUFACTURER_NAME,
+ BT_GATT_CHRC_READ),
+ BT_GATT_DESCRIPTOR(BT_UUID_DIS_MANUFACTURER_NAME, BT_GATT_PERM_READ,
+ read_manuf, NULL, "Manufacturer"),
+};
+
+static const struct bt_data ad[] = {
+ BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
+ BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0x0d, 0x18, 0x0f, 0x18, 0x05, 0x18),
+};
+
+static const struct bt_data sd[] = {
+ BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
+};
+
+static void connected(struct bt_conn *conn, uint8_t err)
+{
+ if (err) {
+ printk("Connection failed (err %u)\n", err);
+ } else {
+ printk("Connected\n");
+ }
+}
+
+static void disconnected(struct bt_conn *conn, uint8_t reason)
+{
+ printk("Disconnected (reason %u)\n", reason);
+}
+
+static struct bt_conn_cb conn_callbacks = {
+ .connected = connected,
+ .disconnected = disconnected,
+};
+
+static void bt_ready(int err)
+{
+ if (err) {
+ printk("Bluetooth init failed (err %d)\n", err);
+ return;
+ }
+
+ printk("Bluetooth initialized\n");
+
+ bt_gatt_register(gap_attrs, ARRAY_SIZE(gap_attrs));
+ bt_gatt_register(hrs_attrs, ARRAY_SIZE(hrs_attrs));
+ bt_gatt_register(bas_attrs, ARRAY_SIZE(bas_attrs));
+ bt_gatt_register(dis_attrs, ARRAY_SIZE(dis_attrs));
+
+ err = bt_le_adv_start(BT_LE_ADV(BT_LE_ADV_IND), ad, ARRAY_SIZE(ad),
+ sd, ARRAY_SIZE(sd));
+ if (err) {
+ printk("Advertising failed to start (err %d)\n", err);
+ return;
+ }
+
+ printk("Advertising successfully started\n");
+}
+
+static void auth_cancel(struct bt_conn *conn)
+{
+ char addr[BT_ADDR_LE_STR_LEN];
+
+ bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
+
+ printk("Pairing cancelled: %s\n", addr);
+}
+
+static struct bt_conn_auth_cb auth_cb_display = {
+ .cancel = auth_cancel,
+};
+
+#ifdef CONFIG_MICROKERNEL
+void mainloop(void)
+#else
+void main(void)
+#endif
+{
+ int err;
+
+ err = bt_enable(bt_ready);
+ if (err) {
+ printk("Bluetooth init failed (err %d)\n", err);
+ return;
+ }
+
+ bt_conn_cb_register(&conn_callbacks);
+ bt_conn_auth_cb_register(&auth_cb_display);
+
+ /* Implement notification. At the moment there is no suitable way
+ * of starting delayed work so we do it here
+ */
+ while (1) {
+ static uint8_t hrm[2];
+
+ task_sleep(sys_clock_ticks_per_sec);
+
+ /* Heartrate measurements simulation */
+ if (simulate_hrm) {
+ hrm[0] = 0x06; /* uint8, sensor contact */
+ hrm[1] = 90 + (sys_rand32_get() % 20);
+
+ bt_gatt_notify(NULL, &hrs_attrs[3], &hrm, sizeof(hrm));
+ }
+
+ /* Battery level simulation */
+ if (simulate_blvl) {
+ battery -= 1;
+
+ if (!battery) {
+ /* Software eco battery charger */
+ battery = 100;
+ }
+
+ bt_gatt_notify(NULL, &bas_attrs[3], &battery,
+ sizeof(battery));
+ }
+ }
+}
diff --git a/samples/bluetooth/peripheral_hr/testcase.ini b/samples/bluetooth/peripheral_hr/testcase.ini
new file mode 100644
index 000000000..a88d972fd
--- /dev/null
+++ b/samples/bluetooth/peripheral_hr/testcase.ini
@@ -0,0 +1,20 @@
+[test_x86]
+tags = bluetooth
+build_only = true
+arch_whitelist = x86
+# FIXME Doesn't work for ia32_pci
+config_whitelist = CONFIG_SOC="ia32"
+
+[test_arm]
+tags = bluetooth
+build_only = true
+arch_whitelist = arm
+platform_exclude = arduino_due
+
+[test_nble]
+tags = bluetooth
+build_only = true
+extra_args = CONF_FILE="prj_nble.conf"
+arch_whitelist = x86
+config_whitelist = CONFIG_SOC_QUARK_SE
+platform_whitelist = arduino_101