diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libcamera/camera_manager.cpp | 2 | ||||
-rw-r--r-- | src/libcamera/device_enumerator.cpp | 157 | ||||
-rw-r--r-- | src/libcamera/device_enumerator_udev.cpp | 163 | ||||
-rw-r--r-- | src/libcamera/include/device_enumerator.h | 24 | ||||
-rw-r--r-- | src/libcamera/include/device_enumerator_udev.h | 42 | ||||
-rw-r--r-- | src/libcamera/meson.build | 10 |
6 files changed, 218 insertions, 180 deletions
diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp index 40a39bd2..cf881ce2 100644 --- a/src/libcamera/camera_manager.cpp +++ b/src/libcamera/camera_manager.cpp @@ -80,7 +80,7 @@ int CameraManager::start() return -EBUSY; enumerator_ = DeviceEnumerator::create(); - if (enumerator_->enumerate()) + if (!enumerator_ || enumerator_->enumerate()) return -ENODEV; /* diff --git a/src/libcamera/device_enumerator.cpp b/src/libcamera/device_enumerator.cpp index 49467546..f6878b3d 100644 --- a/src/libcamera/device_enumerator.cpp +++ b/src/libcamera/device_enumerator.cpp @@ -6,14 +6,9 @@ */ #include "device_enumerator.h" +#include "device_enumerator_udev.h" -#include <fcntl.h> -#include <libudev.h> #include <string.h> -#include <sys/ioctl.h> -#include <unistd.h> - -#include <libcamera/event_notifier.h> #include "log.h" #include "media_device.h" @@ -148,13 +143,11 @@ std::unique_ptr<DeviceEnumerator> DeviceEnumerator::create() { std::unique_ptr<DeviceEnumerator> enumerator; - /** - * \todo Add compile time checks to only try udev enumerator if libudev - * is available. - */ +#ifdef HAVE_LIBUDEV enumerator = utils::make_unique<DeviceEnumeratorUdev>(); if (!enumerator->init()) return enumerator; +#endif /* * Either udev is not available or udev initialization failed. Fall back @@ -327,148 +320,4 @@ std::shared_ptr<MediaDevice> DeviceEnumerator::search(const DeviceMatch &dm) * fails */ -/** - * \class DeviceEnumeratorUdev - * \brief Device enumerator based on libudev - */ - -DeviceEnumeratorUdev::DeviceEnumeratorUdev() - : udev_(nullptr) -{ -} - -DeviceEnumeratorUdev::~DeviceEnumeratorUdev() -{ - delete notifier_; - - if (monitor_) - udev_monitor_unref(monitor_); - if (udev_) - udev_unref(udev_); -} - -int DeviceEnumeratorUdev::init() -{ - int ret; - - if (udev_) - return -EBUSY; - - udev_ = udev_new(); - if (!udev_) - return -ENODEV; - - monitor_ = udev_monitor_new_from_netlink(udev_, "udev"); - if (!monitor_) - return -ENODEV; - - ret = udev_monitor_filter_add_match_subsystem_devtype(monitor_, "media", - nullptr); - if (ret < 0) - return ret; - - return 0; -} - -int DeviceEnumeratorUdev::enumerate() -{ - struct udev_enumerate *udev_enum = nullptr; - struct udev_list_entry *ents, *ent; - int ret; - - udev_enum = udev_enumerate_new(udev_); - if (!udev_enum) - return -ENOMEM; - - ret = udev_enumerate_add_match_subsystem(udev_enum, "media"); - if (ret < 0) - goto done; - - ret = udev_enumerate_scan_devices(udev_enum); - if (ret < 0) - goto done; - - ents = udev_enumerate_get_list_entry(udev_enum); - if (!ents) - goto done; - - udev_list_entry_foreach(ent, ents) { - struct udev_device *dev; - const char *devnode; - const char *syspath = udev_list_entry_get_name(ent); - - dev = udev_device_new_from_syspath(udev_, syspath); - if (!dev) { - LOG(DeviceEnumerator, Warning) - << "Failed to get device for '" - << syspath << "', skipping"; - continue; - } - - devnode = udev_device_get_devnode(dev); - if (!devnode) { - udev_device_unref(dev); - ret = -ENODEV; - goto done; - } - - addDevice(devnode); - - udev_device_unref(dev); - } -done: - udev_enumerate_unref(udev_enum); - if (ret < 0) - return ret; - - ret = udev_monitor_enable_receiving(monitor_); - if (ret < 0) - return ret; - - int fd = udev_monitor_get_fd(monitor_); - notifier_ = new EventNotifier(fd, EventNotifier::Read); - notifier_->activated.connect(this, &DeviceEnumeratorUdev::udevNotify); - - return 0; -} - -std::string DeviceEnumeratorUdev::lookupDeviceNode(int major, int minor) -{ - struct udev_device *device; - const char *name; - dev_t devnum; - std::string deviceNode = std::string(); - - devnum = makedev(major, minor); - device = udev_device_new_from_devnum(udev_, 'c', devnum); - if (!device) - return std::string(); - - name = udev_device_get_devnode(device); - if (name) - deviceNode = name; - - udev_device_unref(device); - - return deviceNode; -} - -void DeviceEnumeratorUdev::udevNotify(EventNotifier *notifier) -{ - struct udev_device *dev = udev_monitor_receive_device(monitor_); - std::string action(udev_device_get_action(dev)); - std::string deviceNode(udev_device_get_devnode(dev)); - - LOG(DeviceEnumerator, Debug) - << action << " device " << udev_device_get_devnode(dev); - - if (action == "add") { - addDevice(deviceNode); - } else if (action == "remove") { - removeDevice(deviceNode); - } - - udev_device_unref(dev); -} - } /* namespace libcamera */ diff --git a/src/libcamera/device_enumerator_udev.cpp b/src/libcamera/device_enumerator_udev.cpp new file mode 100644 index 00000000..cb2d21b9 --- /dev/null +++ b/src/libcamera/device_enumerator_udev.cpp @@ -0,0 +1,163 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018-2019, Google Inc. + * + * device_enumerator_udev.cpp - udev-based device enumerator + */ + +#include "device_enumerator_udev.h" + +#include <fcntl.h> +#include <libudev.h> +#include <string.h> +#include <sys/ioctl.h> +#include <unistd.h> + +#include <libcamera/event_notifier.h> + +#include "log.h" + +namespace libcamera { + +LOG_DECLARE_CATEGORY(DeviceEnumerator) + +DeviceEnumeratorUdev::DeviceEnumeratorUdev() + : udev_(nullptr) +{ +} + +DeviceEnumeratorUdev::~DeviceEnumeratorUdev() +{ + delete notifier_; + + if (monitor_) + udev_monitor_unref(monitor_); + if (udev_) + udev_unref(udev_); +} + +int DeviceEnumeratorUdev::init() +{ + int ret; + + if (udev_) + return -EBUSY; + + udev_ = udev_new(); + if (!udev_) + return -ENODEV; + + monitor_ = udev_monitor_new_from_netlink(udev_, "udev"); + if (!monitor_) + return -ENODEV; + + ret = udev_monitor_filter_add_match_subsystem_devtype(monitor_, "media", + nullptr); + if (ret < 0) + return ret; + + return 0; +} + +int DeviceEnumeratorUdev::enumerate() +{ + struct udev_enumerate *udev_enum = nullptr; + struct udev_list_entry *ents, *ent; + int ret; + + udev_enum = udev_enumerate_new(udev_); + if (!udev_enum) + return -ENOMEM; + + ret = udev_enumerate_add_match_subsystem(udev_enum, "media"); + if (ret < 0) + goto done; + + ret = udev_enumerate_scan_devices(udev_enum); + if (ret < 0) + goto done; + + ents = udev_enumerate_get_list_entry(udev_enum); + if (!ents) + goto done; + + udev_list_entry_foreach(ent, ents) { + struct udev_device *dev; + const char *devnode; + const char *syspath = udev_list_entry_get_name(ent); + + dev = udev_device_new_from_syspath(udev_, syspath); + if (!dev) { + LOG(DeviceEnumerator, Warning) + << "Failed to get device for '" + << syspath << "', skipping"; + continue; + } + + devnode = udev_device_get_devnode(dev); + if (!devnode) { + udev_device_unref(dev); + ret = -ENODEV; + goto done; + } + + addDevice(devnode); + + udev_device_unref(dev); + } +done: + udev_enumerate_unref(udev_enum); + if (ret < 0) + return ret; + + ret = udev_monitor_enable_receiving(monitor_); + if (ret < 0) + return ret; + + int fd = udev_monitor_get_fd(monitor_); + notifier_ = new EventNotifier(fd, EventNotifier::Read); + notifier_->activated.connect(this, &DeviceEnumeratorUdev::udevNotify); + + return 0; +} + +std::string DeviceEnumeratorUdev::lookupDeviceNode(int major, int minor) +{ + struct udev_device *device; + const char *name; + dev_t devnum; + std::string deviceNode = std::string(); + + devnum = makedev(major, minor); + device = udev_device_new_from_devnum(udev_, 'c', devnum); + if (!device) + return std::string(); + + name = udev_device_get_devnode(device); + if (name) + deviceNode = name; + + udev_device_unref(device); + + return deviceNode; +} + +void DeviceEnumeratorUdev::udevNotify(EventNotifier *notifier) +{ + struct udev_device *dev = udev_monitor_receive_device(monitor_); + std::string action(udev_device_get_action(dev)); + std::string deviceNode(udev_device_get_devnode(dev)); + + LOG(DeviceEnumerator, Debug) + << action << " device " << udev_device_get_devnode(dev); + + if (action == "add") { + addDevice(deviceNode); + } else if (action == "remove") { + removeDevice(deviceNode); + } + + udev_device_unref(dev); +} + +} /* namespace libcamera */ diff --git a/src/libcamera/include/device_enumerator.h b/src/libcamera/include/device_enumerator.h index 28018618..02aec3bc 100644 --- a/src/libcamera/include/device_enumerator.h +++ b/src/libcamera/include/device_enumerator.h @@ -7,19 +7,14 @@ #ifndef __LIBCAMERA_DEVICE_ENUMERATOR_H__ #define __LIBCAMERA_DEVICE_ENUMERATOR_H__ -#include <map> #include <memory> #include <string> #include <vector> #include <linux/media.h> -struct udev; -struct udev_monitor; - namespace libcamera { -class EventNotifier; class MediaDevice; class DeviceMatch @@ -58,25 +53,6 @@ private: virtual std::string lookupDeviceNode(int major, int minor) = 0; }; -class DeviceEnumeratorUdev: public DeviceEnumerator -{ -public: - DeviceEnumeratorUdev(); - ~DeviceEnumeratorUdev(); - - int init() final; - int enumerate() final; - -private: - struct udev *udev_; - struct udev_monitor *monitor_; - EventNotifier *notifier_; - - std::string lookupDeviceNode(int major, int minor) final; - - void udevNotify(EventNotifier *notifier); -}; - } /* namespace libcamera */ #endif /* __LIBCAMERA_DEVICE_ENUMERATOR_H__ */ diff --git a/src/libcamera/include/device_enumerator_udev.h b/src/libcamera/include/device_enumerator_udev.h new file mode 100644 index 00000000..80f9372b --- /dev/null +++ b/src/libcamera/include/device_enumerator_udev.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018-2019, Google Inc. + * + * device_enumerator_udev.h - udev-based device enumerator + */ +#ifndef __LIBCAMERA_DEVICE_ENUMERATOR_UDEV_H__ +#define __LIBCAMERA_DEVICE_ENUMERATOR_UDEV_H__ + +#include <string> + +#include "device_enumerator.h" + +struct udev; +struct udev_monitor; + +namespace libcamera { + +class EventNotifier; + +class DeviceEnumeratorUdev : public DeviceEnumerator +{ +public: + DeviceEnumeratorUdev(); + ~DeviceEnumeratorUdev(); + + int init() final; + int enumerate() final; + +private: + struct udev *udev_; + struct udev_monitor *monitor_; + EventNotifier *notifier_; + + std::string lookupDeviceNode(int major, int minor) final; + + void udevNotify(EventNotifier *notifier); +}; + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_DEVICE_ENUMERATOR_UDEV_H__ */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index cf4edec0..2b678237 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -26,6 +26,7 @@ libcamera_sources = files([ libcamera_headers = files([ 'include/camera_sensor.h', 'include/device_enumerator.h', + 'include/device_enumerator_udev.h', 'include/event_dispatcher_poll.h', 'include/formats.h', 'include/log.h', @@ -46,7 +47,14 @@ includes = [ subdir('pipeline') -libudev = dependency('libudev') +libudev = dependency('libudev', required: false) + +if libudev.found() + config_h.set('HAVE_LIBUDEV', 1) + libcamera_sources += files([ + 'device_enumerator_udev.cpp', + ]) +endif libcamera = shared_library('camera', libcamera_sources, |