comparison megawifi.c @ 1516:aaab852803ac

Get enough of MegaWifi implemented so that basic commands from wflash CLI command work
author Michael Pavone <pavone@retrodev.com>
date Mon, 22 Jan 2018 22:02:29 -0800
parents 3fc129eb0653
children 713b504dc577
comparison
equal deleted inserted replaced
1515:3fc129eb0653 1516:aaab852803ac
1 #include <stdlib.h> 1 #include <stdlib.h>
2 #include <stdint.h> 2 #include <stdint.h>
3 #include <string.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>
4 #include "genesis.h" 10 #include "genesis.h"
5 #include "net.h" 11 #include "net.h"
6 12
7 enum { 13 enum {
8 TX_IDLE, 14 TX_IDLE,
39 typedef struct { 45 typedef struct {
40 uint32_t transmit_bytes; 46 uint32_t transmit_bytes;
41 uint32_t expected_bytes; 47 uint32_t expected_bytes;
42 uint32_t receive_bytes; 48 uint32_t receive_bytes;
43 uint32_t receive_read; 49 uint32_t receive_read;
50 int sock_fds[15];
44 uint16_t channel_flags; 51 uint16_t channel_flags;
52 uint8_t channel_state[15];
45 uint8_t scratchpad; 53 uint8_t scratchpad;
46 uint8_t transmit_channel; 54 uint8_t transmit_channel;
47 uint8_t transmit_state; 55 uint8_t transmit_state;
48 uint8_t module_state; 56 uint8_t module_state;
49 uint8_t flags; 57 uint8_t flags;
55 { 63 {
56 m68k_context *m68k = context; 64 m68k_context *m68k = context;
57 genesis_context *gen = m68k->system; 65 genesis_context *gen = m68k->system;
58 if (!gen->extra) { 66 if (!gen->extra) {
59 gen->extra = calloc(1, sizeof(megawifi)); 67 gen->extra = calloc(1, sizeof(megawifi));
60 ((megawifi *)gen->extra)->module_state = STATE_IDLE; 68 megawifi *mw = gen->extra;
69 mw->module_state = STATE_IDLE;
70 for (int i = 0; i < 15; i++)
71 {
72 mw->sock_fds[i] = -1;
73 }
61 } 74 }
62 return gen->extra; 75 return gen->extra;
63 } 76 }
64 77
65 static void mw_putc(megawifi *mw, uint8_t v) 78 static void mw_putc(megawifi *mw, uint8_t v)
94 if ((mw->receive_bytes + len) > sizeof(mw->receive_buffer)) { 107 if ((mw->receive_bytes + len) > sizeof(mw->receive_buffer)) {
95 return; 108 return;
96 } 109 }
97 memcpy(mw->receive_buffer + mw->receive_bytes, s, len); 110 memcpy(mw->receive_buffer + mw->receive_bytes, s, len);
98 mw->receive_bytes += len; 111 mw->receive_bytes += len;
112 }
113
114 static void poll_socket(megawifi *mw, uint8_t channel)
115 {
116 if (mw->sock_fds[channel] < 0) {
117 return;
118 }
119 if (mw->channel_state[channel] == 1) {
120 int res = accept(mw->sock_fds[channel], NULL, NULL);
121 if (res >= 0) {
122 close(mw->sock_fds[channel]);
123 fcntl(res, F_SETFL, O_NONBLOCK);
124 mw->sock_fds[channel] = res;
125 mw->channel_state[channel] = 2;
126 mw->channel_flags |= 1 << (channel + 1);
127 } else if (errno != EAGAIN && errno != EWOULDBLOCK) {
128 close(mw->sock_fds[channel]);
129 mw->channel_state[channel] = 0;
130 mw->channel_flags |= 1 << (channel + 1);
131 }
132 } else if (mw->channel_state[channel] == 2 && mw->receive_bytes < sizeof(mw->receive_buffer) - 4) {
133 int bytes = recv(
134 mw->sock_fds[channel],
135 mw->receive_buffer + mw->receive_bytes + 3,
136 sizeof(mw->receive_buffer) - 4 - mw->receive_bytes,
137 0
138 );
139 if (bytes > 0) {
140 mw_putc(mw, STX);
141 mw_putc(mw, bytes >> 8 | (channel+1) << 4);
142 mw_putc(mw, bytes);
143 mw->receive_bytes += bytes;
144 mw_putc(mw, ETX);
145 //should this set the channel flag?
146 } else if (bytes < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
147 close(mw->sock_fds[channel]);
148 mw->channel_state[channel] = 0;
149 mw->channel_flags |= 1 << (channel + 1);
150 }
151 }
152 }
153
154 static void poll_all_sockets(megawifi *mw)
155 {
156 for (int i = 0; i < 15; i++)
157 {
158 poll_socket(mw, i);
159 }
99 } 160 }
100 161
101 static void start_reply(megawifi *mw, uint8_t cmd) 162 static void start_reply(megawifi *mw, uint8_t cmd)
102 { 163 {
103 mw_putc(mw, STX); 164 mw_putc(mw, STX);
129 uint32_t command = mw->transmit_buffer[0] << 8 | mw->transmit_buffer[1]; 190 uint32_t command = mw->transmit_buffer[0] << 8 | mw->transmit_buffer[1];
130 uint32_t size = mw->transmit_buffer[2] << 8 | mw->transmit_buffer[3]; 191 uint32_t size = mw->transmit_buffer[2] << 8 | mw->transmit_buffer[3];
131 if (size > mw->transmit_bytes - 4) { 192 if (size > mw->transmit_bytes - 4) {
132 size = mw->transmit_bytes - 4; 193 size = mw->transmit_bytes - 4;
133 } 194 }
134 mw->receive_read = mw->receive_bytes = 0; 195 int orig_receive_bytes = mw->receive_bytes;
135 switch (command) 196 switch (command)
136 { 197 {
137 case CMD_VERSION: 198 case CMD_VERSION:
138 start_reply(mw, CMD_OK); 199 start_reply(mw, CMD_OK);
139 mw_putc(mw, 1); 200 mw_putc(mw, 1);
142 end_reply(mw); 203 end_reply(mw);
143 break; 204 break;
144 case CMD_ECHO: 205 case CMD_ECHO:
145 mw->receive_bytes = mw->transmit_bytes; 206 mw->receive_bytes = mw->transmit_bytes;
146 memcpy(mw->receive_buffer, mw->transmit_buffer, mw->transmit_bytes); 207 memcpy(mw->receive_buffer, mw->transmit_buffer, mw->transmit_bytes);
147 break;
148 case CMD_AP_JOIN:
149 mw->module_state = STATE_READY;
150 start_reply(mw, CMD_OK);
151 end_reply(mw);
152 break;
153 case CMD_SYS_STAT:
154 start_reply(mw, CMD_OK);
155 mw_putc(mw, mw->module_state);
156 mw_putc(mw, mw->flags);
157 mw_putc(mw, mw->channel_flags >> 8);
158 mw_putc(mw, mw->channel_flags);
159 end_reply(mw);
160 break; 208 break;
161 case CMD_IP_CURRENT: { 209 case CMD_IP_CURRENT: {
162 iface_info i; 210 iface_info i;
163 if (get_host_address(&i)) { 211 if (get_host_address(&i)) {
164 start_reply(mw, CMD_OK); 212 start_reply(mw, CMD_OK);
182 start_reply(mw, CMD_ERROR); 230 start_reply(mw, CMD_ERROR);
183 } 231 }
184 end_reply(mw); 232 end_reply(mw);
185 break; 233 break;
186 } 234 }
235 case CMD_AP_JOIN:
236 mw->module_state = STATE_READY;
237 start_reply(mw, CMD_OK);
238 end_reply(mw);
239 break;
240 case CMD_TCP_BIND:{
241 if (size < 7){
242 start_reply(mw, CMD_ERROR);
243 end_reply(mw);
244 break;
245 }
246 uint8_t channel = mw->transmit_buffer[10];
247 if (!channel || channel > 15) {
248 start_reply(mw, CMD_ERROR);
249 end_reply(mw);
250 break;
251 }
252 channel--;
253 if (mw->sock_fds[channel] >= 0) {
254 close(mw->sock_fds[channel]);
255 }
256 mw->sock_fds[channel] = socket(AF_INET, SOCK_STREAM, 0);
257 if (mw->sock_fds[channel] < 0) {
258 start_reply(mw, CMD_ERROR);
259 end_reply(mw);
260 break;
261 }
262 int value = 1;
263 setsockopt(mw->sock_fds[channel], SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));
264 struct sockaddr_in bind_addr;
265 memset(&bind_addr, 0, sizeof(bind_addr));
266 bind_addr.sin_family = AF_INET;
267 bind_addr.sin_port = htons(mw->transmit_buffer[8] << 8 | mw->transmit_buffer[9]);
268 if (bind(mw->sock_fds[channel], (struct sockaddr *)&bind_addr, sizeof(bind_addr)) != 0) {
269 close(mw->sock_fds[channel]);
270 mw->sock_fds[channel] = -1;
271 start_reply(mw, CMD_ERROR);
272 end_reply(mw);
273 break;
274 }
275 int res = listen(mw->sock_fds[channel], 2);
276 start_reply(mw, res ? CMD_ERROR : CMD_OK);
277 if (res) {
278 close(mw->sock_fds[channel]);
279 mw->sock_fds[channel] = -1;
280 } else {
281 mw->channel_flags |= 1 << (channel + 1);
282 mw->channel_state[channel] = 1;
283 fcntl(mw->sock_fds[channel], F_SETFL, O_NONBLOCK);
284 }
285 end_reply(mw);
286 break;
287 }
288 case CMD_SOCK_STAT: {
289 uint8_t channel = mw->transmit_buffer[4];
290 if (!channel || channel > 15) {
291 start_reply(mw, CMD_ERROR);
292 end_reply(mw);
293 break;
294 }
295 mw->channel_flags &= ~(1 << channel);
296 channel--;
297 poll_socket(mw, channel);
298 start_reply(mw, CMD_OK);
299 mw_putc(mw, mw->channel_state[channel]);
300 end_reply(mw);
301 break;
302 }
303 case CMD_SYS_STAT:
304 poll_all_sockets(mw);
305 start_reply(mw, CMD_OK);
306 mw_putc(mw, mw->module_state);
307 mw_putc(mw, mw->flags);
308 mw_putc(mw, mw->channel_flags >> 8);
309 mw_putc(mw, mw->channel_flags);
310 end_reply(mw);
311 break;
187 default: 312 default:
188 printf("Unhandled MegaWiFi command %s(%d) with length %X\n", cmd_names[command], command, size); 313 printf("Unhandled MegaWiFi command %s(%d) with length %X\n", cmd_names[command], command, size);
189 break; 314 break;
315 }
316 } else if (mw->sock_fds[mw->transmit_channel - 1] >= 0 && mw->channel_state[mw->transmit_channel - 1] == 2) {
317 uint8_t channel = mw->transmit_channel - 1;
318 int sent = send(mw->sock_fds[channel], mw->transmit_buffer, mw->transmit_bytes, 0);
319 if (sent < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
320 close(mw->sock_fds[channel]);
321 mw->sock_fds[channel] = -1;
322 mw->channel_state[channel] = 0;
323 mw->channel_flags |= 1 << mw->transmit_channel;
324 } else if (sent < mw->transmit_bytes) {
325 //TODO: save this data somewhere so it can be sent in poll_socket
326 printf("Sent %d bytes on channel %d, but %d were requested\n", sent, mw->transmit_channel, mw->transmit_bytes);
190 } 327 }
191 } else { 328 } else {
192 printf("Unhandled receive of MegaWiFi data on channel %d\n", mw->transmit_channel); 329 printf("Unhandled receive of MegaWiFi data on channel %d\n", mw->transmit_channel);
193 } 330 }
194 mw->transmit_bytes = mw->expected_bytes = 0; 331 mw->transmit_bytes = mw->expected_bytes = 0;
257 megawifi *mw = get_megawifi(context); 394 megawifi *mw = get_megawifi(context);
258 address = address >> 1 & 7; 395 address = address >> 1 & 7;
259 switch (address) 396 switch (address)
260 { 397 {
261 case 0: 398 case 0:
399 poll_all_sockets(mw);
262 if (mw->receive_read < mw->receive_bytes) { 400 if (mw->receive_read < mw->receive_bytes) {
263 return mw->receive_buffer[mw->receive_read++]; 401 uint8_t ret = mw->receive_buffer[mw->receive_read++];
402 if (mw->receive_read == mw->receive_bytes) {
403 mw->receive_read = mw->receive_bytes = 0;
404 }
405 return ret;
264 } 406 }
265 return 0xFF; 407 return 0xFF;
266 case 5: 408 case 5:
409 poll_all_sockets(mw);
267 //line status 410 //line status
268 return 0x60 | (mw->receive_read < mw->receive_bytes); 411 return 0x60 | (mw->receive_read < mw->receive_bytes);
269 case 7: 412 case 7:
270 return mw->scratchpad; 413 return mw->scratchpad;
271 default: 414 default: