Show a patch.

GET /api/patches/9390/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 9390,
    "url": "https://patchwork.libcamera.org/api/patches/9390/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/9390/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/projects/1/?format=api",
        "name": "libcamera",
        "link_name": "libcamera",
        "list_id": "libcamera_core",
        "list_email": "libcamera-devel@lists.libcamera.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": ""
    },
    "msgid": "<20200826110926.67192-7-paul.elder@ideasonboard.com>",
    "date": "2020-08-26T11:09:15",
    "name": "[libcamera-devel,RFC,06/17] IPA: IPC: add IPAIPC",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "164c7f073559959ff0cdd8f8cc3b6ae8fb1d9961",
    "submitter": {
        "id": 17,
        "url": "https://patchwork.libcamera.org/api/people/17/?format=api",
        "name": "Paul Elder",
        "email": "paul.elder@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/9390/mbox/",
    "series": [
        {
            "id": 1243,
            "url": "https://patchwork.libcamera.org/api/series/1243/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=1243",
            "date": "2020-08-26T11:09:09",
            "name": "[libcamera-devel,RFC,01/17] IPA: IPC: raspberrypi: Add data definition and generated header",
            "version": 1,
            "mbox": "https://patchwork.libcamera.org/series/1243/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/9390/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/9390/checks/",
    "tags": {},
    "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 B4E2BBD87E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 26 Aug 2020 11:10:04 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 7FDF96290C;\n\tWed, 26 Aug 2020 13:10:04 +0200 (CEST)",
            "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 D582B60387\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 26 Aug 2020 13:10:03 +0200 (CEST)",
            "from pyrite.rasen.tech (unknown\n\t[IPv6:2400:4051:61:600:2c71:1b79:d06d:5032])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id A12FC53C;\n\tWed, 26 Aug 2020 13:10:01 +0200 (CEST)"
        ],
        "Authentication-Results": "lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"HdUWV35N\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1598440203;\n\tbh=az/aNo+37b8u5rH27+RMNMIt3F9hMSEcRSEgHSFh6BY=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=HdUWV35NF5BdmbJuUNAxZhr4mkwaqmgt8Ddh2JxIxRvgv1HKiT/q9MXQF8CHHA995\n\tm79/twQNZPUGCVCYyHziBirpqlcyKN+tty6jk2RkqVdU2aNo6ErnpgrmqusxL5t7i6\n\tlhC5Y/yjc0PDCsp/Hf4RdSH/H+pTBHGM1HgSQdHg=",
        "From": "Paul Elder <paul.elder@ideasonboard.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Wed, 26 Aug 2020 20:09:15 +0900",
        "Message-Id": "<20200826110926.67192-7-paul.elder@ideasonboard.com>",
        "X-Mailer": "git-send-email 2.27.0",
        "In-Reply-To": "<20200826110926.67192-1-paul.elder@ideasonboard.com>",
        "References": "<20200826110926.67192-1-paul.elder@ideasonboard.com>",
        "MIME-Version": "1.0",
        "Subject": "[libcamera-devel] [RFC PATCH 06/17] IPA: IPC: add IPAIPC",
        "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>",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Errors-To": "libcamera-devel-bounces@lists.libcamera.org",
        "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"
    },
    "content": "This patch adds the abstract IPAIPC class and an implementation that uses\nUnixSocket, IPAIPCUnixSocket.\n\nIPAIPC exposes two functions to send a message synchronously, for IPA\nsetup calls such as init(), mapBuffers(), configure(), etc, and to send\na message asynchronously, for streaming calls such as processEvent().\nIt also exposes a signal for callbacks. Just like the callforwards, the\nIPAIPC has no knowledge of the individual IPA functions, therefore it is\nthe responsibililty of the specific IPA proxy to direct the callback to\nthe specific callback handler in the pipeline handler. An IPAIPCFactory\nand REGISTER_IPA_IPC facility is also implemented, similar to how\npipeline handlers and IPA proxies are declared and created.\n\nIPAIPCUnixSocket is an implementation of IPAIPC that uses UnixSocket.\n\nFor now, IPAProxyRPi fetches IPAIPCUnixSocket and uses it, but this can\nbe changed so that the IPAManager fetches it based on some setting\nsomewhere, and feeds the IPAIPC to the proxy.\n\nSigned-off-by: Paul Elder <paul.elder@ideasonboard.com>\n---\n include/libcamera/internal/ipa_ipc.h          |  73 ++++++++\n .../libcamera/internal/ipa_ipc_unixsocket.h   | 116 ++++++++++++\n src/libcamera/ipa_ipc.cpp                     |  58 ++++++\n src/libcamera/ipa_ipc_unixsocket.cpp          | 177 ++++++++++++++++++\n 4 files changed, 424 insertions(+)\n create mode 100644 include/libcamera/internal/ipa_ipc.h\n create mode 100644 include/libcamera/internal/ipa_ipc_unixsocket.h\n create mode 100644 src/libcamera/ipa_ipc.cpp\n create mode 100644 src/libcamera/ipa_ipc_unixsocket.cpp",
    "diff": "diff --git a/include/libcamera/internal/ipa_ipc.h b/include/libcamera/internal/ipa_ipc.h\nnew file mode 100644\nindex 00000000..bd7b9bf2\n--- /dev/null\n+++ b/include/libcamera/internal/ipa_ipc.h\n@@ -0,0 +1,73 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2020, Google Inc.\n+ *\n+ * ipa_ipc.h - Image Processing Algorithm IPC module for IPA proxies\n+ */\n+#ifndef __LIBCAMERA_INTERNAL_IPA_IPC_H__\n+#define __LIBCAMERA_INTERNAL_IPA_IPC_H__\n+\n+#include <vector>\n+\n+namespace libcamera {\n+\n+class IPAIPC\n+{\n+public:\n+\tIPAIPC([[maybe_unused]] const char *ipa_module_path,\n+\t       [[maybe_unused]] const char *ipa_proxy_worker_path);\n+\tvirtual ~IPAIPC();\n+\n+\tbool isValid() const { return valid_; }\n+\n+\tvirtual int sendSync(uint32_t cmd,\n+\t\t\t     const std::vector<uint8_t> &data_in,\n+\t\t\t     const std::vector<int32_t> &fds_in,\n+\t\t\t     std::vector<uint8_t> *data_out = nullptr,\n+\t\t\t     std::vector<int32_t> *fds_out = nullptr) = 0;\n+\n+\tvirtual int sendAsync(uint32_t cmd,\n+\t\t\t      const std::vector<uint8_t> &data_in,\n+\t\t\t      const std::vector<int32_t> &fds_in) = 0;\n+\n+\tSignal<std::vector<uint8_t> &, std::vector<int32_t> &> recvIPC;\n+\n+protected:\n+\tbool valid_;\n+};\n+\n+class IPAIPCFactory\n+{\n+public:\n+\tIPAIPCFactory(const char *name);\n+\tvirtual ~IPAIPCFactory() {}\n+\n+\tvirtual std::unique_ptr<IPAIPC> create(const char *ipa_module_path,\n+\t\t\t\t\t       const char *ipa_proxy_worker_path) = 0;\n+\n+\tconst std::string &name() const { return name_; }\n+\n+\tstatic void registerType(IPAIPCFactory *factory);\n+\tstatic std::vector<IPAIPCFactory *> &factories();\n+\n+private:\n+\tstd::string name_;\n+};\n+\n+#define REGISTER_IPA_IPC(ipc)\t\t\t\t\t\t\\\n+class ipc##Factory final : public IPAIPCFactory\t\t\t\t\\\n+{\t\t\t\t\t\t\t\t\t\\\n+public:\t\t\t\t\t\t\t\t\t\\\n+\tipc##Factory() : IPAIPCFactory(#ipc) {}\t\t\t\t\\\n+\tstd::unique_ptr<IPAIPC> create(const char *ipa_module_path,\t\\\n+\t\t\t\t       const char *ipa_proxy_worker_path)\\\n+\t{\t\t\t\t\t\t\t\t\\\n+\t\treturn std::make_unique<ipc>(ipa_module_path,\t\t\\\n+\t\t\t\t\t     ipa_proxy_worker_path);\t\\\n+\t}\t\t\t\t\t\t\t\t\\\n+};\t\t\t\t\t\t\t\t\t\\\n+static ipc##Factory global_##ipc##Factory;\n+\n+} /* namespace libcamera */\n+\n+#endif /* __LIBCAMERA_INTERNAL_IPA_IPC_H__ */\ndiff --git a/include/libcamera/internal/ipa_ipc_unixsocket.h b/include/libcamera/internal/ipa_ipc_unixsocket.h\nnew file mode 100644\nindex 00000000..4acb27aa\n--- /dev/null\n+++ b/include/libcamera/internal/ipa_ipc_unixsocket.h\n@@ -0,0 +1,116 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2020, Google Inc.\n+ *\n+ * ipa_ipc_unixsocket.h - Image Processing Algorithm IPC module using unix socket\n+ */\n+#ifndef __LIBCAMERA_INTERNAL_IPA_IPC_UNIXSOCKET_H__\n+#define __LIBCAMERA_INTERNAL_IPA_IPC_UNIXSOCKET_H__\n+\n+// TODO move this to an ipaipc header directory\n+\n+#include <vector>\n+\n+#include <libcamera/span.h>\n+\n+#include \"libcamera/internal/ipa_module.h\"\n+#include \"libcamera/internal/ipc_unixsocket.h\"\n+\n+namespace libcamera {\n+\n+class Process;\n+\n+void writeHeader(IPCUnixSocket::Payload &payload, uint32_t cmd, uint32_t seq)\n+{\n+\tuint8_t cmd_arr[] = {static_cast<uint8_t>(cmd & 0xff),\n+\t\t\t     static_cast<uint8_t>(cmd & (0xff << 8)),\n+\t\t\t     static_cast<uint8_t>(cmd & (0xff << 16)),\n+\t\t\t     static_cast<uint8_t>(cmd & (0xff << 24))};\n+\tuint8_t seq_arr[] = {static_cast<uint8_t>(seq & 0xff),\n+\t\t\t     static_cast<uint8_t>(seq & (0xff << 8)),\n+\t\t\t     static_cast<uint8_t>(seq & (0xff << 16)),\n+\t\t\t     static_cast<uint8_t>(seq & (0xff << 24))};\n+\tpayload.data.insert(payload.data.begin(), cmd_arr, cmd_arr+4);\n+\tpayload.data.insert(payload.data.begin() + 4, seq_arr, seq_arr+4);\n+}\n+\n+std::tuple<uint32_t, uint32_t> readHeader(IPCUnixSocket::Payload &payload)\n+{\n+\tuint32_t cmd = (payload.data[0] & 0xff) |\n+\t\t       ((payload.data[1] & 0xff) << 8) |\n+\t\t       ((payload.data[2] & 0xff) << 16) |\n+\t\t       ((payload.data[3] & 0xff) << 24);\n+\tuint32_t seq = (payload.data[4] & 0xff) |\n+\t\t       ((payload.data[5] & 0xff) << 8) |\n+\t\t       ((payload.data[6] & 0xff) << 16) |\n+\t\t       ((payload.data[7] & 0xff) << 24);\n+\n+\treturn {cmd, seq};\n+}\n+\n+void eraseHeader(IPCUnixSocket::Payload &payload)\n+{\n+\tpayload.data.erase(payload.data.begin(), payload.data.begin() + 8);\n+}\n+\n+void writeUInt32(IPCUnixSocket::Payload &payload, uint32_t val, uint32_t pos)\n+{\n+\tif (pos + 4 > payload.data.size())\n+\t\treturn;\n+\n+\tuint8_t arr[] = {static_cast<uint8_t>(val & 0xff),\n+\t\t\t static_cast<uint8_t>(val & (0xff << 8)),\n+\t\t\t static_cast<uint8_t>(val & (0xff << 16)),\n+\t\t\t static_cast<uint8_t>(val & (0xff << 24))};\n+\tstd::copy(arr, arr + 4, payload.data.begin() + pos);\n+}\n+\n+uint32_t readUInt32(IPCUnixSocket::Payload &payload, uint32_t pos)\n+{\n+\tif (pos + 4 > payload.data.size())\n+\t\treturn 0;\n+\n+\treturn payload.data[pos] & (payload.data[pos + 1] << 8) &\n+\t       (payload.data[pos + 2] << 16) & (payload.data[pos + 3] << 24);\n+}\n+\n+\n+class IPAIPCUnixSocket : public IPAIPC\n+{\n+public:\n+\tIPAIPCUnixSocket(const char *ipa_module_path, const char *ipa_proxy_worker_path);\n+\t~IPAIPCUnixSocket();\n+\n+\tbool isValid() const { return valid_; }\n+\n+\tint sendSync(uint32_t cmd,\n+\t\t     const std::vector<uint8_t> &data_in,\n+\t\t     const std::vector<int32_t> &fds_in,\n+\t\t     std::vector<uint8_t> *data_out,\n+\t\t     std::vector<int32_t> *fds_out) override;\n+\n+\tint sendAsync(uint32_t cmd,\n+\t\t      const std::vector<uint8_t> &data_in,\n+\t\t      const std::vector<int32_t> &fds_in) override;\n+\n+private:\n+\tstruct CallData {\n+\t\tIPCUnixSocket::Payload *response;\n+\t\tbool done;\n+\t};\n+\n+\tvoid readyRead(IPCUnixSocket *socket);\n+\tint call(const IPCUnixSocket::Payload &message, IPCUnixSocket::Payload *response, uint32_t seq);\n+\n+\tuint32_t seq_;\n+\n+\tProcess *proc_;\n+\n+\tIPCUnixSocket *socket_;\n+\n+\tstd::map<uint32_t, struct CallData> callData_;\n+};\n+\n+} /* namespace libcamera */\n+\n+#endif /* __LIBCAMERA_INTERNAL_IPA_IPC_UNIXSOCKET_H__ */\ndiff --git a/src/libcamera/ipa_ipc.cpp b/src/libcamera/ipa_ipc.cpp\nnew file mode 100644\nindex 00000000..142f4bc3\n--- /dev/null\n+++ b/src/libcamera/ipa_ipc.cpp\n@@ -0,0 +1,58 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2020, Google Inc.\n+ *\n+ * ipa_ipc.cpp - Image Processing Algorithm IPC module for IPA proxies\n+ */\n+\n+#include <vector>\n+\n+#include \"libcamera/internal/ipc_unixsocket.h\"\n+#include \"libcamera/internal/log.h\"\n+#include \"libcamera/internal/process.h\"\n+#include \"libcamera/internal/thread.h\"\n+\n+#include <libcamera/event_dispatcher.h>\n+#include <libcamera/timer.h>\n+\n+#include \"libcamera/internal/ipa_ipc.h\"\n+\n+namespace libcamera {\n+\n+LOG_DEFINE_CATEGORY(IPAIPC)\n+\n+IPAIPC::IPAIPC([[maybe_unused]] const char *ipa_module_path,\n+\t       [[maybe_unused]] const char *ipa_proxy_worker_path)\n+\t: valid_(false)\n+{\n+}\n+\n+IPAIPC::~IPAIPC()\n+{\n+}\n+\n+IPAIPCFactory::IPAIPCFactory(const char *name)\n+\t: name_(name)\n+{\n+\tregisterType(this);\n+}\n+\n+void IPAIPCFactory::registerType(IPAIPCFactory *factory)\n+{\n+\tstd::vector<IPAIPCFactory *> &factories = IPAIPCFactory::factories();\n+\n+\tfactories.push_back(factory);\n+\n+\tLOG(IPAIPC, Debug)\n+\t\t<< \"Registered IPC \\\"\" << factory->name() << \"\\\"\";\n+}\n+\n+std::vector<IPAIPCFactory *> &IPAIPCFactory::factories()\n+{\n+\tstatic std::vector<IPAIPCFactory *> factories;\n+\treturn factories;\n+}\n+\n+// TODO documentation, obviously\n+\n+} /* namespace libcamera */\ndiff --git a/src/libcamera/ipa_ipc_unixsocket.cpp b/src/libcamera/ipa_ipc_unixsocket.cpp\nnew file mode 100644\nindex 00000000..aabc81bd\n--- /dev/null\n+++ b/src/libcamera/ipa_ipc_unixsocket.cpp\n@@ -0,0 +1,177 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2020, Google Inc.\n+ *\n+ * ipa_ipc_unixsocket.cpp - Image Processing Algorithm IPC module using unix socket\n+ */\n+\n+#include <vector>\n+\n+#include \"libcamera/internal/ipc_unixsocket.h\"\n+#include \"libcamera/internal/log.h\"\n+#include \"libcamera/internal/process.h\"\n+#include \"libcamera/internal/thread.h\"\n+\n+#include <libcamera/event_dispatcher.h>\n+#include <libcamera/timer.h>\n+\n+#include \"libcamera/internal/ipa_ipc.h\"\n+#include \"libcamera/internal/ipa_ipc_unixsocket.h\"\n+\n+namespace libcamera {\n+\n+LOG_DECLARE_CATEGORY(IPAIPC)\n+\n+IPAIPCUnixSocket::IPAIPCUnixSocket(const char *ipa_module_path,\n+\t\t\t\t   const char *ipa_proxy_worker_path)\n+\t: IPAIPC(ipa_module_path, ipa_proxy_worker_path), seq_(0),\n+\t  proc_(nullptr), socket_(nullptr)\n+{\n+\tstd::vector<int> fds;\n+\tstd::vector<std::string> args;\n+\targs.push_back(ipa_module_path);\n+\n+\tsocket_ = new IPCUnixSocket();\n+\tint fd = socket_->create();\n+\tif (fd < 0) {\n+\t\tLOG(IPAIPC, Error)\n+\t\t\t<< \"Failed to create socket\";\n+\t\treturn;\n+\t}\n+\tsocket_->readyRead.connect(this, &IPAIPCUnixSocket::readyRead);\n+\targs.push_back(std::to_string(fd));\n+\tfds.push_back(fd);\n+\n+\tproc_ = new Process();\n+\tint ret = proc_->start(ipa_proxy_worker_path, args, fds);\n+\tif (ret) {\n+\t\tLOG(IPAIPC, Error)\n+\t\t\t<< \"Failed to start proxy worker process\";\n+\t\treturn;\n+\t}\n+\n+\tvalid_ = true;\n+}\n+\n+IPAIPCUnixSocket::~IPAIPCUnixSocket()\n+{\n+\tdelete proc_;\n+\tdelete socket_;\n+}\n+\n+int IPAIPCUnixSocket::sendSync(uint32_t cmd,\n+\t\t\t       const std::vector<uint8_t> &data_in,\n+\t\t\t       const std::vector<int32_t> &fds_in,\n+\t\t\t       std::vector<uint8_t> *data_out,\n+\t\t\t       std::vector<int32_t> *fds_out)\n+{\n+\tIPCUnixSocket::Payload message, response;\n+\tint ret;\n+\n+\t/* It's fine if seq_ overflows; that'll just be the new epoch. */\n+\tseq_++;\n+\twriteHeader(message, cmd, seq_);\n+\tmessage.data.insert(message.data.end(), data_in.begin(), data_in.end());\n+\n+\tmessage.fds = const_cast<std::vector<int32_t> &>(fds_in);\n+\n+\tret = call(message, &response, seq_);\n+\tif (ret) {\n+\t\tLOG(IPAIPC, Error) << \"Failed to call sync\";\n+\t\tcallData_.erase(seq_);\n+\t\treturn ret;\n+\t}\n+\n+\tif (data_out)\n+\t\tdata_out->insert(data_out->end(), response.data.begin(), response.data.end());\n+\n+\tif (fds_out)\n+\t\tfds_out->insert(fds_out->end(), response.fds.begin(), response.fds.end());\n+\n+\treturn 0;\n+}\n+\n+int IPAIPCUnixSocket::sendAsync(uint32_t cmd,\n+\t\t\t\tconst std::vector<uint8_t> &data_in,\n+\t\t\t\tconst std::vector<int32_t> &fds_in)\n+{\n+\tIPCUnixSocket::Payload message;\n+\tint ret;\n+\n+\twriteHeader(message, cmd, 0);\n+\tmessage.data.insert(message.data.end(), data_in.begin(), data_in.end());\n+\n+\tmessage.fds = const_cast<std::vector<int32_t> &>(fds_in);\n+\n+\tret = socket_->send(message);\n+\tif (ret) {\n+\t\tLOG(IPAIPC, Error) << \"Failed to call async\";\n+\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+void IPAIPCUnixSocket::readyRead(IPCUnixSocket *socket)\n+{\n+\tIPCUnixSocket::Payload message;\n+\tint ret = socket->receive(&message);\n+\tif (ret) {\n+\t\tLOG(IPAIPC, Error) << \"Receive message failed\" << ret;\n+\t\treturn;\n+\t}\n+\n+\tuint32_t cmd, seq;\n+\tstd::tie(cmd, seq) = readHeader(message);\n+\n+\tauto callData = callData_.find(seq);\n+\tif (callData != callData_.end()) {\n+\t\teraseHeader(message);\n+\t\t/* Is there any way to avoid this copy? */\n+\t\t*callData->second.response = message;\n+\t\tcallData->second.done = true;\n+\t\treturn;\n+\t}\n+\n+\t/*\n+\t * Received unexpected data, this means it's a call from the IPA.\n+\t * We can't return anything to the IPA (gotta keep them under *our*\n+\t * control, plus returning would require blocking the caller, and we\n+\t * can't afford to do that). Let the proxy do switch-case on cmd.\n+\t */\n+\trecvIPC.emit(message.data, message.fds);\n+\n+\treturn;\n+}\n+\n+int IPAIPCUnixSocket::call(const IPCUnixSocket::Payload &message, IPCUnixSocket::Payload *response, uint32_t seq)\n+{\n+\tTimer timeout;\n+\tint ret;\n+\n+\tcallData_[seq].response = response;\n+\tcallData_[seq].done = false;\n+\n+\tret = socket_->send(message);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\ttimeout.start(200);\n+\twhile (!callData_[seq].done) {\n+\t\tif (!timeout.isRunning()) {\n+\t\t\tLOG(IPAIPC, Error) << \"Call timeout!\";\n+\t\t\tcallData_.erase(seq);\n+\t\t\treturn -ETIMEDOUT;\n+\t\t}\n+\n+\t\tThread::current()->eventDispatcher()->processEvents();\n+\t}\n+\n+\tcallData_.erase(seq);\n+\n+\treturn 0;\n+}\n+\n+REGISTER_IPA_IPC(IPAIPCUnixSocket)\n+\n+} /* namespace libcamera */\n",
    "prefixes": [
        "libcamera-devel",
        "RFC",
        "06/17"
    ]
}