From dd5d2e37f5646698c8c4eaa85382c87b30344bd0 Mon Sep 17 00:00:00 2001 From: Marcio Montenegro Date: Fri, 20 Sep 2019 10:01:18 -0300 Subject: [PATCH] Samples: Bluetooth: Add ST BLE Demo sample This sample demonstrates BLE peripheral for ST BLE Sensor. You can test button notification and LED service using ST BLE Sensor Android application Signed-off-by: Marcio Montenegro --- .../bluetooth/st_ble_sensor/CMakeLists.txt | 12 ++ samples/bluetooth/st_ble_sensor/README.rst | 41 ++++ samples/bluetooth/st_ble_sensor/prj.conf | 8 + samples/bluetooth/st_ble_sensor/sample.yaml | 8 + .../bluetooth/st_ble_sensor/src/button_svc.c | 81 ++++++++ .../bluetooth/st_ble_sensor/src/button_svc.h | 19 ++ samples/bluetooth/st_ble_sensor/src/led_svc.c | 49 +++++ samples/bluetooth/st_ble_sensor/src/led_svc.h | 20 ++ samples/bluetooth/st_ble_sensor/src/main.c | 192 ++++++++++++++++++ 9 files changed, 430 insertions(+) create mode 100644 samples/bluetooth/st_ble_sensor/CMakeLists.txt create mode 100644 samples/bluetooth/st_ble_sensor/README.rst create mode 100644 samples/bluetooth/st_ble_sensor/prj.conf create mode 100644 samples/bluetooth/st_ble_sensor/sample.yaml create mode 100644 samples/bluetooth/st_ble_sensor/src/button_svc.c create mode 100644 samples/bluetooth/st_ble_sensor/src/button_svc.h create mode 100644 samples/bluetooth/st_ble_sensor/src/led_svc.c create mode 100644 samples/bluetooth/st_ble_sensor/src/led_svc.h create mode 100644 samples/bluetooth/st_ble_sensor/src/main.c diff --git a/samples/bluetooth/st_ble_sensor/CMakeLists.txt b/samples/bluetooth/st_ble_sensor/CMakeLists.txt new file mode 100644 index 00000000000..6ea9a297e7a --- /dev/null +++ b/samples/bluetooth/st_ble_sensor/CMakeLists.txt @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.13.1) +include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) +project(st_ble_sensor) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE + ${app_sources} + ) + +zephyr_library_include_directories($ENV{ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/st_ble_sensor/README.rst b/samples/bluetooth/st_ble_sensor/README.rst new file mode 100644 index 00000000000..9f42ee480be --- /dev/null +++ b/samples/bluetooth/st_ble_sensor/README.rst @@ -0,0 +1,41 @@ +.. _bluetooth-st_ble_sensor: + +Bluetooth: ST BLE Sensor Demo +############################# + +Overview +******** + +This application demonstrates BLE peripheral by exposing vendor-specific +GATT services. Currently only button notification and LED service are +implemented. Other BLE sensor services can easily be added. +See `BlueST protocol`_ document for details of how to add a new service. + +Requirements +************ + +* `ST BLE Sensor Android app `_ +* A board with BLE support + +Building and Running +******************** + +This sample can be found under :zephyr_file:`samples/bluetooth/st_ble_sensor` in the +Zephyr tree. + +See :ref:`bluetooth samples section ` for details. + +.. _ST BLE Sensor app: + https://play.google.com/store/apps/details?id=com.st.bluems + +.. _ST Nucleo WB55RG: + https://www.st.com/en/microcontrollers-microprocessors/stm32wb55rg.html + +.. _STM32CubeProgrammer: + https://www.st.com/en/development-tools/stm32cubeprog.html + +.. _BlueST protocol: + https://www.st.com/resource/en/user_manual/dm00550659.pdf + +.. _STM32WB github: + https://github.com/STMicroelectronics/STM32CubeWB/tree/master/Projects/STM32WB_Copro_Wireless_Binaries diff --git a/samples/bluetooth/st_ble_sensor/prj.conf b/samples/bluetooth/st_ble_sensor/prj.conf new file mode 100644 index 00000000000..3c652415b62 --- /dev/null +++ b/samples/bluetooth/st_ble_sensor/prj.conf @@ -0,0 +1,8 @@ +CONFIG_BT=y +CONFIG_BT_DEBUG_LOG=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_DEVICE_NAME="P2PSRV1" +CONFIG_BT_GATT_CLIENT=y +CONFIG_BT_DEBUG=y +CONFIG_LOG=y +CONFIG_LOG_BUFFER_SIZE=2048 diff --git a/samples/bluetooth/st_ble_sensor/sample.yaml b/samples/bluetooth/st_ble_sensor/sample.yaml new file mode 100644 index 00000000000..bae9841b597 --- /dev/null +++ b/samples/bluetooth/st_ble_sensor/sample.yaml @@ -0,0 +1,8 @@ +sample: + description: TBD + name: TBD +tests: + sample.bluetooth.st_ble_sensor: + harness: bluetooth + platform_whitelist: nucleo_wb55rg + tags: bluetooth diff --git a/samples/bluetooth/st_ble_sensor/src/button_svc.c b/samples/bluetooth/st_ble_sensor/src/button_svc.c new file mode 100644 index 00000000000..98edeca9387 --- /dev/null +++ b/samples/bluetooth/st_ble_sensor/src/button_svc.c @@ -0,0 +1,81 @@ +/** @file + * @brief Button Service sample + */ + +/* + * Copyright (c) 2019 Marcio Montenegro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "button_svc.h" + +LOG_MODULE_REGISTER(button_svc); + +#define BUT_PORT DT_ALIAS_SW0_GPIOS_CONTROLLER +#define BUT_PIN DT_ALIAS_SW0_GPIOS_PIN + +extern struct bt_conn *conn; +extern struct bt_gatt_service_static stsensor_svc[]; +extern volatile bool notify_enable; + +static struct device *button_dev; +static struct gpio_callback gpio_cb; +u16_t but_val; + +void button_pressed(struct device *gpiob, struct gpio_callback *cb, + u32_t pins) +{ + int err; + + LOG_INF("Button SW1 pressed"); + if (conn) { + if (notify_enable) { + err = bt_gatt_notify(NULL, &stsensor_svc->attrs[2], + &but_val, sizeof(but_val)); + if (err) { + LOG_ERR("Notify error: %d", err); + } else { + LOG_INF("Send notify ok"); + but_val = (but_val == 0) ? 0x100 : 0; + } + } else { + LOG_INF("Notify not enabled"); + } + } else { + LOG_INF("BLE not connected"); + } +} + +int button_init(void) +{ + button_dev = device_get_binding(BUT_PORT); + if (!button_dev) { + return (-EOPNOTSUPP); + } + + gpio_pin_configure(button_dev, BUT_PIN, + GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | + GPIO_PUD_PULL_UP | GPIO_INT_DEBOUNCE | + GPIO_INT_ACTIVE_LOW); + gpio_init_callback(&gpio_cb, button_pressed, BIT(BUT_PIN)); + gpio_add_callback(button_dev, &gpio_cb); + gpio_pin_enable_callback(button_dev, BUT_PIN); + but_val = 0; + return 0; +} diff --git a/samples/bluetooth/st_ble_sensor/src/button_svc.h b/samples/bluetooth/st_ble_sensor/src/button_svc.h new file mode 100644 index 00000000000..a0c96f0b258 --- /dev/null +++ b/samples/bluetooth/st_ble_sensor/src/button_svc.h @@ -0,0 +1,19 @@ +/** @file + * @brief Button Service + */ + +/* + * Copyright (c) 2019 Marcio Montenegro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifdef __cplusplus +extern "C" { +#endif + +int button_init(void); + +#ifdef __cplusplus +} +#endif diff --git a/samples/bluetooth/st_ble_sensor/src/led_svc.c b/samples/bluetooth/st_ble_sensor/src/led_svc.c new file mode 100644 index 00000000000..25ef73de0a3 --- /dev/null +++ b/samples/bluetooth/st_ble_sensor/src/led_svc.c @@ -0,0 +1,49 @@ +/** @file + * @brief Button Service sample + */ + +/* + * Copyright (c) 2019 Marcio Montenegro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(led_svc); + +#define LED_PORT DT_ALIAS_LED0_GPIOS_CONTROLLER +#define LED DT_ALIAS_LED0_GPIOS_PIN + +struct device *led_dev; +bool led_state; + +void led_on_off(u32_t led_state) +{ + if (led_dev) { + gpio_pin_write(led_dev, LED, led_state); + } +} + +int led_init(void) +{ + led_dev = device_get_binding(LED_PORT); + if (!led_dev) { + return (-EOPNOTSUPP); + } + + /* Set LED pin as output */ + gpio_pin_configure(led_dev, LED, GPIO_DIR_OUT); + led_state = false; + gpio_pin_write(led_dev, LED, 0); + led_on_off(0); + return 0; +} diff --git a/samples/bluetooth/st_ble_sensor/src/led_svc.h b/samples/bluetooth/st_ble_sensor/src/led_svc.h new file mode 100644 index 00000000000..ccf1476d316 --- /dev/null +++ b/samples/bluetooth/st_ble_sensor/src/led_svc.h @@ -0,0 +1,20 @@ +/** @file + * @brief LED Service sample + */ + +/* + * Copyright (c) 2019 Marcio Montenegro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifdef __cplusplus +extern "C" { +#endif + +void led_on_off(u32_t led_state); +int led_init(void); + +#ifdef __cplusplus +} +#endif diff --git a/samples/bluetooth/st_ble_sensor/src/main.c b/samples/bluetooth/st_ble_sensor/src/main.c new file mode 100644 index 00000000000..2efde5335ea --- /dev/null +++ b/samples/bluetooth/st_ble_sensor/src/main.c @@ -0,0 +1,192 @@ +/* main.c - Application main entry point */ + +/* + * Copyright (c) 2015-2016 Intel Corporation + * Copyright (c) 2019 Marcio Montenegro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "button_svc.h" +#include "led_svc.h" + +LOG_MODULE_REGISTER(main); + +extern u16_t but_val; +extern struct device *led_dev; +extern bool led_state; + +/* Prototype */ +static ssize_t recv(struct bt_conn *conn, + const struct bt_gatt_attr *attr, const void *buf, + u16_t len, u16_t offset, u8_t flags); + +/* ST Custom Service */ +static struct bt_uuid_128 st_service_uuid = BT_UUID_INIT_128( + 0x8f, 0xe5, 0xb3, 0xd5, 0x2e, 0x7f, 0x4a, 0x98, + 0x2a, 0x48, 0x7a, 0xcc, 0x40, 0xfe, 0x00, 0x00); + +/* ST LED service */ +static struct bt_uuid_128 led_char_uuid = BT_UUID_INIT_128( + 0x19, 0xed, 0x82, 0xae, 0xed, 0x21, 0x4c, 0x9d, + 0x41, 0x45, 0x22, 0x8e, 0x41, 0xfe, 0x00, 0x00); + +/* ST Notify button service */ +static struct bt_uuid_128 but_notif_uuid = BT_UUID_INIT_128( + 0x19, 0xed, 0x82, 0xae, 0xed, 0x21, 0x4c, 0x9d, + 0x41, 0x45, 0x22, 0x8e, 0x42, 0xfe, 0x00, 0x00); + +#define DEVICE_NAME CONFIG_BT_DEVICE_NAME +#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1) +#define ADV_LEN 12 + +/* Advertising data */ +static u8_t manuf_data[ADV_LEN] = { + 0x01 /*SKD version */, + 0x83 /* STM32WB - P2P Server 1 */, + 0x00 /* GROUP A Feature */, + 0x00 /* GROUP A Feature */, + 0x00 /* GROUP B Feature */, + 0x00 /* GROUP B Feature */, + 0x00, /* BLE MAC start -MSB */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, /* BLE MAC stop */ +}; + +static const struct bt_data ad[] = { + BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), + BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN), + BT_DATA(BT_DATA_MANUFACTURER_DATA, manuf_data, ADV_LEN) +}; + +/* BLE connection */ +struct bt_conn *conn; +/* Notification state */ +volatile bool notify_enable; + +static void mpu_ccc_cfg_changed(const struct bt_gatt_attr *attr, u16_t value) +{ + ARG_UNUSED(attr); + notify_enable = (value == BT_GATT_CCC_NOTIFY); + LOG_INF("Notification %s", notify_enable ? "enabled" : "disabled"); +} + +/* The embedded board is acting as GATT server. + * The ST BLE Android app is the BLE GATT client. + */ + +/* ST BLE Sensor GATT services and characteristic */ + +BT_GATT_SERVICE_DEFINE(stsensor_svc, +BT_GATT_PRIMARY_SERVICE(&st_service_uuid), +BT_GATT_CHARACTERISTIC(&led_char_uuid.uuid, + BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE_WITHOUT_RESP, + BT_GATT_PERM_WRITE, NULL, recv, (void *)1), +BT_GATT_CHARACTERISTIC(&but_notif_uuid.uuid, BT_GATT_CHRC_NOTIFY, + BT_GATT_PERM_READ, NULL, NULL, &but_val), +BT_GATT_CCC(mpu_ccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE), +); + +static ssize_t recv(struct bt_conn *conn, + const struct bt_gatt_attr *attr, const void *buf, + u16_t len, u16_t offset, u8_t flags) +{ + if (led_dev) { + if (led_state == true) { + led_on_off(0); + LOG_INF("Turn off LED"); + } else { + led_on_off(1); + LOG_INF("Turn on LED"); + } + + led_state = !led_state; + } + + return 0; +} + +static void bt_ready(int err) +{ + if (err) { + LOG_ERR("Bluetooth init failed (err %d)", err); + return; + } + LOG_INF("Bluetooth initialized"); + /* Start advertising */ + err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + if (err) { + LOG_ERR("Advertising failed to start (err %d)", err); + return; + } + + LOG_INF("Configuration mode: waiting connections..."); +} + +static void connected(struct bt_conn *connected, u8_t err) +{ + if (err) { + LOG_ERR("Connection failed (err %u)", err); + } else { + LOG_INF("Connected"); + if (!conn) { + conn = bt_conn_ref(connected); + } + } +} + +static void disconnected(struct bt_conn *disconn, u8_t reason) +{ + if (conn) { + bt_conn_unref(conn); + conn = NULL; + } + + LOG_INF("Disconnected (reason %u)", reason); +} + +static struct bt_conn_cb conn_callbacks = { + .connected = connected, + .disconnected = disconnected, +}; + +void main(void) +{ + int err; + + err = button_init(); + if (err) { + LOG_ERR("Button init error: (err %d)", err); + } + + led_init(); + bt_conn_cb_register(&conn_callbacks); + + /* Initialize the Bluetooth Subsystem */ + err = bt_enable(bt_ready); + if (err) { + LOG_ERR("Bluetooth init failed (err %d)", err); + } + + while (1) { + k_sleep(K_SECONDS(1)); + } +}