xref: /openbmc/libmctp/tests/test_serial.c (revision 6896d41e)
1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2 
3 #define _GNU_SOURCE
4 
5 #if HAVE_CONFIG_H
6 #include "config.h"
7 #endif
8 
9 #include "libmctp-log.h"
10 #include "libmctp-serial.h"
11 
12 #ifdef NDEBUG
13 #undef NDEBUG
14 #endif
15 
16 #include <assert.h>
17 #include <fcntl.h>
18 #include <stdbool.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <unistd.h>
22 
23 struct mctp_binding_serial_pipe {
24 	int ingress;
25 	int egress;
26 
27 	struct mctp_binding_serial *serial;
28 };
29 
30 static int mctp_binding_serial_pipe_tx(void *data, void *buf, size_t len)
31 {
32 	struct mctp_binding_serial_pipe *ctx = data;
33 	ssize_t rc;
34 
35 	rc = write(ctx->egress, buf, len);
36 	assert(rc == len);
37 
38 	return rc;
39 }
40 
41 uint8_t mctp_msg_src[2 * MCTP_BTU];
42 
43 static bool seen;
44 
45 static void rx_message(uint8_t eid, void *data, void *msg, size_t len)
46 {
47 	uint8_t type;
48 
49 	type = *(uint8_t *)msg;
50 
51 	mctp_prdebug("MCTP message received: len %zd, type %d", len, type);
52 
53 	assert(sizeof(mctp_msg_src) == len);
54 	assert(!memcmp(mctp_msg_src, msg, len));
55 
56 	seen = true;
57 }
58 
59 struct serial_test {
60 	struct mctp_binding_serial_pipe binding;
61 	struct mctp *mctp;
62 };
63 
64 int main(void)
65 {
66 	struct serial_test scenario[2];
67 
68 	struct mctp_binding_serial_pipe *a;
69 	struct mctp_binding_serial_pipe *b;
70 	int p[2][2];
71 	int rc;
72 
73 	mctp_set_log_stdio(MCTP_LOG_DEBUG);
74 
75 	memset(&mctp_msg_src[0], 0x5a, MCTP_BTU);
76 	memset(&mctp_msg_src[MCTP_BTU], 0xa5, MCTP_BTU);
77 
78 	rc = pipe(p[0]);
79 	assert(!rc);
80 
81 	rc = pipe(p[1]);
82 	assert(!rc);
83 
84 	/* Instantiate the A side of the serial pipe */
85 	scenario[0].mctp = mctp_init();
86 	assert(scenario[0].mctp);
87 	scenario[0].binding.serial = mctp_serial_init();
88 	assert(scenario[0].binding.serial);
89 	a = &scenario[0].binding;
90 	a->ingress = p[0][0];
91 	a->egress = p[1][1];
92 	mctp_serial_open_fd(a->serial, a->ingress);
93 	mctp_serial_set_tx_fn(a->serial, mctp_binding_serial_pipe_tx, a);
94 	mctp_register_bus(scenario[0].mctp, mctp_binding_serial_core(a->serial), 8);
95 
96 	/* Instantiate the B side of the serial pipe */
97 	scenario[1].mctp = mctp_init();
98 	assert(scenario[1].mctp);
99 	mctp_set_rx_all(scenario[1].mctp, rx_message, NULL);
100 	scenario[1].binding.serial = mctp_serial_init();
101 	assert(scenario[1].binding.serial);
102 	b = &scenario[1].binding;
103 	b->ingress = p[1][0];
104 	b->egress = p[0][1];
105 	mctp_serial_open_fd(b->serial, b->ingress);
106 	mctp_serial_set_tx_fn(b->serial, mctp_binding_serial_pipe_tx, a);
107 	mctp_register_bus(scenario[1].mctp, mctp_binding_serial_core(b->serial), 9);
108 
109 	/* Transmit a message from A to B */
110 	rc = mctp_message_tx(scenario[0].mctp, 9, mctp_msg_src, sizeof(mctp_msg_src));
111 	assert(rc == 0);
112 
113 	/* Read the message at B from A */
114 	seen = false;
115 	mctp_serial_read(b->serial);
116 	assert(seen);
117 
118 	mctp_serial_destroy(scenario[1].binding.serial);
119 	mctp_destroy(scenario[1].mctp);
120 	mctp_serial_destroy(scenario[0].binding.serial);
121 	mctp_destroy(scenario[0].mctp);
122 
123 	return 0;
124 }
125