diff --git a/include/libcamera/ipa/raspberrypi.h b/include/libcamera/ipa/raspberrypi.h
index ca62990e..fa7efdbc 100644
--- a/include/libcamera/ipa/raspberrypi.h
+++ b/include/libcamera/ipa/raspberrypi.h
@@ -9,24 +9,7 @@
 
 #include <libcamera/control_ids.h>
 #include <libcamera/controls.h>
-
-enum RPiConfigParameters {
-	RPI_IPA_CONFIG_LS_TABLE = (1 << 0),
-	RPI_IPA_CONFIG_STAGGERED_WRITE = (1 << 1),
-	RPI_IPA_CONFIG_SENSOR = (1 << 2),
-};
-
-enum RPiOperations {
-	RPI_IPA_ACTION_V4L2_SET_STAGGERED = 1,
-	RPI_IPA_ACTION_V4L2_SET_ISP,
-	RPI_IPA_ACTION_STATS_METADATA_COMPLETE,
-	RPI_IPA_ACTION_RUN_ISP,
-	RPI_IPA_ACTION_RUN_ISP_AND_DROP_FRAME,
-	RPI_IPA_ACTION_EMBEDDED_COMPLETE,
-	RPI_IPA_EVENT_SIGNAL_STAT_READY,
-	RPI_IPA_EVENT_SIGNAL_ISP_PREPARE,
-	RPI_IPA_EVENT_QUEUE_REQUEST,
-};
+#include <libcamera/ipa/ipa_interface.h>
 
 enum RPiIpaMask {
 	ID		= 0x0ffff,
@@ -40,6 +23,10 @@ enum RPiIpaMask {
 
 namespace libcamera {
 
+struct RPiConfigureParams;
+struct RPiEventParams;
+struct RPiActionParams;
+
 /* List of controls handled by the Raspberry Pi IPA */
 static const ControlInfoMap RPiControls = {
 	{ &controls::AeEnable, ControlInfo(false, true) },
@@ -59,6 +46,44 @@ static const ControlInfoMap RPiControls = {
 	{ &controls::ColourCorrectionMatrix, ControlInfo(-16.0f, 16.0f) },
 };
 
+// TODO this needs to be automatically generated too
+enum RPiCMD {
+	CMD_INIT = 1,
+	CMD_EXIT,
+	CMD_START,
+	CMD_STOP,
+	CMD_CONFIGURE,
+	CMD_MAPBUFFERS,
+	CMD_UNMAPBUFFERS,
+	CMD_PROCESSEVENT,
+	CMD_QUEUEFRAMEACTION,
+};
+
+// This needs to be here so that the rpi proxy and worker can include it
+// Still needs to inherit from IPAInterface for IPAModule to work
+// TODO This needs to be automatically generated... so put in a different
+// header too, probably
+class IPARPiInterface : public IPAInterface
+{
+public:
+	virtual ~IPARPiInterface() {};
+
+	virtual int init(const IPASettings &settings) = 0;
+	virtual int start() = 0;
+	virtual void stop() = 0;
+
+	virtual void configure(const CameraSensorInfo &sensorInfo,
+			       const std::map<unsigned int, IPAStream> &streamConfig,
+			       const std::map<unsigned int, const ControlInfoMap> &entityControls,
+			       const RPiConfigureParams &data,
+			       RPiConfigureParams *response) = 0;
+	virtual void mapBuffers(const std::vector<IPABuffer> &buffers) = 0;
+	virtual void unmapBuffers(const std::vector<unsigned int> &ids) = 0;
+	virtual void processEvent(const RPiEventParams &event) = 0;
+
+	Signal<unsigned int, const RPiActionParams &> queueFrameAction;
+};
+
 } /* namespace libcamera */
 
 #endif /* __LIBCAMERA_IPA_INTERFACE_RASPBERRYPI_H__ */
diff --git a/include/libcamera/ipa/raspberrypi.mojom b/include/libcamera/ipa/raspberrypi.mojom
new file mode 100644
index 00000000..3baceb37
--- /dev/null
+++ b/include/libcamera/ipa/raspberrypi.mojom
@@ -0,0 +1,97 @@
+// automatically add const and & to all inputs (that are not primitives)
+// automatically add pointer to all outputs (that are not primitives)
+// if return value is single and primitive, then return as ret value
+// if return value is multiple or non-primitive, then return as output param
+interface RPiIPAInterface {
+	init(IPASettings settings) => (int32);
+	start() => (int32);
+	stop() => ();
+
+	configure(CameraSensorInfo sensorInfo,
+		  map<uint32, IPAStream> streamConfig,
+		  map<uint32, ControlInfoMap> entityControls,
+		  RPiConfigureParams ipaConfig)
+		=> (RPiConfigureParams result);
+
+	// arrays get turned into vectors
+	mapBuffers(array<IPABuffer> buffers) => (int32);
+	unmapBuffers(array<uint32> ids) => ();
+
+	processEvent(RPiEventParams data) => ();
+}
+
+// these shall not return anything
+interface RPiIPACallbackInterface {
+	queueFrameAction(uint32, RPiActionPayload) => ();
+}
+
+enum RPiConfigParameters {
+	RPI_IPA_CONFIG_LS_TABLE,
+	RPI_IPA_CONFIG_STAGGERED_WRITE,
+	RPI_IPA_CONFIG_SENSOR,
+	RPI_IPA_CONFIG_SEND_FD,
+};
+
+enum RPiEvents {
+	RPI_IPA_EVENT_SIGNAL_STAT_READY,
+	RPI_IPA_EVENT_SIGNAL_ISP_PREPARE,
+	RPI_IPA_EVENT_QUEUE_REQUEST,
+	RPI_IPA_EVENT_SEND_FD,
+};
+
+enum RPiActions {
+	RPI_IPA_ACTION_V4L2_SET_STAGGERED,
+	RPI_IPA_ACTION_V4L2_SET_ISP,
+	RPI_IPA_ACTION_STATS_METADATA_COMPLETE,
+	RPI_IPA_ACTION_RUN_ISP,
+	RPI_IPA_ACTION_RUN_ISP_AND_DROP_FRAME,
+	RPI_IPA_ACTION_EMBEDDED_COMPLETE,
+};
+
+// Custom Data containers
+
+struct RPiStaggeredWritePayload {
+	uint32 gainDelay;
+	uint32 exposureDelay;
+	uint32 sensorMetadata;
+};
+
+struct RPiIspPreparePayload {
+	uint32 embeddedbufferId;
+	uint32 bayerbufferId;
+};
+
+struct RPiStatsCompletePayload {
+	uint32 bufferId;
+	ControlList controls;
+};
+
+struct RPiConfigurePayload {
+	RPiConfigParameters op;
+	FileDescriptor lsTableHandle;
+	int32 lsTableHandleStatic;
+	RPiStaggeredWritePayload staggeredWriteResult;
+	ControlList controls;
+	int32 bufferFd;
+};
+
+// First level payload
+
+struct RPiConfigureParams {
+	array<RPiConfigurePayload> payload;
+};
+
+struct RPiEventParams {
+	RPiEvents ev;
+	uint32 bufferId;
+	RPiIspPreparePayload ispPrepare;
+	ControlList controls;
+	int32 bufferFd;
+};
+
+struct RPiActionParams {
+	RPiActions op;
+	uint32 bufferId;
+	RPiStatsCompletePayload statsComplete;
+	ControlList controls;
+};
diff --git a/include/libcamera/ipa/raspberrypi_wrapper.h b/include/libcamera/ipa/raspberrypi_wrapper.h
new file mode 100644
index 00000000..ba44526d
--- /dev/null
+++ b/include/libcamera/ipa/raspberrypi_wrapper.h
@@ -0,0 +1,136 @@
+// automatically generated by custom compiler
+
+#ifndef __LIBCAMERA_IPA_INTERFACE_RASPBERRYPI_FB_H__
+#define __LIBCAMERA_IPA_INTERFACE_RASPBERRYPI_FB_H__
+
+#include "libcamera/internal/byte_stream_buffer.h"
+#include "libcamera/internal/control_serializer.h"
+#include "libcamera/internal/ipa_data_serializer.h"
+
+#include <libcamera/ipa/ipa_interface.h>
+#include <libcamera/ipa/raspberrypi.h>
+
+#include <deque>
+#include <vector>
+
+namespace libcamera {
+
+enum RPiConfigParameters {
+	RPI_IPA_CONFIG_LS_TABLE = 1,
+	RPI_IPA_CONFIG_STAGGERED_WRITE = 2,
+	RPI_IPA_CONFIG_SENSOR = 3,
+	RPI_IPA_CONFIG_SEND_FD = 4,
+};
+
+enum RPiEvents {
+	RPI_IPA_EVENT_SIGNAL_STAT_READY = 1,
+	RPI_IPA_EVENT_SIGNAL_ISP_PREPARE = 2,
+	RPI_IPA_EVENT_QUEUE_REQUEST = 3,
+	RPI_IPA_EVENT_SEND_FD = 4,
+};
+
+enum RPiActions {
+	RPI_IPA_ACTION_V4L2_SET_STAGGERED = 1,
+	RPI_IPA_ACTION_V4L2_SET_ISP = 2,
+	RPI_IPA_ACTION_STATS_METADATA_COMPLETE = 3,
+	RPI_IPA_ACTION_RUN_ISP = 4,
+	RPI_IPA_ACTION_RUN_ISP_AND_DROP_FRAME = 5,
+	RPI_IPA_ACTION_EMBEDDED_COMPLETE = 6,
+};
+
+struct RPiStaggeredWritePayload
+{
+public:
+	RPiStaggeredWritePayload() : gainDelay_(0), exposureDelay_(0), sensorMetadata_(0) {}
+	~RPiStaggeredWritePayload() {}
+
+	RPiStaggeredWritePayload(uint32_t gainDelay, uint32_t exposureDelay, uint32_t sensorMetadata) : gainDelay_(gainDelay), exposureDelay_(exposureDelay), sensorMetadata_(sensorMetadata) {}
+
+	uint32_t gainDelay_;
+	uint32_t exposureDelay_;
+	uint32_t sensorMetadata_;
+};
+
+struct RPiIspPreparePayload
+{
+public:
+	RPiIspPreparePayload() : embeddedbufferId_(0), bayerbufferId_(0) {}
+	~RPiIspPreparePayload() {}
+
+	RPiIspPreparePayload(uint32_t embeddedbufferId, uint32_t bayerbufferId) : embeddedbufferId_(embeddedbufferId), bayerbufferId_(bayerbufferId) {}
+
+	uint32_t embeddedbufferId_;
+	uint32_t bayerbufferId_;
+};
+
+struct RPiStatsCompletePayload
+{
+public:
+	RPiStatsCompletePayload() : bufferId_(0) {}
+	~RPiStatsCompletePayload() {}
+
+	RPiStatsCompletePayload(uint32_t bufferId, ControlList &controls) : bufferId_(bufferId), controls_(controls) {}
+
+	uint32_t bufferId_;
+	ControlList controls_;
+};
+
+struct RPiConfigurePayload
+{
+public:
+	RPiConfigurePayload() : op_(static_cast<RPiConfigParameters>(0)), lsTableHandle_(-1), bufferFd_(0) {}
+	~RPiConfigurePayload() {}
+
+	RPiConfigurePayload(enum RPiConfigParameters op, uint32_t lsTableHandle, uint32_t lsTableHandleStatic, RPiStaggeredWritePayload staggeredWriteResult, ControlList controls, int32_t bufferFd) : op_(op), lsTableHandle_(lsTableHandle), lsTableHandleStatic_(lsTableHandleStatic), staggeredWriteResult_(staggeredWriteResult), controls_(controls), bufferFd_(bufferFd) {}
+
+	enum RPiConfigParameters op_;
+	FileDescriptor lsTableHandle_;
+	int32_t lsTableHandleStatic_;
+	RPiStaggeredWritePayload staggeredWriteResult_;
+	ControlList controls_;
+	int32_t bufferFd_;
+};
+
+struct RPiConfigureParams
+{
+public:
+	RPiConfigureParams() {}
+	~RPiConfigureParams() {}
+
+	RPiConfigureParams(std::vector<RPiConfigurePayload> payload) : payload_(payload) {}
+
+	std::vector<RPiConfigurePayload> payload_;
+};
+
+struct RPiEventParams
+{
+public:
+	RPiEventParams() : ev_(static_cast<RPiEvents>(0)), bufferId_(0), bufferFd_(0) {}
+	~RPiEventParams() {}
+
+	RPiEventParams(enum RPiEvents ev, uint32_t bufferId, RPiIspPreparePayload ispPrepare, ControlList controls, int32_t bufferFd) : ev_(ev), bufferId_(bufferId), ispPrepare_(ispPrepare), controls_(controls), bufferFd_(bufferFd) {}
+
+	enum RPiEvents ev_;
+	uint32_t bufferId_;
+	RPiIspPreparePayload ispPrepare_;
+	ControlList controls_;
+	int32_t bufferFd_;
+};
+
+struct RPiActionParams
+{
+public:
+	RPiActionParams() : op_(static_cast<RPiActions>(0)), bufferId_(0) {}
+	~RPiActionParams() {}
+
+	RPiActionParams(enum RPiActions op, uint32_t bufferId, RPiStatsCompletePayload statsComplete, ControlList controls) : op_(op), bufferId_(bufferId), statsComplete_(statsComplete), controls_(controls) {}
+
+	enum RPiActions op_;
+	uint32_t bufferId_;
+	RPiStatsCompletePayload statsComplete_;
+	ControlList controls_;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_IPA_INTERFACE_RASPBERRYPI_FB_H__ */
