blob: b277cd4205a1139183181790c58e16fad6c3119f [file] [log] [blame]
/*
* Copyright (c) 2022 Michal Morsisko
* Copyright (c) 2015-2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/types.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/sys/reboot.h>
#include <zephyr/settings/settings.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/bluetooth/gatt.h>
/* Custom Service Variables */
#define BT_UUID_CUSTOM_SERVICE_VAL \
BT_UUID_128_ENCODE(0x12345678, 0x1234, 0x5678, 0x1234, 0x56789abcdef0)
static const struct bt_uuid_128 primary_service_uuid = BT_UUID_INIT_128(
BT_UUID_CUSTOM_SERVICE_VAL);
static const struct bt_uuid_128 read_characteristic_uuid = BT_UUID_INIT_128(
BT_UUID_128_ENCODE(0x12345678, 0x1234, 0x5678, 0x1234, 0x56789abcdef1));
static const struct bt_uuid_128 write_characteristic_uuid = BT_UUID_INIT_128(
BT_UUID_128_ENCODE(0x12345678, 0x1234, 0x5678, 0x1234, 0x56789abcdef2));
static int signed_value;
static struct bt_le_adv_param adv_param;
static bt_addr_le_t bond_addr;
static ssize_t read_signed(struct bt_conn *conn, const struct bt_gatt_attr *attr,
void *buf, uint16_t len, uint16_t offset)
{
int *value = &signed_value;
return bt_gatt_attr_read(conn, attr, buf, len, offset, value,
sizeof(signed_value));
}
static ssize_t write_signed(struct bt_conn *conn, const struct bt_gatt_attr *attr,
const void *buf, uint16_t len, uint16_t offset,
uint8_t flags)
{
int *value = &signed_value;
if (offset + len > sizeof(signed_value)) {
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
}
memcpy(value + offset, buf, len);
return len;
}
/* Vendor Primary Service Declaration */
BT_GATT_SERVICE_DEFINE(primary_service,
BT_GATT_PRIMARY_SERVICE(&primary_service_uuid),
BT_GATT_CHARACTERISTIC(&read_characteristic_uuid.uuid,
BT_GATT_CHRC_READ,
BT_GATT_PERM_READ,
read_signed, NULL, NULL),
BT_GATT_CHARACTERISTIC(&write_characteristic_uuid.uuid,
BT_GATT_CHRC_WRITE,
BT_GATT_PERM_WRITE_ENCRYPT,
NULL, write_signed, NULL),
);
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_UUID128_ALL, BT_UUID_CUSTOM_SERVICE_VAL),
BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1),
};
static void connected(struct bt_conn *conn, uint8_t err)
{
if (err) {
printk("Connection failed (err 0x%02x)\n", err);
} else {
printk("Connected\n");
}
}
static void disconnected(struct bt_conn *conn, uint8_t reason)
{
printk("Disconnected (reason 0x%02x)\n", reason);
}
BT_CONN_CB_DEFINE(conn_callbacks) = {
.connected = connected,
.disconnected = disconnected
};
static void copy_last_bonded_addr(const struct bt_bond_info *info, void *data)
{
bt_addr_le_copy(&bond_addr, &info->addr);
}
static void bt_ready(void)
{
int err;
char addr[BT_ADDR_LE_STR_LEN];
printk("Bluetooth initialized\n");
if (IS_ENABLED(CONFIG_SETTINGS)) {
settings_load();
}
bt_addr_le_copy(&bond_addr, BT_ADDR_LE_NONE);
bt_foreach_bond(BT_ID_DEFAULT, copy_last_bonded_addr, NULL);
/* Address is equal to BT_ADDR_LE_NONE if compare returns 0.
* This means there is no bond yet.
*/
if (bt_addr_le_cmp(&bond_addr, BT_ADDR_LE_NONE) != 0) {
bt_addr_le_to_str(&bond_addr, addr, sizeof(addr));
printk("Direct advertising to %s\n", addr);
adv_param = *BT_LE_ADV_CONN_DIR_LOW_DUTY(&bond_addr);
adv_param.options |= BT_LE_ADV_OPT_DIR_ADDR_RPA;
err = bt_le_adv_start(&adv_param, NULL, 0, NULL, 0);
} else {
err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0);
}
if (err) {
printk("Advertising failed to start (err %d)\n", err);
} else {
printk("Advertising successfully started\n");
}
}
void pairing_complete(struct bt_conn *conn, bool bonded)
{
printk("Pairing completed. Rebooting in 5 seconds...\n");
k_sleep(K_SECONDS(5));
sys_reboot(SYS_REBOOT_WARM);
}
static struct bt_conn_auth_info_cb bt_conn_auth_info = {
.pairing_complete = pairing_complete
};
int main(void)
{
int err;
err = bt_enable(NULL);
if (err) {
printk("Bluetooth init failed (err %d)\n", err);
return 0;
}
bt_ready();
bt_conn_auth_info_cb_register(&bt_conn_auth_info);
while (1) {
k_sleep(K_FOREVER);
}
return 0;
}