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