libcamera: device_enumerator: add DeviceEnumeratorSysfs class
A udev-based device enumerator is not sufficient, since libudev is an optional dependency, or udev might fail. In these cases, we should fall back to using sysfs to enumerate devices. Add a DeviceEnumeratorSysfs class which is a specialization of DeviceEnumerator that uses sysfs to enumerate media devices on the system. Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
parent
05ff3d56e0
commit
977cfbd526
5 changed files with 142 additions and 3 deletions
|
@ -833,7 +833,9 @@ RECURSIVE = YES
|
||||||
# Note that relative paths are relative to the directory from which doxygen is
|
# Note that relative paths are relative to the directory from which doxygen is
|
||||||
# run.
|
# run.
|
||||||
|
|
||||||
EXCLUDE = ../src/libcamera/device_enumerator_udev.cpp \
|
EXCLUDE = ../src/libcamera/device_enumerator_sysfs.cpp \
|
||||||
|
../src/libcamera/device_enumerator_udev.cpp \
|
||||||
|
../src/libcamera/include/device_enumerator_sysfs.h \
|
||||||
../src/libcamera/include/device_enumerator_udev.h \
|
../src/libcamera/include/device_enumerator_udev.h \
|
||||||
../src/libcamera/pipeline/
|
../src/libcamera/pipeline/
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "device_enumerator.h"
|
#include "device_enumerator.h"
|
||||||
|
#include "device_enumerator_sysfs.h"
|
||||||
#include "device_enumerator_udev.h"
|
#include "device_enumerator_udev.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -153,8 +154,9 @@ std::unique_ptr<DeviceEnumerator> DeviceEnumerator::create()
|
||||||
* Either udev is not available or udev initialization failed. Fall back
|
* Either udev is not available or udev initialization failed. Fall back
|
||||||
* on the sysfs enumerator.
|
* on the sysfs enumerator.
|
||||||
*/
|
*/
|
||||||
|
enumerator = utils::make_unique<DeviceEnumeratorSysfs>();
|
||||||
/** \todo Add a sysfs-based enumerator. */
|
if (!enumerator->init())
|
||||||
|
return enumerator;
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
105
src/libcamera/device_enumerator_sysfs.cpp
Normal file
105
src/libcamera/device_enumerator_sysfs.cpp
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2019, Google Inc.
|
||||||
|
*
|
||||||
|
* device_enumerator_sysfs.cpp - sysfs-based device enumerator
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "device_enumerator_sysfs.h"
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
namespace libcamera {
|
||||||
|
|
||||||
|
LOG_DECLARE_CATEGORY(DeviceEnumerator)
|
||||||
|
|
||||||
|
int DeviceEnumeratorSysfs::init()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DeviceEnumeratorSysfs::enumerate()
|
||||||
|
{
|
||||||
|
struct dirent *ent;
|
||||||
|
DIR *dir;
|
||||||
|
|
||||||
|
static const char * const sysfs_dirs[] = {
|
||||||
|
"/sys/subsystem/media/devices",
|
||||||
|
"/sys/bus/media/devices",
|
||||||
|
"/sys/class/media/devices",
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const char *dirname : sysfs_dirs) {
|
||||||
|
dir = opendir(dirname);
|
||||||
|
if (dir)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dir) {
|
||||||
|
LOG(DeviceEnumerator, Error)
|
||||||
|
<< "No valid sysfs media device directory";
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((ent = readdir(dir)) != nullptr) {
|
||||||
|
if (strncmp(ent->d_name, "media", 5))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
char *end;
|
||||||
|
unsigned int idx = strtoul(ent->d_name + 5, &end, 10);
|
||||||
|
if (*end != '\0')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::string devnode = "/dev/media" + std::to_string(idx);
|
||||||
|
|
||||||
|
/* Verify that the device node exists. */
|
||||||
|
struct stat devstat;
|
||||||
|
if (stat(devnode.c_str(), &devstat) < 0) {
|
||||||
|
LOG(DeviceEnumerator, Warning)
|
||||||
|
<< "Device node /dev/media" << idx
|
||||||
|
<< " should exist but doesn't";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
addDevice(devnode);
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DeviceEnumeratorSysfs::lookupDeviceNode(int major, int minor)
|
||||||
|
{
|
||||||
|
std::string deviceNode;
|
||||||
|
std::string line;
|
||||||
|
std::ifstream ueventFile;
|
||||||
|
|
||||||
|
ueventFile.open("/sys/dev/char/" + std::to_string(major) + ":" +
|
||||||
|
std::to_string(minor) + "/uevent");
|
||||||
|
if (!ueventFile)
|
||||||
|
return std::string();
|
||||||
|
|
||||||
|
while (ueventFile >> line) {
|
||||||
|
if (line.find("DEVNAME=") == 0) {
|
||||||
|
deviceNode = "/dev/" + line.substr(strlen("DEVNAME="));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ueventFile.close();
|
||||||
|
|
||||||
|
return deviceNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace libcamera */
|
28
src/libcamera/include/device_enumerator_sysfs.h
Normal file
28
src/libcamera/include/device_enumerator_sysfs.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2019, Google Inc.
|
||||||
|
*
|
||||||
|
* device_enumerator_sysfs.h - sysfs-based device enumerator
|
||||||
|
*/
|
||||||
|
#ifndef __LIBCAMERA_DEVICE_ENUMERATOR_SYSFS_H__
|
||||||
|
#define __LIBCAMERA_DEVICE_ENUMERATOR_SYSFS_H__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "device_enumerator.h"
|
||||||
|
|
||||||
|
namespace libcamera {
|
||||||
|
|
||||||
|
class DeviceEnumeratorSysfs final : public DeviceEnumerator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int init();
|
||||||
|
int enumerate();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string lookupDeviceNode(int major, int minor);
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace libcamera */
|
||||||
|
|
||||||
|
#endif /* __LIBCAMERA_DEVICE_ENUMERATOR_SYSFS_H__ */
|
|
@ -4,6 +4,7 @@ libcamera_sources = files([
|
||||||
'camera_manager.cpp',
|
'camera_manager.cpp',
|
||||||
'camera_sensor.cpp',
|
'camera_sensor.cpp',
|
||||||
'device_enumerator.cpp',
|
'device_enumerator.cpp',
|
||||||
|
'device_enumerator_sysfs.cpp',
|
||||||
'event_dispatcher.cpp',
|
'event_dispatcher.cpp',
|
||||||
'event_dispatcher_poll.cpp',
|
'event_dispatcher_poll.cpp',
|
||||||
'event_notifier.cpp',
|
'event_notifier.cpp',
|
||||||
|
@ -26,6 +27,7 @@ libcamera_sources = files([
|
||||||
libcamera_headers = files([
|
libcamera_headers = files([
|
||||||
'include/camera_sensor.h',
|
'include/camera_sensor.h',
|
||||||
'include/device_enumerator.h',
|
'include/device_enumerator.h',
|
||||||
|
'include/device_enumerator_sysfs.h',
|
||||||
'include/device_enumerator_udev.h',
|
'include/device_enumerator_udev.h',
|
||||||
'include/event_dispatcher_poll.h',
|
'include/event_dispatcher_poll.h',
|
||||||
'include/formats.h',
|
'include/formats.h',
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue