{#- # SPDX-License-Identifier: LGPL-2.1-or-later # Copyright (C) 2020, Google Inc. -#} {%- import "proxy_functions.tmpl" as proxy_funcs -%} /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2020, Google Inc. * * {{module_name}}_ipa_proxy.cpp - Image Processing Algorithm proxy for {{module_name}} * * This file is auto-generated. Do not edit. */ #include #include #include #include #include #include #include #include #include #include "libcamera/internal/control_serializer.h" #include "libcamera/internal/ipa_data_serializer.h" #include "libcamera/internal/ipa_module.h" #include "libcamera/internal/ipa_proxy.h" #include "libcamera/internal/ipc_pipe.h" #include "libcamera/internal/ipc_pipe_unixsocket.h" #include "libcamera/internal/ipc_unixsocket.h" #include "libcamera/internal/process.h" namespace libcamera { LOG_DECLARE_CATEGORY(IPAProxy) {%- if has_namespace %} {% for ns in namespace %} namespace {{ns}} { {% endfor %} {%- endif %} {{proxy_name}}::{{proxy_name}}(IPAModule *ipam, bool isolate) : IPAProxy(ipam), isolate_(isolate), controlSerializer_(ControlSerializer::Role::Proxy), seq_(0) { LOG(IPAProxy, Debug) << "initializing {{module_name}} proxy: loading IPA from " << ipam->path(); if (isolate_) { const std::string proxyWorkerPath = resolvePath("{{module_name}}_ipa_proxy"); if (proxyWorkerPath.empty()) { LOG(IPAProxy, Error) << "Failed to get proxy worker path"; return; } ipc_ = std::make_unique(ipam->path().c_str(), proxyWorkerPath.c_str()); if (!ipc_->isConnected()) { LOG(IPAProxy, Error) << "Failed to create IPCPipe"; return; } ipc_->recv.connect(this, &{{proxy_name}}::recvMessage); valid_ = true; return; } if (!ipam->load()) return; IPAInterface *ipai = ipam->createInterface(); if (!ipai) { LOG(IPAProxy, Error) << "Failed to create IPA context for " << ipam->path(); return; } ipa_ = std::unique_ptr<{{interface_name}}>(static_cast<{{interface_name}} *>(ipai)); proxy_.setIPA(ipa_.get()); {% for method in interface_event.methods %} ipa_->{{method.mojom_name}}.connect(this, &{{proxy_name}}::{{method.mojom_name}}Thread); {%- endfor %} valid_ = true; } {{proxy_name}}::~{{proxy_name}}() { if (isolate_) { IPCMessage::Header header = { static_cast({{cmd_enum_name}}::Exit), seq_++ }; IPCMessage msg(header); ipc_->sendAsync(msg); } } {% if interface_event.methods|length > 0 %} void {{proxy_name}}::recvMessage(const IPCMessage &data) { size_t dataSize = data.data().size(); {{cmd_event_enum_name}} _cmd = static_cast<{{cmd_event_enum_name}}>(data.header().cmd); switch (_cmd) { {%- for method in interface_event.methods %} case {{cmd_event_enum_name}}::{{method.mojom_name|cap}}: { {{method.mojom_name}}IPC(data.data().cbegin(), dataSize, data.fds()); break; } {%- endfor %} default: LOG(IPAProxy, Error) << "Unknown command " << static_cast(_cmd); } } {%- endif %} {% for method in interface_main.methods %} {{proxy_funcs.func_sig(proxy_name, method)}} { if (isolate_) {{"return " if method|method_return_value != "void"}}{{method.mojom_name}}IPC( {%- for param in method|method_param_names -%} {{param}}{{- ", " if not loop.last}} {%- endfor -%} ); else {{"return " if method|method_return_value != "void"}}{{method.mojom_name}}Thread( {%- for param in method|method_param_names -%} {{param}}{{- ", " if not loop.last}} {%- endfor -%} ); } {{proxy_funcs.func_sig(proxy_name, method, "Thread")}} { {%- if method.mojom_name == "stop" %} {{proxy_funcs.stop_thread_body()}} {%- elif method.mojom_name == "init" %} {{ method|method_return_value + " _ret = " if method|method_return_value != "void" -}} ipa_->{{method.mojom_name}}( {%- for param in method|method_param_names -%} {{param}}{{- ", " if not loop.last}} {%- endfor -%} ); proxy_.moveToThread(&thread_); return {{ "_ret" if method|method_return_value != "void" }}; {%- elif method.mojom_name == "start" %} state_ = ProxyRunning; thread_.start(); {{ "return " if method|method_return_value != "void" -}} proxy_.invokeMethod(&ThreadProxy::start, ConnectionTypeBlocking {{- ", " if method|method_param_names}} {%- for param in method|method_param_names -%} {{param}}{{- ", " if not loop.last}} {%- endfor -%} ); {%- elif not method|is_async %} {{ "return " if method|method_return_value != "void" -}} ipa_->{{method.mojom_name}}( {%- for param in method|method_param_names -%} {{param}}{{- ", " if not loop.last}} {%- endfor -%} ); {% elif method|is_async %} ASSERT(state_ == ProxyRunning); proxy_.invokeMethod(&ThreadProxy::{{method.mojom_name}}, ConnectionTypeQueued {%- for param in method|method_param_names -%} , {{param}} {%- endfor -%} ); {%- endif %} } {{proxy_funcs.func_sig(proxy_name, method, "IPC")}} { {%- if method.mojom_name == "configure" %} controlSerializer_.reset(); {%- endif %} {%- set has_output = true if method|method_param_outputs|length > 0 or method|method_return_value != "void" %} {%- set cmd = cmd_enum_name + "::" + method.mojom_name|cap %} IPCMessage::Header _header = { static_cast({{cmd}}), seq_++ }; IPCMessage _ipcInputBuf(_header); {%- if has_output %} IPCMessage _ipcOutputBuf; {%- endif %} {{proxy_funcs.serialize_call(method|method_param_inputs, '_ipcInputBuf.data()', '_ipcInputBuf.fds()')}} {% if method|is_async %} int _ret = ipc_->sendAsync(_ipcInputBuf); {%- else %} int _ret = ipc_->sendSync(_ipcInputBuf {{- ", &_ipcOutputBuf" if has_output -}} ); {%- endif %} if (_ret < 0) { LOG(IPAProxy, Error) << "Failed to call {{method.mojom_name}}"; {%- if method|method_return_value != "void" %} return static_cast<{{method|method_return_value}}>(_ret); {%- else %} return; {%- endif %} } {% if method|method_return_value != "void" %} {{method|method_return_value}} _retValue = IPADataSerializer<{{method|method_return_value}}>::deserialize(_ipcOutputBuf.data(), 0); {{proxy_funcs.deserialize_call(method|method_param_outputs, '_ipcOutputBuf.data()', '_ipcOutputBuf.fds()', init_offset = method|method_return_value|byte_width|int)}} return _retValue; {% elif method|method_param_outputs|length > 0 %} {{proxy_funcs.deserialize_call(method|method_param_outputs, '_ipcOutputBuf.data()', '_ipcOutputBuf.fds()')}} {% endif -%} } {% endfor %} {% for method in interface_event.methods %} {{proxy_funcs.func_sig(proxy_name, method, "Thread")}} { ASSERT(state_ != ProxyStopped); {{method.mojom_name}}.emit({{method.parameters|params_comma_sep}}); } void {{proxy_name}}::{{method.mojom_name}}IPC( [[maybe_unused]] std::vector::const_iterator data, [[maybe_unused]] size_t dataSize, [[maybe_unused]] const std::vector &fds) { {%- for param in method.parameters %} {{param|name}} {{param.mojom_name}}; {%- endfor %} {{proxy_funcs.deserialize_call(method.parameters, 'data', 'fds', false, false, true, 'dataSize')}} {{method.mojom_name}}.emit({{method.parameters|params_comma_sep}}); } {% endfor %} {%- if has_namespace %} {% for ns in namespace|reverse %} } /* namespace {{ns}} */ {% endfor %} {%- endif %} } /* namespace libcamera */