/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #define _GNU_SOURCE #if HAVE_CONFIG_H #include "config.h" #endif #include "compiler.h" #include "libmctp-log.h" #include "libmctp-serial.h" #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include #include #include #include struct mctp_binding_serial_pipe { int ingress; int egress; struct mctp_binding_serial *serial; }; static int mctp_binding_serial_pipe_tx(void *data, void *buf, size_t len) { struct mctp_binding_serial_pipe *ctx = data; ssize_t rc; rc = write(ctx->egress, buf, len); assert(rc >= 0); assert((size_t)rc == len); return rc; } uint8_t mctp_msg_src[2 * MCTP_BTU]; static bool seen; static bool received_tag_owner; static uint8_t received_msg_tag; static void rx_message(uint8_t eid __unused, bool tag_owner, uint8_t msg_tag, void *data __unused, void *msg, size_t len) { uint8_t type; type = *(uint8_t *)msg; mctp_prdebug("MCTP message received: len %zd, type %d, tag %d", len, type, msg_tag); assert(sizeof(mctp_msg_src) == len); assert(!memcmp(mctp_msg_src, msg, len)); seen = true; received_msg_tag = msg_tag; received_tag_owner = tag_owner; } struct serial_test { struct mctp_binding_serial_pipe binding; struct mctp *mctp; }; int main(void) { struct serial_test scenario[2]; struct mctp_binding_serial_pipe *a; struct mctp_binding_serial_pipe *b; uint8_t msg_tag = 2; bool tag_owner = false; int p[2][2]; int rc; mctp_set_log_stdio(MCTP_LOG_DEBUG); /* * Adding data bytes (0x7e & 0x7d) for testing FCS calculation while the * escaped data is presented. * * Refer to DSP0253 chapter 7, data byte 0x7e / 0x7d should be replaced * to escape sequence 0x7d 0x5e / 0x7d 0x5d. * * For sender, FCS calculation should count data byte (0x7e / 0x7d) only, * not the escape sequece. For receiver, the escape sequence should be * translated back to data byte and put it in FCS calculation. * * If FCS calculation is not expected, similiar error msg * `serial: invalid fcs : 0xf5c1, expect 0x1d3e` will be observed. */ memset(&mctp_msg_src[0], 0x7e, 1); memset(&mctp_msg_src[1], 0x7d, 1); memset(&mctp_msg_src[2], 0x5a, MCTP_BTU - 2); memset(&mctp_msg_src[MCTP_BTU], 0xa5, MCTP_BTU); rc = pipe(p[0]); assert(!rc); rc = pipe(p[1]); assert(!rc); /* Instantiate the A side of the serial pipe */ scenario[0].mctp = mctp_init(); assert(scenario[0].mctp); scenario[0].binding.serial = mctp_serial_init(); assert(scenario[0].binding.serial); a = &scenario[0].binding; a->ingress = p[0][0]; a->egress = p[1][1]; mctp_serial_open_fd(a->serial, a->ingress); mctp_serial_set_tx_fn(a->serial, mctp_binding_serial_pipe_tx, a); mctp_register_bus(scenario[0].mctp, mctp_binding_serial_core(a->serial), 8); /* Instantiate the B side of the serial pipe */ scenario[1].mctp = mctp_init(); assert(scenario[1].mctp); mctp_set_rx_all(scenario[1].mctp, rx_message, NULL); scenario[1].binding.serial = mctp_serial_init(); assert(scenario[1].binding.serial); b = &scenario[1].binding; b->ingress = p[1][0]; b->egress = p[0][1]; mctp_serial_open_fd(b->serial, b->ingress); mctp_serial_set_tx_fn(b->serial, mctp_binding_serial_pipe_tx, a); mctp_register_bus(scenario[1].mctp, mctp_binding_serial_core(b->serial), 9); /* Transmit a message from A to B, with message tag */ rc = mctp_message_tx(scenario[0].mctp, 9, tag_owner, msg_tag, mctp_msg_src, sizeof(mctp_msg_src)); assert(rc == 0); /* Read the message at B from A */ seen = false; received_tag_owner = true; received_msg_tag = 0; mctp_serial_read(b->serial); assert(seen); assert(received_tag_owner == tag_owner); assert(received_msg_tag == msg_tag); mctp_serial_destroy(scenario[1].binding.serial); mctp_destroy(scenario[1].mctp); mctp_serial_destroy(scenario[0].binding.serial); mctp_destroy(scenario[0].mctp); return 0; }