libcamera: device_enumerator_udev: Support entities sharing device nodes

Some media devices, such as V4L2 M2M devices, share the same device node
for multiple entities. The udev enumerator used to support this, but
commit 6e62034900 ("libcamera: device_enumerator: fix udev media graph
loading dependency") broke this.

To fix the problem, rework the media device to V4L2 devices matching
code. A new MediaDeviceDeps internal struct stores unmet device number
dependencies for a media device, and is stored in a list of pending
media devices. To avoid linear lookups, the dependencies are cached in a
reverse map of device number to media device dependencies.

Fixes: 6e62034900 ("libcamera: device_enumerator: fix udev media graph loading dependency")
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
This commit is contained in:
Laurent Pinchart
2019-09-09 17:18:03 +03:00
parent e832a00bab
commit 04b20723d4
2 changed files with 89 additions and 36 deletions
+21 -4
View File
@@ -10,6 +10,7 @@
#include <list>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <sys/types.h>
@@ -39,11 +40,27 @@ 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_;
using DependencyMap = std::map<dev_t, std::list<MediaEntity *>>;
std::list<dev_t> orphans_;
struct MediaDeviceDeps {
MediaDeviceDeps(const std::shared_ptr<MediaDevice> &media,
const DependencyMap &deps)
: media_(media), deps_(deps)
{
}
bool operator==(const MediaDeviceDeps &other) const
{
return media_ == other.media_;
}
std::shared_ptr<MediaDevice> media_;
DependencyMap deps_;
};
std::set<dev_t> orphans_;
std::list<MediaDeviceDeps> pending_;
std::map<dev_t, MediaDeviceDeps *> devMap_;
int addUdevDevice(struct udev_device *dev);
int populateMediaDevice(const std::shared_ptr<MediaDevice> &media);