1 /* bttester.c - Bluetooth Tester */
2
3 /*
4 * Copyright (c) 2015-2016 Intel Corporation
5 * Copyright (c) 2022 Codecoup
6 *
7 * SPDX-License-Identifier: Apache-2.0
8 */
9
10 #include <zephyr/kernel.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <zephyr/types.h>
14 #include <zephyr/device.h>
15 #include <zephyr/drivers/uart.h>
16 #include <zephyr/toolchain.h>
17 #include <zephyr/bluetooth/bluetooth.h>
18 #include <zephyr/sys/byteorder.h>
19 #include <zephyr/drivers/uart_pipe.h>
20
21 #include <zephyr/logging/log.h>
22 #define LOG_MODULE_NAME bttester
23 LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL);
24
25 #include "btp/btp.h"
26
27 #define STACKSIZE CONFIG_BTTESTER_BTP_CMD_THREAD_STACK_SIZE
28 static K_THREAD_STACK_DEFINE(stack, STACKSIZE);
29 static struct k_thread cmd_thread;
30
31 #define CMD_QUEUED 2
32 struct btp_buf {
33 intptr_t _reserved;
34 uint8_t data[BTP_MTU]; /* includes btp header */
35 uint8_t rsp[BTP_DATA_MAX_SIZE];
36 };
37
38 static struct btp_buf cmd_buf[CMD_QUEUED];
39
40 static K_FIFO_DEFINE(cmds_queue);
41 static K_FIFO_DEFINE(avail_queue);
42
43 static struct btp_buf *delayed_cmd;
44
45 static struct {
46 const struct btp_handler *handlers;
47 size_t num;
48 } service_handler[BTP_SERVICE_ID_MAX + 1];
49
50 static struct net_buf_simple *rsp_buf = NET_BUF_SIMPLE(BTP_MTU);
51 static K_MUTEX_DEFINE(rsp_buf_mutex);
52
53 static void tester_send_with_index(uint8_t service, uint8_t opcode, uint8_t index,
54 const uint8_t *data, size_t len);
55 static void tester_rsp_with_index(uint8_t service, uint8_t opcode, uint8_t index,
56 uint8_t status);
57
tester_register_command_handlers(uint8_t service,const struct btp_handler * handlers,size_t num)58 void tester_register_command_handlers(uint8_t service,
59 const struct btp_handler *handlers,
60 size_t num)
61 {
62 __ASSERT_NO_MSG(service <= BTP_SERVICE_ID_MAX);
63 __ASSERT_NO_MSG(service_handler[service].handlers == NULL);
64
65 service_handler[service].handlers = handlers;
66 service_handler[service].num = num;
67 }
68
find_btp_handler(uint8_t service,uint8_t opcode)69 static const struct btp_handler *find_btp_handler(uint8_t service, uint8_t opcode)
70 {
71 if ((service > BTP_SERVICE_ID_MAX) ||
72 (service_handler[service].handlers == NULL)) {
73 return NULL;
74 }
75
76 for (uint8_t i = 0; i < service_handler[service].num; i++) {
77 if (service_handler[service].handlers[i].opcode == opcode) {
78 return &service_handler[service].handlers[i];
79 }
80 }
81
82 return NULL;
83 }
84
cmd_handler(void * p1,void * p2,void * p3)85 static void cmd_handler(void *p1, void *p2, void *p3)
86 {
87 while (1) {
88 const struct btp_handler *btp;
89 struct btp_buf *cmd;
90 struct btp_hdr *hdr;
91 uint8_t status;
92 uint16_t rsp_len = 0;
93
94 cmd = k_fifo_get(&cmds_queue, K_FOREVER);
95 hdr = (struct btp_hdr *)cmd->data;
96
97 LOG_DBG("cmd service 0x%02x opcode 0x%02x index 0x%02x",
98 hdr->service, hdr->opcode, hdr->index);
99
100 btp = find_btp_handler(hdr->service, hdr->opcode);
101 if (btp) {
102 uint16_t len = sys_le16_to_cpu(hdr->len);
103
104 if (len > BTP_DATA_MAX_SIZE) {
105 status = BTP_STATUS_FAILED;
106 } else if (btp->index != hdr->index) {
107 status = BTP_STATUS_FAILED;
108 } else if ((btp->expect_len >= 0) && (btp->expect_len != len)) {
109 status = BTP_STATUS_FAILED;
110 } else {
111 status = btp->func(hdr->data, len,
112 cmd->rsp, &rsp_len);
113 }
114
115 /* This means that caller likely overwrote rsp buffer */
116 __ASSERT_NO_MSG(rsp_len <= BTP_DATA_MAX_SIZE);
117 } else {
118 status = BTP_STATUS_UNKNOWN_CMD;
119 }
120 /* Allow to delay only 1 command. This is for convenience only
121 * of using cmd data without need of copying those in async
122 * functions. Should be not needed eventually.
123 */
124 if (status == BTP_STATUS_DELAY_REPLY) {
125 __ASSERT_NO_MSG(delayed_cmd == NULL);
126 delayed_cmd = cmd;
127 continue;
128 }
129
130 if ((status == BTP_STATUS_SUCCESS) && rsp_len > 0) {
131 tester_send_with_index(hdr->service, hdr->opcode,
132 hdr->index, cmd->rsp, rsp_len);
133 } else {
134 tester_rsp_with_index(hdr->service, hdr->opcode,
135 hdr->index, status);
136 }
137
138 (void)memset(cmd, 0, sizeof(*cmd));
139 k_fifo_put(&avail_queue, cmd);
140 }
141 }
142
recv_cb(uint8_t * buf,size_t * off)143 static uint8_t *recv_cb(uint8_t *buf, size_t *off)
144 {
145 struct btp_hdr *cmd = (void *) buf;
146 struct btp_buf *new_buf;
147 uint16_t len;
148
149 if (*off < sizeof(*cmd)) {
150 return buf;
151 }
152
153 len = sys_le16_to_cpu(cmd->len);
154 if (len > BTP_MTU - sizeof(*cmd)) {
155 LOG_ERR("BT tester: invalid packet length");
156 *off = 0;
157 return buf;
158 }
159
160 if (*off < sizeof(*cmd) + len) {
161 return buf;
162 }
163
164 new_buf = k_fifo_get(&avail_queue, K_NO_WAIT);
165 if (!new_buf) {
166 LOG_ERR("BT tester: RX overflow");
167 *off = 0;
168 return buf;
169 }
170
171 k_fifo_put(&cmds_queue, CONTAINER_OF(buf, struct btp_buf, data[0]));
172
173 *off = 0;
174 return new_buf->data;
175 }
176
177 #if defined(CONFIG_UART_PIPE)
178 /* Uart Pipe */
uart_init(uint8_t * data)179 static void uart_init(uint8_t *data)
180 {
181 uart_pipe_register(data, BTP_MTU, recv_cb);
182 }
183
uart_send(const uint8_t * data,size_t len)184 static void uart_send(const uint8_t *data, size_t len)
185 {
186 uart_pipe_send(data, len);
187 }
188 #else /* !CONFIG_UART_PIPE */
189 static uint8_t *recv_buf;
190 static size_t recv_off;
191 static const struct device *const dev =
192 DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
193
timer_expiry_cb(struct k_timer * timer)194 static void timer_expiry_cb(struct k_timer *timer)
195 {
196 uint8_t c;
197
198 while (uart_poll_in(dev, &c) == 0) {
199 recv_buf[recv_off++] = c;
200 recv_buf = recv_cb(recv_buf, &recv_off);
201 }
202 }
203
204 K_TIMER_DEFINE(timer, timer_expiry_cb, NULL);
205
206 /* Uart Poll */
uart_init(uint8_t * data)207 static void uart_init(uint8_t *data)
208 {
209 __ASSERT_NO_MSG(device_is_ready(dev));
210
211 recv_buf = data;
212
213 k_timer_start(&timer, K_MSEC(10), K_MSEC(10));
214 }
215
uart_send(const uint8_t * data,size_t len)216 static void uart_send(const uint8_t *data, size_t len)
217 {
218 int i;
219
220 for (i = 0; i < len; i++) {
221 uart_poll_out(dev, data[i]);
222 }
223 }
224 #endif /* CONFIG_UART_PIPE */
225
tester_init(void)226 void tester_init(void)
227 {
228 int i;
229 struct btp_buf *buf;
230
231 LOG_DBG("Initializing tester");
232
233 for (i = 0; i < CMD_QUEUED; i++) {
234 k_fifo_put(&avail_queue, &cmd_buf[i]);
235 }
236
237 k_thread_create(&cmd_thread, stack, STACKSIZE, cmd_handler,
238 NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT);
239
240 buf = k_fifo_get(&avail_queue, K_NO_WAIT);
241
242 uart_init(buf->data);
243
244 /* core service is always available */
245 tester_init_core();
246
247 tester_send_with_index(BTP_SERVICE_ID_CORE, BTP_CORE_EV_IUT_READY,
248 BTP_INDEX_NONE, NULL, 0);
249 }
250
tester_rsp_buffer_lock(void)251 int tester_rsp_buffer_lock(void)
252 {
253 if (k_mutex_lock(&rsp_buf_mutex, Z_FOREVER) != 0) {
254 LOG_ERR("Cannot lock rsp_ring_buf");
255
256 return -EACCES;
257 }
258
259 return 0;
260 }
261
tester_rsp_buffer_unlock(void)262 void tester_rsp_buffer_unlock(void)
263 {
264 k_mutex_unlock(&rsp_buf_mutex);
265 }
266
tester_rsp_buffer_free(void)267 void tester_rsp_buffer_free(void)
268 {
269 net_buf_simple_init(rsp_buf, 0);
270 }
271
tester_rsp_buffer_allocate(size_t len,uint8_t ** data)272 void tester_rsp_buffer_allocate(size_t len, uint8_t **data)
273 {
274 tester_rsp_buffer_free();
275
276 *data = net_buf_simple_add(rsp_buf, len);
277 }
278
tester_send_with_index(uint8_t service,uint8_t opcode,uint8_t index,const uint8_t * data,size_t len)279 static void tester_send_with_index(uint8_t service, uint8_t opcode, uint8_t index,
280 const uint8_t *data, size_t len)
281 {
282 struct btp_hdr msg;
283
284 msg.service = service;
285 msg.opcode = opcode;
286 msg.index = index;
287 msg.len = sys_cpu_to_le16(len);
288
289 uart_send((uint8_t *)&msg, sizeof(msg));
290 if (data && len) {
291 uart_send(data, len);
292 }
293 }
294
tester_rsp_with_index(uint8_t service,uint8_t opcode,uint8_t index,uint8_t status)295 static void tester_rsp_with_index(uint8_t service, uint8_t opcode, uint8_t index,
296 uint8_t status)
297 {
298 struct btp_status s;
299
300 LOG_DBG("service 0x%02x opcode 0x%02x index 0x%02x status 0x%02x", service, opcode, index,
301 status);
302
303 if (status == BTP_STATUS_SUCCESS) {
304 tester_send_with_index(service, opcode, index, NULL, 0);
305 return;
306 }
307
308 s.code = status;
309 tester_send_with_index(service, BTP_STATUS, index, (uint8_t *) &s, sizeof(s));
310 }
311
tester_event(uint8_t service,uint8_t opcode,const void * data,size_t len)312 void tester_event(uint8_t service, uint8_t opcode, const void *data, size_t len)
313 {
314 __ASSERT_NO_MSG(opcode >= 0x80);
315
316 LOG_DBG("service 0x%02x opcode 0x%02x", service, opcode);
317
318 tester_send_with_index(service, opcode, BTP_INDEX, data, len);
319 }
320
tester_rsp_full(uint8_t service,uint8_t opcode,const void * rsp,size_t len)321 void tester_rsp_full(uint8_t service, uint8_t opcode, const void *rsp, size_t len)
322 {
323 struct btp_buf *cmd;
324
325 __ASSERT_NO_MSG(opcode < 0x80);
326 __ASSERT_NO_MSG(delayed_cmd != NULL);
327
328 LOG_DBG("service 0x%02x opcode 0x%02x", service, opcode);
329
330 tester_send_with_index(service, opcode, BTP_INDEX, rsp, len);
331
332 cmd = delayed_cmd;
333 delayed_cmd = NULL;
334
335 (void)memset(cmd, 0, sizeof(*cmd));
336 k_fifo_put(&avail_queue, cmd);
337 }
338
tester_rsp(uint8_t service,uint8_t opcode,uint8_t status)339 void tester_rsp(uint8_t service, uint8_t opcode, uint8_t status)
340 {
341 struct btp_buf *cmd;
342
343 __ASSERT_NO_MSG(opcode < 0x80);
344 __ASSERT_NO_MSG(delayed_cmd != NULL);
345
346 LOG_DBG("service 0x%02x opcode 0x%02x status 0x%02x", service, opcode, status);
347
348 tester_rsp_with_index(service, opcode, BTP_INDEX, status);
349
350 cmd = delayed_cmd;
351 delayed_cmd = NULL;
352
353 (void)memset(cmd, 0, sizeof(*cmd));
354 k_fifo_put(&avail_queue, cmd);
355 }
356