From patchwork Mon Sep 30 05:35:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 2069 X-Patchwork-Delegate: paul.elder@ideasonboard.com Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4D6F96101D for ; Mon, 30 Sep 2019 07:35:36 +0200 (CEST) Received: from neptunite.amanokami.net (unknown [96.44.9.94]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 724B4311; Mon, 30 Sep 2019 07:35:35 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1569821735; bh=/x5C6zWhUrqEDK1L/f8m6FH6A+YSTtWIQuSEdo0uw04=; h=From:To:Cc:Subject:Date:From; b=QEUyAr3o16HuDVCr/l2Oj5lF38sxVBM89+UrNvSRsR/2EKP64V8uJOCmw8UahxbOV W2oMnBm1dEPGUIEiB2dRsyNCDkBHi6LOi9rjv1fJ3apBoBLg/Fw8qj0dfkgV1gQdra ukQf5cozjFdgY8NXmBTYU0G55eXw4rz2/mdYLgro= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Mon, 30 Sep 2019 01:35:18 -0400 Message-Id: <20190930053520.2711-1-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.23.0 MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH 1/3] libcamera: pipeline: Add device IDs 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-List-Received-Date: Mon, 30 Sep 2019 05:35:36 -0000 Allow pipeline handlers to declare a list of camera device IDs that they support. This list will eventually be used to check against the list of camera devices that the system has, but have yet to be initialized by the kernel or by udev. PipelineHandlerFactory exposes a static method to retrieve the list of all such camera device IDs from all pipeline handlers. Signed-off-by: Paul Elder --- src/libcamera/include/pipeline_handler.h | 58 +++++++++++++++++++++++- src/libcamera/pipeline/ipu3/ipu3.cpp | 4 +- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 2 +- src/libcamera/pipeline/uvcvideo.cpp | 2 +- src/libcamera/pipeline/vimc.cpp | 2 +- src/libcamera/pipeline_handler.cpp | 16 +++++++ 6 files changed, 79 insertions(+), 5 deletions(-) diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h index 1fdef9ce..f16f37ab 100644 --- a/src/libcamera/include/pipeline_handler.h +++ b/src/libcamera/include/pipeline_handler.h @@ -30,6 +30,48 @@ class MediaDevice; class PipelineHandler; class Request; +class DeviceID +{ +public: + DeviceID(std::string type) + : type_(type){}; + ~DeviceID(){}; + + template + bool compare(const DeviceID &id) const + { + return this->type_.compare(id.type_) || + static_cast(this)->compare(static_cast(id)); + } + + const std::string type_; +}; + +class PCIDeviceID : public DeviceID +{ +public: + PCIDeviceID(uint16_t vendor, uint16_t device) + : DeviceID("pci"), vendor_(vendor), device_(device){}; + ~PCIDeviceID(){}; + + bool compare(const PCIDeviceID &pci) const + { + uint32_t thisID = (vendor_ << 16) + device_; + uint32_t otherID = (pci.vendor_ << 16) + pci.device_; + + return thisID < otherID; + } + + const uint16_t vendor_; + const uint16_t device_; +}; + +template +bool compareDevices(const DeviceID &id1, const DeviceID &id2) +{ + return id1.compare(id2); +} + class CameraData { public: @@ -117,6 +159,10 @@ public: static void registerType(PipelineHandlerFactory *factory); static std::vector &factories(); + static std::vector> &getDeviceIDs(); + +protected: + virtual std::vector &deviceIDs() = 0; private: virtual PipelineHandler *createInstance(CameraManager *manager) = 0; @@ -124,12 +170,22 @@ private: std::string name_; }; -#define REGISTER_PIPELINE_HANDLER(handler) \ +#define P99_PROTECT(...) __VA_ARGS__ + +#define REGISTER_PIPELINE_HANDLER(handler, cameras) \ class handler##Factory final : public PipelineHandlerFactory \ { \ public: \ handler##Factory() : PipelineHandlerFactory(#handler) {} \ \ +protected: \ + std::vector &deviceIDs() \ + { \ + static std::vector handler##Cameras = \ + std::vector(cameras); \ + return handler##Cameras; \ + } \ + \ private: \ PipelineHandler *createInstance(CameraManager *manager) \ { \ diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 827906d5..562ee9fb 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -1504,6 +1504,8 @@ int CIO2Device::mediaBusToFormat(unsigned int code) } } -REGISTER_PIPELINE_HANDLER(PipelineHandlerIPU3); +REGISTER_PIPELINE_HANDLER(PipelineHandlerIPU3, + P99_PROTECT({ PCIDeviceID(0x8086, 0x1919), + PCIDeviceID(0x8086, 0x9D32) })); } /* namespace libcamera */ diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index de4ab523..85225f9b 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -513,6 +513,6 @@ void PipelineHandlerRkISP1::bufferReady(Buffer *buffer) completeRequest(activeCamera_, request); } -REGISTER_PIPELINE_HANDLER(PipelineHandlerRkISP1); +REGISTER_PIPELINE_HANDLER(PipelineHandlerRkISP1, {}); } /* namespace libcamera */ diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp index 89652105..376eb92a 100644 --- a/src/libcamera/pipeline/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo.cpp @@ -390,6 +390,6 @@ void UVCCameraData::bufferReady(Buffer *buffer) pipe_->completeRequest(camera_, request); } -REGISTER_PIPELINE_HANDLER(PipelineHandlerUVC); +REGISTER_PIPELINE_HANDLER(PipelineHandlerUVC, {}); } /* namespace libcamera */ diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp index f26a91f8..75d0236f 100644 --- a/src/libcamera/pipeline/vimc.cpp +++ b/src/libcamera/pipeline/vimc.cpp @@ -459,6 +459,6 @@ void VimcCameraData::bufferReady(Buffer *buffer) pipe_->completeRequest(camera_, request); } -REGISTER_PIPELINE_HANDLER(PipelineHandlerVimc); +REGISTER_PIPELINE_HANDLER(PipelineHandlerVimc, {}); } /* namespace libcamera */ diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp index 3e54aa23..9113bf18 100644 --- a/src/libcamera/pipeline_handler.cpp +++ b/src/libcamera/pipeline_handler.cpp @@ -593,6 +593,22 @@ std::vector &PipelineHandlerFactory::factories() return factories; } +std::vector> &PipelineHandlerFactory::getDeviceIDs() +{ + static std::vector> devices; + if (!devices.empty()) + return devices; + + std::vector &factories = PipelineHandlerFactory::factories(); + + for (PipelineHandlerFactory *factory : factories) { + std::vector &factoryDevices = factory->deviceIDs(); + devices.insert(devices.end(), factoryDevices.begin(), factoryDevices.end()); + } + + return devices; +} + /** * \fn PipelineHandlerFactory::createInstance() * \brief Create an instance of the PipelineHandler corresponding to the factory From patchwork Mon Sep 30 05:35:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 2070 X-Patchwork-Delegate: paul.elder@ideasonboard.com Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6FDFA6101D for ; Mon, 30 Sep 2019 07:35:38 +0200 (CEST) Received: from neptunite.amanokami.net (unknown [96.44.9.94]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id C5415311; Mon, 30 Sep 2019 07:35:37 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1569821738; bh=Spx0K1o4ot3i00+ww3EvoCG0uSp+P1+EzVEIWstK66M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=B6nYfWfj3i/gRrlErZMJl/sYQ2ukMRymB22EAiszpJ+qpU/m+zCYjg3AwueBB7ZnS /qg3HatZ0RH9TnPo1tQPn5x/iLjevU7u0JrjCbm7bCThbx6rvHlimi96sonhQYIkdx vuCbwjbUvpUlednSob7vBIj2vtlKjNrBNqrWbeqA= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Mon, 30 Sep 2019 01:35:19 -0400 Message-Id: <20190930053520.2711-2-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20190930053520.2711-1-paul.elder@ideasonboard.com> References: <20190930053520.2711-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH 2/3] libcamera: device_enumerator: Check that expected cameras are available 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-List-Received-Date: Mon, 30 Sep 2019 05:35:38 -0000 Add a static method to DeviceEnumerator to check if the expected number of cameras have been enumerated. The expected cameras are the supported cameras declared by the pipeline handlers that the system has. Signed-off-by: Paul Elder --- src/libcamera/device_enumerator.cpp | 69 +++++++++++++++++++++++ src/libcamera/include/device_enumerator.h | 4 ++ 2 files changed, 73 insertions(+) diff --git a/src/libcamera/device_enumerator.cpp b/src/libcamera/device_enumerator.cpp index 0b596bce..7d28f9b8 100644 --- a/src/libcamera/device_enumerator.cpp +++ b/src/libcamera/device_enumerator.cpp @@ -9,10 +9,15 @@ #include "device_enumerator_sysfs.h" #include "device_enumerator_udev.h" +#include +#include +#include #include +#include #include "log.h" #include "media_device.h" +#include "pipeline_handler.h" #include "utils.h" /** @@ -306,4 +311,68 @@ std::shared_ptr DeviceEnumerator::search(const DeviceMatch &dm) return nullptr; } +int extractNumberFromFile(std::string &path) +{ + std::ifstream file; + std::string line; + + file.open(path); + if (!file) + return -1; + + file >> line; + int i = std::stoi(line, 0, 16); + file.close(); + + return i; +} + +bool DeviceEnumerator::haveExpectedCameras(CameraManager *cm) +{ + std::vector> &supportedDevices = + PipelineHandlerFactory::getDeviceIDs(); + std::vector availableDevices; + std::vector intersection; + struct dirent *ent; + DIR *dir; + const char *pciDir = "/sys/bus/pci/devices"; + + dir = opendir(pciDir); + if (!dir) { + LOG(DeviceEnumerator, Error) + << "Failed to open sysfs PCI directory"; + /* We can't expect any cameras, so we vacuously have them all. */ + return true; + } + + while ((ent = readdir(dir)) != nullptr) { + std::string path = pciDir + std::string("/") + ent->d_name + "/vendor"; + int vendor = extractNumberFromFile(path); + if (vendor < 0) + continue; + + path = pciDir + std::string("/") + ent->d_name + "/device"; + int device = extractNumberFromFile(path); + if (device < 0) + continue; + + availableDevices.push_back(PCIDeviceID(vendor, device)); + } + + closedir(dir); + + std::set_intersection(supportedDevices.begin(), supportedDevices.end(), + availableDevices.begin(), availableDevices.end(), + back_inserter(intersection), + compareDevices); + + if (cm->cameras().size() < intersection.size()) { + LOG(DeviceEnumerator, Warning) << "Not enough cameras!"; + return false; + } + + LOG(DeviceEnumerator, Debug) << "All cameras correctly initialized"; + return true; +} + } /* namespace libcamera */ diff --git a/src/libcamera/include/device_enumerator.h b/src/libcamera/include/device_enumerator.h index 770f4277..11c4cdfb 100644 --- a/src/libcamera/include/device_enumerator.h +++ b/src/libcamera/include/device_enumerator.h @@ -13,6 +13,8 @@ #include +#include + namespace libcamera { class MediaDevice; @@ -43,6 +45,8 @@ public: std::shared_ptr search(const DeviceMatch &dm); + static bool haveExpectedCameras(CameraManager *cm); + protected: std::shared_ptr createDevice(const std::string &deviceNode); void addDevice(const std::shared_ptr &media); From patchwork Mon Sep 30 05:35:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 2071 X-Patchwork-Delegate: paul.elder@ideasonboard.com Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2AF85616FF for ; Mon, 30 Sep 2019 07:35:39 +0200 (CEST) Received: from neptunite.amanokami.net (unknown [96.44.9.94]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 76AB733E; Mon, 30 Sep 2019 07:35:38 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1569821738; bh=5JGPeX95v15oEyuLbdZVjlU/1AeTb+w5JennIhaW6PM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HAQzkCIQVPtMx9hTLZxRYvAhfAu0GHDwlXn2r82VXKJTLKdD9IlPtgmdnhOHWUDva v5aa3TSpCg+1LGBTAg8M64LOIK3Be0aVru1hfeKCJC7iRAACUDLoJyC9TR1KXH2Xrq e6fxS9B96wy0Q/NspQt0mHSbQbKbPyw1lbWiSk/A= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Mon, 30 Sep 2019 01:35:20 -0400 Message-Id: <20190930053520.2711-3-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20190930053520.2711-1-paul.elder@ideasonboard.com> References: <20190930053520.2711-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH 3/3] android: camera_hal_manager: error on init if cameras not initialized 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-List-Received-Date: Mon, 30 Sep 2019 05:35:39 -0000 Return error from hal_init() if the built-in cameras have not been initialized yet. On Chromium OS, this causes Upstart to restart the camera service at a later time, allowing the built-in cameras to be enumerated correctly. This fixes the problem where the camera service is started before the camera device nodes are available. Signed-off-by: Paul Elder --- src/android/camera3_hal.cpp | 4 +--- src/android/camera_hal_manager.cpp | 11 ++++++++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/android/camera3_hal.cpp b/src/android/camera3_hal.cpp index 8d2629ca..9d18b999 100644 --- a/src/android/camera3_hal.cpp +++ b/src/android/camera3_hal.cpp @@ -56,9 +56,7 @@ static int hal_init() { LOG(HAL, Info) << "Initialising Android camera HAL"; - cameraManager.init(); - - return 0; + return cameraManager.init(); } /*------------------------------------------------------------------------------ diff --git a/src/android/camera_hal_manager.cpp b/src/android/camera_hal_manager.cpp index 22f0323b..af0114fc 100644 --- a/src/android/camera_hal_manager.cpp +++ b/src/android/camera_hal_manager.cpp @@ -13,11 +13,14 @@ #include "camera_device.h" #include "camera_proxy.h" +#include "device_enumerator.h" using namespace libcamera; LOG_DECLARE_CATEGORY(HAL); +static int initRet = 0; + /* * \class CameraHalManager * @@ -49,7 +52,7 @@ int CameraHalManager::init() MutexLocker locker(mutex_); cv_.wait(locker); - return 0; + return initRet; } void CameraHalManager::run() @@ -68,6 +71,12 @@ void CameraHalManager::run() return; } + if (!DeviceEnumerator::haveExpectedCameras(cameraManager_)) { + LOG(HAL, Warning) << "Expected cameras not loaded"; + initRet = -EAGAIN; + cv_.notify_one(); + } + /* * For each Camera registered in the system, a CameraProxy * gets created here to wraps a camera device.