main
megawifi.c
1#include <stdlib.h>
2#include <stdint.h>
3#include <string.h>
4#include <sys/types.h>
5#include <sys/socket.h>
6#include <unistd.h>
7#include <netinet/in.h>
8#include <errno.h>
9#include <fcntl.h>
10#include "genesis.h"
11#include "net.h"
12
13enum {
14 TX_IDLE,
15 TX_LEN1,
16 TX_LEN2,
17 TX_PAYLOAD,
18 TX_WAIT_ETX
19};
20#define STX 0x7E
21#define ETX 0x7E
22#define MAX_RECV_SIZE 1440
23
24#define E(N) N
25enum {
26#include "mw_commands.c"
27 CMD_ERROR = 255
28};
29#undef E
30#define E(N) #N
31static const char *cmd_names[] = {
32#include "mw_commands.c"
33 [255] = "CMD_ERROR"
34};
35
36#ifndef MSG_NOSIGNAL
37#define MSG_NOSIGNAL 0
38#endif
39
40enum {
41 STATE_IDLE=1,
42 STATE_AP_JOIN,
43 STATE_SCAN,
44 STATE_READY,
45 STATE_TRANSPARENT
46};
47
48#define FLAG_ONLINE
49
50typedef struct {
51 uint32_t transmit_bytes;
52 uint32_t expected_bytes;
53 uint32_t receive_bytes;
54 uint32_t receive_read;
55 int sock_fds[15];
56 uint16_t channel_flags;
57 uint8_t channel_state[15];
58 uint8_t scratchpad;
59 uint8_t transmit_channel;
60 uint8_t transmit_state;
61 uint8_t module_state;
62 uint8_t flags;
63 uint8_t transmit_buffer[4096];
64 uint8_t receive_buffer[4096];
65} megawifi;
66
67static megawifi *get_megawifi(void *context)
68{
69 m68k_context *m68k = context;
70 genesis_context *gen = m68k->system;
71 if (!gen->extra) {
72 gen->extra = calloc(1, sizeof(megawifi));
73 megawifi *mw = gen->extra;
74 mw->module_state = STATE_IDLE;
75 for (int i = 0; i < 15; i++)
76 {
77 mw->sock_fds[i] = -1;
78 }
79 }
80 return gen->extra;
81}
82
83static void mw_putc(megawifi *mw, uint8_t v)
84{
85 if (mw->receive_bytes == sizeof(mw->receive_buffer)) {
86 return;
87 }
88 mw->receive_buffer[mw->receive_bytes++] = v;
89}
90
91static void mw_set(megawifi *mw, uint8_t val, uint32_t count)
92{
93 if (count + mw->receive_bytes > sizeof(mw->receive_buffer)) {
94 count = sizeof(mw->receive_buffer) - mw->receive_bytes;
95 }
96 memset(mw->receive_buffer + mw->receive_bytes, val, count);
97 mw->receive_bytes += count;
98}
99
100static void mw_copy(megawifi *mw, const uint8_t *src, uint32_t count)
101{
102 if (count + mw->receive_bytes > sizeof(mw->receive_buffer)) {
103 count = sizeof(mw->receive_buffer) - mw->receive_bytes;
104 }
105 memcpy(mw->receive_buffer + mw->receive_bytes, src, count);
106 mw->receive_bytes += count;
107}
108
109static void mw_puts(megawifi *mw, char *s)
110{
111 uint32_t len = strlen(s);
112 if ((mw->receive_bytes + len) > sizeof(mw->receive_buffer)) {
113 return;
114 }
115 memcpy(mw->receive_buffer + mw->receive_bytes, s, len);
116 mw->receive_bytes += len;
117}
118
119static void poll_socket(megawifi *mw, uint8_t channel)
120{
121 if (mw->sock_fds[channel] < 0) {
122 return;
123 }
124 if (mw->channel_state[channel] == 1) {
125 int res = accept(mw->sock_fds[channel], NULL, NULL);
126 if (res >= 0) {
127 close(mw->sock_fds[channel]);
128 fcntl(res, F_SETFL, O_NONBLOCK);
129 mw->sock_fds[channel] = res;
130 mw->channel_state[channel] = 2;
131 mw->channel_flags |= 1 << (channel + 1);
132 } else if (errno != EAGAIN && errno != EWOULDBLOCK) {
133 close(mw->sock_fds[channel]);
134 mw->channel_state[channel] = 0;
135 mw->channel_flags |= 1 << (channel + 1);
136 }
137 } else if (mw->channel_state[channel] == 2 && mw->receive_bytes < sizeof(mw->receive_buffer) - 4) {
138 size_t max = sizeof(mw->receive_buffer) - 4 - mw->receive_bytes;
139 if (max > MAX_RECV_SIZE) {
140 max = MAX_RECV_SIZE;
141 }
142 int bytes = recv(mw->sock_fds[channel], mw->receive_buffer + mw->receive_bytes + 3, max, 0);
143 if (bytes > 0) {
144 mw_putc(mw, STX);
145 mw_putc(mw, bytes >> 8 | (channel+1) << 4);
146 mw_putc(mw, bytes);
147 mw->receive_bytes += bytes;
148 mw_putc(mw, ETX);
149 //should this set the channel flag?
150 } else if (bytes < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
151 close(mw->sock_fds[channel]);
152 mw->channel_state[channel] = 0;
153 mw->channel_flags |= 1 << (channel + 1);
154 }
155 }
156}
157
158static void poll_all_sockets(megawifi *mw)
159{
160 for (int i = 0; i < 15; i++)
161 {
162 poll_socket(mw, i);
163 }
164}
165
166static void start_reply(megawifi *mw, uint8_t cmd)
167{
168 mw_putc(mw, STX);
169 //reserve space for length
170 mw->receive_bytes += 2;
171 //cmd
172 mw_putc(mw, 0);
173 mw_putc(mw, cmd);
174 //reserve space for length
175 mw->receive_bytes += 2;
176}
177
178static void end_reply(megawifi *mw)
179{
180 uint32_t len = mw->receive_bytes - 3;
181 //LSD packet length
182 mw->receive_buffer[1] = len >> 8;
183 mw->receive_buffer[2] = len;
184 //command length
185 len -= 4;
186 mw->receive_buffer[5] = len >> 8;
187 mw->receive_buffer[6] = len;
188 mw_putc(mw, ETX);
189}
190
191static void process_packet(megawifi *mw)
192{
193 if (mw->transmit_channel == 0) {
194 uint32_t command = mw->transmit_buffer[0] << 8 | mw->transmit_buffer[1];
195 uint32_t size = mw->transmit_buffer[2] << 8 | mw->transmit_buffer[3];
196 if (size > mw->transmit_bytes - 4) {
197 size = mw->transmit_bytes - 4;
198 }
199 int orig_receive_bytes = mw->receive_bytes;
200 switch (command)
201 {
202 case CMD_VERSION:
203 start_reply(mw, CMD_OK);
204 mw_putc(mw, 1);
205 mw_putc(mw, 0);
206 mw_puts(mw, "blastem");
207 end_reply(mw);
208 break;
209 case CMD_ECHO:
210 mw->receive_bytes = mw->transmit_bytes;
211 memcpy(mw->receive_buffer, mw->transmit_buffer, mw->transmit_bytes);
212 break;
213 case CMD_IP_CURRENT: {
214 iface_info i;
215 if (get_host_address(&i)) {
216 start_reply(mw, CMD_OK);
217 //config number and reserved bytes
218 mw_set(mw, 0, 4);
219 //ip
220 mw_copy(mw, i.ip, sizeof(i.ip));
221 //net mask
222 mw_copy(mw, i.net_mask, sizeof(i.net_mask));
223 //gateway guess
224 mw_putc(mw, i.ip[0] & i.net_mask[0]);
225 mw_putc(mw, i.ip[1] & i.net_mask[1]);
226 mw_putc(mw, i.ip[2] & i.net_mask[2]);
227 mw_putc(mw, (i.ip[3] & i.net_mask[3]) + 1);
228 //dns
229 static const uint8_t localhost[] = {127,0,0,1};
230 mw_copy(mw, localhost, sizeof(localhost));
231 mw_copy(mw, localhost, sizeof(localhost));
232
233 } else {
234 start_reply(mw, CMD_ERROR);
235 }
236 end_reply(mw);
237 break;
238 }
239 case CMD_AP_JOIN:
240 mw->module_state = STATE_READY;
241 start_reply(mw, CMD_OK);
242 end_reply(mw);
243 break;
244 case CMD_TCP_BIND:{
245 if (size < 7){
246 start_reply(mw, CMD_ERROR);
247 end_reply(mw);
248 break;
249 }
250 uint8_t channel = mw->transmit_buffer[10];
251 if (!channel || channel > 15) {
252 start_reply(mw, CMD_ERROR);
253 end_reply(mw);
254 break;
255 }
256 channel--;
257 if (mw->sock_fds[channel] >= 0) {
258 close(mw->sock_fds[channel]);
259 }
260 mw->sock_fds[channel] = socket(AF_INET, SOCK_STREAM, 0);
261 if (mw->sock_fds[channel] < 0) {
262 start_reply(mw, CMD_ERROR);
263 end_reply(mw);
264 break;
265 }
266 int value = 1;
267 setsockopt(mw->sock_fds[channel], SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));
268 struct sockaddr_in bind_addr;
269 memset(&bind_addr, 0, sizeof(bind_addr));
270 bind_addr.sin_family = AF_INET;
271 bind_addr.sin_port = htons(mw->transmit_buffer[8] << 8 | mw->transmit_buffer[9]);
272 if (bind(mw->sock_fds[channel], (struct sockaddr *)&bind_addr, sizeof(bind_addr)) != 0) {
273 close(mw->sock_fds[channel]);
274 mw->sock_fds[channel] = -1;
275 start_reply(mw, CMD_ERROR);
276 end_reply(mw);
277 break;
278 }
279 int res = listen(mw->sock_fds[channel], 2);
280 start_reply(mw, res ? CMD_ERROR : CMD_OK);
281 if (res) {
282 close(mw->sock_fds[channel]);
283 mw->sock_fds[channel] = -1;
284 } else {
285 mw->channel_flags |= 1 << (channel + 1);
286 mw->channel_state[channel] = 1;
287 fcntl(mw->sock_fds[channel], F_SETFL, O_NONBLOCK);
288 }
289 end_reply(mw);
290 break;
291 }
292 case CMD_SOCK_STAT: {
293 uint8_t channel = mw->transmit_buffer[4];
294 if (!channel || channel > 15) {
295 start_reply(mw, CMD_ERROR);
296 end_reply(mw);
297 break;
298 }
299 mw->channel_flags &= ~(1 << channel);
300 channel--;
301 poll_socket(mw, channel);
302 start_reply(mw, CMD_OK);
303 mw_putc(mw, mw->channel_state[channel]);
304 end_reply(mw);
305 break;
306 }
307 case CMD_SYS_STAT:
308 poll_all_sockets(mw);
309 start_reply(mw, CMD_OK);
310 mw_putc(mw, mw->module_state);
311 mw_putc(mw, mw->flags);
312 mw_putc(mw, mw->channel_flags >> 8);
313 mw_putc(mw, mw->channel_flags);
314 end_reply(mw);
315 break;
316 default:
317 printf("Unhandled MegaWiFi command %s(%d) with length %X\n", cmd_names[command], command, size);
318 break;
319 }
320 } else if (mw->sock_fds[mw->transmit_channel - 1] >= 0 && mw->channel_state[mw->transmit_channel - 1] == 2) {
321 uint8_t channel = mw->transmit_channel - 1;
322 int sent = send(mw->sock_fds[channel], mw->transmit_buffer, mw->transmit_bytes, MSG_NOSIGNAL);
323 if (sent < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
324 close(mw->sock_fds[channel]);
325 mw->sock_fds[channel] = -1;
326 mw->channel_state[channel] = 0;
327 mw->channel_flags |= 1 << mw->transmit_channel;
328 } else if (sent < mw->transmit_bytes) {
329 //TODO: save this data somewhere so it can be sent in poll_socket
330 printf("Sent %d bytes on channel %d, but %d were requested\n", sent, mw->transmit_channel, mw->transmit_bytes);
331 }
332 } else {
333 printf("Unhandled receive of MegaWiFi data on channel %d\n", mw->transmit_channel);
334 }
335 mw->transmit_bytes = mw->expected_bytes = 0;
336}
337
338void *megawifi_write_b(uint32_t address, void *context, uint8_t value)
339{
340 if (!(address & 1)) {
341 return context;
342 }
343 megawifi *mw = get_megawifi(context);
344 address = address >> 1 & 7;
345 switch (address)
346 {
347 case 0:
348 switch (mw->transmit_state)
349 {
350 case TX_IDLE:
351 if (value == STX) {
352 mw->transmit_state = TX_LEN1;
353 }
354 break;
355 case TX_LEN1:
356 mw->transmit_channel = value >> 4;
357 mw->expected_bytes = value << 8 & 0xF00;
358 mw->transmit_state = TX_LEN2;
359 break;
360 case TX_LEN2:
361 mw->expected_bytes |= value;
362 mw->transmit_state = TX_PAYLOAD;
363 break;
364 case TX_PAYLOAD:
365 mw->transmit_buffer[mw->transmit_bytes++] = value;
366 if (mw->transmit_bytes == mw->expected_bytes) {
367 mw->transmit_state = TX_WAIT_ETX;
368 }
369 break;
370 case TX_WAIT_ETX:
371 if (value == ETX) {
372 mw->transmit_state = TX_IDLE;
373 process_packet(mw);
374 }
375 break;
376 }
377 break;
378 case 7:
379 mw->scratchpad = value;
380 break;
381 default:
382 printf("Unhandled write to MegaWiFi UART register %X: %X\n", address, value);
383 }
384 return context;
385}
386
387void *megawifi_write_w(uint32_t address, void *context, uint16_t value)
388{
389 return megawifi_write_b(address | 1, context, value);
390}
391
392uint8_t megawifi_read_b(uint32_t address, void *context)
393{
394
395 if (!(address & 1)) {
396 return 0xFF;
397 }
398 megawifi *mw = get_megawifi(context);
399 address = address >> 1 & 7;
400 switch (address)
401 {
402 case 0:
403 poll_all_sockets(mw);
404 if (mw->receive_read < mw->receive_bytes) {
405 uint8_t ret = mw->receive_buffer[mw->receive_read++];
406 if (mw->receive_read == mw->receive_bytes) {
407 mw->receive_read = mw->receive_bytes = 0;
408 }
409 return ret;
410 }
411 return 0xFF;
412 case 5:
413 poll_all_sockets(mw);
414 //line status
415 return 0x60 | (mw->receive_read < mw->receive_bytes);
416 case 7:
417 return mw->scratchpad;
418 default:
419 printf("Unhandled read from MegaWiFi UART register %X\n", address);
420 return 0xFF;
421 }
422}
423
424uint16_t megawifi_read_w(uint32_t address, void *context)
425{
426 return 0xFF00 | megawifi_read_b(address | 1, context);
427}