mirror of
https://git.libcamera.org/libcamera/libcamera.git
synced 2025-07-24 17:15:07 +03:00
libcamera: Add IPCPipe
Create a virtual IPCPipe class that models an IPC/RPC system. IPA proxies and proxy workers will call into the IPCPipe, rather than implementing the IPC themselves. Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
parent
13f7d58569
commit
e1ccded833
3 changed files with 288 additions and 0 deletions
69
include/libcamera/internal/ipc_pipe.h
Normal file
69
include/libcamera/internal/ipc_pipe.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
/*
|
||||
* Copyright (C) 2020, Google Inc.
|
||||
*
|
||||
* ipc_pipe.h - Image Processing Algorithm IPC module for IPA proxies
|
||||
*/
|
||||
#ifndef __LIBCAMERA_INTERNAL_IPA_IPC_H__
|
||||
#define __LIBCAMERA_INTERNAL_IPA_IPC_H__
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "libcamera/internal/ipc_unixsocket.h"
|
||||
|
||||
#include <libcamera/signal.h>
|
||||
|
||||
namespace libcamera {
|
||||
|
||||
class IPCMessage
|
||||
{
|
||||
public:
|
||||
struct Header {
|
||||
uint32_t cmd;
|
||||
uint32_t cookie;
|
||||
};
|
||||
|
||||
IPCMessage();
|
||||
IPCMessage(uint32_t cmd);
|
||||
IPCMessage(const Header &header);
|
||||
IPCMessage(const IPCUnixSocket::Payload &payload);
|
||||
|
||||
IPCUnixSocket::Payload payload() const;
|
||||
|
||||
Header &header() { return header_; }
|
||||
std::vector<uint8_t> &data() { return data_; }
|
||||
std::vector<int32_t> &fds() { return fds_; }
|
||||
|
||||
const Header &header() const { return header_; }
|
||||
const std::vector<uint8_t> &data() const { return data_; }
|
||||
const std::vector<int32_t> &fds() const { return fds_; }
|
||||
|
||||
private:
|
||||
Header header_;
|
||||
|
||||
std::vector<uint8_t> data_;
|
||||
std::vector<int32_t> fds_;
|
||||
};
|
||||
|
||||
class IPCPipe
|
||||
{
|
||||
public:
|
||||
IPCPipe();
|
||||
virtual ~IPCPipe();
|
||||
|
||||
bool isConnected() const { return connected_; }
|
||||
|
||||
virtual int sendSync(const IPCMessage &in,
|
||||
IPCMessage *out) = 0;
|
||||
|
||||
virtual int sendAsync(const IPCMessage &data) = 0;
|
||||
|
||||
Signal<const IPCMessage &> recv;
|
||||
|
||||
protected:
|
||||
bool connected_;
|
||||
};
|
||||
|
||||
} /* namespace libcamera */
|
||||
|
||||
#endif /* __LIBCAMERA_INTERNAL_IPA_IPC_H__ */
|
218
src/libcamera/ipc_pipe.cpp
Normal file
218
src/libcamera/ipc_pipe.cpp
Normal file
|
@ -0,0 +1,218 @@
|
|||
/* 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/internal/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.
|
||||
*/
|
||||
IPCMessage::IPCMessage(const IPCUnixSocket::Payload &payload)
|
||||
{
|
||||
memcpy(&header_, payload.data.data(), sizeof(header_));
|
||||
data_ = std::vector<uint8_t>(payload.data.begin() + sizeof(header_),
|
||||
payload.data.end());
|
||||
fds_ = payload.fds;
|
||||
}
|
||||
|
||||
/**
|
||||
* \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));
|
||||
|
||||
/* \todo Make this work without copy */
|
||||
memcpy(payload.data.data() + sizeof(Header), data_.data(), data_.size());
|
||||
payload.fds = fds_;
|
||||
|
||||
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 */
|
|
@ -31,6 +31,7 @@ libcamera_sources = files([
|
|||
'ipa_manager.cpp',
|
||||
'ipa_module.cpp',
|
||||
'ipa_proxy.cpp',
|
||||
'ipc_pipe.cpp',
|
||||
'ipc_unixsocket.cpp',
|
||||
'log.cpp',
|
||||
'media_device.cpp',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue