[libcamera-devel] [RFC 5/9] libcamera: device_enumerator_udev: Enumerate USB devices
Jacopo Mondi
jacopo.mondi at ideasonboard.com
Tue Aug 8 14:52:24 CEST 2023
Add experimental support for USB device enumeration in the udev-based
device enumerator.
Signed-off-by: Jacopo Mondi <jacopo.mondi at ideasonboard.com>
---
.../libcamera/internal/device_enumerator.h | 5 +++
.../internal/device_enumerator_udev.h | 1 +
src/libcamera/device_enumerator.cpp | 21 ++++++++++++
src/libcamera/device_enumerator_udev.cpp | 32 +++++++++++++++++++
4 files changed, 59 insertions(+)
diff --git a/include/libcamera/internal/device_enumerator.h b/include/libcamera/internal/device_enumerator.h
index 8df6a3e2ac92..1d6dbcb104b8 100644
--- a/include/libcamera/internal/device_enumerator.h
+++ b/include/libcamera/internal/device_enumerator.h
@@ -18,6 +18,7 @@
namespace libcamera {
class MediaDevice;
+class USBDevice;
class DeviceEnumerator
{
@@ -38,8 +39,12 @@ protected:
void addMediaDevice(std::unique_ptr<MediaDevice> media);
void removeMediaDevice(const std::string &deviceNode);
+ void addUSBDevice(std::unique_ptr<USBDevice> usb);
+ /* \todo implement remove() */
+
private:
std::vector<std::shared_ptr<MediaDevice>> mediaDevices_;
+ std::vector<std::shared_ptr<USBDevice>> usbDevices_;
};
} /* namespace libcamera */
diff --git a/include/libcamera/internal/device_enumerator_udev.h b/include/libcamera/internal/device_enumerator_udev.h
index 1b3360df31ba..e67ee31e0376 100644
--- a/include/libcamera/internal/device_enumerator_udev.h
+++ b/include/libcamera/internal/device_enumerator_udev.h
@@ -59,6 +59,7 @@ private:
std::string lookupDeviceNode(dev_t devnum);
int addV4L2Device(dev_t devnum);
+ int createUSBDevice(struct udev_device *dev);
void udevNotify();
struct udev *udev_;
diff --git a/src/libcamera/device_enumerator.cpp b/src/libcamera/device_enumerator.cpp
index 2ab731c68db9..1fde7367cfa8 100644
--- a/src/libcamera/device_enumerator.cpp
+++ b/src/libcamera/device_enumerator.cpp
@@ -7,6 +7,7 @@
#include "libcamera/internal/device_enumerator.h"
+#include <algorithm>
#include <string.h>
#include <libcamera/base/log.h>
@@ -14,6 +15,7 @@
#include "libcamera/internal/device_enumerator_sysfs.h"
#include "libcamera/internal/device_enumerator_udev.h"
#include "libcamera/internal/media_device.h"
+#include "libcamera/internal/usb_device.h"
/**
* \file device_enumerator.h
@@ -189,6 +191,25 @@ void DeviceEnumerator::addMediaDevice(std::unique_ptr<MediaDevice> media)
devicesAdded.emit();
}
+void DeviceEnumerator::addUSBDevice(std::unique_ptr<USBDevice> usb)
+{
+ /*
+ * This is a bit of an hack and could be improved!
+ *
+ * Can't use std::sort() + std::unique() because we're storing
+ * unique_ptr<>
+ */
+ for (const auto &dev : usbDevices_) {
+ if (dev->pid() == usb->pid() && dev->vid() == usb->vid())
+ return;
+ }
+
+ LOG(DeviceEnumerator, Debug)
+ << "Added USB device " << usb->vid() << "-" << usb->pid();
+
+ usbDevices_.push_back(std::move(usb));
+}
+
/**
* \brief Remove a media device from the enumerator
* \param[in] deviceNode Path to the media device to remove
diff --git a/src/libcamera/device_enumerator_udev.cpp b/src/libcamera/device_enumerator_udev.cpp
index 3cb0044a9434..ce4543698ed4 100644
--- a/src/libcamera/device_enumerator_udev.cpp
+++ b/src/libcamera/device_enumerator_udev.cpp
@@ -12,6 +12,7 @@
#include <libudev.h>
#include <list>
#include <map>
+#include <memory>
#include <string.h>
#include <string_view>
#include <sys/ioctl.h>
@@ -22,6 +23,7 @@
#include <libcamera/base/log.h>
#include "libcamera/internal/media_device.h"
+#include "libcamera/internal/usb_device.h"
namespace libcamera {
@@ -115,6 +117,9 @@ int DeviceEnumeratorUdev::addUdevDevice(struct udev_device *dev)
return 0;
}
+ if (!strcmp(subsystem, "input"))
+ return createUSBDevice(dev);
+
return -ENODEV;
}
@@ -136,6 +141,14 @@ int DeviceEnumeratorUdev::enumerate()
if (ret < 0)
goto done;
+ /*
+ * FIXME: this should use the appoprtiate subsystem for USB cameras.
+ * As a test, match on USB input devices.
+ */
+ ret = udev_enumerate_add_match_subsystem(udev_enum, "input");
+ if (ret < 0)
+ goto done;
+
ret = udev_enumerate_add_match_is_initialized(udev_enum);
if (ret < 0)
goto done;
@@ -329,6 +342,25 @@ int DeviceEnumeratorUdev::addV4L2Device(dev_t devnum)
return 0;
}
+int DeviceEnumeratorUdev::createUSBDevice(struct udev_device *dev)
+{
+ /* Get the USB parent device to get VID/PID information. */
+ struct udev_device *usb_device =
+ udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_device");
+ if (!usb_device)
+ return -ENODEV;
+
+ const char *vid = udev_device_get_sysattr_value(usb_device, "idVendor");
+ const char *pid = udev_device_get_sysattr_value(usb_device, "idProduct");
+ if (!vid || !pid)
+ return -ENODEV;
+
+ std::unique_ptr<USBDevice> usbDev = std::make_unique<USBDevice>(vid, pid);
+ addUSBDevice(std::move(usbDev));
+
+ return 0;
+}
+
void DeviceEnumeratorUdev::udevNotify()
{
struct udev_device *dev = udev_monitor_receive_device(monitor_);
--
2.40.1
More information about the libcamera-devel
mailing list