[libcamera-devel] [RFC PATCH 2/3] libcamera: device_enumerator: Check that expected cameras are available

Paul Elder paul.elder at ideasonboard.com
Mon Sep 30 07:35:19 CEST 2019


Add a static method to DeviceEnumerator to check if the expected number
of cameras have been enumerated. The expected cameras are the supported
cameras declared by the pipeline handlers that the system has.

Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
---
 src/libcamera/device_enumerator.cpp       | 69 +++++++++++++++++++++++
 src/libcamera/include/device_enumerator.h |  4 ++
 2 files changed, 73 insertions(+)

diff --git a/src/libcamera/device_enumerator.cpp b/src/libcamera/device_enumerator.cpp
index 0b596bce..7d28f9b8 100644
--- a/src/libcamera/device_enumerator.cpp
+++ b/src/libcamera/device_enumerator.cpp
@@ -9,10 +9,15 @@
 #include "device_enumerator_sysfs.h"
 #include "device_enumerator_udev.h"
 
+#include <algorithm>
+#include <dirent.h>
+#include <fstream>
 #include <string.h>
+#include <sys/types.h>
 
 #include "log.h"
 #include "media_device.h"
+#include "pipeline_handler.h"
 #include "utils.h"
 
 /**
@@ -306,4 +311,68 @@ std::shared_ptr<MediaDevice> DeviceEnumerator::search(const DeviceMatch &dm)
 	return nullptr;
 }
 
+int extractNumberFromFile(std::string &path)
+{
+	std::ifstream file;
+	std::string line;
+
+	file.open(path);
+	if (!file)
+		return -1;
+
+	file >> line;
+	int i = std::stoi(line, 0, 16);
+	file.close();
+
+	return i;
+}
+
+bool DeviceEnumerator::haveExpectedCameras(CameraManager *cm)
+{
+	std::vector<std::reference_wrapper<DeviceID>> &supportedDevices =
+		PipelineHandlerFactory::getDeviceIDs();
+	std::vector<DeviceID> availableDevices;
+	std::vector<DeviceID> intersection;
+	struct dirent *ent;
+	DIR *dir;
+	const char *pciDir = "/sys/bus/pci/devices";
+
+	dir = opendir(pciDir);
+	if (!dir) {
+		LOG(DeviceEnumerator, Error)
+			<< "Failed to open sysfs PCI directory";
+		/* We can't expect any cameras, so we vacuously have them all. */
+		return true;
+	}
+
+	while ((ent = readdir(dir)) != nullptr) {
+		std::string path = pciDir + std::string("/") + ent->d_name + "/vendor";
+		int vendor = extractNumberFromFile(path);
+		if (vendor < 0)
+			continue;
+
+		path = pciDir + std::string("/") + ent->d_name + "/device";
+		int device = extractNumberFromFile(path);
+		if (device < 0)
+			continue;
+
+		availableDevices.push_back(PCIDeviceID(vendor, device));
+	}
+
+	closedir(dir);
+
+	std::set_intersection(supportedDevices.begin(), supportedDevices.end(),
+			      availableDevices.begin(), availableDevices.end(),
+			      back_inserter(intersection),
+			      compareDevices<PCIDeviceID>);
+
+	if (cm->cameras().size() < intersection.size()) {
+		LOG(DeviceEnumerator, Warning) << "Not enough cameras!";
+		return false;
+	}
+
+	LOG(DeviceEnumerator, Debug) << "All cameras correctly initialized";
+	return true;
+}
+
 } /* namespace libcamera */
diff --git a/src/libcamera/include/device_enumerator.h b/src/libcamera/include/device_enumerator.h
index 770f4277..11c4cdfb 100644
--- a/src/libcamera/include/device_enumerator.h
+++ b/src/libcamera/include/device_enumerator.h
@@ -13,6 +13,8 @@
 
 #include <linux/media.h>
 
+#include <libcamera/camera_manager.h>
+
 namespace libcamera {
 
 class MediaDevice;
@@ -43,6 +45,8 @@ public:
 
 	std::shared_ptr<MediaDevice> search(const DeviceMatch &dm);
 
+	static bool haveExpectedCameras(CameraManager *cm);
+
 protected:
 	std::shared_ptr<MediaDevice> createDevice(const std::string &deviceNode);
 	void addDevice(const std::shared_ptr<MediaDevice> &media);
-- 
2.23.0



More information about the libcamera-devel mailing list