/* * Copyright (c) 2018 Nordic Semiconductor ASA * * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ /** @file * @brief LED Button Service (LBS) sample */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include LOG_MODULE_REGISTER(bt_lbs, CONFIG_BT_LBS_LOG_LEVEL); static bool notify_enabled; #ifdef CONFIG_BT_LBS_POLL_BUTTON static bool button_state; #endif static struct bt_lbs_cb lbs_cb; static void lbslc_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value) { notify_enabled = (value == BT_GATT_CCC_NOTIFY); } static ssize_t write_led(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, uint16_t len, uint16_t offset, uint8_t flags) { LOG_DBG("Attribute write, handle: %u, conn: %p", attr->handle, (void *)conn); if (len != 1U) { LOG_DBG("Write led: Incorrect data length"); return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN); } if (offset != 0) { LOG_DBG("Write led: Incorrect data offset"); return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET); } if (lbs_cb.led_cb) { uint8_t val = *((uint8_t *)buf); if (val == 0x00 || val == 0x01) { lbs_cb.led_cb(val ? true : false); } else { LOG_DBG("Write led: Incorrect value"); return BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED); } } return len; } #ifdef CONFIG_BT_LBS_POLL_BUTTON static ssize_t read_button(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { const char *value = attr->user_data; LOG_DBG("Attribute read, handle: %u, conn: %p", attr->handle, (void *)conn); if (lbs_cb.button_cb) { button_state = lbs_cb.button_cb(); return bt_gatt_attr_read(conn, attr, buf, len, offset, value, sizeof(*value)); } return 0; } #endif /* LED Button Service Declaration */ BT_GATT_SERVICE_DEFINE(lbs_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_LBS), #ifdef CONFIG_BT_LBS_POLL_BUTTON BT_GATT_CHARACTERISTIC(BT_UUID_LBS_BUTTON, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ, read_button, NULL, &button_state), #else BT_GATT_CHARACTERISTIC(BT_UUID_LBS_BUTTON, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ, NULL, NULL, NULL), #endif BT_GATT_CCC(lbslc_ccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE), BT_GATT_CHARACTERISTIC(BT_UUID_LBS_LED, BT_GATT_CHRC_WRITE, BT_GATT_PERM_WRITE, NULL, write_led, NULL), ); int bt_lbs_init(struct bt_lbs_cb *callbacks) { if (callbacks) { lbs_cb.led_cb = callbacks->led_cb; lbs_cb.button_cb = callbacks->button_cb; } return 0; } int bt_lbs_send_button_state(bool button_state) { if (!notify_enabled) { return -EACCES; } return bt_gatt_notify(NULL, &lbs_svc.attrs[2], &button_state, sizeof(button_state)); }