Skip to content

Added support for SERIAL transport on Windows #349

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: ros2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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