1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/net_buf.h>
8 #include <zephyr/kernel.h>
9 #include <string.h>
10 #include <zephyr/mgmt/mcumgr/smp/smp_client.h>
11 #include <zephyr/mgmt/mcumgr/mgmt/mgmt.h>
12 #include <zephyr/sys/byteorder.h>
13 #include <mgmt/mcumgr/transport/smp_internal.h>
14 #include "smp_stub.h"
15 
16 K_THREAD_STACK_DEFINE(smp_stub_work_queue_stack, CONFIG_MCUMGR_TRANSPORT_WORKQUEUE_STACK_SIZE);
17 
18 static mcmgr_client_data_check_fn rx_verify_cb;
19 static int send_client_failure;
20 static struct net_buf *response_buf;
21 static struct smp_hdr res_hdr;
22 static struct smp_transport smpt_test;
23 static struct smp_client_transport_entry smp_client_transport;
24 static struct k_work_q smp_work_queue;
25 static struct k_work stub_work;
26 
27 static const struct k_work_queue_config smp_work_queue_config = {
28 	.name = "mcumgr smp"
29 };
30 
smp_stub_set_rx_data_verify(mcmgr_client_data_check_fn cb)31 void smp_stub_set_rx_data_verify(mcmgr_client_data_check_fn cb)
32 {
33 	rx_verify_cb = cb;
34 }
35 
smp_client_send_status_stub(int status)36 void smp_client_send_status_stub(int status)
37 {
38 	send_client_failure = status;
39 }
40 
smp_response_buf_allocation(void)41 struct net_buf *smp_response_buf_allocation(void)
42 {
43 	smp_client_response_buf_clean();
44 
45 	response_buf = smp_packet_alloc();
46 
47 	return response_buf;
48 }
49 
smp_client_response_buf_clean(void)50 void smp_client_response_buf_clean(void)
51 {
52 	if (response_buf) {
53 		smp_client_buf_free(response_buf);
54 		response_buf = NULL;
55 	}
56 }
57 
smp_transport_read_hdr(const struct net_buf * nb,struct smp_hdr * dst_hdr)58 void smp_transport_read_hdr(const struct net_buf *nb, struct smp_hdr *dst_hdr)
59 {
60 	memcpy(dst_hdr, nb->data, sizeof(*dst_hdr));
61 	dst_hdr->nh_len = sys_be16_to_cpu(dst_hdr->nh_len);
62 	dst_hdr->nh_group = sys_be16_to_cpu(dst_hdr->nh_group);
63 }
64 
65 
smp_uart_get_mtu(const struct net_buf * nb)66 static uint16_t smp_uart_get_mtu(const struct net_buf *nb)
67 {
68 	return 256;
69 }
70 
smp_uart_tx_pkt(struct net_buf * nb)71 static int smp_uart_tx_pkt(struct net_buf *nb)
72 {
73 	if (send_client_failure) {
74 		/* Test Send cmd fail */
75 		return send_client_failure;
76 	}
77 
78 	memcpy(&res_hdr, nb->data, sizeof(res_hdr));
79 	res_hdr.nh_len = sys_be16_to_cpu(res_hdr.nh_len);
80 	res_hdr.nh_group = sys_be16_to_cpu(res_hdr.nh_group);
81 	res_hdr.nh_op += 1; /* Request to response */
82 
83 	/* Validate Input data if callback is configured */
84 	if (rx_verify_cb) {
85 		rx_verify_cb(nb);
86 	}
87 
88 	/* Free tx buf */
89 	net_buf_unref(nb);
90 
91 	if (response_buf) {
92 		k_work_submit_to_queue(&smp_work_queue, &stub_work);
93 	}
94 
95 	return 0;
96 }
97 
smp_client_handle_reqs(struct k_work * work)98 static void smp_client_handle_reqs(struct k_work *work)
99 {
100 	if (response_buf) {
101 		smp_client_single_response(response_buf, &res_hdr);
102 	}
103 }
104 
stub_smp_client_transport_register(void)105 void stub_smp_client_transport_register(void)
106 {
107 
108 	smpt_test.functions.output = smp_uart_tx_pkt;
109 	smpt_test.functions.get_mtu = smp_uart_get_mtu;
110 
111 	smp_transport_init(&smpt_test);
112 	smp_client_transport.smpt = &smpt_test;
113 	smp_client_transport.smpt_type = SMP_SERIAL_TRANSPORT;
114 	smp_client_transport_register(&smp_client_transport);
115 
116 
117 	k_work_queue_init(&smp_work_queue);
118 
119 	k_work_queue_start(&smp_work_queue, smp_stub_work_queue_stack,
120 			   K_THREAD_STACK_SIZEOF(smp_stub_work_queue_stack),
121 			   CONFIG_MCUMGR_TRANSPORT_WORKQUEUE_THREAD_PRIO, &smp_work_queue_config);
122 
123 	k_work_init(&stub_work, smp_client_handle_reqs);
124 }
125