comparison megawifi.c @ 1692:5dacaef602a7 segacd

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