blob: 31a0ca09f9f02fd12f9d49ce734b4f16c0c69d1a [file] [log] [blame]
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2020, Google Inc.
*
* ipc_pipe.cpp - Image Processing Algorithm IPC module for IPA proxies
*/
#include "libcamera/internal/ipc_pipe.h"
#include <libcamera/base/log.h>
/**
* \file ipc_pipe.h
* \brief IPC mechanism for IPA isolation
*/
namespace libcamera {
LOG_DEFINE_CATEGORY(IPCPipe)
/**
* \struct IPCMessage::Header
* \brief Container for an IPCMessage header
*
* Holds a cmd code for the IPC message, and a cookie.
*/
/**
* \var IPCMessage::Header::cmd
* \brief Type of IPCMessage
*
* Typically used to carry a command code for an RPC.
*/
/**
* \var IPCMessage::Header::cookie
* \brief Cookie to identify the message and a corresponding reply.
*
* Populated and used by IPCPipe implementations for matching calls with
* replies.
*/
/**
* \class IPCMessage
* \brief IPC message to be passed through IPC message pipe
*/
/**
* \brief Construct an empty IPCMessage instance
*/
IPCMessage::IPCMessage()
: header_(Header{ 0, 0 })
{
}
/**
* \brief Construct an IPCMessage instance with a given command code
* \param[in] cmd The command code
*/
IPCMessage::IPCMessage(uint32_t cmd)
: header_(Header{ cmd, 0 })
{
}
/**
* \brief Construct an IPCMessage instance with a given header
* \param[in] header The header that the constructed IPCMessage will contain
*/
IPCMessage::IPCMessage(const Header &header)
: header_(header)
{
}
/**
* \brief Construct an IPCMessage instance from an IPC payload
* \param[in] payload The IPCUnixSocket payload to construct from
*
* This essentially converts an IPCUnixSocket payload into an IPCMessage.
* The header is extracted from the payload into the IPCMessage's header field.
*
* If the IPCUnixSocket payload had any valid file descriptors, then they will
* all be invalidated.
*/
IPCMessage::IPCMessage(IPCUnixSocket::Payload &payload)
{
memcpy(&header_, payload.data.data(), sizeof(header_));
data_ = std::vector<uint8_t>(payload.data.begin() + sizeof(header_),
payload.data.end());
for (int32_t &fd : payload.fds)
fds_.push_back(SharedFD(std::move(fd)));
}
/**
* \brief Create an IPCUnixSocket payload from the IPCMessage
*
* This essentially converts the IPCMessage into an IPCUnixSocket payload.
*
* \todo Resolve the layering violation (add other converters later?)
*/
IPCUnixSocket::Payload IPCMessage::payload() const
{
IPCUnixSocket::Payload payload;
payload.data.resize(sizeof(Header) + data_.size());
payload.fds.reserve(fds_.size());
memcpy(payload.data.data(), &header_, sizeof(Header));
if (data_.size() > 0) {
/* \todo Make this work without copy */
memcpy(payload.data.data() + sizeof(Header),
data_.data(), data_.size());
}
for (const SharedFD &fd : fds_)
payload.fds.push_back(fd.get());
return payload;
}
/**
* \fn IPCMessage::header()
* \brief Returns a reference to the header
*/
/**
* \fn IPCMessage::data()
* \brief Returns a reference to the byte vector containing data
*/
/**
* \fn IPCMessage::fds()
* \brief Returns a reference to the vector containing file descriptors
*/
/**
* \fn IPCMessage::header() const
* \brief Returns a const reference to the header
*/
/**
* \fn IPCMessage::data() const
* \brief Returns a const reference to the byte vector containing data
*/
/**
* \fn IPCMessage::fds() const
* \brief Returns a const reference to the vector containing file descriptors
*/
/**
* \class IPCPipe
* \brief IPC message pipe for IPA isolation
*
* Virtual class to model an IPC message pipe for use by IPA proxies for IPA
* isolation. sendSync() and sendAsync() must be implemented, and the recvMessage
* signal must be emitted whenever new data is available.
*/
/**
* \brief Construct an IPCPipe instance
*/
IPCPipe::IPCPipe()
: connected_(false)
{
}
IPCPipe::~IPCPipe()
{
}
/**
* \fn IPCPipe::isConnected()
* \brief Check if the IPCPipe instance is connected
*
* An IPCPipe instance is connected if IPC is successfully set up.
*
* \return True if the IPCPipe is connected, false otherwise
*/
/**
* \fn IPCPipe::sendSync()
* \brief Send a message over IPC synchronously
* \param[in] in Data to send
* \param[in] out IPCMessage instance in which to receive data, if applicable
*
* This function will not return until a response is received. The event loop
* will still continue to execute, however.
*
* \return Zero on success, negative error code otherwise
*
* \todo Determine if the event loop should limit the types of messages it
* processes, to avoid reintrancy in the caller, and carefully document what
* the caller needs to implement to make this safe.
*/
/**
* \fn IPCPipe::sendAsync()
* \brief Send a message over IPC asynchronously
* \param[in] data Data to send
*
* This function will return immediately after sending the message.
*
* \return Zero on success, negative error code otherwise
*/
/**
* \var IPCPipe::recv
* \brief Signal to be emitted when a message is received over IPC
*
* When a message is received over IPC, this signal shall be emitted. Users must
* connect to this to receive messages.
*/
/**
* \var IPCPipe::connected_
* \brief Flag to indicate if the IPCPipe instance is connected
*
* An IPCPipe instance is connected if IPC is successfully set up.
*
* This flag can be read via IPCPipe::isConnected().
*
* Implementations of the IPCPipe class should set this flag upon successful
* connection.
*/
} /* namespace libcamera */