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 <errno.h> 19 #include <fcntl.h> 20 #include <stdbool.h> 21 #include <stdio.h> 22 #include <string.h> 23 #include <unistd.h> 24 25 struct mctp_binding_serial_pipe { 26 int ingress; 27 int egress; 28 29 struct mctp_binding_serial *serial; 30 }; 31 32 static int mctp_binding_serial_pipe_tx(void *data, void *buf, size_t len) 33 { 34 struct mctp_binding_serial_pipe *ctx = data; 35 ssize_t rc; 36 37 rc = write(ctx->egress, buf, len); 38 assert(rc >= 0); 39 assert((size_t)rc == len); 40 41 return rc; 42 } 43 44 uint8_t mctp_msg_src[2 * MCTP_BTU]; 45 46 static bool seen; 47 static bool received_tag_owner; 48 static uint8_t received_msg_tag; 49 50 static void rx_message(uint8_t eid __unused, bool tag_owner, uint8_t msg_tag, 51 void *data __unused, void *msg, size_t len) 52 { 53 uint8_t type; 54 55 type = *(uint8_t *)msg; 56 57 mctp_prdebug("MCTP message received: len %zd, type %d, tag %d", len, 58 type, msg_tag); 59 60 assert(sizeof(mctp_msg_src) == len); 61 assert(!memcmp(mctp_msg_src, msg, len)); 62 63 seen = true; 64 received_msg_tag = msg_tag; 65 received_tag_owner = tag_owner; 66 } 67 68 struct serial_test { 69 struct mctp_binding_serial_pipe binding; 70 struct mctp *mctp; 71 }; 72 73 int main(void) 74 { 75 struct serial_test scenario[2]; 76 77 struct mctp_binding_serial_pipe *a; 78 struct mctp_binding_serial_pipe *b; 79 uint8_t msg_tag = 2; 80 bool tag_owner = false; 81 int p[2][2]; 82 int rc; 83 84 mctp_set_log_stdio(MCTP_LOG_DEBUG); 85 86 /* 87 * Adding data bytes (0x7e & 0x7d) for testing FCS calculation while the 88 * escaped data is presented. 89 * 90 * Refer to DSP0253 chapter 7, data byte 0x7e / 0x7d should be replaced 91 * to escape sequence 0x7d 0x5e / 0x7d 0x5d. 92 * 93 * For sender, FCS calculation should count data byte (0x7e / 0x7d) only, 94 * not the escape sequece. For receiver, the escape sequence should be 95 * translated back to data byte and put it in FCS calculation. 96 * 97 * If FCS calculation is not expected, similiar error msg 98 * `serial: invalid fcs : 0xf5c1, expect 0x1d3e` will be observed. 99 */ 100 memset(&mctp_msg_src[0], 0x7e, 1); 101 memset(&mctp_msg_src[1], 0x7d, 1); 102 memset(&mctp_msg_src[2], 0x5a, MCTP_BTU - 2); 103 memset(&mctp_msg_src[MCTP_BTU], 0xa5, MCTP_BTU); 104 105 rc = pipe(p[0]); 106 assert(!rc); 107 108 rc = pipe(p[1]); 109 assert(!rc); 110 111 /* Instantiate the A side of the serial pipe */ 112 scenario[0].mctp = mctp_init(); 113 assert(scenario[0].mctp); 114 scenario[0].binding.serial = mctp_serial_init(); 115 assert(scenario[0].binding.serial); 116 a = &scenario[0].binding; 117 a->ingress = p[0][0]; 118 a->egress = p[1][1]; 119 mctp_serial_open_fd(a->serial, a->ingress); 120 mctp_serial_set_tx_fn(a->serial, mctp_binding_serial_pipe_tx, a); 121 mctp_register_bus(scenario[0].mctp, mctp_binding_serial_core(a->serial), 122 8); 123 124 /* Instantiate the B side of the serial pipe */ 125 scenario[1].mctp = mctp_init(); 126 assert(scenario[1].mctp); 127 mctp_set_rx_all(scenario[1].mctp, rx_message, NULL); 128 scenario[1].binding.serial = mctp_serial_init(); 129 assert(scenario[1].binding.serial); 130 b = &scenario[1].binding; 131 b->ingress = p[1][0]; 132 b->egress = p[0][1]; 133 mctp_serial_open_fd(b->serial, b->ingress); 134 mctp_serial_set_tx_fn(b->serial, mctp_binding_serial_pipe_tx, a); 135 mctp_register_bus(scenario[1].mctp, mctp_binding_serial_core(b->serial), 136 9); 137 138 /* Transmit a message from A to B, with message tag */ 139 rc = mctp_message_tx(scenario[0].mctp, 9, tag_owner, msg_tag, 140 mctp_msg_src, sizeof(mctp_msg_src)); 141 assert(rc == 0); 142 143 /* Read the message at B from A */ 144 seen = false; 145 received_tag_owner = true; 146 received_msg_tag = 0; 147 mctp_serial_read(b->serial); 148 assert(seen); 149 assert(received_tag_owner == tag_owner); 150 assert(received_msg_tag == msg_tag); 151 152 mctp_serial_destroy(scenario[1].binding.serial); 153 mctp_destroy(scenario[1].mctp); 154 mctp_serial_destroy(scenario[0].binding.serial); 155 mctp_destroy(scenario[0].mctp); 156 157 return 0; 158 } 159