rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
wifi_console.cpp
Go to the documentation of this file.
1#include "pch.h"
2
3#if EFI_WIFI
4
5#include "driver/include/m2m_wifi.h"
6#include "socket/include/socket.h"
7
8#include "thread_controller.h"
9#include "tunerstudio.h"
10
11static int listenerSocket = -1;
12static int connectionSocket = -1;
13
14chibios_rt::BinarySemaphore isrSemaphore(/* taken =*/ true);
15
17 isrSemaphore.signalI();
18}
19
20// TX Helper data
21static const uint8_t* sendBuffer;
22static size_t sendSize;
23bool sendRequest = false;
24chibios_rt::BinarySemaphore sendDoneSemaphore(/* taken =*/ true);
25
26// RX Helper data
27static uint8_t recvBuffer[512];
28static input_queue_t wifiIqueue;
29
30static bool socketReady = false;
31
32class WifiChannel final : public TsChannelBase {
33public:
34 WifiChannel()
35 : TsChannelBase("WiFi")
36 {
37 }
38
39 bool isReady() const override {
40 return socketReady;
41 }
42
43 void write(const uint8_t* buffer, size_t size, bool /*isEndOfPacket*/) final override {
44 while (size > 0) {
45 // Write at most SOCKET_BUFFER_MAX_LENGTH bytes at a time
46 size_t chunkSize = size > SOCKET_BUFFER_MAX_LENGTH ? SOCKET_BUFFER_MAX_LENGTH : size;
47
48 // Write this chunk
50 sendSize = chunkSize;
51 sendRequest = true;
52 isrSemaphore.signal();
53
54 // Step buffer/size for the next chunk
55 buffer += chunkSize;
56 size -= chunkSize;
57
58 // Wait for this chunk to complete
59 sendDoneSemaphore.wait();
60 }
61 }
62
63 size_t readTimeout(uint8_t* buffer, size_t size, int timeout) override {
64 return iqReadTimeout(&wifiIqueue, buffer, size, timeout);
65 }
66};
67
68static NO_CACHE WifiChannel wifiChannel;
69
70class WifiHelperThread : public ThreadController<4096> {
71public:
72 WifiHelperThread() : ThreadController("WiFi", WIFI_THREAD_PRIORITY) {}
73 void ThreadTask() override {
74 while (true)
75 {
76 m2m_wifi_handle_events(nullptr);
77
78 if (socketReady && sendRequest) {
79 send(connectionSocket, (void*)sendBuffer, sendSize, 0);
80 sendRequest = false;
81 } else {
82 isrSemaphore.wait(TIME_MS2I(1));
83 }
84 }
85 }
86};
87
88static NO_CACHE WifiHelperThread wifiHelper;
89
90static tstrWifiInitParam param;
91
92static tstrM2MAPConfig apConfig;
93
94void wifiCallback(uint8 u8MsgType, void* pvMsg) {
95 switch (u8MsgType) {
96 case M2M_WIFI_REQ_DHCP_CONF: {
97 auto& dhcpInfo = *reinterpret_cast<tstrM2MIPConfig*>(pvMsg);
98 uint8_t* addr = reinterpret_cast<uint8_t*>(&dhcpInfo.u32StaticIP);
99 efiPrintf("WiFi client connected DHCP IP is %d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
100 } break;
101 default:
102 efiPrintf("WifiCallback: %d", (int)u8MsgType);
103 break;
104 }
105}
106
107static NO_CACHE uint8_t rxBuf[512];
108
109static void socketCallback(SOCKET sock, uint8_t u8Msg, void* pvMsg) {
110 switch (u8Msg) {
111 case SOCKET_MSG_BIND: {
112 auto bindMsg = reinterpret_cast<tstrSocketBindMsg*>(pvMsg);
113
114 if (bindMsg && bindMsg->status == 0) {
115 // Socket bind complete, now listen!
116 listen(sock, 1);
117 }
118 } break;
119 case SOCKET_MSG_LISTEN: {
120 auto listenMsg = reinterpret_cast<tstrSocketListenMsg*>(pvMsg);
121 if (listenMsg && listenMsg->status == 0) {
122 // Listening, now accept a connection
123 accept(sock, nullptr, nullptr);
124 }
125 } break;
126 case SOCKET_MSG_ACCEPT: {
127 auto acceptMsg = reinterpret_cast<tstrSocketAcceptMsg*>(pvMsg);
128 if (acceptMsg && (acceptMsg->sock >= 0)) {
129 connectionSocket = acceptMsg->sock;
130
131 recv(connectionSocket, &rxBuf, 1, 0);
132
133 socketReady = true;
134 }
135 } break;
136 case SOCKET_MSG_RECV: {
137 auto recvMsg = reinterpret_cast<tstrSocketRecvMsg*>(pvMsg);
138 if (recvMsg && (recvMsg->s16BufferSize > 0)) {
139 {
140 chibios_rt::CriticalSectionLocker csl;
141
142 for (size_t i = 0; i < recvMsg->s16BufferSize; i++) {
143 iqPutI(&wifiIqueue, rxBuf[i]);
144 }
145 }
146
147 size_t nextRecv;
148 if (recvMsg->u16RemainingSize < 1) {
149 // Always try to read at least 1 byte
150 nextRecv = 1;
151 } else if (recvMsg->u16RemainingSize > sizeof(rxBuf)) {
152 // Remaining is too big for the buffer, so just read one buffer worth
153 nextRecv = sizeof(rxBuf);
154 } else {
155 // The full thing will fit, try to read it
156 nextRecv = recvMsg->u16RemainingSize;
157 }
158
159 // start the next recv
160 recv(sock, &rxBuf, nextRecv, 0);
161 } else {
162 close(sock);
163
164 socketReady = false;
165
166 {
167 chibios_rt::CriticalSectionLocker csl;
168 iqResetI(&wifiIqueue);
169 }
170 }
171 } break;
172 case SOCKET_MSG_SEND: {
173 // Send completed, notify caller!
174 chibios_rt::CriticalSectionLocker csl;
175 sendDoneSemaphore.signalI();
176 } break;
177 }
178}
179
180struct WifiConsoleThread : public TunerstudioThread {
181 WifiConsoleThread() : TunerstudioThread("WiFi Console") { }
182
183 TsChannelBase* setupChannel() override {
184 // Initialize the WiFi module
185 param.pfAppWifiCb = wifiCallback;
186 if (M2M_SUCCESS != m2m_wifi_init(&param)) {
187 return nullptr;
188 }
189
190 strcpy(apConfig.au8SSID, "FOME EFI");
191 apConfig.u8ListenChannel = 1;
192 apConfig.u8SecType = M2M_WIFI_SEC_OPEN;
193 apConfig.u8SsidHide = 0;
194
195 // IP Address
196 apConfig.au8DHCPServerIP[0] = 192;
197 apConfig.au8DHCPServerIP[1] = 168;
198 apConfig.au8DHCPServerIP[2] = 1;
199 apConfig.au8DHCPServerIP[3] = 1;
200
201 // Trigger AP
202 if (M2M_SUCCESS != m2m_wifi_enable_ap(&apConfig)) {
203 return nullptr;
204 }
205
206 // Start the helper thread
207 wifiHelper.start();
208
209 // Set up the socket APIs
210 socketInit();
211 registerSocketCallback(socketCallback, nullptr);
212
213 // Start listening on the socket
214 sockaddr_in address;
215 address.sin_family = AF_INET;
216 address.sin_port = _htons(17999);
217 address.sin_addr.s_addr = 0;
218
219 listenerSocket = socket(AF_INET, SOCK_STREAM, SOCKET_CONFIG_SSL_OFF);
220 bind(listenerSocket, (sockaddr*)&address, sizeof(address));
221
222 return &wifiChannel;
223 }
224};
225
226static NO_CACHE WifiConsoleThread wifiThread;
227
229 iqObjectInit(&wifiIqueue, recvBuffer, sizeof(recvBuffer), nullptr, nullptr);
230
231 wifiThread.start();
232}
233
234#endif // EFI_WIFI
constexpr uint8_t addr
Definition ads1015.cpp:14
A base class for a controller that requires its own thread.
virtual void ThreadTask()=0
virtual bool isReady() const
virtual void write(const uint8_t *buffer, size_t size, bool isEndOfPacket=false)=0
virtual size_t readTimeout(uint8_t *buffer, size_t size, int timeout)=0
virtual TsChannelBase * setupChannel()=0
static union @47 NO_CACHE
composite packet size
static BigBufferHandle buffer
static NO_CACHE WifiChannel wifiChannel
static bool socketReady
static int connectionSocket
static tstrWifiInitParam param
static NO_CACHE WifiHelperThread wifiHelper
static const uint8_t * sendBuffer
static NO_CACHE WifiConsoleThread wifiThread
static void socketCallback(SOCKET sock, uint8_t u8Msg, void *pvMsg)
void wifiCallback(uint8 u8MsgType, void *pvMsg)
void os_hook_isr()
static size_t sendSize
static int listenerSocket
static NO_CACHE uint8_t rxBuf[512]
static input_queue_t wifiIqueue
bool sendRequest
static uint8_t recvBuffer[512]
void startWifiConsole()
chibios_rt::BinarySemaphore sendDoneSemaphore(true)
chibios_rt::BinarySemaphore isrSemaphore(true)
static tstrM2MAPConfig apConfig