Skip to content

Commit b51aa05

Browse files
alxelaxrlubos
authored andcommitted
net: openthread: rpc: add commissioning serialization
Commit adds some commissioning API serialization otThreadDiscover otDatasetIsCommissioned otDatasetSetActiveTlvs otDatasetGetActiveTlvs Signed-off-by: Aleksandr Khromykh <[email protected]>
1 parent a040c16 commit b51aa05

File tree

8 files changed

+339
-3
lines changed

8 files changed

+339
-3
lines changed

subsys/net/openthread/rpc/client/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ zephyr_library_sources(
1010
ot_rpc_if_client.c
1111
ot_rpc_cli_client.c
1212
ot_rpc_ctrl_client.c
13+
ot_rpc_commissioning_client.c
1314
)
1415

1516
zephyr_library_include_directories(
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#include <ot_rpc_ids.h>
8+
#include <ot_rpc_types.h>
9+
#include <ot_rpc_common.h>
10+
11+
#include <nrf_rpc/nrf_rpc_serialize.h>
12+
#include <nrf_rpc/nrf_rpc_cbkproxy.h>
13+
14+
static void ot_rpc_thread_discover_cb_rpc_handler(const struct nrf_rpc_group *group,
15+
struct nrf_rpc_cbor_ctx *ctx, void *handler_data)
16+
{
17+
otHandleActiveScanResult callback;
18+
otActiveScanResult result;
19+
void *context;
20+
bool is_result_present =
21+
NULL != nrf_rpc_decode_buffer(ctx, result.mExtAddress.m8, OT_EXT_ADDRESS_SIZE);
22+
23+
if (is_result_present) {
24+
nrf_rpc_decode_str(ctx, result.mNetworkName.m8, OT_NETWORK_NAME_MAX_SIZE + 1);
25+
nrf_rpc_decode_buffer(ctx, result.mExtendedPanId.m8, OT_EXT_PAN_ID_SIZE);
26+
nrf_rpc_decode_buffer(ctx, result.mSteeringData.m8, OT_STEERING_DATA_MAX_LENGTH);
27+
28+
result.mPanId = nrf_rpc_decode_uint(ctx);
29+
result.mJoinerUdpPort = nrf_rpc_decode_uint(ctx);
30+
result.mChannel = nrf_rpc_decode_uint(ctx);
31+
result.mRssi = nrf_rpc_decode_int(ctx);
32+
result.mLqi = nrf_rpc_decode_uint(ctx);
33+
result.mVersion = nrf_rpc_decode_uint(ctx);
34+
result.mIsNative = nrf_rpc_decode_bool(ctx);
35+
result.mDiscover = nrf_rpc_decode_bool(ctx);
36+
result.mIsJoinable = nrf_rpc_decode_bool(ctx);
37+
}
38+
context = (void *)nrf_rpc_decode_uint(ctx);
39+
callback = (otHandleActiveScanResult)nrf_rpc_decode_callback_call(ctx);
40+
41+
if (!nrf_rpc_decoding_done_and_check(group, ctx)) {
42+
ot_rpc_report_decoding_error(OT_RPC_CMD_THREAD_DISCOVER_CB);
43+
return;
44+
}
45+
46+
if (callback) {
47+
callback(is_result_present ? &result : NULL, context);
48+
}
49+
50+
nrf_rpc_rsp_send_void(group);
51+
}
52+
53+
NRF_RPC_CBOR_CMD_DECODER(ot_group, ot_rpc_thread_discover_cb, OT_RPC_CMD_THREAD_DISCOVER_CB,
54+
ot_rpc_thread_discover_cb_rpc_handler, NULL);
55+
56+
otError otThreadDiscover(otInstance *aInstance, uint32_t aScanChannels, uint16_t aPanId,
57+
bool aJoiner, bool aEnableEui64Filtering,
58+
otHandleActiveScanResult aCallback, void *aCallbackContext)
59+
{
60+
struct nrf_rpc_cbor_ctx ctx;
61+
size_t cbor_buffer_size = 0;
62+
otError error;
63+
64+
ARG_UNUSED(aInstance);
65+
66+
cbor_buffer_size += sizeof(uint32_t) + 1; /* aScanChannels */
67+
cbor_buffer_size += sizeof(uint16_t) + 1; /* aPanId */
68+
cbor_buffer_size += 1; /* aJoiner */
69+
cbor_buffer_size += 1; /* aEnableEui64Filtering */
70+
cbor_buffer_size += sizeof(uintptr_t) + 1; /* aCallback */
71+
cbor_buffer_size += sizeof(uint32_t) + 1; /* aCallbackContext */
72+
73+
NRF_RPC_CBOR_ALLOC(&ot_group, ctx, cbor_buffer_size);
74+
75+
nrf_rpc_encode_uint(&ctx, aScanChannels);
76+
nrf_rpc_encode_uint(&ctx, aPanId);
77+
nrf_rpc_encode_bool(&ctx, aJoiner);
78+
nrf_rpc_encode_bool(&ctx, aEnableEui64Filtering);
79+
nrf_rpc_encode_callback(&ctx, aCallback);
80+
nrf_rpc_encode_uint(&ctx, (uintptr_t)aCallbackContext);
81+
82+
nrf_rpc_cbor_cmd_no_err(&ot_group, OT_RPC_CMD_THREAD_DISCOVER, &ctx, ot_rpc_decode_error,
83+
&error);
84+
85+
return error;
86+
}
87+
88+
bool otDatasetIsCommissioned(otInstance *aInstance)
89+
{
90+
struct nrf_rpc_cbor_ctx ctx;
91+
bool result;
92+
93+
ARG_UNUSED(aInstance);
94+
95+
NRF_RPC_CBOR_ALLOC(&ot_group, ctx, 0);
96+
97+
nrf_rpc_cbor_cmd_no_err(&ot_group, OT_RPC_CMD_DATASET_IS_COMMISSIONED, &ctx,
98+
nrf_rpc_rsp_decode_bool, &result);
99+
100+
return result;
101+
}
102+
103+
otError otDatasetSetActiveTlvs(otInstance *aInstance, const otOperationalDatasetTlvs *aDataset)
104+
{
105+
struct nrf_rpc_cbor_ctx ctx;
106+
size_t cbor_buffer_size;
107+
otError error;
108+
109+
ARG_UNUSED(aInstance);
110+
111+
if (aDataset == NULL || aDataset->mLength > OT_OPERATIONAL_DATASET_MAX_LENGTH) {
112+
return OT_ERROR_INVALID_ARGS;
113+
}
114+
115+
cbor_buffer_size = aDataset->mLength + 2;
116+
117+
NRF_RPC_CBOR_ALLOC(&ot_group, ctx, cbor_buffer_size);
118+
119+
nrf_rpc_encode_buffer(&ctx, aDataset->mTlvs, aDataset->mLength);
120+
121+
nrf_rpc_cbor_cmd_no_err(&ot_group, OT_RPC_CMD_DATA_SET_ACTIVE_TLVS, &ctx,
122+
ot_rpc_decode_error, &error);
123+
124+
return error;
125+
}
126+
127+
otError otDatasetGetActiveTlvs(otInstance *aInstance, otOperationalDatasetTlvs *aDataset)
128+
{
129+
struct nrf_rpc_cbor_ctx ctx;
130+
otOperationalDatasetTlvs *dataset = aDataset;
131+
132+
ARG_UNUSED(aInstance);
133+
134+
if (aDataset == NULL) {
135+
return OT_ERROR_NOT_FOUND;
136+
}
137+
138+
NRF_RPC_CBOR_ALLOC(&ot_group, ctx, 0);
139+
140+
nrf_rpc_cbor_cmd_no_err(&ot_group, OT_RPC_CMD_DATA_GET_ACTIVE_TLVS, &ctx,
141+
ot_rpc_decode_dataset_tlvs, &dataset);
142+
143+
return dataset ? OT_ERROR_NONE : OT_ERROR_NOT_FOUND;
144+
}

subsys/net/openthread/rpc/common/ot_rpc_common.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,14 @@ void ot_rpc_decode_dataset_tlvs(const struct nrf_rpc_group *group, struct nrf_rp
3232
data = nrf_rpc_decode_buffer_ptr_and_size(ctx, &length);
3333

3434
if (data == NULL) {
35-
handler_data = NULL;
35+
*(otOperationalDatasetTlvs **)handler_data = NULL;
3636
} else {
3737
dataset->mLength = length;
3838
memcpy(dataset->mTlvs, data, dataset->mLength);
3939
}
4040
}
4141

42-
void ot_rpc_report_decoding_error(uint8_t cmd_evt_id, void *data)
42+
void ot_rpc_report_decoding_error(uint8_t cmd_evt_id)
4343
{
4444
nrf_rpc_err(-EBADMSG, NRF_RPC_ERR_SRC_RECV, &ot_group, cmd_evt_id, NRF_RPC_PACKET_TYPE_CMD);
4545
}

subsys/net/openthread/rpc/common/ot_rpc_common.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ void ot_rpc_decode_void(const struct nrf_rpc_group *group, struct nrf_rpc_cbor_c
1717
void *handler_data);
1818
void ot_rpc_decode_dataset_tlvs(const struct nrf_rpc_group *group, struct nrf_rpc_cbor_ctx *ctx,
1919
void *handler_data);
20-
void ot_rpc_report_decoding_error(uint8_t cmd_evt_id, void *data);
20+
/* The function reports about command decoding error (not responses). */
21+
void ot_rpc_report_decoding_error(uint8_t cmd_evt_id);
2122

2223
#endif /* OT_RPC_COMMON_H_ */

subsys/net/openthread/rpc/common/ot_rpc_ids.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ enum ot_rpc_cmd_client {
1010
OT_RPC_CMD_CLI_OUTPUT = 0,
1111
OT_RPC_CMD_STATE_CHANGED,
1212
OT_RPC_CMD_IF_RECEIVE,
13+
OT_RPC_CMD_THREAD_DISCOVER_CB,
1314
};
1415

1516
/** @brief Command IDs accepted by the OpenThread over RPC server.
@@ -34,4 +35,8 @@ enum ot_rpc_cmd_server {
3435
OT_RPC_CMD_IF_ENABLE,
3536
OT_RPC_CMD_IF_SEND,
3637
OT_RPC_CMD_IF_EXTADDR,
38+
OT_RPC_CMD_THREAD_DISCOVER,
39+
OT_RPC_CMD_DATASET_IS_COMMISSIONED,
40+
OT_RPC_CMD_DATA_SET_ACTIVE_TLVS,
41+
OT_RPC_CMD_DATA_GET_ACTIVE_TLVS,
3742
};

subsys/net/openthread/rpc/common/ot_rpc_types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
55
*/
66

7+
#include <stdint.h>
8+
#include <openthread/thread.h>
9+
710
/** @brief Offsets used to encode otNetifAddress bit-fields.
811
*/
912
enum ot_rpc_netif_address_offsets {

subsys/net/openthread/rpc/server/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ zephyr_library_sources(
1010
ot_rpc_cli_server.c
1111
ot_rpc_ctrl_server.c
1212
ot_rpc_if_server.c
13+
ot_rpc_commissioning_server.c
1314
)
1415

1516
zephyr_library_include_directories(
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#include <ot_rpc_ids.h>
8+
#include <ot_rpc_types.h>
9+
#include <ot_rpc_common.h>
10+
11+
#include <nrf_rpc/nrf_rpc_serialize.h>
12+
#include <nrf_rpc/nrf_rpc_cbkproxy.h>
13+
14+
#include <zephyr/net/openthread.h>
15+
16+
#include <openthread/link.h>
17+
18+
#define ACTIVE_SCAN_RESULTS_LENGTH(result) \
19+
sizeof((result)->mExtAddress.m8) + 1 + \
20+
sizeof((result)->mNetworkName.m8) + 1 + \
21+
sizeof((result)->mExtendedPanId.m8) + 1 + \
22+
sizeof((result)->mSteeringData.m8) + 1 + \
23+
sizeof((result)->mPanId) + 1 + \
24+
sizeof((result)->mJoinerUdpPort) + 1 + \
25+
sizeof((result)->mChannel) + 1 + \
26+
sizeof((result)->mRssi) + 1 + \
27+
sizeof((result)->mLqi) + 1 + \
28+
sizeof(uint8_t) + 1 + 3 /* mIsNative, mDiscover, mIsJoinable as booleans */
29+
30+
static void ot_thread_discover_cb(otActiveScanResult *result, void *context, uint32_t callback_slot)
31+
{
32+
struct nrf_rpc_cbor_ctx ctx;
33+
size_t cbor_buffer_size = result ? ACTIVE_SCAN_RESULTS_LENGTH(result) : 1;
34+
35+
cbor_buffer_size += 10; /* for context and callback slot */
36+
NRF_RPC_CBOR_ALLOC(&ot_group, ctx, cbor_buffer_size);
37+
38+
if (result) {
39+
nrf_rpc_encode_buffer(&ctx, result->mExtAddress.m8, OT_EXT_ADDRESS_SIZE);
40+
nrf_rpc_encode_str(&ctx, result->mNetworkName.m8, strlen(result->mNetworkName.m8));
41+
nrf_rpc_encode_buffer(&ctx, result->mExtendedPanId.m8, OT_EXT_PAN_ID_SIZE);
42+
nrf_rpc_encode_buffer(&ctx, result->mSteeringData.m8, OT_STEERING_DATA_MAX_LENGTH);
43+
nrf_rpc_encode_uint(&ctx, result->mPanId);
44+
nrf_rpc_encode_uint(&ctx, result->mJoinerUdpPort);
45+
nrf_rpc_encode_uint(&ctx, result->mChannel);
46+
nrf_rpc_encode_int(&ctx, result->mRssi);
47+
nrf_rpc_encode_uint(&ctx, result->mLqi);
48+
nrf_rpc_encode_uint(&ctx, result->mVersion);
49+
nrf_rpc_encode_bool(&ctx, result->mIsNative);
50+
nrf_rpc_encode_bool(&ctx, result->mDiscover);
51+
nrf_rpc_encode_bool(&ctx, result->mIsJoinable);
52+
} else {
53+
nrf_rpc_encode_null(&ctx);
54+
}
55+
56+
nrf_rpc_encode_uint(&ctx, (uintptr_t)context);
57+
nrf_rpc_encode_uint(&ctx, callback_slot);
58+
59+
nrf_rpc_cbor_cmd_no_err(&ot_group, OT_RPC_CMD_THREAD_DISCOVER_CB, &ctx, ot_rpc_decode_void,
60+
NULL);
61+
}
62+
63+
NRF_RPC_CBKPROXY_HANDLER(ot_thread_discover_cb_encoder, ot_thread_discover_cb,
64+
(otActiveScanResult *result, void *context), (result, context));
65+
66+
static void ot_rpc_thread_discover_rpc_handler(const struct nrf_rpc_group *group,
67+
struct nrf_rpc_cbor_ctx *ctx, void *handler_data)
68+
{
69+
uint32_t scan_channels;
70+
uint16_t pan_id;
71+
bool joiner;
72+
bool enable_eui64_filtering;
73+
otHandleActiveScanResult cb;
74+
void *cb_ctx;
75+
otError error;
76+
77+
scan_channels = nrf_rpc_decode_uint(ctx);
78+
pan_id = nrf_rpc_decode_uint(ctx);
79+
joiner = nrf_rpc_decode_bool(ctx);
80+
enable_eui64_filtering = nrf_rpc_decode_bool(ctx);
81+
cb = (otHandleActiveScanResult)nrf_rpc_decode_callbackd(ctx, ot_thread_discover_cb_encoder);
82+
cb_ctx = (void *)nrf_rpc_decode_uint(ctx);
83+
84+
if (!nrf_rpc_decoding_done_and_check(group, ctx)) {
85+
ot_rpc_report_decoding_error(OT_RPC_CMD_THREAD_DISCOVER);
86+
return;
87+
}
88+
89+
openthread_api_mutex_lock(openthread_get_default_context());
90+
error = otThreadDiscover(openthread_get_default_instance(), scan_channels, pan_id, joiner,
91+
enable_eui64_filtering, cb, cb_ctx);
92+
openthread_api_mutex_unlock(openthread_get_default_context());
93+
94+
nrf_rpc_rsp_send_uint(group, error);
95+
}
96+
97+
NRF_RPC_CBOR_CMD_DECODER(ot_group, ot_rpc_thread_discover, OT_RPC_CMD_THREAD_DISCOVER,
98+
ot_rpc_thread_discover_rpc_handler, NULL);
99+
100+
static void ot_rpc_dataset_is_commissioned_rpc_handler(const struct nrf_rpc_group *group,
101+
struct nrf_rpc_cbor_ctx *ctx,
102+
void *handler_data)
103+
{
104+
bool result;
105+
106+
if (!nrf_rpc_decoding_done_and_check(group, ctx)) {
107+
ot_rpc_report_decoding_error(OT_RPC_CMD_DATASET_IS_COMMISSIONED);
108+
return;
109+
}
110+
111+
openthread_api_mutex_lock(openthread_get_default_context());
112+
result = otDatasetIsCommissioned(openthread_get_default_instance());
113+
openthread_api_mutex_unlock(openthread_get_default_context());
114+
115+
nrf_rpc_rsp_send_bool(group, result);
116+
}
117+
118+
NRF_RPC_CBOR_CMD_DECODER(ot_group, ot_rpc_dataset_is_commissioned,
119+
OT_RPC_CMD_DATASET_IS_COMMISSIONED,
120+
ot_rpc_dataset_is_commissioned_rpc_handler, NULL);
121+
122+
static void ot_rpc_data_set_active_tlvs_rpc_handler(const struct nrf_rpc_group *group,
123+
struct nrf_rpc_cbor_ctx *ctx,
124+
void *handler_data)
125+
{
126+
otOperationalDatasetTlvs dataset;
127+
void *data_ptr = &dataset;
128+
otError error;
129+
130+
ot_rpc_decode_dataset_tlvs(group, ctx, &data_ptr);
131+
132+
if (!nrf_rpc_decoding_done_and_check(group, ctx)) {
133+
ot_rpc_report_decoding_error(OT_RPC_CMD_DATA_SET_ACTIVE_TLVS);
134+
return;
135+
}
136+
137+
if (data_ptr) {
138+
openthread_api_mutex_lock(openthread_get_default_context());
139+
error = otDatasetSetActiveTlvs(openthread_get_default_instance(), &dataset);
140+
openthread_api_mutex_unlock(openthread_get_default_context());
141+
} else {
142+
error = OT_ERROR_INVALID_ARGS;
143+
}
144+
145+
nrf_rpc_rsp_send_uint(group, error);
146+
}
147+
148+
NRF_RPC_CBOR_CMD_DECODER(ot_group, ot_rpc_data_set_active_tlvs, OT_RPC_CMD_DATA_SET_ACTIVE_TLVS,
149+
ot_rpc_data_set_active_tlvs_rpc_handler, NULL);
150+
151+
static void ot_rpc_rsp_send_dataset(otOperationalDatasetTlvs *dataset)
152+
{
153+
struct nrf_rpc_cbor_ctx ctx;
154+
155+
NRF_RPC_CBOR_ALLOC(&ot_group, ctx, dataset ? dataset->mLength + 1 : 1);
156+
nrf_rpc_encode_buffer(&ctx, dataset ? dataset->mTlvs : NULL,
157+
dataset ? dataset->mLength : 0);
158+
nrf_rpc_cbor_rsp_no_err(&ot_group, &ctx);
159+
}
160+
161+
static void ot_rpc_data_get_active_tlvs_rpc_handler(const struct nrf_rpc_group *group,
162+
struct nrf_rpc_cbor_ctx *ctx,
163+
void *handler_data)
164+
{
165+
otOperationalDatasetTlvs dataset;
166+
otError error;
167+
168+
if (!nrf_rpc_decoding_done_and_check(group, ctx)) {
169+
ot_rpc_report_decoding_error(OT_RPC_CMD_DATA_GET_ACTIVE_TLVS);
170+
return;
171+
}
172+
173+
openthread_api_mutex_lock(openthread_get_default_context());
174+
error = otDatasetGetActiveTlvs(openthread_get_default_instance(), &dataset);
175+
openthread_api_mutex_unlock(openthread_get_default_context());
176+
177+
ot_rpc_rsp_send_dataset(error == OT_ERROR_NONE ? &dataset : NULL);
178+
}
179+
180+
NRF_RPC_CBOR_CMD_DECODER(ot_group, ot_rpc_data_get_active_tlvs, OT_RPC_CMD_DATA_GET_ACTIVE_TLVS,
181+
ot_rpc_data_get_active_tlvs_rpc_handler, NULL);

0 commit comments

Comments
 (0)