Skip to content

Commit 1191cb9

Browse files
committed
cleanup
1 parent d813011 commit 1191cb9

File tree

12 files changed

+738
-757
lines changed

12 files changed

+738
-757
lines changed

.vscode/settings.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
"string_view": "c",
1111
"ble_svc_gap.h": "c",
1212
"console.h": "c",
13-
"esp_nimble_hci.h": "c"
13+
"esp_nimble_hci.h": "c",
14+
"stdio.h": "c",
15+
"freertosconfig.h": "c"
1416
}
1517
}

components/ble/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ set(srcs "gap.c" "gatt.c" "ble.c")
22

33
idf_component_register(SRCS "${srcs}"
44
INCLUDE_DIRS "include"
5-
REQUIRES bt)
5+
REQUIRES bt
6+
PRIV_REQUIRES nimble_peripheral_utils)

components/ble/ble.c

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,124 @@
1-
#include "ble.h"
1+
#include "ble.h"
2+
3+
void initBLE(){
4+
//store for returncodes
5+
//mynewt.apache.org/latest/network/ble_hs/ble_hs_return_codes.html
6+
int rc;
7+
8+
/* Initialize NVS — it is used to store PHY calibration data */
9+
//NVS = Non-volatile storage library is designed to store key-balue pairs in flash
10+
//Ablauf ist in esp idf beschrieben
11+
//docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/bluetooth/nimble/index.html
12+
esp_err_t ret = nvs_flash_init();
13+
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
14+
ESP_ERROR_CHECK(nvs_flash_erase());
15+
ret = nvs_flash_init();
16+
}
17+
ESP_ERROR_CHECK(ret);
18+
19+
ESP_ERROR_CHECK(esp_nimble_hci_and_controller_init());
20+
21+
nimble_port_init();
22+
23+
/* Initialize the NimBLE host configuration */
24+
ble_hs_cfg.sync_cb = bleOnSync;
25+
ble_hs_cfg.reset_cb = bleOnReset;
26+
27+
/**
28+
* Round-robin status callback. If a there is insufficient storage capacity
29+
* for a new record, delete the oldest bond and proceed with the persist
30+
* operation.
31+
*
32+
* Note: This is not the best behavior for an actual product because
33+
* uninteresting peers could cause important bonds to be deleted. This is
34+
* useful for demonstrations and sample apps.
35+
*/
36+
ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
37+
38+
//optional wird ausgeführt wenn ein gatt resource (characteristic, descriptor, sevice) hinzugefügt wird. Also nicht benötigt
39+
ble_hs_cfg.gatts_register_cb = gattSvrRegisterCb;
40+
41+
/*Security Manager local input output capabilities*/
42+
//io types zum aufbau einer sicheren verbindung
43+
//BLE_SM_IO_CAP_DISP_ONLY = Display only
44+
//BLE_SM_IO_CAP_DISP_YES_NO = Display & yes & no buttons
45+
//BLE_SM_IO_CAP_KEYBOARD_ONLY = Keyboard only
46+
//BLE_SM_IO_CAP_NO_IO = just work
47+
//BLE_SM_IO_CAP_KEYBOARD_DISP = Keyboard and display
48+
ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_NO_IO;
49+
/*Security Manager secure connections flag
50+
if set proper flag in pairing request/response will be set. this results in using LE Secure Connections for pairing if also supported by remote device. Fallback to legacy pairing if not supported by remote.*/
51+
ble_hs_cfg.sm_sc = 1;
52+
/*security Manager bond flag
53+
if set proper flag in Pairing request/response will be set. This results in storing keys distributed during bonding.*/
54+
ble_hs_cfg.sm_bonding = 1;
55+
/*security manager mitm flag
56+
if set proper flag in pairing request/response will be set. This results in requiring man-in-the-middle protection when pairing.*/
57+
ble_hs_cfg.sm_mitm = 1;
58+
/*Security Manager Local Key Distribution Mask*/
59+
ble_hs_cfg.sm_our_key_dist = BLE_SM_PAIR_KEY_DIST_ENC | BLE_SM_PAIR_KEY_DIST_ID;
60+
/* Refer components/nimble/nimble/nimble/host/include/host/ble_sm.h for
61+
* more information */
62+
/*Security Manager Remote Key Distribution Mask*/
63+
ble_hs_cfg.sm_their_key_dist = BLE_SM_PAIR_KEY_DIST_ENC | BLE_SM_PAIR_KEY_DIST_ID;
64+
65+
rc = gattSvrInit();
66+
assert(rc == 0);
67+
68+
/* Set the default device name */
69+
rc = ble_svc_gap_device_name_set(CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME);
70+
assert(rc == 0);
71+
}
72+
73+
//This callback is executed when the host and controller become synced. This happens at startup and after a reset
74+
void bleOnSync(void){
75+
int rc;
76+
77+
/* Generate a non-resolvable private address. */
78+
//ble_app_set_addr();
79+
80+
ble_hs_pvcy_rpa_config(1);
81+
82+
/* Make sure we have proper identity address set (public preferred) */
83+
rc = ble_hs_util_ensure_addr(0);
84+
85+
86+
/*use privacy*/
87+
rc = ble_hs_id_infer_auto(bleAddressType, &bleAddressType);
88+
assert(rc == 0);
89+
90+
uint8_t addr_val[6] = {0};
91+
rc = ble_hs_id_copy_addr(bleAddressType, addr_val, NULL);
92+
93+
ESP_LOGI(tag_BLE, "Device Address: ");
94+
print_addr(addr_val);
95+
ESP_LOGI(tag_BLE, "\n");
96+
97+
taskYIELD();
98+
99+
/*start advertising, when controller and host are in sync*/
100+
bleAdvertise();
101+
}
102+
103+
//This callback is executed when the host resets itself and the controller
104+
void bleOnReset(int reason){
105+
ESP_LOGI(tag_BLE, "Resetting state; reason=%d\n", reason);
106+
}
107+
108+
//start nimble in a task
109+
void bleHostTask(void *param)
110+
{
111+
ESP_LOGI(tag_BLE, "BLE Host Task Started");
112+
/* This function will return only when nimble_port_stop() is executed */
113+
nimble_port_run();
114+
115+
nimble_port_freertos_deinit();
116+
}
117+
118+
void print_addr(const void *addr){
119+
const uint8_t *u8p;
120+
121+
u8p = addr;
122+
ESP_LOGI(tag_BLE, "%02x:%02x:%02x:%02x:%02x:%02x",
123+
u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]);
124+
}

components/ble/gap.c

Lines changed: 220 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,220 @@
1-
#include "gap.h"
1+
#include "gap.h"
2+
3+
/*
4+
* Enables advertising with parameters:
5+
* o General discoverable mode
6+
* o Undirected connectable mode
7+
*/
8+
void bleAdvertise(void){
9+
struct ble_gap_adv_params adv_params;
10+
struct ble_hs_adv_fields fields;
11+
int rc;
12+
13+
/*
14+
* Set the advertisement data included in our advertisements:
15+
* o Flags (indicates advertisement type and other general info)
16+
* o Advertising tx power
17+
* o Device name
18+
*/
19+
memset(&fields, 0, sizeof(fields));
20+
21+
/*
22+
* Advertise two flags:
23+
* o Discoverability in forthcoming advertisement (general)
24+
* o BLE-only (BR/EDR unsupported)
25+
*/
26+
fields.flags = BLE_HS_ADV_F_DISC_GEN |
27+
BLE_HS_ADV_F_BREDR_UNSUP;
28+
29+
/*
30+
* Indicate that the TX power level field should be included; have the
31+
* stack fill this value automatically. This is done by assigning the
32+
* special value BLE_HS_ADV_TX_PWR_LVL_AUTO.
33+
*/
34+
fields.tx_pwr_lvl_is_present = 1;
35+
fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
36+
37+
fields.name = (uint8_t *)CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME;
38+
fields.name_len = strlen(CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME);
39+
fields.name_is_complete = 1;
40+
41+
fields.num_uuids16 = 1;
42+
fields.uuids16_is_complete = 0;
43+
fields.uuids16 = (ble_uuid16_t[]){
44+
hid_service_uuid
45+
};
46+
//geht nur eins weil sonst die adv packetgröße nicht reicht
47+
48+
rc = ble_gap_adv_set_fields(&fields);
49+
if (rc != 0) {
50+
ESP_LOGI(tag_GAP, "error setting advertisement data; rc=%d\n", rc);
51+
return;
52+
}
53+
54+
/* Begin advertising */
55+
memset(&adv_params, 0, sizeof(adv_params));
56+
//undirected-connectable
57+
adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
58+
//general-discoverable
59+
adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
60+
rc = ble_gap_adv_start(bleAddressType, NULL, BLE_HS_FOREVER,
61+
&adv_params, bleGAPEevent, NULL);
62+
if (rc != 0) {
63+
ESP_LOGI(tag_GAP, "error enabling advertisement; rc=%d\n", rc);
64+
return;
65+
}
66+
}
67+
68+
//The callback to associate with this advertising procedure. If advertising ends, the event is reported through this callback. If advertising results in a connection, the connection inherits this callback as its event-reporting mechanism.
69+
int bleGAPEevent(struct ble_gap_event *event, void *arg) {
70+
struct ble_gap_conn_desc desc;
71+
int rc;
72+
73+
switch (event->type) {
74+
case BLE_GAP_EVENT_CONNECT:
75+
/* A new connection was established or a connection attempt failed */
76+
ESP_LOGI(tag_GAP, "connection %s; status=%d\n",
77+
event->connect.status == 0 ? "established" : "failed",
78+
event->connect.status);
79+
80+
if (event->connect.status != 0) {
81+
/* Connection failed; resume advertising */
82+
bleAdvertise();
83+
} else {
84+
struct ble_gap_upd_params connectionParameters = {
85+
//itvl: These determine how often the devices will "ping-pong" each other and also when they will send any data required. So if you set the value to something like 20, that would mean packets are sent every 25ms, which will obviously consume more power than say a value of 80 (100ms). The reason for the min max values is so the devices can negotiate a compromise for the best possible communication, you can set these to the same value if you prefer.
86+
.itvl_min = (int)(11.25/1.25), //1.25ms units; laut apple 11.25 minimum fuer hid
87+
.itvl_max = (int)(20/1.25), //minimum ist laut apple eigentlich 15ms deswegen etwas höher setzen
88+
//latency: This is how many "ping-pong" (connection interval) events the slave(server) device is allowed to skip without the client device considering the connection terminated. So if you had a 25ms connection interval and you wanted to sleep for 1 second you could set this value to 40 and the client would consider the connection active for up to 40 skipped intervals.
89+
.latency = 30, //up to 30 connection intervals
90+
//timeout: This is the absolute (disconnection) timeout, if no packets are received by either device within this time the connection is considered terminated.
91+
.supervision_timeout = 1860/10 //10ms units, laut apple größer als itvl_max * (latency + 1) * 3
92+
};
93+
94+
//ESP_ERROR_CHECK(ble_gap_update_params(event->connect.conn_handle, &connectionParameters));
95+
}
96+
97+
98+
conn_handle = event->connect.conn_handle;
99+
100+
break;
101+
102+
case BLE_GAP_EVENT_DISCONNECT:
103+
ESP_LOGI(tag_GAP, "disconnect; reason=%d\n", event->disconnect.reason);
104+
//531 = Remote User Terminated Connection
105+
106+
/* Connection terminated; resume advertising */
107+
bleAdvertise();
108+
break;
109+
110+
case BLE_GAP_EVENT_ADV_COMPLETE:
111+
ESP_LOGI(tag_GAP, "adv complete; reason = %d\n", event->adv_complete.reason);
112+
bleAdvertise();
113+
break;
114+
115+
case BLE_GAP_EVENT_SUBSCRIBE:
116+
ESP_LOGI(tag_GAP, "subscribe event; cur_notify=%d\n value handle; val_handle=%d\n", event->subscribe.cur_notify, report_data_handle);
117+
118+
rc = ble_gap_conn_find(event->subscribe.conn_handle, &desc);
119+
if (rc != 0) {
120+
break;
121+
}
122+
123+
//muss eigentlich nur gemacht werden bei den attr_handle wo es auf encrypted nur gelesen wird --> input report
124+
if(!desc.sec_state.encrypted) {
125+
ble_gap_security_initiate(event->subscribe.conn_handle);
126+
}
127+
128+
if (event->subscribe.attr_handle == report_data_handle) {
129+
notify_state = event->subscribe.cur_notify;
130+
//blehr_tx_hrate_reset();
131+
} else if (event->subscribe.attr_handle != report_data_handle) {
132+
notify_state = event->subscribe.cur_notify;
133+
//blehr_tx_hrate_stop();
134+
}
135+
ESP_LOGI(tag_GAP, "conn_handle from subscribe=%d", conn_handle);
136+
break;
137+
138+
case BLE_GAP_EVENT_MTU:
139+
ESP_LOGI(tag_GAP, "mtu update event; mtu already updated; nothing todo; conn_handle=%d mtu=%d\n",
140+
event->mtu.conn_handle,
141+
event->mtu.value);
142+
break;
143+
case BLE_GAP_EVENT_ENC_CHANGE:
144+
ESP_LOGI(tag_GAP, "encryption change event; status=%d ",
145+
event->enc_change.status);
146+
break;
147+
case BLE_GAP_EVENT_REPEAT_PAIRING:
148+
/* We already have a bond with the peer, but it is attempting to
149+
* establish a new secure link. This app sacrifices security for
150+
* convenience: just throw away the old bond and accept the new link.
151+
*/
152+
ESP_LOGI(tag_GAP, "establisch new secure link");
153+
154+
/* Delete the old bond. */
155+
rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc);
156+
assert(rc == 0);
157+
ble_store_util_delete_peer(&desc.peer_id_addr);
158+
159+
/* Return BLE_GAP_REPEAT_PAIRING_RETRY to indicate that the host should
160+
* continue with the pairing operation.
161+
*/
162+
return BLE_GAP_REPEAT_PAIRING_RETRY;
163+
break;
164+
165+
case BLE_GAP_EVENT_PASSKEY_ACTION:
166+
ESP_LOGI(tag_GAP, "PASSKEY_ACTION_EVENT started \n");
167+
168+
struct ble_sm_io pkey = {0};
169+
int key = 0;
170+
171+
if (event->passkey.params.action == BLE_SM_IOACT_DISP) {
172+
pkey.action = event->passkey.params.action;
173+
pkey.passkey = 123456; // This is the passkey to be entered on peer
174+
ESP_LOGI(tag_GAP, "Enter passkey %d on the peer side", pkey.passkey);
175+
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
176+
ESP_LOGI(tag_GAP, "ble_sm_inject_io result: %d\n", rc);
177+
} else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) {
178+
ESP_LOGI(tag_GAP, "Passkey on device's display: %d", event->passkey.params.numcmp);
179+
ESP_LOGI(tag_GAP, "Accept or reject the passkey through console in this format -> key Y or key N");
180+
pkey.action = event->passkey.params.action;
181+
if (scli_receive_key(&key)) {
182+
pkey.numcmp_accept = key;
183+
} else {
184+
pkey.numcmp_accept = 0;
185+
ESP_LOGE(tag_GAP, "Timeout! Rejecting the key");
186+
}
187+
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
188+
ESP_LOGI(tag_GAP, "ble_sm_inject_io result: %d\n", rc);
189+
} else if (event->passkey.params.action == BLE_SM_IOACT_OOB) {
190+
static uint8_t tem_oob[16] = {0};
191+
pkey.action = event->passkey.params.action;
192+
for (int i = 0; i < 16; i++) {
193+
pkey.oob[i] = tem_oob[i];
194+
}
195+
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
196+
ESP_LOGI(tag_GAP, "ble_sm_inject_io result: %d\n", rc);
197+
} else if (event->passkey.params.action == BLE_SM_IOACT_INPUT) {
198+
ESP_LOGI(tag_GAP, "Enter the passkey through console in this format-> key 123456");
199+
pkey.action = event->passkey.params.action;
200+
if (scli_receive_key(&key)) {
201+
pkey.passkey = key;
202+
} else {
203+
pkey.passkey = 0;
204+
ESP_LOGE(tag_GAP, "Timeout! Passing 0 as the key");
205+
}
206+
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
207+
ESP_LOGI(tag_GAP, "ble_sm_inject_io result: %d\n", rc);
208+
}
209+
return 0;
210+
case BLE_GAP_EVENT_NOTIFY_TX:
211+
//Represents a transmitted ATT notification or indication, or a
212+
//completed indication transaction.
213+
ESP_LOGI(tag_GAP, "notify tx event occured");
214+
return 0;
215+
default:
216+
ESP_LOGI(tag_GAP, "GAP EVENT ID: %d\n",event->type);
217+
}
218+
219+
return 0;
220+
}

0 commit comments

Comments
 (0)