Skip to content

Commit afec831

Browse files
committed
info: initial implementation
Read INFO characteristic as the first action after discovering device. Save information about server and device certificates, i.e. whether they were already provisioned. Reading INFO characteristic replaces reading server cert serial number, since the same information is provided. When device certificate provisioned flag is set, this reduces overhead by about 350ms (with default configuration of pouch device). Signed-off-by: Marcin Niestroj <m.niestroj@emb.dev>
1 parent 2ba86f1 commit afec831

11 files changed

Lines changed: 334 additions & 85 deletions

File tree

.github/workflows/bsim.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ jobs:
7171
run: |
7272
uv pip install \
7373
-r pouch/requirements.txt \
74+
-r pouch-gateway/requirements.txt \
7475
-r zephyr/scripts/requirements-base.txt \
7576
-r zephyr/scripts/requirements-build-test.txt \
7677
-r zephyr/scripts/requirements-run-test.txt \

.github/workflows/build.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ jobs:
8282
- name: Install pip packages
8383
run: |
8484
uv pip install \
85+
-r pouch-gateway/requirements.txt \
8586
-r zephyr/scripts/requirements-base.txt
8687
8788
uv pip install \

include/pouch_gateway/bt/info.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* Copyright (c) 2025 Golioth, Inc.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#pragma once
8+
9+
struct bt_conn;
10+
11+
/**
12+
* Start reading info characteristic for the given Bluetooth connection.
13+
*
14+
* @param conn The Bluetooth connection.
15+
*/
16+
void pouch_gateway_info_read_start(struct bt_conn *conn);

include/pouch_gateway/info.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright (c) 2025 Golioth, Inc.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#pragma once
8+
9+
#include <stdbool.h>
10+
#include <stddef.h>
11+
#include <stdint.h>
12+
13+
struct pouch_gateway_info_context;
14+
15+
/**
16+
* @brief Flag indicating that the device certificate is provisioned.
17+
*/
18+
#define POUCH_GATEWAY_INFO_FLAG_DEVICE_PROVISIONED BIT(0)
19+
20+
/**
21+
* @brief Start info read operation.
22+
*
23+
* @return Pointer to the info context, or NULL on failure.
24+
*/
25+
struct pouch_gateway_info_context *pouch_gateway_info_start(void);
26+
/**
27+
* @brief Push data to the info context.
28+
*
29+
* @param context The info context.
30+
* @param data The data to push.
31+
* @param len The length of the data.
32+
* @return 0 on success, negative on error.
33+
*/
34+
int pouch_gateway_info_push(struct pouch_gateway_info_context *context,
35+
const void *data,
36+
size_t len);
37+
/**
38+
* @brief Abort the info read operation.
39+
*
40+
* @param context The info context.
41+
*/
42+
void pouch_gateway_info_abort(struct pouch_gateway_info_context *context);
43+
/**
44+
* @brief Finish the info read operation.
45+
*
46+
* @param context The info context.
47+
* @param[out] server_cert_provisioned Set to true if server cert is provisioned.
48+
* @param[out] device_cert_provisioned Set to true if device cert is provisioned.
49+
* @return 0 on success, negative on error.
50+
*/
51+
int pouch_gateway_info_finish(struct pouch_gateway_info_context *context,
52+
bool *server_cert_provisioned,
53+
bool *device_cert_provisioned);

include/pouch_gateway/types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,11 @@ struct pouch_gateway_node_info
4444
void *server_cert_scratch;
4545
struct pouch_gatt_packetizer *packetizer;
4646
struct pouch_gateway_uplink *uplink;
47+
struct pouch_gateway_info_context *info_ctx;
4748
struct pouch_gateway_device_cert_context *device_cert_ctx;
4849
struct pouch_gateway_server_cert_context *server_cert_ctx;
50+
bool server_cert_provisioned;
51+
bool device_cert_provisioned;
4952
};
5053

5154
/**

lib/CMakeLists.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@ zephyr_library()
33
zephyr_library_sources(bt/cert.c)
44
zephyr_library_sources(bt/connect.c)
55
zephyr_library_sources(bt/downlink.c)
6+
zephyr_library_sources(bt/info.c)
67
zephyr_library_sources(bt/scan.c)
78
zephyr_library_sources(bt/uplink.c)
89
zephyr_library_sources(block.c)
910
zephyr_library_sources(cert.c)
1011
zephyr_library_sources(downlink.c)
12+
zephyr_library_sources(info.c)
13+
zephyr_library_sources(info_decode.c)
1114
zephyr_library_sources(uplink.c)
1215

1316
zephyr_library_link_libraries(mbedTLS)
@@ -23,3 +26,18 @@ endif()
2326
generate_inc_file_for_target(${lib_name}
2427
${cert_name}
2528
${ZEPHYR_BINARY_DIR}/include/generated/pouch_gateway_server.pem.inc)
29+
30+
message("${ZEPHYR_POUCH_MODULE_DIR}/src/transport/gatt/info.cddl")
31+
32+
add_custom_command(OUTPUT info_decode.c
33+
COMMAND zcbor code
34+
-c ${ZEPHYR_POUCH_MODULE_DIR}/src/transport/gatt/info.cddl
35+
-s
36+
-t pouch_gatt_info
37+
-d --include-prefix cddl/
38+
--output-c ${CMAKE_CURRENT_BINARY_DIR}/info_decode.c
39+
--output-h ${CMAKE_CURRENT_BINARY_DIR}/include/cddl/info_decode.h
40+
BYPRODUCTS include/cddl/info_decode.h include/cddl/info_decode_types.h
41+
DEPENDS ${ZEPHYR_POUCH_MODULE_DIR}/src/transport/gatt/info.cddl)
42+
43+
zephyr_library_include_directories(${CMAKE_CURRENT_BINARY_DIR}/include)

lib/bt/cert.c

Lines changed: 12 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -51,72 +51,6 @@ static void server_cert_cleanup(struct bt_conn *conn)
5151
}
5252
}
5353

54-
static uint8_t server_cert_read_cb(struct bt_conn *conn,
55-
uint8_t err,
56-
struct bt_gatt_read_params *params,
57-
const void *data,
58-
uint16_t length)
59-
{
60-
if (err)
61-
{
62-
LOG_ERR("Failed to read BLE GATT %s (err %d)", "server cert", err);
63-
return BT_GATT_ITER_STOP;
64-
}
65-
66-
if (length == 0)
67-
{
68-
gateway_server_cert_write_start(conn);
69-
return BT_GATT_ITER_STOP;
70-
}
71-
72-
bool is_first = false;
73-
bool is_last = false;
74-
const void *payload = NULL;
75-
ssize_t payload_len = pouch_gatt_packetizer_decode(data, length, &payload, &is_first, &is_last);
76-
if (payload_len < 0)
77-
{
78-
LOG_ERR("Failed to decode BLE GATT %s (err %d)", "server cert", (int) payload_len);
79-
server_cert_cleanup(conn);
80-
pouch_gateway_bt_finished(conn);
81-
return BT_GATT_ITER_STOP;
82-
}
83-
84-
if (data)
85-
{
86-
LOG_HEXDUMP_DBG(data, length, "[READ] BLE GATT server cert");
87-
}
88-
89-
if (is_last)
90-
{
91-
uint8_t serial[CERT_SERIAL_MAXLEN];
92-
size_t serial_len = sizeof(serial);
93-
94-
pouch_gateway_server_cert_get_serial(serial, &serial_len);
95-
96-
if (payload_len > 0 && payload_len == serial_len
97-
&& memcmp(serial, payload, payload_len) == 0)
98-
{
99-
LOG_DBG("server cert match");
100-
gateway_device_cert_read_start(conn);
101-
}
102-
else
103-
{
104-
LOG_DBG("server cert mismatch");
105-
gateway_server_cert_write_start(conn);
106-
}
107-
108-
return BT_GATT_ITER_STOP;
109-
}
110-
111-
err = bt_gatt_read(conn, params);
112-
if (err)
113-
{
114-
LOG_ERR("BT (re)read request failed: %d", err);
115-
return BT_GATT_ITER_STOP;
116-
}
117-
118-
return BT_GATT_ITER_STOP;
119-
}
12054

12155
static void device_cert_cleanup(struct bt_conn *conn)
12256
{
@@ -262,6 +196,7 @@ static void write_response_cb(struct bt_conn *conn,
262196
{
263197
// There was certificate update in the meantime, so send it once again.
264198
LOG_INF("Noticed certificate update, sending once again");
199+
node->server_cert_provisioned = false;
265200
gateway_server_cert_write_start(conn);
266201
}
267202
}
@@ -301,6 +236,12 @@ static void gateway_server_cert_write_start(struct bt_conn *conn)
301236
{
302237
struct pouch_gateway_node_info *node = pouch_gateway_get_node_info(conn);
303238

239+
if (node->server_cert_provisioned)
240+
{
241+
gateway_device_cert_read_start(conn);
242+
return;
243+
}
244+
304245
if (0 == node->attr_handles[POUCH_GATEWAY_GATT_ATTR_SERVER_CERT].value)
305246
{
306247
LOG_ERR("%s characteristic undiscovered", "server cert");
@@ -325,28 +266,15 @@ static void gateway_server_cert_write_start(struct bt_conn *conn)
325266
write_server_cert_characteristic(conn);
326267
}
327268

328-
static void gateway_server_cert_serial_read_start(struct bt_conn *conn)
269+
static void gateway_device_cert_read_start(struct bt_conn *conn)
329270
{
330271
struct pouch_gateway_node_info *node = pouch_gateway_get_node_info(conn);
331272

332-
struct bt_gatt_read_params *read_params = &node->read_params;
333-
memset(read_params, 0, sizeof(*read_params));
334-
335-
read_params->func = server_cert_read_cb;
336-
read_params->handle_count = 1;
337-
read_params->single.handle = node->attr_handles[POUCH_GATEWAY_GATT_ATTR_SERVER_CERT].value;
338-
int err = bt_gatt_read(conn, read_params);
339-
if (err)
273+
if (node->device_cert_provisioned)
340274
{
341-
LOG_ERR("BT read request failed: %d", err);
342-
server_cert_cleanup(conn);
343-
pouch_gateway_bt_finished(conn);
275+
pouch_gateway_uplink_start(conn);
276+
return;
344277
}
345-
}
346-
347-
static void gateway_device_cert_read_start(struct bt_conn *conn)
348-
{
349-
struct pouch_gateway_node_info *node = pouch_gateway_get_node_info(conn);
350278

351279
struct bt_gatt_read_params *read_params = &node->read_params;
352280
memset(read_params, 0, sizeof(*read_params));
@@ -367,5 +295,5 @@ static void gateway_device_cert_read_start(struct bt_conn *conn)
367295

368296
void pouch_gateway_cert_exchange_start(struct bt_conn *conn)
369297
{
370-
gateway_server_cert_serial_read_start(conn);
298+
gateway_server_cert_write_start(conn);
371299
}

lib/bt/connect.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <pouch_gateway/bt/connect.h>
1818
#include <pouch_gateway/bt/cert.h>
1919
#include <pouch_gateway/bt/downlink.h>
20+
#include <pouch_gateway/bt/info.h>
2021
#include <pouch_gateway/bt/scan.h>
2122
#include <pouch_gateway/bt/uplink.h>
2223

@@ -79,7 +80,7 @@ static uint8_t discover_descriptors(struct bt_conn *conn,
7980
if (node->attr_handles[POUCH_GATEWAY_GATT_ATTR_SERVER_CERT].value
8081
&& node->attr_handles[POUCH_GATEWAY_GATT_ATTR_DEVICE_CERT].value)
8182
{
82-
pouch_gateway_cert_exchange_start(conn);
83+
pouch_gateway_info_read_start(conn);
8384
}
8485
else
8586
{

0 commit comments

Comments
 (0)