core: Add infrastructure for packet captures

A callback and user data member is defined to abstract out the
implementation details of capturing the packets. The captured packets
are in DSP0236 form, i.e. no binding metadata is present.

Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Change-Id: Id8234d6e8f7856c70a0ca3fe5d4cee38ec11bd8c
diff --git a/core.c b/core.c
index 1050c4d..4d945db 100644
--- a/core.c
+++ b/core.c
@@ -56,6 +56,10 @@
 	mctp_rx_fn		message_rx;
 	void			*message_rx_data;
 
+	/* Packet capture callback */
+	mctp_capture_fn		capture;
+	void			*capture_data;
+
 	/* Message reassembly.
 	 * @todo: flexible context count
 	 */
@@ -283,6 +287,12 @@
 	mctp->max_message_size = message_size;
 }
 
+void mctp_set_capture_handler(struct mctp *mctp, mctp_capture_fn fn, void *user)
+{
+	mctp->capture = fn;
+	mctp->capture_data = user;
+}
+
 static void mctp_bus_destroy(struct mctp_bus *bus)
 {
 	while (bus->tx_queue_head) {
@@ -514,6 +524,9 @@
 	if (mctp_pktbuf_size(pkt) <= sizeof(struct mctp_hdr))
 		goto out;
 
+	if (mctp->capture)
+		mctp->capture(pkt, mctp->capture_data);
+
 	hdr = mctp_pktbuf_hdr(pkt);
 
 	/* small optimisation: don't bother reassembly if we're going to
@@ -638,9 +651,14 @@
 static int mctp_packet_tx(struct mctp_bus *bus,
 		struct mctp_pktbuf *pkt)
 {
+	struct mctp *mctp = bus->binding->mctp;
+
 	if (bus->state != mctp_bus_state_tx_enabled)
 		return -1;
 
+	if (mctp->capture)
+		mctp->capture(pkt, mctp->capture_data);
+
 	return bus->binding->tx(bus->binding, pkt);
 }
 
diff --git a/libmctp.h b/libmctp.h
index 46bda90..09672ac 100644
--- a/libmctp.h
+++ b/libmctp.h
@@ -67,6 +67,8 @@
 
 struct mctp *mctp_init(void);
 void mctp_set_max_message_size(struct mctp *mctp, size_t message_size);
+typedef void (*mctp_capture_fn)(struct mctp_pktbuf *pkt, void *user);
+void mctp_set_capture_handler(struct mctp *mctp, mctp_capture_fn fn, void *user);
 void mctp_destroy(struct mctp *mctp);
 
 /* Register a binding to the MCTP core, and creates a bus (populating