[{"id":5356,"web_url":"https://patchwork.libcamera.org/comment/5356/","msgid":"<20200623221421.GF5870@pendragon.ideasonboard.com>","date":"2020-06-23T22:14:21","subject":"Re: [libcamera-devel] [PATCH v3 02/22] v4l2: V4L2CameraProxy: Take\n\tV4L2CameraFile as argument for intercepted calls","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Paul,\n\nThank you for the patch.\n\nOn Wed, Jun 24, 2020 at 04:08:16AM +0900, Paul Elder wrote:\n> Prepare for using the V4L2CameraFile as a container for file-specific\n> information in the V4L2 compatibility layer by making it a required\n> argument for all V4L2CameraProxy calls that are directed from\n> V4L2CompatManager, which are intercepted via LD_PRELOAD. Change\n> V4L2CameraFile accordingly.\n> \n> Also change V4L2CompatManager accordingly. Instead of keeping a map of\n> file descriptors to V4L2CameraProxy instances, we keep a map of\n> V4L2CameraFile instances to V4L2CameraProxy instances. When the\n> proxy methods are called, feed the file as a parameter.\n> \n> The dup function is also modified, in that it is removed from\n> V4L2CameraProxy, and is handled completely in V4L2CompatManager, as a\n> map from file descriptors to V4L2CameraFile instances.\n> \n> Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>\n> \n> ---\n> New in v3\n> - split from \"v4l2: v4l2_compat: Support multiple open\"\n> ---\n>  src/v4l2/v4l2_camera_file.cpp    |  4 +-\n>  src/v4l2/v4l2_camera_proxy.cpp   | 89 +++++++++++++++-----------------\n>  src/v4l2/v4l2_camera_proxy.h     | 31 ++++++-----\n>  src/v4l2/v4l2_compat_manager.cpp | 69 +++++++++++--------------\n>  src/v4l2/v4l2_compat_manager.h   |  4 +-\n>  5 files changed, 90 insertions(+), 107 deletions(-)\n> \n> diff --git a/src/v4l2/v4l2_camera_file.cpp b/src/v4l2/v4l2_camera_file.cpp\n> index d3232ab..a07679b 100644\n> --- a/src/v4l2/v4l2_camera_file.cpp\n> +++ b/src/v4l2/v4l2_camera_file.cpp\n> @@ -17,10 +17,10 @@ V4L2CameraFile::V4L2CameraFile(int efd, bool nonBlocking, V4L2CameraProxy *proxy\n>  \t: proxy_(proxy), nonBlocking_(nonBlocking), efd_(efd),\n>  \t  priority_(V4L2_PRIORITY_DEFAULT)\n>  {\n> -\tproxy_->open(nonBlocking);\n> +\tproxy_->open(this);\n>  }\n>  \n>  V4L2CameraFile::~V4L2CameraFile()\n>  {\n> -\tproxy_->close();\n> +\tproxy_->close(this);\n>  }\n> diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp\n> index bf47aa7..c1ee1be 100644\n> --- a/src/v4l2/v4l2_camera_proxy.cpp\n> +++ b/src/v4l2/v4l2_camera_proxy.cpp\n> @@ -23,6 +23,7 @@\n>  #include \"libcamera/internal/utils.h\"\n>  \n>  #include \"v4l2_camera.h\"\n> +#include \"v4l2_camera_file.h\"\n>  #include \"v4l2_compat_manager.h\"\n>  \n>  #define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))\n> @@ -39,9 +40,9 @@ V4L2CameraProxy::V4L2CameraProxy(unsigned int index,\n>  \tquerycap(camera);\n>  }\n>  \n> -int V4L2CameraProxy::open(bool nonBlocking)\n> +int V4L2CameraProxy::open(V4L2CameraFile *file)\n>  {\n> -\tLOG(V4L2Compat, Debug) << \"Servicing open\";\n> +\tLOG(V4L2Compat, Debug) << \"Servicing open fd = \" << file->efd();\n>  \n>  \tint ret = vcam_->open();\n>  \tif (ret < 0) {\n> @@ -49,8 +50,6 @@ int V4L2CameraProxy::open(bool nonBlocking)\n>  \t\treturn -1;\n>  \t}\n>  \n> -\tnonBlocking_ = nonBlocking;\n> -\n>  \tvcam_->getStreamConfig(&streamConfig_);\n>  \tsetFmtFromConfig(streamConfig_);\n>  \tsizeimage_ = calculateSizeImage(streamConfig_);\n> @@ -60,14 +59,10 @@ int V4L2CameraProxy::open(bool nonBlocking)\n>  \treturn 0;\n>  }\n>  \n> -void V4L2CameraProxy::dup()\n> +void V4L2CameraProxy::close(V4L2CameraFile *file)\n>  {\n> -\trefcount_++;\n> -}\n> +\tLOG(V4L2Compat, Debug) << \"Servicing close fd = \" << file->efd();\n>  \n> -void V4L2CameraProxy::close()\n> -{\n> -\tLOG(V4L2Compat, Debug) << \"Servicing close\";\n>  \n>  \tif (--refcount_ > 0)\n>  \t\treturn;\n> @@ -221,9 +216,9 @@ int V4L2CameraProxy::vidioc_querycap(struct v4l2_capability *arg)\n>  \treturn 0;\n>  }\n>  \n> -int V4L2CameraProxy::vidioc_enum_fmt(struct v4l2_fmtdesc *arg)\n> +int V4L2CameraProxy::vidioc_enum_fmt(V4L2CameraFile *file, struct v4l2_fmtdesc *arg)\n>  {\n> -\tLOG(V4L2Compat, Debug) << \"Servicing vidioc_enum_fmt\";\n> +\tLOG(V4L2Compat, Debug) << \"Servicing vidioc_enum_fmt fd = \" << file->efd();\n>  \n>  \tif (!validateBufferType(arg->type) ||\n>  \t    arg->index >= streamConfig_.formats().pixelformats().size())\n> @@ -237,9 +232,9 @@ int V4L2CameraProxy::vidioc_enum_fmt(struct v4l2_fmtdesc *arg)\n>  \treturn 0;\n>  }\n>  \n> -int V4L2CameraProxy::vidioc_g_fmt(struct v4l2_format *arg)\n> +int V4L2CameraProxy::vidioc_g_fmt(V4L2CameraFile *file, struct v4l2_format *arg)\n>  {\n> -\tLOG(V4L2Compat, Debug) << \"Servicing vidioc_g_fmt\";\n> +\tLOG(V4L2Compat, Debug) << \"Servicing vidioc_g_fmt fd = \" << file->efd();\n>  \n>  \tif (!validateBufferType(arg->type))\n>  \t\treturn -EINVAL;\n> @@ -275,9 +270,9 @@ void V4L2CameraProxy::tryFormat(struct v4l2_format *arg)\n>  \targ->fmt.pix.colorspace   = V4L2_COLORSPACE_SRGB;\n>  }\n>  \n> -int V4L2CameraProxy::vidioc_s_fmt(struct v4l2_format *arg)\n> +int V4L2CameraProxy::vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg)\n>  {\n> -\tLOG(V4L2Compat, Debug) << \"Servicing vidioc_s_fmt\";\n> +\tLOG(V4L2Compat, Debug) << \"Servicing vidioc_s_fmt fd = \" << file->efd();\n>  \n>  \tif (!validateBufferType(arg->type))\n>  \t\treturn -EINVAL;\n> @@ -302,9 +297,9 @@ int V4L2CameraProxy::vidioc_s_fmt(struct v4l2_format *arg)\n>  \treturn 0;\n>  }\n>  \n> -int V4L2CameraProxy::vidioc_try_fmt(struct v4l2_format *arg)\n> +int V4L2CameraProxy::vidioc_try_fmt(V4L2CameraFile *file, struct v4l2_format *arg)\n>  {\n> -\tLOG(V4L2Compat, Debug) << \"Servicing vidioc_try_fmt\";\n> +\tLOG(V4L2Compat, Debug) << \"Servicing vidioc_try_fmt fd = \" << file->efd();\n>  \n>  \tif (!validateBufferType(arg->type))\n>  \t\treturn -EINVAL;\n> @@ -329,11 +324,9 @@ int V4L2CameraProxy::freeBuffers()\n>  \treturn 0;\n>  }\n>  \n> -int V4L2CameraProxy::vidioc_reqbufs(struct v4l2_requestbuffers *arg)\n> +int V4L2CameraProxy::vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuffers *arg)\n>  {\n> -\tint ret;\n> -\n> -\tLOG(V4L2Compat, Debug) << \"Servicing vidioc_reqbufs\";\n> +\tLOG(V4L2Compat, Debug) << \"Servicing vidioc_reqbufs fd = \" << file->efd();\n>  \n>  \tif (!validateBufferType(arg->type) ||\n>  \t    !validateMemoryType(arg->memory))\n> @@ -347,9 +340,9 @@ int V4L2CameraProxy::vidioc_reqbufs(struct v4l2_requestbuffers *arg)\n>  \t\treturn freeBuffers();\n>  \n>  \tSize size(curV4L2Format_.fmt.pix.width, curV4L2Format_.fmt.pix.height);\n> -\tret = vcam_->configure(&streamConfig_, size,\n> -\t\t\t       v4l2ToDrm(curV4L2Format_.fmt.pix.pixelformat),\n> -\t\t\t       arg->count);\n> +\tint ret = vcam_->configure(&streamConfig_, size,\n> +\t\t\t\t   v4l2ToDrm(curV4L2Format_.fmt.pix.pixelformat),\n> +\t\t\t\t   arg->count);\n>  \tif (ret < 0)\n>  \t\treturn -EINVAL;\n>  \n> @@ -396,9 +389,9 @@ int V4L2CameraProxy::vidioc_reqbufs(struct v4l2_requestbuffers *arg)\n>  \treturn 0;\n>  }\n>  \n> -int V4L2CameraProxy::vidioc_querybuf(struct v4l2_buffer *arg)\n> +int V4L2CameraProxy::vidioc_querybuf(V4L2CameraFile *file, struct v4l2_buffer *arg)\n>  {\n> -\tLOG(V4L2Compat, Debug) << \"Servicing vidioc_querybuf\";\n> +\tLOG(V4L2Compat, Debug) << \"Servicing vidioc_querybuf fd = \" << file->efd();\n>  \n>  \tif (!validateBufferType(arg->type) ||\n>  \t    arg->index >= bufferCount_)\n> @@ -411,10 +404,10 @@ int V4L2CameraProxy::vidioc_querybuf(struct v4l2_buffer *arg)\n>  \treturn 0;\n>  }\n>  \n> -int V4L2CameraProxy::vidioc_qbuf(struct v4l2_buffer *arg)\n> +int V4L2CameraProxy::vidioc_qbuf(V4L2CameraFile *file, struct v4l2_buffer *arg)\n>  {\n>  \tLOG(V4L2Compat, Debug) << \"Servicing vidioc_qbuf, index = \"\n> -\t\t\t       << arg->index;\n> +\t\t\t       << arg->index << \" fd = \" << file->efd();\n>  \n>  \tif (!validateBufferType(arg->type) ||\n>  \t    !validateMemoryType(arg->memory) ||\n> @@ -431,15 +424,15 @@ int V4L2CameraProxy::vidioc_qbuf(struct v4l2_buffer *arg)\n>  \treturn ret;\n>  }\n>  \n> -int V4L2CameraProxy::vidioc_dqbuf(struct v4l2_buffer *arg)\n> +int V4L2CameraProxy::vidioc_dqbuf(V4L2CameraFile *file, struct v4l2_buffer *arg)\n>  {\n> -\tLOG(V4L2Compat, Debug) << \"Servicing vidioc_dqbuf\";\n> +\tLOG(V4L2Compat, Debug) << \"Servicing vidioc_dqbuf fd = \" << file->efd();\n>  \n>  \tif (!validateBufferType(arg->type) ||\n>  \t    !validateMemoryType(arg->memory))\n>  \t\treturn -EINVAL;\n>  \n> -\tif (!nonBlocking_)\n> +\tif (!(file->nonBlocking()))\n\nNo need for parentheses around file->nonBlock().\n\n>  \t\tvcam_->bufferSema_.acquire();\n>  \telse if (!vcam_->bufferSema_.tryAcquire())\n>  \t\treturn -EAGAIN;\n> @@ -455,16 +448,16 @@ int V4L2CameraProxy::vidioc_dqbuf(struct v4l2_buffer *arg)\n>  \tcurrentBuf_ = (currentBuf_ + 1) % bufferCount_;\n>  \n>  \tuint64_t data;\n> -\tint ret = ::read(efd_, &data, sizeof(data));\n> +\tint ret = ::read(file->efd(), &data, sizeof(data));\n>  \tif (ret != sizeof(data))\n>  \t\tLOG(V4L2Compat, Error) << \"Failed to clear eventfd POLLIN\";\n>  \n>  \treturn 0;\n>  }\n>  \n> -int V4L2CameraProxy::vidioc_streamon(int *arg)\n> +int V4L2CameraProxy::vidioc_streamon(V4L2CameraFile *file, int *arg)\n>  {\n> -\tLOG(V4L2Compat, Debug) << \"Servicing vidioc_streamon\";\n> +\tLOG(V4L2Compat, Debug) << \"Servicing vidioc_streamon fd = \" << file->efd();\n>  \n>  \tif (!validateBufferType(*arg))\n>  \t\treturn -EINVAL;\n> @@ -474,9 +467,9 @@ int V4L2CameraProxy::vidioc_streamon(int *arg)\n>  \treturn vcam_->streamOn();\n>  }\n>  \n> -int V4L2CameraProxy::vidioc_streamoff(int *arg)\n> +int V4L2CameraProxy::vidioc_streamoff(V4L2CameraFile *file, int *arg)\n>  {\n> -\tLOG(V4L2Compat, Debug) << \"Servicing vidioc_streamoff\";\n> +\tLOG(V4L2Compat, Debug) << \"Servicing vidioc_streamoff fd = \" << file->efd();\n>  \n>  \tif (!validateBufferType(*arg))\n>  \t\treturn -EINVAL;\n> @@ -489,7 +482,7 @@ int V4L2CameraProxy::vidioc_streamoff(int *arg)\n>  \treturn ret;\n>  }\n>  \n> -int V4L2CameraProxy::ioctl(unsigned long request, void *arg)\n> +int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long request, void *arg)\n>  {\n>  \tint ret;\n>  \tswitch (request) {\n> @@ -497,34 +490,34 @@ int V4L2CameraProxy::ioctl(unsigned long request, void *arg)\n>  \t\tret = vidioc_querycap(static_cast<struct v4l2_capability *>(arg));\n>  \t\tbreak;\n>  \tcase VIDIOC_ENUM_FMT:\n> -\t\tret = vidioc_enum_fmt(static_cast<struct v4l2_fmtdesc *>(arg));\n> +\t\tret = vidioc_enum_fmt(file, static_cast<struct v4l2_fmtdesc *>(arg));\n>  \t\tbreak;\n>  \tcase VIDIOC_G_FMT:\n> -\t\tret = vidioc_g_fmt(static_cast<struct v4l2_format *>(arg));\n> +\t\tret = vidioc_g_fmt(file, static_cast<struct v4l2_format *>(arg));\n>  \t\tbreak;\n>  \tcase VIDIOC_S_FMT:\n> -\t\tret = vidioc_s_fmt(static_cast<struct v4l2_format *>(arg));\n> +\t\tret = vidioc_s_fmt(file, static_cast<struct v4l2_format *>(arg));\n>  \t\tbreak;\n>  \tcase VIDIOC_TRY_FMT:\n> -\t\tret = vidioc_try_fmt(static_cast<struct v4l2_format *>(arg));\n> +\t\tret = vidioc_try_fmt(file, static_cast<struct v4l2_format *>(arg));\n>  \t\tbreak;\n>  \tcase VIDIOC_REQBUFS:\n> -\t\tret = vidioc_reqbufs(static_cast<struct v4l2_requestbuffers *>(arg));\n> +\t\tret = vidioc_reqbufs(file, static_cast<struct v4l2_requestbuffers *>(arg));\n>  \t\tbreak;\n>  \tcase VIDIOC_QUERYBUF:\n> -\t\tret = vidioc_querybuf(static_cast<struct v4l2_buffer *>(arg));\n> +\t\tret = vidioc_querybuf(file, static_cast<struct v4l2_buffer *>(arg));\n>  \t\tbreak;\n>  \tcase VIDIOC_QBUF:\n> -\t\tret = vidioc_qbuf(static_cast<struct v4l2_buffer *>(arg));\n> +\t\tret = vidioc_qbuf(file, static_cast<struct v4l2_buffer *>(arg));\n>  \t\tbreak;\n>  \tcase VIDIOC_DQBUF:\n> -\t\tret = vidioc_dqbuf(static_cast<struct v4l2_buffer *>(arg));\n> +\t\tret = vidioc_dqbuf(file, static_cast<struct v4l2_buffer *>(arg));\n>  \t\tbreak;\n>  \tcase VIDIOC_STREAMON:\n> -\t\tret = vidioc_streamon(static_cast<int *>(arg));\n> +\t\tret = vidioc_streamon(file, static_cast<int *>(arg));\n>  \t\tbreak;\n>  \tcase VIDIOC_STREAMOFF:\n> -\t\tret = vidioc_streamoff(static_cast<int *>(arg));\n> +\t\tret = vidioc_streamoff(file, static_cast<int *>(arg));\n>  \t\tbreak;\n>  \tdefault:\n>  \t\tret = -ENOTTY;\n> diff --git a/src/v4l2/v4l2_camera_proxy.h b/src/v4l2/v4l2_camera_proxy.h\n> index 27d3e50..b2197ef 100644\n> --- a/src/v4l2/v4l2_camera_proxy.h\n> +++ b/src/v4l2/v4l2_camera_proxy.h\n> @@ -21,20 +21,20 @@\n>  \n>  using namespace libcamera;\n>  \n> +class V4L2CameraFile;\n> +\n>  class V4L2CameraProxy\n>  {\n>  public:\n>  \tV4L2CameraProxy(unsigned int index, std::shared_ptr<Camera> camera);\n>  \n> -\tint open(bool nonBlocking);\n> -\tvoid dup();\n> -\tvoid close();\n> +\tint open(V4L2CameraFile *file);\n> +\tvoid close(V4L2CameraFile *file);\n>  \tvoid *mmap(void *addr, size_t length, int prot, int flags, off64_t offset);\n>  \tint munmap(void *addr, size_t length);\n>  \n> -\tint ioctl(unsigned long request, void *arg);\n> -\n>  \tvoid bind(int fd);\n> +\tint ioctl(V4L2CameraFile *file, unsigned long request, void *arg);\n>  \n>  private:\n>  \tbool validateBufferType(uint32_t type);\n> @@ -47,16 +47,16 @@ private:\n>  \tint freeBuffers();\n>  \n>  \tint vidioc_querycap(struct v4l2_capability *arg);\n> -\tint vidioc_enum_fmt(struct v4l2_fmtdesc *arg);\n> -\tint vidioc_g_fmt(struct v4l2_format *arg);\n> -\tint vidioc_s_fmt(struct v4l2_format *arg);\n> -\tint vidioc_try_fmt(struct v4l2_format *arg);\n> -\tint vidioc_reqbufs(struct v4l2_requestbuffers *arg);\n> -\tint vidioc_querybuf(struct v4l2_buffer *arg);\n> -\tint vidioc_qbuf(struct v4l2_buffer *arg);\n> -\tint vidioc_dqbuf(struct v4l2_buffer *arg);\n> -\tint vidioc_streamon(int *arg);\n> -\tint vidioc_streamoff(int *arg);\n> +\tint vidioc_enum_fmt(V4L2CameraFile *file, struct v4l2_fmtdesc *arg);\n> +\tint vidioc_g_fmt(V4L2CameraFile *file, struct v4l2_format *arg);\n> +\tint vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg);\n> +\tint vidioc_try_fmt(V4L2CameraFile *file, struct v4l2_format *arg);\n> +\tint vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuffers *arg);\n> +\tint vidioc_querybuf(V4L2CameraFile *file, struct v4l2_buffer *arg);\n> +\tint vidioc_qbuf(V4L2CameraFile *file, struct v4l2_buffer *arg);\n> +\tint vidioc_dqbuf(V4L2CameraFile *file, struct v4l2_buffer *arg);\n> +\tint vidioc_streamon(V4L2CameraFile *file, int *arg);\n> +\tint vidioc_streamoff(V4L2CameraFile *file, int *arg);\n>  \n>  \tstatic unsigned int bplMultiplier(uint32_t format);\n>  \tstatic unsigned int imageSize(uint32_t format, unsigned int width,\n> @@ -67,7 +67,6 @@ private:\n>  \n>  \tunsigned int refcount_;\n>  \tunsigned int index_;\n> -\tbool nonBlocking_;\n>  \n>  \tstruct v4l2_format curV4L2Format_;\n>  \tStreamConfiguration streamConfig_;\n> diff --git a/src/v4l2/v4l2_compat_manager.cpp b/src/v4l2/v4l2_compat_manager.cpp\n> index 8da3316..8118170 100644\n> --- a/src/v4l2/v4l2_compat_manager.cpp\n> +++ b/src/v4l2/v4l2_compat_manager.cpp\n> @@ -24,6 +24,8 @@\n>  \n>  #include \"libcamera/internal/log.h\"\n>  \n> +#include \"v4l2_camera_file.h\"\n> +\n>  using namespace libcamera;\n>  \n>  LOG_DEFINE_CATEGORY(V4L2Compat)\n> @@ -49,7 +51,7 @@ V4L2CompatManager::V4L2CompatManager()\n>  \n>  V4L2CompatManager::~V4L2CompatManager()\n>  {\n> -\tdevices_.clear();\n> +\tfiles_.clear();\n>  \tmmaps_.clear();\n>  \n>  \tif (cm_) {\n> @@ -95,13 +97,13 @@ V4L2CompatManager *V4L2CompatManager::instance()\n>  \treturn &instance;\n>  }\n>  \n> -V4L2CameraProxy *V4L2CompatManager::getProxy(int fd)\n> +std::shared_ptr<V4L2CameraFile> V4L2CompatManager::cameraFile(int fd)\n>  {\n> -\tauto device = devices_.find(fd);\n> -\tif (device == devices_.end())\n> -\t\treturn nullptr;\n> +\tauto file = files_.find(fd);\n> +\tif (file == files_.end())\n> +\t\treturn std::shared_ptr<V4L2CameraFile>();\n\nI think you can return nullptr directly as the corresponding\nstd::shared_ptr constructor is not explicit:\n\n\tconstexpr shared_ptr( std::nullptr_t ) noexcept;\n\n(https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr)\n\n>  \n> -\treturn device->second;\n> +\treturn file->second;\n>  }\n>  \n>  int V4L2CompatManager::getCameraIndex(int fd)\n> @@ -148,25 +150,15 @@ int V4L2CompatManager::openat(int dirfd, const char *path, int oflag, mode_t mod\n>  \n>  \tfops_.close(fd);\n>  \n> -\tunsigned int camera_index = static_cast<unsigned int>(ret);\n> -\n> -\tV4L2CameraProxy *proxy = proxies_[camera_index].get();\n> -\tret = proxy->open(oflag & O_NONBLOCK);\n> -\tif (ret < 0)\n> -\t\treturn ret;\n> -\n>  \tint efd = eventfd(0, EFD_SEMAPHORE |\n>  \t\t\t     ((oflag & O_CLOEXEC) ? EFD_CLOEXEC : 0) |\n>  \t\t\t     ((oflag & O_NONBLOCK) ? EFD_NONBLOCK : 0));\n> -\tif (efd < 0) {\n> -\t\tint err = errno;\n> -\t\tproxy->close();\n> -\t\terrno = err;\n> +\tif (efd < 0)\n>  \t\treturn efd;\n> -\t}\n>  \n> -\tproxy->bind(efd);\n> -\tdevices_.emplace(efd, proxy);\n> +\tunsigned int index = static_cast<unsigned int>(ret);\n> +\tV4L2CameraProxy *proxy = proxies_[index].get();\n\nCan you use ret directly and remove the index variable ?\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n> +\tfiles_.emplace(efd, std::make_shared<V4L2CameraFile>(efd, oflag & O_NONBLOCK, proxy));\n>  \n>  \treturn efd;\n>  }\n> @@ -177,40 +169,39 @@ int V4L2CompatManager::dup(int oldfd)\n>  \tif (newfd < 0)\n>  \t\treturn newfd;\n>  \n> -\tauto device = devices_.find(oldfd);\n> -\tif (device != devices_.end()) {\n> -\t\tV4L2CameraProxy *proxy = device->second;\n> -\t\tdevices_[newfd] = proxy;\n> -\t\tproxy->dup();\n> -\t}\n> +\tauto file = files_.find(oldfd);\n> +\tif (file != files_.end())\n> +\t\tfiles_[newfd] = file->second;\n>  \n>  \treturn newfd;\n>  }\n>  \n>  int V4L2CompatManager::close(int fd)\n>  {\n> -\tV4L2CameraProxy *proxy = getProxy(fd);\n> -\tif (proxy) {\n> -\t\tproxy->close();\n> -\t\tdevices_.erase(fd);\n> -\t\treturn 0;\n> -\t}\n> +\tauto file = files_.find(fd);\n> +\tif (file != files_.end())\n> +\t\tfiles_.erase(file);\n>  \n> +\t/* We still need to close the eventfd. */\n>  \treturn fops_.close(fd);\n>  }\n>  \n>  void *V4L2CompatManager::mmap(void *addr, size_t length, int prot, int flags,\n>  \t\t\t      int fd, off64_t offset)\n>  {\n> -\tV4L2CameraProxy *proxy = getProxy(fd);\n> -\tif (!proxy)\n> +\tstd::shared_ptr<V4L2CameraFile> file = cameraFile(fd);\n> +\tif (!file)\n>  \t\treturn fops_.mmap(addr, length, prot, flags, fd, offset);\n>  \n> -\tvoid *map = proxy->mmap(addr, length, prot, flags, offset);\n> +\tvoid *map = file->proxy()->mmap(addr, length, prot, flags, offset);\n>  \tif (map == MAP_FAILED)\n>  \t\treturn map;\n>  \n> -\tmmaps_[map] = proxy;\n> +\t/*\n> +\t * Map to V4L2CameraProxy directly to prevent adding more references\n> +\t * to V4L2CameraFile.\n> +\t */\n> +\tmmaps_[map] = file->proxy();\n>  \treturn map;\n>  }\n>  \n> @@ -233,9 +224,9 @@ int V4L2CompatManager::munmap(void *addr, size_t length)\n>  \n>  int V4L2CompatManager::ioctl(int fd, unsigned long request, void *arg)\n>  {\n> -\tV4L2CameraProxy *proxy = getProxy(fd);\n> -\tif (!proxy)\n> +\tstd::shared_ptr<V4L2CameraFile> file = cameraFile(fd);\n> +\tif (!file)\n>  \t\treturn fops_.ioctl(fd, request, arg);\n>  \n> -\treturn proxy->ioctl(request, arg);\n> +\treturn file->proxy()->ioctl(file.get(), request, arg);\n>  }\n> diff --git a/src/v4l2/v4l2_compat_manager.h b/src/v4l2/v4l2_compat_manager.h\n> index 3d4e512..bc548ab 100644\n> --- a/src/v4l2/v4l2_compat_manager.h\n> +++ b/src/v4l2/v4l2_compat_manager.h\n> @@ -44,7 +44,6 @@ public:\n>  \n>  \tstatic V4L2CompatManager *instance();\n>  \n> -\tV4L2CameraProxy *getProxy(int fd);\n>  \tconst FileOperations &fops() const { return fops_; }\n>  \n>  \tint openat(int dirfd, const char *path, int oflag, mode_t mode);\n> @@ -62,13 +61,14 @@ private:\n>  \n>  \tint start();\n>  \tint getCameraIndex(int fd);\n> +\tstd::shared_ptr<V4L2CameraFile> cameraFile(int fd);\n>  \n>  \tFileOperations fops_;\n>  \n>  \tCameraManager *cm_;\n>  \n>  \tstd::vector<std::unique_ptr<V4L2CameraProxy>> proxies_;\n> -\tstd::map<int, V4L2CameraProxy *> devices_;\n> +\tstd::map<int, std::shared_ptr<V4L2CameraFile>> files_;\n>  \tstd::map<void *, V4L2CameraProxy *> mmaps_;\n>  };\n>","headers":{"Return-Path":"<laurent.pinchart@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 501D5603B9\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 24 Jun 2020 00:14:48 +0200 (CEST)","from pendragon.ideasonboard.com (81-175-216-236.bb.dnainternet.fi\n\t[81.175.216.236])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id AE0342A9;\n\tWed, 24 Jun 2020 00:14:47 +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=\"hOSI7CPa\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1592950487;\n\tbh=HNuKzazWiQmDmWoHYAI34p+/c0Y5l697jDGd2yrSAFs=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=hOSI7CPam/figWSeCnucSnBSazizFliCmoqgSp9pVMdNP2oI/q6y/PyCneFDmvIqG\n\tkXvHRyuU33qk6z7PV0CsO/ip86tdgDzcSPwsUjClraFy4gJuRaMnkiTa844h6UZsqg\n\tBH/5d+CztfkM+wQZUnEeGFSB52QLT8q7Fx0I/Umk=","Date":"Wed, 24 Jun 2020 01:14:21 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Paul Elder <paul.elder@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20200623221421.GF5870@pendragon.ideasonboard.com>","References":"<20200623190836.53446-1-paul.elder@ideasonboard.com>\n\t<20200623190836.53446-3-paul.elder@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20200623190836.53446-3-paul.elder@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v3 02/22] v4l2: V4L2CameraProxy: Take\n\tV4L2CameraFile as argument for intercepted calls","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":"Tue, 23 Jun 2020 22:14:48 -0000"}}]