Skip to content

Commit

Permalink
Added support for SERIAL transport on Windows
Browse files Browse the repository at this point in the history
Signed-off-by: THOMAS Sebastien <[email protected]>
  • Loading branch information
sebastieninria committed Oct 24, 2023
1 parent 2cbbc4a commit d2edf12
Show file tree
Hide file tree
Showing 9 changed files with 605 additions and 22 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
src/cpp/transport/udp/UDPv6AgentWindows.cpp
src/cpp/transport/tcp/TCPv4AgentWindows.cpp
src/cpp/transport/tcp/TCPv6AgentWindows.cpp
src/cpp/transport/serial/SerialAgentWindows.cpp
src/cpp/transport/serial/TermiosAgentWindows.cpp
$<$<BOOL:${UAGENT_DISCOVERY_PROFILE}>:src/cpp/transport/discovery/DiscoveryServerWindows.cpp>
)
endif()
Expand Down
79 changes: 79 additions & 0 deletions include/uxr/agent/transport/serial/SerialAgentWindows.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright 2017-present Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef UXR_AGENT_TRANSPORT_SERIAL_SERIALAGENTWINDOWS_HPP_
#define UXR_AGENT_TRANSPORT_SERIAL_SERIALAGENTWINDOWS_HPP_

#include <uxr/agent/transport/Server.hpp>
#include <uxr/agent/transport/endpoint/SerialEndPoint.hpp>
#include <uxr/agent/transport/stream_framing/StreamFramingProtocol.hpp>

#include <cstdint>
#include <cstddef>
#include <WinSock2.h>

namespace eprosima {
namespace uxr {

class SerialAgent : public Server<SerialEndPoint>
{
public:
SerialAgent(
uint8_t addr,
Middleware::Kind middleware_kind);

#ifdef UAGENT_DISCOVERY_PROFILE
bool has_discovery() final { return false; }
#endif

#ifdef UAGENT_P2P_PROFILE
bool has_p2p() final { return false; }
#endif

private:
virtual bool init() = 0;

virtual bool fini() = 0;

bool recv_message(
InputPacket<SerialEndPoint>& input_packet,
int timeout,
TransportRc& transport_rc) final;

bool send_message(
OutputPacket<SerialEndPoint> output_packet,
TransportRc& transport_rc) final;

ssize_t write_data(
uint8_t* buf,
size_t len,
TransportRc& transport_rc);

ssize_t read_data(
uint8_t* buf,
size_t len,
int timeout,
TransportRc& transport_rc);

protected:
const uint8_t addr_;
HANDLE serial_handle;
uint8_t buffer_[SERVER_BUFFER_SIZE];
FramingIO framing_io_;
};

} // namespace uxr
} // namespace eprosima

#endif // UXR_AGENT_TRANSPORT_SERIAL_SERIALAGENTWINDOWS_HPP_
49 changes: 49 additions & 0 deletions include/uxr/agent/transport/serial/TermiosAgentWindows.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2017-present Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef UXR_AGENT_TRANSPORT_SERIAL_TERMIOSAGENTWINDOWS_HPP_
#define UXR_AGENT_TRANSPORT_SERIAL_TERMIOSAGENTWINDOWS_HPP_

#include <uxr/agent/transport/serial/SerialAgentWindows.hpp>
namespace eprosima {
namespace uxr {

class TermiosAgent : public SerialAgent
{
public:
TermiosAgent(
char const * dev,
DCB const & termios_attrs,
uint8_t addr,
Middleware::Kind middleware_kind);

~TermiosAgent();

HANDLE getfd() { return serial_handle; };

private:
bool init() final;
bool fini() final;
bool handle_error(
TransportRc transport_rc) final;

private:
const std::string dev_;
const DCB termios_attrs_;
};

} // namespace uxr
} // namespace eprosima

#endif // UXR_AGENT_TRANSPORT_SERIAL_TERMIOSAGENTWINDOWS_HPP_
86 changes: 86 additions & 0 deletions include/uxr/agent/transport/serial/baud_rate_table_windows.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Copyright 2019 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef UXR_AGENT_TRANSPORT_SERIAL_BAUD_RATE_TABLE_H
#define UXR_AGENT_TRANSPORT_SERIAL_BAUD_RATE_TABLE_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

inline
DWORD getBaudRate(const char* baudrate_str)
{
DWORD rv;
if (0 == strcmp(baudrate_str, "0"))
{
rv = 0;
}
else if (0 == strcmp(baudrate_str, "110"))
{
rv = CBR_110;
}
else if (0 == strcmp(baudrate_str, "300")) {
rv = CBR_300;
}
else if (0 == strcmp(baudrate_str, "600")) {
rv = CBR_600;
}
else if (0 == strcmp(baudrate_str, "1200")) {
rv = CBR_1200;
}
else if (0 == strcmp(baudrate_str, "2400")) {
rv = CBR_2400;
}
else if (0 == strcmp(baudrate_str, "4800")) {
rv = CBR_4800;
}
else if (0 == strcmp(baudrate_str, "9600")) {
rv = CBR_9600;
}
else if (0 == strcmp(baudrate_str, "14400")) {
rv = CBR_14400;
}
else if (0 == strcmp(baudrate_str, "19200")) {
rv = CBR_19200;
}
else if (0 == strcmp(baudrate_str, "38400")) {
rv = CBR_38400;
}
else if (0 == strcmp(baudrate_str, "56000")) {
rv = CBR_56000;
}
else if (0 == strcmp(baudrate_str, "57600")) {
rv = CBR_57600;
}
else if (0 == strcmp(baudrate_str, "115200")) {
rv = CBR_115200;
}
else if (0 == strcmp(baudrate_str, "128000")) {
rv = CBR_128000;
}
else if (0 == strcmp(baudrate_str, "256000")) {
rv = CBR_256000;
}
else
{
DWORD custom_baud_rate = (DWORD)atoi(baudrate_str);
printf("Warning: Custom baud rate set to: %d\n", custom_baud_rate);
rv = custom_baud_rate;
}
return rv;
}

#endif // UXR_AGENT_TRANSPORT_SERIAL_BAUD_RATE_TABLE_H

63 changes: 49 additions & 14 deletions include/uxr/agent/utils/ArgumentParser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include <uxr/agent/transport/udp/UDPv6AgentWindows.hpp>
#include <uxr/agent/transport/tcp/TCPv4AgentWindows.hpp>
#include <uxr/agent/transport/tcp/TCPv6AgentWindows.hpp>
#include <uxr/agent/transport/serial/TermiosAgentWindows.hpp>
#include <uxr/agent/transport/serial/baud_rate_table_windows.h>
#else
#include <uxr/agent/transport/udp/UDPv4AgentLinux.hpp>
#include <uxr/agent/transport/udp/UDPv6AgentLinux.hpp>
Expand Down Expand Up @@ -64,11 +66,11 @@ enum class TransportKind
UDP6,
TCP4,
TCP6,
SERIAL,
#ifndef _WIN32
#ifdef UAGENT_SOCKETCAN_PROFILE
CAN,
#endif // UAGENT_SOCKETCAN_PROFILE
SERIAL,
MULTISERIAL,
PSEUDOTERMINAL,
#endif // _WIN32
Expand Down Expand Up @@ -659,7 +661,6 @@ class IPvXArgs
Argument<uint16_t> port_;
};

#ifndef _WIN32
/*************************************************************************************************
* Specific arguments for pseudoterminal transports
*************************************************************************************************/
Expand Down Expand Up @@ -782,6 +783,8 @@ class SerialArgs : public PseudoTerminalArgs<AgentType>
Argument<std::string> file_;
};


#ifndef _WIN32
/*************************************************************************************************
* Specific arguments for multi serial termios transports
*************************************************************************************************/
Expand Down Expand Up @@ -943,11 +946,11 @@ class ArgumentParser
, argv_(argv)
, common_args_()
, ip_args_()
, serial_args_()
#ifndef _WIN32
#ifdef UAGENT_SOCKETCAN_PROFILE
, can_args_()
#endif // UAGENT_SOCKETCAN_PROFILE
, serial_args_()
, multiserial_args_()
, pseudoterminal_args_()
#endif // _WIN32
Expand Down Expand Up @@ -979,6 +982,11 @@ class ArgumentParser
result &= ip_args_.parse(argc_, argv_);
break;
}
case TransportKind::SERIAL:
{
result &= serial_args_.parse(argc_, argv_);
break;
}
#ifndef _WIN32
#ifdef UAGENT_SOCKETCAN_PROFILE
case TransportKind::CAN:
Expand All @@ -987,11 +995,6 @@ class ArgumentParser
break;
}
#endif // UAGENT_SOCKETCAN_PROFILE
case TransportKind::SERIAL:
{
result &= serial_args_.parse(argc_, argv_);
break;
}
case TransportKind::MULTISERIAL:
{
result &= multiserial_args_.parse(argc_, argv_);
Expand Down Expand Up @@ -1075,6 +1078,29 @@ class ArgumentParser
attr.c_ospeed = baudrate;
#endif

return attr;
}
#else
DCB init_termios(const char* baudrate_str) {
DCB attr = {};

/* Setting baudrate. */
attr.Parity = NOPARITY;
attr.StopBits = ONESTOPBIT;
attr.ByteSize = 8;
attr.BaudRate = getBaudRate(baudrate_str);

attr.fBinary = FALSE;
attr.fParity = FALSE;
attr.fOutxCtsFlow = FALSE;
attr.fOutxDsrFlow = FALSE;
attr.fDtrControl = DTR_CONTROL_ENABLE;
attr.fRtsControl = RTS_CONTROL_ENABLE;
attr.fInX = FALSE;
attr.fOutX = FALSE;
attr.fDsrSensitivity = FALSE;
attr.fErrorChar = FALSE;

return attr;
}
#endif // _WIN32
Expand Down Expand Up @@ -1107,25 +1133,32 @@ class ArgumentParser
char** argv_;
CommonArgs<AgentType> common_args_;
IPvXArgs<AgentType> ip_args_;
SerialArgs<AgentType> serial_args_;
#ifndef _WIN32
#ifdef UAGENT_SOCKETCAN_PROFILE
CanArgs<AgentType> can_args_;
#endif // UAGENT_SOCKETCAN_PROFILE
SerialArgs<AgentType> serial_args_;
MultiSerialArgs<AgentType> multiserial_args_;
PseudoTerminalArgs<AgentType> pseudoterminal_args_;
#endif // _WIN32
TransportKind transport_kind_;
std::unique_ptr<AgentType> agent_server_;
};

template<> inline bool ArgumentParser<TermiosAgent>::launch_agent() {
#ifndef _WIN32
template<> inline bool ArgumentParser<TermiosAgent>::launch_agent()
{
struct termios attr = init_termios(serial_args_.baud_rate().c_str());

termios
#else
DCB
#endif
attr = init_termios(serial_args_.baud_rate().c_str());

agent_server_.reset(new TermiosAgent(
serial_args_.dev().c_str(), O_RDWR | O_NOCTTY, attr, 0, utils::get_mw_kind(common_args_.middleware())));
#ifndef _WIN32
serial_args_.dev().c_str(), O_RDWR | O_NOCTTY, attr, 0, utils::get_mw_kind(common_args_.middleware())));
#else
serial_args_.dev().c_str(), attr, 0, utils::get_mw_kind(common_args_.middleware())));
#endif

if (agent_server_->start())
{
Expand All @@ -1140,6 +1173,8 @@ template<> inline bool ArgumentParser<TermiosAgent>::launch_agent()
return false;
}


#ifndef _WIN32
template<> inline bool ArgumentParser<MultiTermiosAgent>::launch_agent()
{
struct termios attr = init_termios(multiserial_args_.baud_rate().c_str());
Expand Down
Loading

0 comments on commit d2edf12

Please sign in to comment.