/
main.c
203 lines (157 loc) · 4.43 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/
/** @file
* @brief Peripheral Heart Rate over LE Coded PHY sample
*/
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <zephyr/kernel.h>
#include <zephyr/types.h>
#include <zephyr/sys/printk.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/bluetooth/services/bas.h>
#include <zephyr/bluetooth/services/hrs.h>
#include <dk_buttons_and_leds.h>
#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
#define RUN_STATUS_LED DK_LED1
#define CON_STATUS_LED DK_LED2
#define RUN_LED_BLINK_INTERVAL 1000
#define NOTIFY_INTERVAL 1000
static void start_advertising_coded(struct k_work *work);
static void notify_work_handler(struct k_work *work);
static K_WORK_DEFINE(start_advertising_worker, start_advertising_coded);
static K_WORK_DELAYABLE_DEFINE(notify_work, notify_work_handler);
static struct bt_le_ext_adv *adv;
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, BT_UUID_16_ENCODE(BT_UUID_HRS_VAL),
BT_UUID_16_ENCODE(BT_UUID_BAS_VAL),
BT_UUID_16_ENCODE(BT_UUID_DIS_VAL)),
BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN)
};
static void connected(struct bt_conn *conn, uint8_t conn_err)
{
int err;
struct bt_conn_info info;
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
if (conn_err) {
printk("Connection failed (err %d)\n", conn_err);
return;
}
err = bt_conn_get_info(conn, &info);
if (err) {
printk("Failed to get connection info (err %d)\n", err);
} else {
const struct bt_conn_le_phy_info *phy_info;
phy_info = info.le.phy;
printk("Connected: %s, tx_phy %u, rx_phy %u\n",
addr, phy_info->tx_phy, phy_info->rx_phy);
}
dk_set_led_on(CON_STATUS_LED);
}
static void disconnected(struct bt_conn *conn, uint8_t reason)
{
printk("Disconnected (reason 0x%02x)\n", reason);
k_work_submit(&start_advertising_worker);
dk_set_led_off(CON_STATUS_LED);
}
BT_CONN_CB_DEFINE(conn_callbacks) = {
.connected = connected,
.disconnected = disconnected,
};
static int create_advertising_coded(void)
{
int err;
struct bt_le_adv_param param =
BT_LE_ADV_PARAM_INIT(BT_LE_ADV_OPT_CONNECTABLE |
BT_LE_ADV_OPT_EXT_ADV |
BT_LE_ADV_OPT_CODED,
BT_GAP_ADV_FAST_INT_MIN_2,
BT_GAP_ADV_FAST_INT_MAX_2,
NULL);
err = bt_le_ext_adv_create(¶m, NULL, &adv);
if (err) {
printk("Failed to create advertiser set (err %d)\n", err);
return err;
}
printk("Created adv: %p\n", adv);
err = bt_le_ext_adv_set_data(adv, ad, ARRAY_SIZE(ad), NULL, 0);
if (err) {
printk("Failed to set advertising data (err %d)\n", err);
return err;
}
return 0;
}
static void start_advertising_coded(struct k_work *work)
{
int err;
err = bt_le_ext_adv_start(adv, NULL);
if (err) {
printk("Failed to start advertising set (err %d)\n", err);
return;
}
printk("Advertiser %p set started\n", adv);
}
static void bas_notify(void)
{
uint8_t battery_level = bt_bas_get_battery_level();
__ASSERT_NO_MSG(battery_level > 0);
battery_level--;
if (!battery_level) {
battery_level = 100;
}
bt_bas_set_battery_level(battery_level);
}
static void hrs_notify(void)
{
static uint8_t heartrate = 100;
heartrate++;
if (heartrate == 160) {
heartrate = 100;
}
bt_hrs_notify(heartrate);
}
static void notify_work_handler(struct k_work *work)
{
/* Services data simulation. */
hrs_notify();
bas_notify();
k_work_reschedule(k_work_delayable_from_work(work), K_MSEC(NOTIFY_INTERVAL));
}
int main(void)
{
uint32_t led_status = 0;
int err;
printk("Starting Bluetooth Peripheral HR coded example\n");
err = dk_leds_init();
if (err) {
printk("LEDs init failed (err %d)\n", err);
return 0;
}
err = bt_enable(NULL);
if (err) {
printk("Bluetooth init failed (err %d)\n", err);
return 0;
}
printk("Bluetooth initialized\n");
err = create_advertising_coded();
if (err) {
printk("Advertising failed to create (err %d)\n", err);
return 0;
}
k_work_submit(&start_advertising_worker);
k_work_schedule(¬ify_work, K_NO_WAIT);
for (;;) {
dk_set_led(RUN_STATUS_LED, (++led_status) % 2);
k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL));
}
}