[{"id":24946,"web_url":"https://patchwork.libcamera.org/comment/24946/","msgid":"<166245630364.4009730.11773747052590493057@Monstersaurus>","date":"2022-09-06T09:25:03","subject":"Re: [libcamera-devel] [PATCH 1/3] pipeline: uvcvideo: Move camera\n\tID generation to UVCCameraData class","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Laurent Pinchart via libcamera-devel (2022-09-03 19:10:35)\n> Move the camera ID generation to UVCCameraData, and cache the ID in that\n> class. This will be useful to access the ID in multiple locations, such\n> as when printing error messages.\n> \n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n>  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 149 ++++++++++---------\n>  1 file changed, 78 insertions(+), 71 deletions(-)\n> \n> diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> index 2ae640a31f68..22b67faf309e 100644\n> --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> @@ -46,8 +46,15 @@ public:\n>                         ControlInfoMap::Map *ctrls);\n>         void bufferReady(FrameBuffer *buffer);\n>  \n> +       const std::string &id() const { return id_; }\n> +\n>         std::unique_ptr<V4L2VideoDevice> video_;\n>         Stream stream_;\n> +\n> +private:\n> +       bool generateId();\n> +\n> +       std::string id_;\n>  };\n>  \n>  class UVCCameraConfiguration : public CameraConfiguration\n> @@ -81,8 +88,6 @@ public:\n>         bool match(DeviceEnumerator *enumerator) override;\n>  \n>  private:\n> -       std::string generateId(const UVCCameraData *data);\n> -\n>         int processControl(ControlList *controls, unsigned int id,\n>                            const ControlValue &value);\n>         int processControls(UVCCameraData *data, Request *request);\n> @@ -384,69 +389,6 @@ int PipelineHandlerUVC::queueRequestDevice(Camera *camera, Request *request)\n>         return 0;\n>  }\n>  \n> -std::string PipelineHandlerUVC::generateId(const UVCCameraData *data)\n> -{\n> -       const std::string path = data->video_->devicePath();\n> -\n> -       /* Create a controller ID from first device described in firmware. */\n> -       std::string controllerId;\n> -       std::string searchPath = path;\n> -       while (true) {\n> -               std::string::size_type pos = searchPath.rfind('/');\n> -               if (pos <= 1) {\n> -                       LOG(UVC, Error) << \"Can not find controller ID\";\n> -                       return {};\n> -               }\n> -\n> -               searchPath = searchPath.substr(0, pos);\n> -\n> -               controllerId = sysfs::firmwareNodePath(searchPath);\n> -               if (!controllerId.empty())\n> -                       break;\n> -       }\n> -\n> -       /*\n> -        * Create a USB ID from the device path which has the known format:\n> -        *\n> -        *      path = bus, \"-\", ports, \":\", config, \".\", interface ;\n> -        *      bus = number ;\n> -        *      ports = port, [ \".\", ports ] ;\n> -        *      port = number ;\n> -        *      config = number ;\n> -        *      interface = number ;\n> -        *\n> -        * Example: 3-2.4:1.0\n> -        *\n> -        * The bus is not guaranteed to be stable and needs to be stripped from\n> -        * the USB ID. The final USB ID is built up of the ports, config and\n> -        * interface properties.\n> -        *\n> -        * Example 2.4:1.0.\n> -        */\n> -       std::string usbId = utils::basename(path.c_str());\n> -       usbId = usbId.substr(usbId.find('-') + 1);\n> -\n> -       /* Creata a device ID from the USB devices vendor and product ID. */\n> -       std::string deviceId;\n> -       for (const char *name : { \"idVendor\", \"idProduct\" }) {\n> -               std::ifstream file(path + \"/../\" + name);\n> -\n> -               if (!file.is_open())\n> -                       return {};\n> -\n> -               std::string value;\n> -               std::getline(file, value);\n> -               file.close();\n> -\n> -               if (!deviceId.empty())\n> -                       deviceId += \":\";\n> -\n> -               deviceId += value;\n> -       }\n> -\n> -       return controllerId + \"-\" + usbId + \"-\" + deviceId;\n> -}\n> -\n>  bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)\n>  {\n>         MediaDevice *media;\n> @@ -462,12 +404,7 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)\n>                 return false;\n>  \n>         /* Create and register the camera. */\n> -       std::string id = generateId(data.get());\n> -       if (id.empty()) {\n> -               LOG(UVC, Error) << \"Failed to generate camera ID\";\n> -               return false;\n> -       }\n> -\n> +       std::string id = data->id();\n>         std::set<Stream *> streams{ &data->stream_ };\n>         std::shared_ptr<Camera> camera =\n>                 Camera::create(std::move(data), id, streams);\n\nI wonder if CameraData should always be responsible for creating and\nstoring the id (even for other pipelines). Then Camera::create() would\nget the id from the data it's already being passed.\n\nBut that's not required for this patch.\n\nI think this is still valid alone:\n\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n> @@ -502,6 +439,12 @@ int UVCCameraData::init(MediaDevice *media)\n>  \n>         video_->bufferReady.connect(this, &UVCCameraData::bufferReady);\n>  \n> +       /* Generate the camera ID. */\n> +       if (!generateId()) {\n> +               LOG(UVC, Error) << \"Failed to generate camera ID\";\n> +               return -EINVAL;\n> +       }\n> +\n>         properties_.set(properties::Model, utils::toAscii(media->model()));\n>  \n>         /*\n> @@ -563,6 +506,70 @@ int UVCCameraData::init(MediaDevice *media)\n>         return 0;\n>  }\n>  \n> +bool UVCCameraData::generateId()\n> +{\n> +       const std::string path = video_->devicePath();\n> +\n> +       /* Create a controller ID from first device described in firmware. */\n> +       std::string controllerId;\n> +       std::string searchPath = path;\n> +       while (true) {\n> +               std::string::size_type pos = searchPath.rfind('/');\n> +               if (pos <= 1) {\n> +                       LOG(UVC, Error) << \"Can not find controller ID\";\n> +                       return false;\n> +               }\n> +\n> +               searchPath = searchPath.substr(0, pos);\n> +\n> +               controllerId = sysfs::firmwareNodePath(searchPath);\n> +               if (!controllerId.empty())\n> +                       break;\n> +       }\n> +\n> +       /*\n> +        * Create a USB ID from the device path which has the known format:\n> +        *\n> +        *      path = bus, \"-\", ports, \":\", config, \".\", interface ;\n> +        *      bus = number ;\n> +        *      ports = port, [ \".\", ports ] ;\n> +        *      port = number ;\n> +        *      config = number ;\n> +        *      interface = number ;\n> +        *\n> +        * Example: 3-2.4:1.0\n> +        *\n> +        * The bus is not guaranteed to be stable and needs to be stripped from\n> +        * the USB ID. The final USB ID is built up of the ports, config and\n> +        * interface properties.\n> +        *\n> +        * Example 2.4:1.0.\n> +        */\n> +       std::string usbId = utils::basename(path.c_str());\n> +       usbId = usbId.substr(usbId.find('-') + 1);\n> +\n> +       /* Creata a device ID from the USB devices vendor and product ID. */\n> +       std::string deviceId;\n> +       for (const char *name : { \"idVendor\", \"idProduct\" }) {\n> +               std::ifstream file(path + \"/../\" + name);\n> +\n> +               if (!file.is_open())\n> +                       return false;\n> +\n> +               std::string value;\n> +               std::getline(file, value);\n> +               file.close();\n> +\n> +               if (!deviceId.empty())\n> +                       deviceId += \":\";\n> +\n> +               deviceId += value;\n> +       }\n> +\n> +       id_ = controllerId + \"-\" + usbId + \"-\" + deviceId;\n> +       return true;\n> +}\n> +\n>  void UVCCameraData::addControl(uint32_t cid, const ControlInfo &v4l2Info,\n>                                ControlInfoMap::Map *ctrls)\n>  {\n> -- \n> Regards,\n> \n> Laurent Pinchart\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id C1B0BC0DA4\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue,  6 Sep 2022 09:25:09 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id CABF26207C;\n\tTue,  6 Sep 2022 11:25:08 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 32C1B6203B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue,  6 Sep 2022 11:25:07 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 54DB125B;\n\tTue,  6 Sep 2022 11:25:06 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1662456308;\n\tbh=Xp7Obx7NuceDjw51oXS4eYtsdCAzDWgcJPTJ+AfIsuU=;\n\th=In-Reply-To:References:To:Date:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:\n\tFrom;\n\tb=yBtGGcSH+5zQVNu37na4X1tC0kSn09RvIWCVyofYjsZOR1DhDfIPywx/iZwpodAoI\n\ts4l5Q0XjvIeB9JXxUSabRqNydOjRXYEibAUE3UaFZTVujbKRDMGNHbfU1CM3dopftf\n\tnpsH7nUG6MpYJ8+KA60tBfnwMA19Msq0S1RkrQfm7GzMT/wcWaSCNa2B79/geL6k9a\n\t5eaMCnzs85wugrBeT2saEkx8fqzl54BlfNbL5EHacNbIxV6ZbufbOc6pkPRTzTxTHq\n\tl8VRgWHpeTNH6pzd9Q36ALfEhaFxh2LqpJe2CtI2VKIWQsNYZ5rozzOZgy1LxvQVfY\n\t2plo9iCN/aMOg==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1662456306;\n\tbh=Xp7Obx7NuceDjw51oXS4eYtsdCAzDWgcJPTJ+AfIsuU=;\n\th=In-Reply-To:References:Subject:From:To:Date:From;\n\tb=WHYc0rz5kgf2FT5uQmFxT8jDgl0Fy+HDhZWi7Ov5yDkG4rhggRNKsypvkULaov0ut\n\tTspjPwhhc4v1U3bVOWgYKKi5eOqn3/4Qdvkp2/gpZNJJX3oBlT7L3POFNOn8ixdmG7\n\tsvffHvu7SYRcHBCwT6kumcdrrm1QORBCRS0yL5E0="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"WHYc0rz5\"; dkim-atps=neutral","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20220903181037.1406-2-laurent.pinchart@ideasonboard.com>","References":"<20220903181037.1406-1-laurent.pinchart@ideasonboard.com>\n\t<20220903181037.1406-2-laurent.pinchart@ideasonboard.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Tue, 06 Sep 2022 10:25:03 +0100","Message-ID":"<166245630364.4009730.11773747052590493057@Monstersaurus>","User-Agent":"alot/0.10","Subject":"Re: [libcamera-devel] [PATCH 1/3] pipeline: uvcvideo: Move camera\n\tID generation to UVCCameraData class","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>","From":"Kieran Bingham via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":24950,"web_url":"https://patchwork.libcamera.org/comment/24950/","msgid":"<Yxdb1tqHoYdZi2+P@pendragon.ideasonboard.com>","date":"2022-09-06T14:40:22","subject":"Re: [libcamera-devel] [PATCH 1/3] pipeline: uvcvideo: Move camera\n\tID generation to UVCCameraData class","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Tue, Sep 06, 2022 at 10:25:03AM +0100, Kieran Bingham wrote:\n> Quoting Laurent Pinchart via libcamera-devel (2022-09-03 19:10:35)\n> > Move the camera ID generation to UVCCameraData, and cache the ID in that\n> > class. This will be useful to access the ID in multiple locations, such\n> > as when printing error messages.\n> > \n> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > ---\n> >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 149 ++++++++++---------\n> >  1 file changed, 78 insertions(+), 71 deletions(-)\n> > \n> > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > index 2ae640a31f68..22b67faf309e 100644\n> > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > @@ -46,8 +46,15 @@ public:\n> >                         ControlInfoMap::Map *ctrls);\n> >         void bufferReady(FrameBuffer *buffer);\n> >  \n> > +       const std::string &id() const { return id_; }\n> > +\n> >         std::unique_ptr<V4L2VideoDevice> video_;\n> >         Stream stream_;\n> > +\n> > +private:\n> > +       bool generateId();\n> > +\n> > +       std::string id_;\n> >  };\n> >  \n> >  class UVCCameraConfiguration : public CameraConfiguration\n> > @@ -81,8 +88,6 @@ public:\n> >         bool match(DeviceEnumerator *enumerator) override;\n> >  \n> >  private:\n> > -       std::string generateId(const UVCCameraData *data);\n> > -\n> >         int processControl(ControlList *controls, unsigned int id,\n> >                            const ControlValue &value);\n> >         int processControls(UVCCameraData *data, Request *request);\n> > @@ -384,69 +389,6 @@ int PipelineHandlerUVC::queueRequestDevice(Camera *camera, Request *request)\n> >         return 0;\n> >  }\n> >  \n> > -std::string PipelineHandlerUVC::generateId(const UVCCameraData *data)\n> > -{\n> > -       const std::string path = data->video_->devicePath();\n> > -\n> > -       /* Create a controller ID from first device described in firmware. */\n> > -       std::string controllerId;\n> > -       std::string searchPath = path;\n> > -       while (true) {\n> > -               std::string::size_type pos = searchPath.rfind('/');\n> > -               if (pos <= 1) {\n> > -                       LOG(UVC, Error) << \"Can not find controller ID\";\n> > -                       return {};\n> > -               }\n> > -\n> > -               searchPath = searchPath.substr(0, pos);\n> > -\n> > -               controllerId = sysfs::firmwareNodePath(searchPath);\n> > -               if (!controllerId.empty())\n> > -                       break;\n> > -       }\n> > -\n> > -       /*\n> > -        * Create a USB ID from the device path which has the known format:\n> > -        *\n> > -        *      path = bus, \"-\", ports, \":\", config, \".\", interface ;\n> > -        *      bus = number ;\n> > -        *      ports = port, [ \".\", ports ] ;\n> > -        *      port = number ;\n> > -        *      config = number ;\n> > -        *      interface = number ;\n> > -        *\n> > -        * Example: 3-2.4:1.0\n> > -        *\n> > -        * The bus is not guaranteed to be stable and needs to be stripped from\n> > -        * the USB ID. The final USB ID is built up of the ports, config and\n> > -        * interface properties.\n> > -        *\n> > -        * Example 2.4:1.0.\n> > -        */\n> > -       std::string usbId = utils::basename(path.c_str());\n> > -       usbId = usbId.substr(usbId.find('-') + 1);\n> > -\n> > -       /* Creata a device ID from the USB devices vendor and product ID. */\n> > -       std::string deviceId;\n> > -       for (const char *name : { \"idVendor\", \"idProduct\" }) {\n> > -               std::ifstream file(path + \"/../\" + name);\n> > -\n> > -               if (!file.is_open())\n> > -                       return {};\n> > -\n> > -               std::string value;\n> > -               std::getline(file, value);\n> > -               file.close();\n> > -\n> > -               if (!deviceId.empty())\n> > -                       deviceId += \":\";\n> > -\n> > -               deviceId += value;\n> > -       }\n> > -\n> > -       return controllerId + \"-\" + usbId + \"-\" + deviceId;\n> > -}\n> > -\n> >  bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)\n> >  {\n> >         MediaDevice *media;\n> > @@ -462,12 +404,7 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)\n> >                 return false;\n> >  \n> >         /* Create and register the camera. */\n> > -       std::string id = generateId(data.get());\n> > -       if (id.empty()) {\n> > -               LOG(UVC, Error) << \"Failed to generate camera ID\";\n> > -               return false;\n> > -       }\n> > -\n> > +       std::string id = data->id();\n> >         std::set<Stream *> streams{ &data->stream_ };\n> >         std::shared_ptr<Camera> camera =\n> >                 Camera::create(std::move(data), id, streams);\n> \n> I wonder if CameraData should always be responsible for creating and\n> storing the id (even for other pipelines). Then Camera::create() would\n> get the id from the data it's already being passed.\n\nI've thought about it and then decided to explore a different rabbit\nhole :-) I think it's a good idea though, and would prevent a common bug\n(that was present in the first version of this patch, before I sent it).\nI initially wrote\n\n         std::shared_ptr<Camera> camera =\n                 Camera::create(std::move(data), data->id(), streams);\n\n> But that's not required for this patch.\n> \n> I think this is still valid alone:\n> \n> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> \n> > @@ -502,6 +439,12 @@ int UVCCameraData::init(MediaDevice *media)\n> >  \n> >         video_->bufferReady.connect(this, &UVCCameraData::bufferReady);\n> >  \n> > +       /* Generate the camera ID. */\n> > +       if (!generateId()) {\n> > +               LOG(UVC, Error) << \"Failed to generate camera ID\";\n> > +               return -EINVAL;\n> > +       }\n> > +\n> >         properties_.set(properties::Model, utils::toAscii(media->model()));\n> >  \n> >         /*\n> > @@ -563,6 +506,70 @@ int UVCCameraData::init(MediaDevice *media)\n> >         return 0;\n> >  }\n> >  \n> > +bool UVCCameraData::generateId()\n> > +{\n> > +       const std::string path = video_->devicePath();\n> > +\n> > +       /* Create a controller ID from first device described in firmware. */\n> > +       std::string controllerId;\n> > +       std::string searchPath = path;\n> > +       while (true) {\n> > +               std::string::size_type pos = searchPath.rfind('/');\n> > +               if (pos <= 1) {\n> > +                       LOG(UVC, Error) << \"Can not find controller ID\";\n> > +                       return false;\n> > +               }\n> > +\n> > +               searchPath = searchPath.substr(0, pos);\n> > +\n> > +               controllerId = sysfs::firmwareNodePath(searchPath);\n> > +               if (!controllerId.empty())\n> > +                       break;\n> > +       }\n> > +\n> > +       /*\n> > +        * Create a USB ID from the device path which has the known format:\n> > +        *\n> > +        *      path = bus, \"-\", ports, \":\", config, \".\", interface ;\n> > +        *      bus = number ;\n> > +        *      ports = port, [ \".\", ports ] ;\n> > +        *      port = number ;\n> > +        *      config = number ;\n> > +        *      interface = number ;\n> > +        *\n> > +        * Example: 3-2.4:1.0\n> > +        *\n> > +        * The bus is not guaranteed to be stable and needs to be stripped from\n> > +        * the USB ID. The final USB ID is built up of the ports, config and\n> > +        * interface properties.\n> > +        *\n> > +        * Example 2.4:1.0.\n> > +        */\n> > +       std::string usbId = utils::basename(path.c_str());\n> > +       usbId = usbId.substr(usbId.find('-') + 1);\n> > +\n> > +       /* Creata a device ID from the USB devices vendor and product ID. */\n> > +       std::string deviceId;\n> > +       for (const char *name : { \"idVendor\", \"idProduct\" }) {\n> > +               std::ifstream file(path + \"/../\" + name);\n> > +\n> > +               if (!file.is_open())\n> > +                       return false;\n> > +\n> > +               std::string value;\n> > +               std::getline(file, value);\n> > +               file.close();\n> > +\n> > +               if (!deviceId.empty())\n> > +                       deviceId += \":\";\n> > +\n> > +               deviceId += value;\n> > +       }\n> > +\n> > +       id_ = controllerId + \"-\" + usbId + \"-\" + deviceId;\n> > +       return true;\n> > +}\n> > +\n> >  void UVCCameraData::addControl(uint32_t cid, const ControlInfo &v4l2Info,\n> >                                ControlInfoMap::Map *ctrls)\n> >  {","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id F01EBC0DA4\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue,  6 Sep 2022 14:40:39 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6DF0062079;\n\tTue,  6 Sep 2022 16:40:39 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id AA7EE6041F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue,  6 Sep 2022 16:40:37 +0200 (CEST)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id EBC47478;\n\tTue,  6 Sep 2022 16:40:36 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1662475239;\n\tbh=h7Ff3vIP5VymC1MiGlOJ+VY35Ylxf/owpb+/s/JrApw=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=XsRk+FIDQ32wcZM1WqFWQUfthgoyBWnyb37oxfwch0oNBGNi40EmLb1BttpkfBAqU\n\tPtyUNAgyTjtwY/Q3ntzEvODvlsHCZg5xnBt+wNSyxkO0Pj7kkV1BcQl3CS9Vj3WD5Q\n\tYrDEyIDaLbTkkzTGnE7h2y/CycYZhQsffeDWGz666k2roKKmwDF3pWuJ00MwNprwUT\n\t6zW4MzxmpnLJilhosa5KAtqmvHBg4CZauFf/EYn2NkYGS9yyHvrDvu8FJp5NZ8+5aE\n\tF46EQIQRXhu21ZaTn5PNOYajytj0OfXAH8FW1i+naJKPO7leOpEfPbM/+WtsaIg8pn\n\tvDRiKDiSIR5RQ==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1662475237;\n\tbh=h7Ff3vIP5VymC1MiGlOJ+VY35Ylxf/owpb+/s/JrApw=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=RzyBih3kqafTdQu8Smi4RPNQXv5/T22wKYewEgIgxhC847ux4lSdRv5NQNJZESLk7\n\tMxPZaRUzzwQPmmk55fH5Dv16Xdp4QuJRs/DDMfKh/HbaHcRuYclPxK4kUwlNjxW1BB\n\t1pg5+/kcY+dRg4C5kpO5kyFoTYcKexzdcAU36yzA="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"RzyBih3k\"; dkim-atps=neutral","Date":"Tue, 6 Sep 2022 17:40:22 +0300","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Message-ID":"<Yxdb1tqHoYdZi2+P@pendragon.ideasonboard.com>","References":"<20220903181037.1406-1-laurent.pinchart@ideasonboard.com>\n\t<20220903181037.1406-2-laurent.pinchart@ideasonboard.com>\n\t<166245630364.4009730.11773747052590493057@Monstersaurus>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<166245630364.4009730.11773747052590493057@Monstersaurus>","Subject":"Re: [libcamera-devel] [PATCH 1/3] pipeline: uvcvideo: Move camera\n\tID generation to UVCCameraData class","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>","From":"Laurent Pinchart via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]