Closed TPopiel closed 3 years ago
Hi,
Could you please provide some clarifications, case detailed description and code example, which the changes are required for? You're changing external API (and it is still unclear from the code, what the changes solve), and that can be harmful for other users.
Best regards
Hi,
I would like to simultaneously handle multiple devices connected to desktop PC over various COM ports. Every device implements HDLC FD protocol with use of tinyproto library. So I propose following implementation at desktop host:
static int serial_send_fd(void* context, const void* b, int s) // call function with previously set user_context - this happens in HdlcFdProxy
{
try
{
auto proxy = reinterpret_cast<HdlcFdProxy*>(context);
auto buffer = reinterpret_cast<uint8_t*>(const_cast<void*>(b));
std::vector<uint8_t> output;
std::copy_n(buffer, s, std::back_inserter(output));
return static_cast<int>(proxy->write(output));
}
catch(...)
{
return -1;
}
}
static int serial_read_fd(void* context, void* b, int s) // call function with previously set user_context - this happens in HdlcFdProxy
{
try
{
auto proxy = reinterpret_cast<HdlcFdProxy*>(context);
std::vector<uint8_t> input;
auto readBytes = proxy->read(input, s);
auto buffer = static_cast<uint8_t*>(b);
std::copy_n(input.begin(), input.size(), buffer);
return static_cast<int>(readBytes);
}
catch (...)
{
return -1;
}
}
static void on_receive_callback(void* context, Tiny::IPacket &pkt) // call function with previously set user_context - this happens in HdlcFdProxy
{
auto proxy = reinterpret_cast<HdlcFdProxy*>(context);
if (proxy != nullptr)
{
auto data = pkt.data();
std::vector<uint8_t> received;
std::copy_n(data, pkt.size(), std::back_inserter(received));
proxy->onReceive(received);
}
}
HdlcFdProxy::HdlcFdProxy(...) :
{
auto proto = std::make_unique<Tiny::ProtoFdD>(static_cast<int>(tiny_fd_buffer_size_by_mtu( MAX_FRAME_SIZE, WINDOW_SIZE )));
proto->enableCrc16();
proto->setWindowSize(WINDOW_SIZE);
proto->setSendTimeout(500);
proto->setReceiveCallback( on_receive_callback );
proto->begin( serial_send_fd , serial_read_fd , this ); // sets user_context with this!!!
}
...
size_t HdlcFdProxy::read(std::vector< uint8_t > &buffer, size_t size)
{
if (m_connectionIsOpen)
{
return m_serial->read(buffer, size);
}
return 0;
}
size_t HdlcFdProxy::write(const std::vector< uint8_t > &data)
{
if (m_connectionIsOpen)
{
return m_serial->write(data);
}
return 0;
}
Please let me know if still more detailed explanation or examples are required. Regards, Tomek
Please, check latest sources, and let me know if new code suites your needs.
Latest commit fully address my needs, many thanks for it! I also noticed that there is build error under MSVC - it deals with struct default initialization, could you look on that?
Thank you. Fixed that on my MSVC 2019. Keep an eye on the upcoming changes: cpp_api, there will be changes to API. I'm still trying to make library usage as simple as possible.
Since the requested capabilities are already on the master, I 'm closing my PR. Many thanks!
Multiple devices support is realized with additional pointer to user context provided during FD protocol initialization, and then the same pointer to user context is received when callbacks are called by the library.