radio_tool 0.2.1
Loading...
Searching...
No Matches
ymodem_device.cpp
1
19#include <radio_tool/device/ymodem_device.hpp>
20
21#include <stdexcept>
22#include <fymodem.h>
23#include <stdio.h>
24#include <fcntl.h>
25
26#ifdef _WIN32
27#include <Windows.h>
28#include <io.h>
29#include <sstream>
30#else
31#include <termios.h>
32#endif
33
34using namespace radio_tool::device;
35
36YModemDevice::YModemDevice(const std::string& port, const std::string& filename) : port(port), filename(filename), fd(-1)
37{
38 int fdOpen = -1;
39#ifdef _WIN32
40 std::stringstream portPath;
41 portPath << "\\\\.\\" << port;
42
43 fdOpen = (int)CreateFileA(portPath.str().c_str(), GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
44#else
45 fdOpen = open(port.c_str(), O_RDWR | O_NOCTTY | O_SYNC);
46#endif
47
48 if (fdOpen < 0)
49 {
50 throw std::runtime_error("Failed to open port: " + port);
51 }
52 fd = fdOpen;
53}
54
55auto YModemDevice::SetAddress(const uint32_t&) const -> void
56{
57 throw std::runtime_error("SetAddress not supported for YModem device");
58}
59
60auto YModemDevice::Erase(const uint32_t&) const -> void
61{
62 throw std::runtime_error("Erase not supported for YModem device");
63}
64
65auto YModemDevice::Write(const std::vector<uint8_t>& data) const -> void
66{
67 auto fn = std::string(filename);
68 size_t wlen = fymodem_send(fd, (uint8_t*)data.data(), data.size(), fn.data());
69 if (wlen != data.size())
70 {
71 throw std::runtime_error("Write error");
72 }
73}
74
75auto YModemDevice::Read(const uint16_t& size) const -> std::vector<uint8_t>
76{
77 auto ret = std::vector<uint8_t>();
78 ret.resize(size);
79
80 auto fn = std::string(filename);
81 auto rsize = fymodem_receive(ret.data(), size, fn.data());
82 if (rsize != size)
83 {
84 throw std::runtime_error("Read error");
85 }
86 return ret;
87}
88
89auto YModemDevice::Status() const -> const std::string
90{
91 return "OK";
92}
93
94auto YModemDevice::SetInterfaceAttribs(const uint32_t& speed, const int& parity) const -> int
95{
96#ifdef _WIN32
97 // Do some basic settings
98 DCB serialParams = { 0 };
99 serialParams.DCBlength = sizeof(serialParams);
100
101 auto handle = (HANDLE)fd;
102 GetCommState(handle, &serialParams);
103 serialParams.BaudRate = speed;
104 serialParams.ByteSize = 8;
105 serialParams.StopBits = TWOSTOPBITS;
106 serialParams.Parity = parity;
107 SetCommState(handle, &serialParams);
108
109 // Set timeouts
110 COMMTIMEOUTS timeout = { 0 };
111 timeout.ReadIntervalTimeout = 50;
112 timeout.ReadTotalTimeoutConstant = 50;
113 timeout.ReadTotalTimeoutMultiplier = 50;
114 timeout.WriteTotalTimeoutConstant = 50;
115 timeout.WriteTotalTimeoutMultiplier = 10;
116
117 SetCommTimeouts(handle, &timeout);
118 return 0;
119#else
120 struct termios tty;
121 if (tcgetattr(fd, &tty) != 0)
122 {
123 throw std::runtime_error("Error accessing TTY attributes");
124 return -1;
125 }
126
127 cfsetospeed(&tty, speed);
128 cfsetispeed(&tty, speed);
129
130 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
131 // disable IGNBRK for mismatched speed tests; otherwise receive break
132 // as \000 chars
133 tty.c_iflag &= ~IGNBRK; // disable break processing
134 tty.c_lflag = 0; // no signaling chars, no echo,
135 // no canonical processing
136 tty.c_oflag = 0; // no remapping, no delays
137 tty.c_cc[VMIN] = 0;
138 tty.c_cc[VTIME] = 20;
139
140 tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
141
142 tty.c_cflag |= (CLOCAL | CREAD); // ignore modem controls,
143 // enable reading
144 tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
145 tty.c_cflag |= parity;
146 tty.c_cflag &= ~CSTOPB;
147 tty.c_cflag &= ~CRTSCTS;
148
149 if (tcsetattr(fd, TCSANOW, &tty) != 0)
150 {
151 throw std::runtime_error("Error setting TTY attributes");
152 return -1;
153 }
154 return 0;
155#endif
156}