Skip to content

Commit e77ab66

Browse files
committed
2 parents 95bd167 + 0f130ea commit e77ab66

6 files changed

Lines changed: 348 additions & 21 deletions

File tree

ArduinoCore-Linux/cores/arduino/Ethernet.h

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <arpa/inet.h> // for inet_pton
2323
#include <netdb.h> // for gethostbyname, struct hostent
2424
#include <unistd.h> // for close
25+
#include <memory> // This is the include you need
2526

2627
#include "ArduinoLogger.h"
2728
#include "RingBufferExt.h"
@@ -80,13 +81,13 @@ class EthernetClient : public Client {
8081
public:
8182
EthernetClient() {
8283
setTimeout(2000);
83-
p_sock = new SocketImpl();
84+
p_sock = std::make_shared<SocketImpl>();
8485
readBuffer = RingBufferExt(bufferSize);
8586
writeBuffer = RingBufferExt(bufferSize);
8687
registerCleanup();
8788
active_clients().push_back(this);
8889
}
89-
EthernetClient(SocketImpl* sock, int bufferSize = 256, long timeout = 2000) {
90+
EthernetClient(std::shared_ptr<SocketImpl> sock, int bufferSize = 256, long timeout = 2000) {
9091
if (sock) {
9192
setTimeout(timeout);
9293
this->bufferSize = bufferSize;
@@ -102,22 +103,8 @@ class EthernetClient : public Client {
102103
setTimeout(2000);
103104
readBuffer = RingBufferExt(bufferSize);
104105
writeBuffer = RingBufferExt(bufferSize);
105-
p_sock = new SocketImpl(socket);
106+
p_sock = std::make_shared<SocketImpl>(socket);
106107
is_connected = p_sock->connected();
107-
registerCleanup();
108-
active_clients().push_back(this);
109-
}
110-
111-
virtual ~EthernetClient() {
112-
auto& clients = active_clients();
113-
auto it = std::find(clients.begin(), clients.end(), this);
114-
if (it != clients.end()) {
115-
clients.erase(it);
116-
}
117-
if (p_sock) {
118-
delete p_sock;
119-
p_sock = nullptr;
120-
}
121108
}
122109

123110
// checks if we are connected - using a timeout
@@ -269,7 +256,7 @@ class EthernetClient : public Client {
269256

270257
protected:
271258
const char* WIFICLIENT = "EthernetClient";
272-
SocketImpl* p_sock = nullptr;
259+
std::shared_ptr<SocketImpl> p_sock = nullptr;
273260
int bufferSize = 256;
274261
RingBufferExt readBuffer;
275262
RingBufferExt writeBuffer;

ArduinoCore-Linux/cores/arduino/EthernetServer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ class EthernetServer : public Server {
186186
Logger.error("accept failed");
187187
return result;
188188
}
189-
SocketImpl* sock_impl = new SocketImpl(client_fd, (struct sockaddr_in*)&client_addr);
189+
std::shared_ptr<SocketImpl> sock_impl = std::make_shared<SocketImpl>(client_fd, (struct sockaddr_in*)&client_addr);
190190
EthernetClient result{sock_impl};
191191
return result;
192192
}

ArduinoCore-Linux/cores/arduino/SocketImpl.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ int SocketImpl::connect(const char *address, uint16_t port) {
103103
// -1=>Error
104104
size_t SocketImpl::write(const uint8_t *str, size_t len) {
105105
Logger.debug(SOCKET_IMPL, "write");
106-
return ::send(sock, str, len, 0);
106+
return ::send(sock, str, len, MSG_NOSIGNAL);
107107
}
108108

109109
// provides the available bytes
@@ -118,7 +118,7 @@ size_t SocketImpl::available() {
118118

119119
// direct read
120120
size_t SocketImpl::read(uint8_t *buffer, size_t len) {
121-
size_t result = ::recv(sock, buffer, len, MSG_DONTWAIT);
121+
size_t result = ::recv(sock, buffer, len, MSG_DONTWAIT | MSG_NOSIGNAL);
122122
char lenStr[80];
123123
sprintf(lenStr, "%ld -> %ld", len, result);
124124
Logger.debug(SOCKET_IMPL, "read->", lenStr);

ArduinoCore-Linux/cores/arduino/SocketImpl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ class SocketImpl {
3636
is_connected = true;
3737
serv_addr = *address;
3838
};
39+
virtual ~SocketImpl() {
40+
if (sock != -1) {
41+
close();
42+
}
43+
}
3944
// checks if we are connected
4045
virtual uint8_t connected();
4146
// opens a conection
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
2+
3+
#include "HardwareGPIO_FIR.h"
4+
#include "Stream.h" // or <Stream.h> if needed
5+
#include <map>
6+
#include <vector>
7+
#include <cstdint>
8+
9+
namespace arduino {
10+
11+
12+
Stream* firmataStream = nullptr;
13+
std::map<pin_size_t, PinMode> pinModes;
14+
std::map<pin_size_t, PinStatus> pinStates;
15+
std::map<pin_size_t, int> analogValues;
16+
std::vector<uint8_t> rxBuffer;
17+
18+
// Firmata protocol constants
19+
constexpr uint8_t DIGITAL_MESSAGE = 0x90;
20+
constexpr uint8_t ANALOG_MESSAGE = 0xE0;
21+
constexpr uint8_t SET_PIN_MODE = 0xF4;
22+
constexpr uint8_t REPORT_DIGITAL = 0xD0;
23+
constexpr uint8_t REPORT_ANALOG = 0xC0;
24+
25+
HardwareGPIO_FIRMATA::~HardwareGPIO_FIRMATA() {
26+
end();
27+
}
28+
29+
bool HardwareGPIO_FIRMATA::begin(Stream &stream) {
30+
firmataStream = &stream;
31+
is_open = true;
32+
rxBuffer.clear();
33+
return true;
34+
}
35+
36+
void HardwareGPIO_FIRMATA::end() {
37+
is_open = false;
38+
firmataStream = nullptr;
39+
pinModes.clear();
40+
pinStates.clear();
41+
analogValues.clear();
42+
rxBuffer.clear();
43+
}
44+
45+
void HardwareGPIO_FIRMATA::pinMode(pin_size_t pinNumber, PinMode pinMode) {
46+
pinModes[pinNumber] = pinMode;
47+
if (firmataStream) {
48+
firmataStream->write(SET_PIN_MODE);
49+
firmataStream->write(pinNumber);
50+
firmataStream->write(pinMode);
51+
}
52+
}
53+
54+
void HardwareGPIO_FIRMATA::digitalWrite(pin_size_t pinNumber, PinStatus status) {
55+
pinStates[pinNumber] = status;
56+
if (firmataStream) {
57+
uint8_t port = pinNumber / 8;
58+
uint8_t portValue = 0;
59+
for (int i = 0; i < 8; ++i) {
60+
pin_size_t p = port * 8 + i;
61+
if (pinStates[p] == HIGH) {
62+
portValue |= (1 << i);
63+
}
64+
}
65+
firmataStream->write(DIGITAL_MESSAGE | port);
66+
firmataStream->write(portValue & 0x7F);
67+
firmataStream->write((portValue >> 7) & 0x7F);
68+
}
69+
}
70+
71+
PinStatus HardwareGPIO_FIRMATA::digitalRead(pin_size_t pinNumber) {
72+
// Request digital report for the port
73+
if (firmataStream) {
74+
uint8_t port = pinNumber / 8;
75+
firmataStream->write(REPORT_DIGITAL | port);
76+
firmataStream->write(1); // enable reporting
77+
}
78+
// Try to parse digital message from rxBuffer
79+
for (size_t i = 0; i + 2 < rxBuffer.size(); ++i) {
80+
uint8_t msg = rxBuffer[i];
81+
if ((msg & 0xF0) == DIGITAL_MESSAGE) {
82+
uint8_t port = msg & 0x0F;
83+
uint8_t lsb = rxBuffer[i+1];
84+
uint8_t msb = rxBuffer[i+2];
85+
uint16_t portValue = lsb | (msb << 7);
86+
pin_size_t p = port * 8;
87+
for (int j = 0; j < 8; ++j) {
88+
pinStates[p + j] = (portValue & (1 << j)) ? HIGH : LOW;
89+
}
90+
// Remove processed message
91+
rxBuffer.erase(rxBuffer.begin(), rxBuffer.begin() + i + 3);
92+
break;
93+
}
94+
}
95+
auto it = pinStates.find(pinNumber);
96+
if (it != pinStates.end()) {
97+
return it->second;
98+
}
99+
return LOW;
100+
}
101+
102+
int HardwareGPIO_FIRMATA::analogRead(pin_size_t pinNumber) {
103+
// Request analog report for the pin
104+
if (firmataStream) {
105+
firmataStream->write(REPORT_ANALOG | (pinNumber & 0x0F));
106+
firmataStream->write(1); // enable reporting
107+
}
108+
// Try to parse analog message from rxBuffer
109+
for (size_t i = 0; i + 2 < rxBuffer.size(); ++i) {
110+
uint8_t msg = rxBuffer[i];
111+
if ((msg & 0xF0) == ANALOG_MESSAGE) {
112+
uint8_t pin = msg & 0x0F;
113+
uint8_t lsb = rxBuffer[i+1];
114+
uint8_t msb = rxBuffer[i+2];
115+
int value = lsb | (msb << 7);
116+
analogValues[pin] = value;
117+
// Remove processed message
118+
rxBuffer.erase(rxBuffer.begin(), rxBuffer.begin() + i + 3);
119+
break;
120+
}
121+
}
122+
auto it = analogValues.find(pinNumber);
123+
if (it != analogValues.end()) {
124+
return it->second;
125+
}
126+
return 0;
127+
}
128+
129+
void HardwareGPIO_FIRMATA::analogReference(uint8_t mode) {
130+
// Not supported by Firmata, do nothing
131+
}
132+
133+
void HardwareGPIO_FIRMATA::analogWrite(pin_size_t pinNumber, int value) {
134+
if (firmataStream) {
135+
firmataStream->write(ANALOG_MESSAGE | (pinNumber & 0x0F));
136+
firmataStream->write(value & 0x7F);
137+
firmataStream->write((value >> 7) & 0x7F);
138+
}
139+
}
140+
141+
void HardwareGPIO_FIRMATA::analogWriteFrequency(pin_size_t pinNumber, uint32_t frequency) {
142+
// Not supported by Firmata, do nothing
143+
}
144+
145+
void HardwareGPIO_FIRMATA::tone(uint8_t _pin, unsigned int frequency, unsigned long duration) {
146+
// Not supported by Firmata, do nothing
147+
}
148+
149+
void HardwareGPIO_FIRMATA::noTone(uint8_t _pin) {
150+
// Not supported by Firmata, do nothing
151+
}
152+
153+
unsigned long HardwareGPIO_FIRMATA::pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) {
154+
// Not supported by Firmata, return 0
155+
return 0;
156+
}
157+
158+
unsigned long HardwareGPIO_FIRMATA::pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout) {
159+
// Not supported by Firmata, return 0
160+
return 0;
161+
}
162+
163+
void HardwareGPIO_FIRMATA::analogWriteResolution(uint8_t bits) {
164+
// Firmata supports 8-bit resolution, do nothing
165+
}
166+
167+
} // namespace arduino

0 commit comments

Comments
 (0)