mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-27 01:43:33 +08:00
TransferListener partially implemented
This commit is contained in:
@@ -74,18 +74,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
class MultiFrameIncomingTransfer : public IncomingTransfer, Noncopyable
|
class MultiFrameIncomingTransfer : public IncomingTransfer, Noncopyable
|
||||||
{
|
{
|
||||||
ITransferBufferManager* const bufmgr_;
|
TransferBufferAccessor& buf_acc_;
|
||||||
const TransferBufferManagerKey bufmgr_key_;
|
|
||||||
const uint8_t buffer_offset_; ///< Number of bytes to skip from the beginning of the buffer space
|
const uint8_t buffer_offset_; ///< Number of bytes to skip from the beginning of the buffer space
|
||||||
public:
|
public:
|
||||||
MultiFrameIncomingTransfer(const RxFrame& last_frame, uint8_t buffer_offset, ITransferBufferManager* bufmgr,
|
MultiFrameIncomingTransfer(const RxFrame& last_frame, uint8_t buffer_offset, TransferBufferAccessor& tba);
|
||||||
const TransferBufferManagerKey& bufmgr_key);
|
|
||||||
int read(unsigned int offset, uint8_t* data, unsigned int len) const;
|
int read(unsigned int offset, uint8_t* data, unsigned int len) const;
|
||||||
void release() { bufmgr_->remove(bufmgr_key_); }
|
void release() { buf_acc_.remove(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transport internal, for dispatcher.
|
* Internal, refer to transport dispatcher.
|
||||||
*/
|
*/
|
||||||
class TransferListenerBase : public LinkedListNode<TransferListenerBase>
|
class TransferListenerBase : public LinkedListNode<TransferListenerBase>
|
||||||
{
|
{
|
||||||
@@ -100,7 +98,7 @@ protected:
|
|||||||
|
|
||||||
virtual ~TransferListenerBase() { }
|
virtual ~TransferListenerBase() { }
|
||||||
|
|
||||||
void handleReception(TransferReceiver& receiver, const RxFrame& frame);
|
void handleReception(TransferReceiver& receiver, const RxFrame& frame, TransferBufferAccessor& tba);
|
||||||
|
|
||||||
virtual void handleIncomingTransfer(IncomingTransfer& transfer) = 0;
|
virtual void handleIncomingTransfer(IncomingTransfer& transfer) = 0;
|
||||||
|
|
||||||
@@ -112,36 +110,80 @@ public:
|
|||||||
/**
|
/**
|
||||||
* This class should be derived by transfer receivers (subscribers, servers, callers).
|
* This class should be derived by transfer receivers (subscribers, servers, callers).
|
||||||
*/
|
*/
|
||||||
template <unsigned int STATIC_BUF_SIZE, unsigned int NUM_STATIC_BUFS>
|
template <unsigned int MAX_BUF_SIZE, unsigned int NUM_STATIC_BUFS, unsigned int NUM_STATIC_RECEIVERS>
|
||||||
class TransferListener : protected TransferListenerBase, Noncopyable
|
class TransferListener : protected TransferListenerBase, Noncopyable
|
||||||
{
|
{
|
||||||
TransferBufferManager<STATIC_BUF_SIZE, NUM_STATIC_BUFS> bufmgr_;
|
typedef TransferBufferManager<MAX_BUF_SIZE, NUM_STATIC_BUFS> BufferManager;
|
||||||
Map<TransferBufferManagerKey, TransferReceiver, NUM_STATIC_BUFS> receivers_;
|
BufferManager bufmgr_;
|
||||||
|
Map<TransferBufferManagerKey, TransferReceiver, NUM_STATIC_RECEIVERS> receivers_;
|
||||||
|
|
||||||
void handleFrame(const RxFrame& frame)
|
void handleFrame(const RxFrame& frame)
|
||||||
{
|
{
|
||||||
// TODO
|
const TransferBufferManagerKey key(frame.source_node_id, frame.transfer_type);
|
||||||
|
|
||||||
|
TransferReceiver* recv = receivers_.access(key);
|
||||||
|
if (recv == NULL)
|
||||||
|
{
|
||||||
|
if (frame.frame_index != 0) // We don't want to add registrations mid-transfer, that's pointless
|
||||||
|
return;
|
||||||
|
|
||||||
|
TransferReceiver new_recv;
|
||||||
|
recv = receivers_.insert(key, new_recv);
|
||||||
|
if (recv == NULL)
|
||||||
|
{
|
||||||
|
UAVCAN_TRACE("TransferListener", "Receiver registration failed; frame %s", frame.toString().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TransferBufferAccessor tba(&bufmgr_, key);
|
||||||
|
handleReception(*recv, frame, tba);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TimedOutReceiverPredicate
|
class TimedOutReceiverPredicate
|
||||||
{
|
{
|
||||||
const uint64_t ts_monotonic;
|
const uint64_t ts_monotonic_;
|
||||||
TimedOutReceiverPredicate(uint64_t ts_monotonic) : ts_monotonic(ts_monotonic) { }
|
BufferManager& bufmgr_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TimedOutReceiverPredicate(uint64_t ts_monotonic, BufferManager& bufmgr)
|
||||||
|
: ts_monotonic_(ts_monotonic)
|
||||||
|
, bufmgr_(bufmgr)
|
||||||
|
{ }
|
||||||
|
|
||||||
bool operator()(const TransferBufferManagerKey& key, const TransferReceiver& value) const
|
bool operator()(const TransferBufferManagerKey& key, const TransferReceiver& value) const
|
||||||
{
|
{
|
||||||
(void)key;
|
if (value.isTimedOut(ts_monotonic_))
|
||||||
return value.isTimedOut(ts_monotonic);
|
{
|
||||||
|
/*
|
||||||
|
* TransferReceivers do not own their buffers - this helps the Map<> container to copy them
|
||||||
|
* around quickly and safely (using default operator==()). Downside is that we need to destroy
|
||||||
|
* the buffers manually.
|
||||||
|
* Maybe it is not good that the predicate is being using as mapping functor, but I ran out
|
||||||
|
* of better ideas.
|
||||||
|
*/
|
||||||
|
bufmgr_.remove(key);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void cleanup(uint64_t ts_monotonic)
|
void cleanup(uint64_t ts_monotonic)
|
||||||
{
|
{
|
||||||
receivers_.removeWhere(TimedOutReceiverPredicate(ts_monotonic));
|
receivers_.removeWhere(TimedOutReceiverPredicate(ts_monotonic, bufmgr_));
|
||||||
|
#if UAVCAN_DEBUG
|
||||||
|
if (receivers_.isEmpty())
|
||||||
|
{
|
||||||
|
assert(bufmgr_.isEmpty());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TransferListener(const DataTypeDescriptor* data_type)
|
TransferListener(const DataTypeDescriptor* data_type, IAllocator* allocator)
|
||||||
: TransferListenerBase(data_type)
|
: TransferListenerBase(data_type)
|
||||||
|
, bufmgr_(allocator)
|
||||||
|
, receivers_(allocator)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
~TransferListener()
|
~TransferListener()
|
||||||
|
|||||||
@@ -41,26 +41,21 @@ int SingleFrameIncomingTransfer::read(unsigned int offset, uint8_t* data, unsign
|
|||||||
* MultiFrameIncomingTransfer
|
* MultiFrameIncomingTransfer
|
||||||
*/
|
*/
|
||||||
MultiFrameIncomingTransfer::MultiFrameIncomingTransfer(const RxFrame& last_frame, uint8_t buffer_offset,
|
MultiFrameIncomingTransfer::MultiFrameIncomingTransfer(const RxFrame& last_frame, uint8_t buffer_offset,
|
||||||
ITransferBufferManager* bufmgr,
|
TransferBufferAccessor& tba)
|
||||||
const TransferBufferManagerKey& bufmgr_key)
|
|
||||||
: IncomingTransfer(last_frame.ts_monotonic, last_frame.ts_utc, last_frame.transfer_type,
|
: IncomingTransfer(last_frame.ts_monotonic, last_frame.ts_utc, last_frame.transfer_type,
|
||||||
last_frame.transfer_id, last_frame.source_node_id)
|
last_frame.transfer_id, last_frame.source_node_id)
|
||||||
, bufmgr_(bufmgr)
|
, buf_acc_(tba)
|
||||||
, bufmgr_key_(bufmgr_key)
|
|
||||||
, buffer_offset_(buffer_offset)
|
, buffer_offset_(buffer_offset)
|
||||||
{
|
{
|
||||||
assert(bufmgr);
|
|
||||||
assert(!bufmgr_key.isEmpty());
|
|
||||||
assert(last_frame.last_frame);
|
assert(last_frame.last_frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
int MultiFrameIncomingTransfer::read(unsigned int offset, uint8_t* data, unsigned int len) const
|
int MultiFrameIncomingTransfer::read(unsigned int offset, uint8_t* data, unsigned int len) const
|
||||||
{
|
{
|
||||||
const TransferBufferBase* const tbb = const_cast<ITransferBufferManager*>(bufmgr_)->access(bufmgr_key_);
|
const TransferBufferBase* const tbb = const_cast<TransferBufferAccessor&>(buf_acc_).access();
|
||||||
if (tbb == NULL)
|
if (tbb == NULL)
|
||||||
{
|
{
|
||||||
UAVCAN_TRACE("MultiFrameIncomingTransfer", "Read failed: no such buffer %s",
|
UAVCAN_TRACE("MultiFrameIncomingTransfer", "Read failed: no such buffer");
|
||||||
bufmgr_key_.toString().c_str());
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return tbb->read(offset + buffer_offset_, data, len);
|
return tbb->read(offset + buffer_offset_, data, len);
|
||||||
@@ -70,10 +65,30 @@ int MultiFrameIncomingTransfer::read(unsigned int offset, uint8_t* data, unsigne
|
|||||||
* TransferListenerBase
|
* TransferListenerBase
|
||||||
*/
|
*/
|
||||||
void TransferListenerBase::handleReception(TransferReceiver& receiver, const RxFrame& frame,
|
void TransferListenerBase::handleReception(TransferReceiver& receiver, const RxFrame& frame,
|
||||||
const TransferBufferManagerKey& bufmgr_key)
|
TransferBufferAccessor& tba)
|
||||||
{
|
{
|
||||||
const TransferReceiver::ResultCode result = receiver.addFrame(frame, bufmgr_key);
|
const TransferReceiver::ResultCode result = receiver.addFrame(frame, tba);
|
||||||
(void)result;
|
switch (result)
|
||||||
|
{
|
||||||
|
case TransferReceiver::RESULT_NOT_COMPLETE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TransferReceiver::RESULT_SINGLE_FRAME:
|
||||||
|
{
|
||||||
|
SingleFrameIncomingTransfer it(frame);
|
||||||
|
handleIncomingTransfer(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TransferReceiver::RESULT_COMPLETE:
|
||||||
|
{
|
||||||
|
// TODO: check CRC
|
||||||
|
// TODO: select the buffer offset
|
||||||
|
const int buffer_offset = 123;
|
||||||
|
MultiFrameIncomingTransfer it(frame, buffer_offset, tba);
|
||||||
|
handleIncomingTransfer(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,8 +76,9 @@ TEST(MultiFrameIncomingTransfer, Basic)
|
|||||||
|
|
||||||
const RxFrame frame = makeFrame();
|
const RxFrame frame = makeFrame();
|
||||||
uavcan::TransferBufferManagerKey bufmgr_key(frame.source_node_id, frame.transfer_type);
|
uavcan::TransferBufferManagerKey bufmgr_key(frame.source_node_id, frame.transfer_type);
|
||||||
|
uavcan::TransferBufferAccessor tba(&bufmgr, bufmgr_key);
|
||||||
|
|
||||||
MultiFrameIncomingTransfer it(frame, 3, &bufmgr, bufmgr_key);
|
MultiFrameIncomingTransfer it(frame, 3, tba);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Empty read must fail
|
* Empty read must fail
|
||||||
|
|||||||
Reference in New Issue
Block a user