1 /*
2 * Copyright (c) 2023, Meta
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/console/console.h>
8 #include <zephyr/drivers/misc/devmux/devmux.h>
9 #include <zephyr/drivers/serial/uart_emul.h>
10 #include <zephyr/kernel.h>
11 #include <zephyr/ztest.h>
12
13 #define BUF_SIZE 32
14
15 /* array of const struct device* */
16 static const struct device *devs[] = {
17 DT_FOREACH_PROP_ELEM_SEP(DT_NODELABEL(devmux0), devices, DEVICE_DT_GET_BY_IDX, (,))};
18
19 /* array of names, e.g. "euart0" */
20 #define PHANDLE_TO_NAME(node_id, prop, idx) DT_NODE_FULL_NAME(DT_PHANDLE_BY_IDX(node_id, prop, idx))
21 static const char *const name[] = {
22 DT_FOREACH_PROP_ELEM_SEP(DT_NODELABEL(devmux0), devices, PHANDLE_TO_NAME, (,))};
23
24 /* array of greetings, e.g. "Hello, euart0!" */
25 #define PHANDLE_TO_TEXT(node_id, prop, idx) \
26 "Hello, " DT_NODE_FULL_NAME(DT_PHANDLE_BY_IDX(node_id, prop, idx)) "!"
27 static const char *const text[] = {
28 DT_FOREACH_PROP_ELEM_SEP(DT_NODELABEL(devmux0), devices, PHANDLE_TO_TEXT, (,))};
29
ZTEST(console_switching,test_write)30 ZTEST(console_switching, test_write)
31 {
32 size_t normal_uart = DT_PROP(DT_NODELABEL(devmux0), selected);
33 struct device *const devmux_dev = DEVICE_DT_GET(DT_NODELABEL(devmux0));
34
35 /* for each uart_emul device */
36 for (size_t i = 0, j = 0, N = ARRAY_SIZE(devs); i < 2 * N; i++, j++, j %= N) {
37 if (j == normal_uart) {
38 /* skip testing non-emul uart */
39 continue;
40 }
41
42 int ret[4];
43 char buf[BUF_SIZE] = {0};
44
45 /* write text[j] to dev[j] */
46 ret[0] = devmux_select_set(devmux_dev, j);
47 printk("%s", text[j]);
48 ret[1] = uart_emul_get_tx_data(devs[j], buf, ARRAY_SIZE(buf));
49 ret[2] = devmux_select_set(devmux_dev, normal_uart);
50
51 zassert_ok(ret[0], "Failed to select devmux %zu", j);
52 zassert_ok(ret[2], "Switching back to selection %zu failed", normal_uart);
53
54 /* verify that text[j] was written to dev[j] */
55 TC_PRINT("wrote '%s' to %s\n", buf, name[j]);
56
57 zassert_equal(ret[1], strlen(text[j]), "Only wrote %d/%zu bytes of '%s'",
58 ret[1], strlen(text[j]), text[j]);
59 zassert_equal(0, strcmp(text[j], buf), "Strings '%s' and '%s' do not match",
60 text[j], buf);
61 }
62 }
63
ZTEST(console_switching,test_read)64 ZTEST(console_switching, test_read)
65 {
66 size_t normal_uart = DT_PROP(DT_NODELABEL(devmux0), selected);
67 struct device *const devmux_dev = DEVICE_DT_GET(DT_NODELABEL(devmux0));
68
69 /* for each uart_emul device */
70 for (size_t i = 0, j = 0, N = ARRAY_SIZE(devs); i < 2 * N; i++, j++, j %= N) {
71 if (j == normal_uart) {
72 /* skip testing non-emul uart */
73 continue;
74 }
75
76 int ret[4];
77 char buf[BUF_SIZE] = {0};
78
79 /* read text[j] from dev[j] */
80 ret[0] = devmux_select_set(devmux_dev, j);
81 console_getline_init();
82 ret[1] = uart_emul_put_rx_data(devs[j], (uint8_t *)text[j], strlen(text[j]));
83 ret[3] = uart_emul_put_rx_data(devs[j], "\n", 1);
84 snprintf(buf, BUF_SIZE, "%s", console_getline());
85 ret[2] = devmux_select_set(devmux_dev, normal_uart);
86
87 zassert_ok(ret[0], "Failed to select devmux %zu", j);
88 zassert_ok(ret[2], "Switching back to selection %zu failed", normal_uart);
89
90 /* verify that text[j] was written to dev[j] */
91 TC_PRINT("read '%s' from %s\n", buf, name[j]);
92
93 zassert_equal(ret[1], strlen(text[j]), "Only put %d/%zu bytes of '%s'",
94 ret[1], strlen(text[j]), text[j]);
95 zassert_equal(0, strcmp(text[j], buf), "Strings '%s' and '%s' do not match",
96 text[j], buf);
97 }
98 }
99
setup(void)100 static void *setup(void)
101 {
102 size_t selected = DT_PROP(DT_NODELABEL(devmux1), selected);
103 struct device *const devmux_dev = DEVICE_DT_GET(DT_NODELABEL(devmux1));
104
105 /* ensure that non-default initial selection via DT works */
106 zassert_equal(devmux_select_get(devmux_dev), selected);
107
108 return NULL;
109 }
110
before(void * arg)111 static void before(void *arg)
112 {
113 struct device *const devmux_dev = DEVICE_DT_GET(DT_NODELABEL(devmux0));
114
115 zassert_ok(devmux_select_set(devmux_dev, 0));
116 zassert_ok(devmux_select_get(devmux_dev));
117
118 for (size_t i = 1; i < ARRAY_SIZE(devs); ++i) {
119 uart_emul_flush_tx_data(devs[i]);
120 }
121 }
122
123 ZTEST_SUITE(console_switching, NULL, setup, before, NULL, NULL);
124