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