summaryrefslogtreecommitdiff
path: root/src/libcamera/include
diff options
context:
space:
mode:
authorPaul Elder <paul.elder@ideasonboard.com>2019-09-01 23:53:02 -0400
committerPaul Elder <paul.elder@ideasonboard.com>2019-09-08 19:50:11 -0400
commit6e620349009de675250a7e3e753480b85a6df10b (patch)
tree3fa87d45d3518ba49906f0da4df0afb3bb95a30a /src/libcamera/include
parent19f85f43ff2ad4da255aebe8440a0aa6a3650632 (diff)
libcamera: device_enumerator: fix udev media graph loading dependency
When a MediaDevice is enumerated and populated by the DeviceEnumeratorUdev, there is a possibility that the member device nodes of the media graph would not be ready (either not created, or without proper permissions set by udev yet). The MediaDevice is still passed up to the pipeline handler, where an attempt to access the device nodes will fail in EPERM. This whole issue is especially likely to happen when libcamera is run at system init time. To fix this, we first split DeviceEnumerator::addDevice() into three methods: - createDevice() to simply create the MediaDevice - populateMediaDevice() to populate the MediaDevice - addDevice() to pass the MediaDevice up to the pipeline handler DeviceEnumeratorSysfs calls these methods in succession, similar to what it did before when they were all together as addDevice(). DeviceEnumeratorUdev additionally keeps a map of MediaDevices to a list of pending device nodes (plus some other auxillary maps), and a simple list of orphan device nodes. If a v4l device node is ready and there does not exist any MediaDevice node for it, then it goes to the orphan list, otherwise it is initialized and removed from the pending list of the corresponding MediaDevice in the dependency map. When a MediaDevice is populated via DeviceEnumeratorUdev::populateMediaDevice(), it first checks the orphan list to see if the device nodes it needs are there, otherwise it tries to initialize the device nodes and if it fails, then it adds the device nodes it wants to its list in the dependency map. This allows MediaDevice instances to be created and initialized properly with udev when v4l device nodes in the media graph may not be ready when the MediaDevice is populated. Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'src/libcamera/include')
-rw-r--r--src/libcamera/include/device_enumerator.h3
-rw-r--r--src/libcamera/include/device_enumerator_sysfs.h6
-rw-r--r--src/libcamera/include/device_enumerator_udev.h16
3 files changed, 23 insertions, 2 deletions
diff --git a/src/libcamera/include/device_enumerator.h b/src/libcamera/include/device_enumerator.h
index 02aec3bc..c5d26f1a 100644
--- a/src/libcamera/include/device_enumerator.h
+++ b/src/libcamera/include/device_enumerator.h
@@ -44,7 +44,8 @@ public:
std::shared_ptr<MediaDevice> search(const DeviceMatch &dm);
protected:
- int addDevice(const std::string &deviceNode);
+ std::shared_ptr<MediaDevice> createDevice(const std::string &deviceNode);
+ void addDevice(const std::shared_ptr<MediaDevice> &media);
void removeDevice(const std::string &deviceNode);
private:
diff --git a/src/libcamera/include/device_enumerator_sysfs.h b/src/libcamera/include/device_enumerator_sysfs.h
index 8d3adc91..242b22b2 100644
--- a/src/libcamera/include/device_enumerator_sysfs.h
+++ b/src/libcamera/include/device_enumerator_sysfs.h
@@ -7,10 +7,13 @@
#ifndef __LIBCAMERA_DEVICE_ENUMERATOR_SYSFS_H__
#define __LIBCAMERA_DEVICE_ENUMERATOR_SYSFS_H__
+#include <memory>
#include <string>
#include "device_enumerator.h"
+class MediaDevice;
+
namespace libcamera {
class DeviceEnumeratorSysfs final : public DeviceEnumerator
@@ -20,7 +23,8 @@ public:
int enumerate();
private:
- std::string lookupDeviceNode(int major, int minor);
+ int populateMediaDevice(const std::shared_ptr<MediaDevice> &media);
+ std::string lookupDeviceNode(int major, int minor) final;
};
} /* namespace libcamera */
diff --git a/src/libcamera/include/device_enumerator_udev.h b/src/libcamera/include/device_enumerator_udev.h
index 80f9372b..5bdcdea6 100644
--- a/src/libcamera/include/device_enumerator_udev.h
+++ b/src/libcamera/include/device_enumerator_udev.h
@@ -7,16 +7,23 @@
#ifndef __LIBCAMERA_DEVICE_ENUMERATOR_UDEV_H__
#define __LIBCAMERA_DEVICE_ENUMERATOR_UDEV_H__
+#include <list>
+#include <map>
+#include <memory>
#include <string>
+#include <sys/types.h>
#include "device_enumerator.h"
struct udev;
+struct udev_device;
struct udev_monitor;
namespace libcamera {
class EventNotifier;
+class MediaDevice;
+class MediaEntity;
class DeviceEnumeratorUdev : public DeviceEnumerator
{
@@ -32,8 +39,17 @@ private:
struct udev_monitor *monitor_;
EventNotifier *notifier_;
+ std::map<std::shared_ptr<MediaDevice>, std::list<dev_t>> deps_;
+ std::map<dev_t, std::shared_ptr<MediaDevice>> devnumToDevice_;
+ std::map<dev_t, MediaEntity *> devnumToEntity_;
+
+ std::list<dev_t> orphans_;
+
+ int addUdevDevice(struct udev_device *dev);
+ int populateMediaDevice(const std::shared_ptr<MediaDevice> &media);
std::string lookupDeviceNode(int major, int minor) final;
+ int addV4L2Device(dev_t devnum);
void udevNotify(EventNotifier *notifier);
};