From patchwork Tue Aug 8 12:52:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 18935 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 55C65C32B2 for ; Tue, 8 Aug 2023 12:52:59 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8722A62806; Tue, 8 Aug 2023 14:52:58 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1691499178; bh=mtyz3Oza0nU6tQb7l72g9z6aNbT0OdIHbijtg8CYxEU=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=sTu09M1uHJ36VhfUOltLAh3oVGvD+rWbnDyXC7APeW/Taw/r1jJMn/lKV6C6p+9vH fZm9A5wMOl7bgs/RSSRmoG/omY4Dm9WoGsZWWhlI3tMo4p8uaG7Tdr62xYi2hbn7st UHKHYfpkhXIef7qYiW5KWRXdYvtwZDxMh8SZEK4c5MO3Wyjtw1EOWZ19pi1wkqA9ze cOX5uxkzlNFuMnx7cRE94A6HCaMjw9aLlcDraME4Xf9020txRyRbPSOpHSalVsnKXB FpqdK0mf1WlT2xaE4xcGyRT1nodUisCR9K8BGkxPsf0+HExgRm64hqZMsP187Qkhbk SX5cn39K2xQaw== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 28D71627EB for ; Tue, 8 Aug 2023 14:52:51 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="MPsnwXhN"; dkim-atps=neutral Received: from uno.localdomain (mob-5-90-60-22.net.vodafone.it [5.90.60.22]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 4D062864C; Tue, 8 Aug 2023 14:51:43 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1691499103; bh=mtyz3Oza0nU6tQb7l72g9z6aNbT0OdIHbijtg8CYxEU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MPsnwXhNvYrfm5q3UI4RfY0JHbYMsR5/lfqWt9W3DAOoum0aL+HAmSiXfhiJZqODg 1HcqcJUmbXvsIHRP+t2R5zFSCfb4eEd+nH3TmLXRuTSjIunrynEicWMi4bV18jX1TP zulMwnEWQer6EeEpgyCSK48/wMLRfVxrhzY5Lpao= To: libcamera-devel@lists.libcamera.org, Sophie Friedrich Date: Tue, 8 Aug 2023 14:52:27 +0200 Message-Id: <20230808125228.29043-9-jacopo.mondi@ideasonboard.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230808125228.29043-1-jacopo.mondi@ideasonboard.com> References: <20230808125228.29043-1-jacopo.mondi@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC 8/9] libcamera: pipeline_handler: Add function to acquire a USB device X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Cc: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a function to the PipelineHandler base class to acquire a USB device by providing a USBDeviceMatch class instance. Support multiple CameraDevice derived classes by generalizing whenever possible the device type in use. Signed-off-by: Jacopo Mondi --- include/libcamera/internal/pipeline_handler.h | 9 ++- src/libcamera/pipeline_handler.cpp | 69 +++++++++++++++---- 2 files changed, 64 insertions(+), 14 deletions(-) diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h index 02b2f33727a3..b6b68aab1521 100644 --- a/include/libcamera/internal/pipeline_handler.h +++ b/include/libcamera/internal/pipeline_handler.h @@ -26,6 +26,7 @@ namespace libcamera { class Camera; class CameraConfiguration; +class CameraDevice; class CameraManager; class DeviceEnumerator; class MediaDeviceMatch; @@ -33,6 +34,8 @@ class FrameBuffer; class MediaDevice; class PipelineHandler; class Request; +class USBDevice; +class USBDeviceMatch; class PipelineHandler : public std::enable_shared_from_this, public Object @@ -44,6 +47,8 @@ public: virtual bool match(DeviceEnumerator *enumerator) = 0; MediaDevice *acquireMediaDevice(DeviceEnumerator *enumerator, const MediaDeviceMatch &dm); + USBDevice *acquireUSBDevice(DeviceEnumerator *enumerator, + const USBDeviceMatch &dm); bool acquire(); void release(Camera *camera); @@ -82,7 +87,7 @@ protected: CameraManager *manager_; private: - void unlockMediaDevices(); + void unlockCameraDevices(); void mediaDeviceDisconnected(MediaDevice *media); virtual void disconnect(); @@ -90,7 +95,7 @@ private: void doQueueRequest(Request *request); void doQueueRequests(); - std::vector> mediaDevices_; + std::vector> cameraDevices_; std::vector> cameras_; std::queue waitingRequests_; diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp index ca177cad985c..0b3e0fd8fa8b 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 media : mediaDevices_) - media->release(); + for (std::shared_ptr device : cameraDevices_) + device->release(); } /** @@ -139,11 +140,42 @@ 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 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 * @@ -173,9 +205,9 @@ bool PipelineHandler::acquire() return true; } - for (std::shared_ptr &media : mediaDevices_) { - if (!media->lock()) { - unlockMediaDevices(); + for (std::shared_ptr &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 &media : mediaDevices_) - media->unlock(); + for (std::shared_ptr &device : cameraDevices_) + device->unlock(); } /** @@ -606,7 +638,7 @@ void PipelineHandler::registerCamera(std::shared_ptr 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) * to the camera. */ std::vector devnums; - for (const std::shared_ptr &media : mediaDevices_) { + for (const std::shared_ptr &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(device.get()); + if (!media) + continue; + for (const MediaEntity *entity : media->entities()) { if (entity->pads().size() == 1 && (entity->pads()[0]->flags() & MEDIA_PAD_FL_SINK) &&