{"id":3960,"url":"https://patchwork.libcamera.org/api/patches/3960/?format=json","web_url":"https://patchwork.libcamera.org/patch/3960/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20200606080706.14290-1-paul.elder@ideasonboard.com>","date":"2020-06-06T08:07:06","name":"[libcamera-devel,v2] libcamera: CameraManager, PipelineHandler: Automatically map devnums to Camera","commit_ref":null,"pull_url":null,"state":"superseded","archived":false,"hash":"c82a2a397a98867c887f74c3341b97553dba8003","submitter":{"id":17,"url":"https://patchwork.libcamera.org/api/people/17/?format=json","name":"Paul Elder","email":"paul.elder@ideasonboard.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/3960/mbox/","series":[{"id":962,"url":"https://patchwork.libcamera.org/api/series/962/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=962","date":"2020-06-06T08:07:06","name":"[libcamera-devel,v2] libcamera: CameraManager, PipelineHandler: Automatically map devnums to Camera","version":2,"mbox":"https://patchwork.libcamera.org/series/962/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/3960/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/3960/checks/","tags":{},"headers":{"Return-Path":"<paul.elder@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 520E9600F7\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat,  6 Jun 2020 10:07:26 +0200 (CEST)","from emerald.amanokami.net (fs76eef344.knge213.ap.nuro.jp\n\t[118.238.243.68])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 46F9527C;\n\tSat,  6 Jun 2020 10:07:23 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"VBoiKfAn\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1591430845;\n\tbh=+tZvKFCwU9bVV3iE3ct0WybHyk8MjCudcq86kSJesfI=;\n\th=From:To:Cc:Subject:Date:From;\n\tb=VBoiKfAncHEmcrkyHVWslHPgOyIYLwwqRx5ohNEoQbCfKCZPDqGLmq0gNZpH+T+2b\n\tYE2ydRpsQoBCChdXGM4Bd+z5bjxKFyDB3DW2pTgDexwoGFl2WM86s4ScPRxaSO1FiB\n\t6WCjmeKLxrUcInbX4EN9rBGIMga/F2400gKYjscY=","From":"Paul Elder <paul.elder@ideasonboard.com>","To":"libcamera-devel@lists.libcamera.org","Date":"Sat,  6 Jun 2020 17:07:06 +0900","Message-Id":"<20200606080706.14290-1-paul.elder@ideasonboard.com>","X-Mailer":"git-send-email 2.20.1","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Subject":"[libcamera-devel] [PATCH v2] libcamera: CameraManager,\n\tPipelineHandler: Automatically map devnums to Camera","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Sat, 06 Jun 2020 08:07:26 -0000"},"content":"The V4L2 compatibility layer uses devnum to match video device nodes to\nlibcamera Cameras. Some pipeline handlers don't report a devnum for\ntheir camera, which prevents the V4L2 compatibility layer from matching\nvideo device nodes to these cameras. To fix this, we first allow the\ncamera manager to map multiple devnums to a camera. Next, we walk the\nmedia device and entity list and tell the camera manager to map every\none of these devnums that is a video capture node to the camera.\n\nSince we decided that all video capture nodes that belong to a camera\ncan be opened via the V4L2 compatibility layer to map to that camera, it\nwould cause confusion for users if some pipeline handlers decided that\nonly specific device nodes would map to the camera. To prevent this\nconfusion, remove the ability for pipeline handlers to declare their own\ndevnum-to-camera mapping. The only pipeline handler that declares the\ndevnum mapping is the UVC pipeline handler, so remove the devnum there.\n\nWe considered walking the media entity list and taking the devnum from\njust the one with the default flag set, but we found that some drivers\n(eg. vimc) don't set this flag for any entity. Instead, we take all the\nvideo capture nodes (entities with the sink pad flag set).\n\nSigned-off-by: Paul Elder <paul.elder@ideasonboard.com>\nReviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n\n---\nChanges in v2:\n- pipeline handlers can no longer declare their own devnum\n  mapping.\n  - remove the uvc pipeline handler devnum mapping\n- cosmetic changes\n---\n include/libcamera/camera_manager.h            |  3 ++-\n include/libcamera/internal/pipeline_handler.h |  2 +-\n src/libcamera/camera_manager.cpp              | 17 ++++++-------\n src/libcamera/pipeline/uvcvideo/uvcvideo.cpp  |  4 +---\n src/libcamera/pipeline_handler.cpp            | 24 ++++++++++++-------\n 5 files changed, 28 insertions(+), 22 deletions(-)","diff":"diff --git a/include/libcamera/camera_manager.h b/include/libcamera/camera_manager.h\nindex 079f848a..95dc6360 100644\n--- a/include/libcamera/camera_manager.h\n+++ b/include/libcamera/camera_manager.h\n@@ -34,7 +34,8 @@ public:\n \tstd::shared_ptr<Camera> get(const std::string &name);\n \tstd::shared_ptr<Camera> get(dev_t devnum);\n \n-\tvoid addCamera(std::shared_ptr<Camera> camera, dev_t devnum);\n+\tvoid addCamera(std::shared_ptr<Camera> camera,\n+\t\t       const std::vector<dev_t> &devnums);\n \tvoid removeCamera(Camera *camera);\n \n \tstatic const std::string &version() { return version_; }\ndiff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h\nindex 56968d14..22e629a8 100644\n--- a/include/libcamera/internal/pipeline_handler.h\n+++ b/include/libcamera/internal/pipeline_handler.h\n@@ -91,7 +91,7 @@ public:\n \n protected:\n \tvoid registerCamera(std::shared_ptr<Camera> camera,\n-\t\t\t    std::unique_ptr<CameraData> data, dev_t devnum = 0);\n+\t\t\t    std::unique_ptr<CameraData> data);\n \tvoid hotplugMediaDevice(MediaDevice *media);\n \n \tvirtual int queueRequestDevice(Camera *camera, Request *request) = 0;\ndiff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp\nindex da806fa7..3d055f78 100644\n--- a/src/libcamera/camera_manager.cpp\n+++ b/src/libcamera/camera_manager.cpp\n@@ -36,7 +36,8 @@ public:\n \tPrivate(CameraManager *cm);\n \n \tint start();\n-\tvoid addCamera(std::shared_ptr<Camera> &camera, dev_t devnum);\n+\tvoid addCamera(std::shared_ptr<Camera> &camera,\n+\t\t       const std::vector<dev_t> &devnums);\n \tvoid removeCamera(Camera *camera);\n \n \t/*\n@@ -168,7 +169,7 @@ void CameraManager::Private::cleanup()\n }\n \n void CameraManager::Private::addCamera(std::shared_ptr<Camera> &camera,\n-\t\t\t\t       dev_t devnum)\n+\t\t\t\t       const std::vector<dev_t> &devnums)\n {\n \tMutexLocker locker(mutex_);\n \n@@ -183,10 +184,9 @@ void CameraManager::Private::addCamera(std::shared_ptr<Camera> &camera,\n \n \tcameras_.push_back(std::move(camera));\n \n-\tif (devnum) {\n-\t\tunsigned int index = cameras_.size() - 1;\n+\tunsigned int index = cameras_.size() - 1;\n+\tfor (dev_t devnum : devnums)\n \t\tcamerasByDevnum_[devnum] = cameras_[index];\n-\t}\n }\n \n void CameraManager::Private::removeCamera(Camera *camera)\n@@ -374,7 +374,7 @@ std::shared_ptr<Camera> CameraManager::get(dev_t devnum)\n /**\n  * \\brief Add a camera to the camera manager\n  * \\param[in] camera The camera to be added\n- * \\param[in] devnum The device number to associate with \\a camera\n+ * \\param[in] devnums The device numbers to associate with \\a camera\n  *\n  * This function is called by pipeline handlers to register the cameras they\n  * handle with the camera manager. Registered cameras are immediately made\n@@ -385,11 +385,12 @@ std::shared_ptr<Camera> CameraManager::get(dev_t devnum)\n  *\n  * \\context This function shall be called from the CameraManager thread.\n  */\n-void CameraManager::addCamera(std::shared_ptr<Camera> camera, dev_t devnum)\n+void CameraManager::addCamera(std::shared_ptr<Camera> camera,\n+\t\t\t      const std::vector<dev_t> &devnums)\n {\n \tASSERT(Thread::current() == p_.get());\n \n-\tp_->addCamera(camera, devnum);\n+\tp_->addCamera(camera, devnums);\n }\n \n /**\ndiff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\nindex a0749094..396bbe9b 100644\n--- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n+++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n@@ -396,12 +396,10 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)\n \tif (data->init(*entity))\n \t\treturn false;\n \n-\tdev_t devnum = makedev((*entity)->deviceMajor(), (*entity)->deviceMinor());\n-\n \t/* Create and register the camera. */\n \tstd::set<Stream *> streams{ &data->stream_ };\n \tstd::shared_ptr<Camera> camera = Camera::create(this, media->model(), streams);\n-\tregisterCamera(std::move(camera), std::move(data), devnum);\n+\tregisterCamera(std::move(camera), std::move(data));\n \n \t/* Enable hot-unplug notifications. */\n \thotplugMediaDevice(media);\ndiff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp\nindex 53aeebdc..125e1779 100644\n--- a/src/libcamera/pipeline_handler.cpp\n+++ b/src/libcamera/pipeline_handler.cpp\n@@ -481,28 +481,34 @@ void PipelineHandler::completeRequest(Camera *camera, Request *request)\n  * \\brief Register a camera to the camera manager and pipeline handler\n  * \\param[in] camera The camera to be added\n  * \\param[in] data Pipeline-specific data for the camera\n- * \\param[in] devnum Device number of the camera (optional)\n  *\n  * This method is called by pipeline handlers to register the cameras they\n  * handle with the camera manager. It associates the pipeline-specific \\a data\n  * with the camera, for later retrieval with cameraData(). Ownership of \\a data\n  * is transferred to the PipelineHandler.\n  *\n- * \\a devnum is the device number (as returned by makedev) that the \\a camera\n- * is to be associated with. This is for the V4L2 compatibility layer to map\n- * device nodes to Camera instances based on the device number\n- * registered by this method in \\a devnum.\n- *\n  * \\context This function shall be called from the CameraManager thread.\n  */\n void PipelineHandler::registerCamera(std::shared_ptr<Camera> camera,\n-\t\t\t\t     std::unique_ptr<CameraData> data,\n-\t\t\t\t     dev_t devnum)\n+\t\t\t\t     std::unique_ptr<CameraData> data)\n {\n \tdata->camera_ = camera.get();\n \tcameraData_[camera.get()] = std::move(data);\n \tcameras_.push_back(camera);\n-\tmanager_->addCamera(std::move(camera), devnum);\n+\n+\t/*\n+\t * Walk the entity list and map the devnums of all capture video nodes\n+\t * to the camera.\n+\t */\n+\tstd::vector<dev_t> devnums;\n+\tfor (const std::shared_ptr<MediaDevice> media : mediaDevices_)\n+\t\tfor (const MediaEntity *entity : media->entities())\n+\t\t\tif (entity->pads().size() == 1 &&\n+\t\t\t    (entity->pads()[0]->flags() & MEDIA_PAD_FL_SINK))\n+\t\t\t\tdevnums.push_back(makedev(entity->deviceMajor(),\n+\t\t\t\t\t\t\t  entity->deviceMinor()));\n+\n+\tmanager_->addCamera(std::move(camera), devnums);\n }\n \n /**\n","prefixes":["libcamera-devel","v2"]}