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