xref: /openbmc/libmctp/tests/test_serial.c (revision ac1cd9dc)
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 >= 0);
37 	assert((size_t)rc == len);
38 
39 	return rc;
40 }
41 
42 uint8_t mctp_msg_src[2 * MCTP_BTU];
43 
44 static bool seen;
45 
46 #define __unused __attribute__((unused))
47 
48 static void rx_message(uint8_t eid __unused, void *data __unused, void *msg,
49 		       size_t len)
50 {
51 	uint8_t type;
52 
53 	type = *(uint8_t *)msg;
54 
55 	mctp_prdebug("MCTP message received: len %zd, type %d", len, type);
56 
57 	assert(sizeof(mctp_msg_src) == len);
58 	assert(!memcmp(mctp_msg_src, msg, len));
59 
60 	seen = true;
61 }
62 
63 struct serial_test {
64 	struct mctp_binding_serial_pipe binding;
65 	struct mctp *mctp;
66 };
67 
68 int main(void)
69 {
70 	struct serial_test scenario[2];
71 
72 	struct mctp_binding_serial_pipe *a;
73 	struct mctp_binding_serial_pipe *b;
74 	int p[2][2];
75 	int rc;
76 
77 	mctp_set_log_stdio(MCTP_LOG_DEBUG);
78 
79 	memset(&mctp_msg_src[0], 0x5a, MCTP_BTU);
80 	memset(&mctp_msg_src[MCTP_BTU], 0xa5, MCTP_BTU);
81 
82 	rc = pipe(p[0]);
83 	assert(!rc);
84 
85 	rc = pipe(p[1]);
86 	assert(!rc);
87 
88 	/* Instantiate the A side of the serial pipe */
89 	scenario[0].mctp = mctp_init();
90 	assert(scenario[0].mctp);
91 	scenario[0].binding.serial = mctp_serial_init();
92 	assert(scenario[0].binding.serial);
93 	a = &scenario[0].binding;
94 	a->ingress = p[0][0];
95 	a->egress = p[1][1];
96 	mctp_serial_open_fd(a->serial, a->ingress);
97 	mctp_serial_set_tx_fn(a->serial, mctp_binding_serial_pipe_tx, a);
98 	mctp_register_bus(scenario[0].mctp, mctp_binding_serial_core(a->serial), 8);
99 
100 	/* Instantiate the B side of the serial pipe */
101 	scenario[1].mctp = mctp_init();
102 	assert(scenario[1].mctp);
103 	mctp_set_rx_all(scenario[1].mctp, rx_message, NULL);
104 	scenario[1].binding.serial = mctp_serial_init();
105 	assert(scenario[1].binding.serial);
106 	b = &scenario[1].binding;
107 	b->ingress = p[1][0];
108 	b->egress = p[0][1];
109 	mctp_serial_open_fd(b->serial, b->ingress);
110 	mctp_serial_set_tx_fn(b->serial, mctp_binding_serial_pipe_tx, a);
111 	mctp_register_bus(scenario[1].mctp, mctp_binding_serial_core(b->serial), 9);
112 
113 	/* Transmit a message from A to B */
114 	rc = mctp_message_tx(scenario[0].mctp, 9, mctp_msg_src, sizeof(mctp_msg_src));
115 	assert(rc == 0);
116 
117 	/* Read the message at B from A */
118 	seen = false;
119 	mctp_serial_read(b->serial);
120 	assert(seen);
121 
122 	mctp_serial_destroy(scenario[1].binding.serial);
123 	mctp_destroy(scenario[1].mctp);
124 	mctp_serial_destroy(scenario[0].binding.serial);
125 	mctp_destroy(scenario[0].mctp);
126 
127 	return 0;
128 }
129