[libcamera-devel] [RFC PATCH 10/10] libcamera: ipa: shim: load IPA module into an IPAInterface

Paul Elder paul.elder at ideasonboard.com
Thu Jun 6 00:18:17 CEST 2019


Implement the dummy shim's init method that takes a path for the IPA
module to be loaded. Set up IPC, then fork and load the IPAInterface
implementation from the IPA module shared object.

Implement a cleanup method along with it.

Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
---
This is the most draft-y patch of the whole series. I wasn't sure how to
put what kind of IPC, so I kind of just did this very skeletal "give you
an idea" type of IPC initialization. Privilege dropping will be looked
into for the next version.

 src/ipa/shim_dummy.cpp | 79 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 77 insertions(+), 2 deletions(-)

diff --git a/src/ipa/shim_dummy.cpp b/src/ipa/shim_dummy.cpp
index 4d28c2d..f2e6961 100644
--- a/src/ipa/shim_dummy.cpp
+++ b/src/ipa/shim_dummy.cpp
@@ -6,6 +6,14 @@
  */
 
 #include <iostream>
+#include <memory>
+
+#include <dlfcn.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 #include <libcamera/ipa/ipa_interface.h>
 #include <libcamera/ipa/ipa_module_info.h>
@@ -17,20 +25,87 @@ class ShimDummy : public IPAInterface
 public:
 	int init();
 	int init(const char *path);
+
+	void cleanup();
+
+private:
+	std::unique_ptr<IPAInterface> ipa_;
+
+	int sockets_[2];
+	int childPid_;
+	void *dlHandle_;
+
+	typedef IPAInterface *(*IPAIntfFactory)(void);
 };
 
 int ShimDummy::init()
 {
-	std::cout << "okay shim init without path" << std::endl;
+	std::cout << "initializing IPA via dummy shim!" << std::endl;
 	return 0;
 }
 
 int ShimDummy::init(const char *path)
 {
-	std::cout << "initializing dummy shim!" << std::endl;
+	std::cout << "initializing dummy shim! loading IPA from " << path
+		  << std::endl;
+
+	/* We know the IPA module is valid, otherwise IPAManager wouldn't
+	 * even give its path to us. */
+
+	// setup comm
+	if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets_)) {
+		int err = errno;
+		std::cerr << "Error opening sockets: " << strerror(errno)
+			  << std::endl;
+		return err;
+	}
+
+	// fork
+	if ((childPid_ = fork()) == -1) {
+		int err = errno;
+		std::cerr << "Failed to fork: " << strerror(errno) << std::endl;
+		return err;
+	} else if (childPid_) {
+		// we are parent
+		// we can read/write sockets_[1]
+		close(sockets_[0]);
+	} else {
+		// we are child
+		// we can read/write sockets_[0]
+		close(sockets_[1]);
+
+		dlHandle_ = dlopen(path, RTLD_LAZY);
+		if (!dlHandle_) {
+			std::cerr << "Failed to open IPA module: "
+				  << dlerror() << std::endl;
+			return -1;
+		}
+
+		void *symbol = dlsym(dlHandle_, "ipaCreate");
+		if (!symbol) {
+			std::cerr
+				<< "Failed to load ipaCreate() from IPA module shared object: "
+				<< dlerror();
+			dlclose(dlHandle_);
+			dlHandle_ = nullptr;
+			return -1;
+		}
+
+		IPAIntfFactory ipaCreate = reinterpret_cast<IPAIntfFactory>(symbol);
+		ipa_ = std::unique_ptr<IPAInterface>(ipaCreate());
+		exit(0);
+	}
+
 	return 0;
 }
 
+void ShimDummy::cleanup()
+{
+	if (dlHandle_)
+		dlclose(dlHandle_);
+	dlHandle_ = nullptr;
+}
+
 /*
  * External IPA module interface
  */
-- 
2.20.1



More information about the libcamera-devel mailing list