diff options
author | Jacopo Mondi <jacopo.mondi@ideasonboard.com> | 2023-08-07 13:12:46 +0200 |
---|---|---|
committer | Jacopo Mondi <jacopo.mondi@ideasonboard.com> | 2023-08-08 13:47:30 +0200 |
commit | 59fde8be87724184c89dee112499b4921caa82c6 (patch) | |
tree | ef926833fa52e94bf8c73c6856e33f52fe7ad030 | |
parent | 41ebdcd2a98c8648542e5201ebe06adc278f321a (diff) |
libcamera: device_enumerator_udev: Enumerate USB devices
Add experimental support for USB device enumeration in the udev-based
device enumerator.
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
-rw-r--r-- | include/libcamera/internal/device_enumerator.h | 5 | ||||
-rw-r--r-- | include/libcamera/internal/device_enumerator_udev.h | 1 | ||||
-rw-r--r-- | src/libcamera/device_enumerator.cpp | 21 | ||||
-rw-r--r-- | src/libcamera/device_enumerator_udev.cpp | 32 |
4 files changed, 59 insertions, 0 deletions
diff --git a/include/libcamera/internal/device_enumerator.h b/include/libcamera/internal/device_enumerator.h index 8df6a3e2..1d6dbcb1 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 1b3360df..e67ee31e 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 2ab731c6..1fde7367 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 3cb0044a..ce454369 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_); |