summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libcamera/pipeline_handler.cpp69
1 files changed, 57 insertions, 12 deletions
diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
index ca177cad..0b3e0fd8 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -27,6 +27,7 @@
#include "libcamera/internal/media_device.h"
#include "libcamera/internal/request.h"
#include "libcamera/internal/tracepoints.h"
+#include "libcamera/internal/usb_device.h"
/**
* \file pipeline_handler.h
@@ -76,8 +77,8 @@ PipelineHandler::PipelineHandler(CameraManager *manager)
PipelineHandler::~PipelineHandler()
{
- for (std::shared_ptr<MediaDevice> media : mediaDevices_)
- media->release();
+ for (std::shared_ptr<CameraDevice> device : cameraDevices_)
+ device->release();
}
/**
@@ -139,12 +140,43 @@ MediaDevice *PipelineHandler::acquireMediaDevice(DeviceEnumerator *enumerator,
if (!media->acquire())
return nullptr;
- mediaDevices_.push_back(media);
+ cameraDevices_.push_back(media);
return media.get();
}
/**
+ * \brief Search and acquire a USBDevice matching a device pattern
+ * \param[in] enumerator Enumerator containing all media devices in the system
+ * \param[in] dm Device match pattern
+ *
+ * Search the device \a enumerator for an available USB device matching the
+ * device match pattern \a dm. Matching devices that have previously been
+ * acquired by MediaDevice::acquire() are not considered. If a match is found,
+ * the USB device is acquired and returned. The caller shall not release the
+ * device explicitly, it will be automatically released when the pipeline
+ * handler is destroyed.
+ *
+ * \context This function shall be called from the CameraManager thread.
+ *
+ * \return A pointer to the matching USBDevice, or nullptr if no match is found
+ */
+USBDevice *PipelineHandler::acquireUSBDevice(DeviceEnumerator *enumerator,
+ const USBDeviceMatch &dm)
+{
+ std::shared_ptr<USBDevice> usb = enumerator->search(dm);
+ if (!usb)
+ return nullptr;
+
+ if (!usb->acquire())
+ return nullptr;
+
+ cameraDevices_.push_back(usb);
+
+ return usb.get();
+}
+
+/**
* \brief Acquire exclusive access to the pipeline handler for the process
*
* This function locks all the media devices used by the pipeline to ensure
@@ -173,9 +205,9 @@ bool PipelineHandler::acquire()
return true;
}
- for (std::shared_ptr<MediaDevice> &media : mediaDevices_) {
- if (!media->lock()) {
- unlockMediaDevices();
+ for (std::shared_ptr<CameraDevice> &device : cameraDevices_) {
+ if (!device->lock()) {
+ unlockCameraDevices();
return false;
}
}
@@ -206,7 +238,7 @@ void PipelineHandler::release(Camera *camera)
ASSERT(useCount_);
- unlockMediaDevices();
+ unlockCameraDevices();
releaseDevice(camera);
@@ -224,10 +256,10 @@ void PipelineHandler::releaseDevice([[maybe_unused]] Camera *camera)
{
}
-void PipelineHandler::unlockMediaDevices()
+void PipelineHandler::unlockCameraDevices()
{
- for (std::shared_ptr<MediaDevice> &media : mediaDevices_)
- media->unlock();
+ for (std::shared_ptr<CameraDevice> &device : cameraDevices_)
+ device->unlock();
}
/**
@@ -606,7 +638,7 @@ void PipelineHandler::registerCamera(std::shared_ptr<Camera> camera)
{
cameras_.push_back(camera);
- if (mediaDevices_.empty())
+ if (cameraDevices_.empty())
LOG(Pipeline, Fatal)
<< "Registering camera with no media devices!";
@@ -615,7 +647,20 @@ void PipelineHandler::registerCamera(std::shared_ptr<Camera> camera)
* to the camera.
*/
std::vector<int64_t> devnums;
- for (const std::shared_ptr<MediaDevice> &media : mediaDevices_) {
+ for (const std::shared_ptr<CameraDevice> &device : cameraDevices_) {
+ /*
+ * Only MediaDevice has entities and devnums.
+ *
+ * FIXME: This code path "abuses" RTTI. In general, conditional
+ * execution based on type information is discouraged and is
+ * a symptom of a fragile design. However this could be
+ * considered a temporary workaround, as USB-based devices
+ * should report devnums as well in future.
+ */
+ MediaDevice *media = dynamic_cast<MediaDevice *>(device.get());
+ if (!media)
+ continue;
+
for (const MediaEntity *entity : media->entities()) {
if (entity->pads().size() == 1 &&
(entity->pads()[0]->flags() & MEDIA_PAD_FL_SINK) &&