Initial commit
This commit is contained in:
Binary file not shown.
@@ -0,0 +1 @@
|
||||
ic.exe com5
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
||||
ic_115200.exe COM5
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,546 @@
|
||||
#include <winsock2.h>
|
||||
|
||||
#include "ic_comm.h"
|
||||
#include "ic_cmds.h"
|
||||
#include "uart.h"
|
||||
#include "log.h"
|
||||
|
||||
//Winsock shit
|
||||
WORD wVersionRequested;
|
||||
WSADATA wsaData;
|
||||
|
||||
|
||||
//vars
|
||||
SOCKET sockets[SOCKET_MAX];
|
||||
|
||||
|
||||
|
||||
//Init
|
||||
int init(char *comport)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<SOCKET_MAX; ++i)
|
||||
sockets[i]=0;
|
||||
|
||||
if(uart_init(comport) < 0) return -1;
|
||||
|
||||
//Init winsock
|
||||
wVersionRequested = MAKEWORD(2,2);
|
||||
WSAStartup(wVersionRequested, &wsaData);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Process
|
||||
void process(void)
|
||||
{
|
||||
unsigned char cmd;
|
||||
|
||||
while(1)
|
||||
{
|
||||
//read command
|
||||
uart_read(&cmd,1);
|
||||
|
||||
switch(cmd)
|
||||
{
|
||||
case IC_CMD_SOCKET: cmd_socket(); break;
|
||||
case IC_CMD_BIND: cmd_bind(); break;
|
||||
case IC_CMD_CONNECT: cmd_connect(); break;
|
||||
case IC_CMD_LISTEN: cmd_listen(); break;
|
||||
case IC_CMD_ACCEPT: cmd_accept(); break;
|
||||
case IC_CMD_CLOSE: cmd_close(); break;
|
||||
case IC_CMD_SELECT: cmd_select(); break;
|
||||
|
||||
case IC_CMD_GETHOSTBYNAME: cmd_gethostbyname(); break;
|
||||
case IC_CMD_GETHOSTBYADDR: cmd_gethostbyaddr(); break;
|
||||
|
||||
case IC_CMD_SEND: cmd_send(); break;
|
||||
case IC_CMD_RECV: cmd_recv(); break;
|
||||
case IC_CMD_SENDTO: cmd_sendto(); break;
|
||||
case IC_CMD_RECVFROM: cmd_recvfrom(); break;
|
||||
|
||||
default:
|
||||
logerr("Wrong command #%2x!",cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cmd_res_fail(void)
|
||||
{
|
||||
unsigned char t=IC_CMD_RES_FAIL;
|
||||
uart_write(&t,1);
|
||||
}
|
||||
|
||||
void cmd_res_ok(void)
|
||||
{
|
||||
unsigned char t=IC_CMD_RES_OK;
|
||||
uart_write(&t,1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cmd_socket(void)
|
||||
{
|
||||
unsigned char params[10];
|
||||
SOCKET tsock;
|
||||
int i;
|
||||
|
||||
//get params
|
||||
uart_read(params,3);
|
||||
//find free socket
|
||||
for(i=0; i<SOCKET_MAX; ++i)
|
||||
if(sockets[i]==0) break;
|
||||
|
||||
if(i==SOCKET_MAX)
|
||||
{ //not found, result=fail
|
||||
cmd_res_fail();
|
||||
logerr("CMD_SOCKET: No free sockets.");
|
||||
}
|
||||
else
|
||||
{ //found, create real socket
|
||||
tsock=socket((int)params[0],(int)params[1],(int)params[2]);
|
||||
|
||||
if(tsock==INVALID_SOCKET)
|
||||
{ //socket() fail
|
||||
cmd_res_fail();
|
||||
logerr("socket() failed.");
|
||||
}
|
||||
else
|
||||
{ //socket created
|
||||
sockets[i]=tsock;
|
||||
params[0]=IC_CMD_RES_OK; //res=ok
|
||||
params[1]=i; //fd
|
||||
uart_write(params,2);
|
||||
log_("Socket created, id=%i.",i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cmd_bind(void)
|
||||
{
|
||||
unsigned char params[10];
|
||||
unsigned char fd;
|
||||
struct sockaddr_in loc_addr;
|
||||
|
||||
//get params
|
||||
uart_read(params,7);
|
||||
fd=params[0];
|
||||
if(fd>=SOCKET_MAX || sockets[fd]==0)
|
||||
{ //wrong fd
|
||||
cmd_res_fail();
|
||||
logerr("CMD_BIND: Wrong socket descriptor, id=%i.",fd);
|
||||
}
|
||||
else
|
||||
{ //correct fd
|
||||
loc_addr.sin_family = AF_INET; //fix in proto?
|
||||
loc_addr.sin_addr.S_un.S_addr=htonl(params[1] | (params[2]<<8) | (params[3]<<16) | (params[4]<<24));
|
||||
loc_addr.sin_port=htons(params[5] | (params[6]<<8));
|
||||
if(bind(sockets[fd], (struct sockaddr *)&loc_addr, sizeof(loc_addr)) == 0)
|
||||
{ //bind ok
|
||||
cmd_res_ok();
|
||||
log_("Socket id=%i binded to %u.%u.%u.%u:%u.",fd,params[1],params[2],params[3],params[4], params[5] | (params[6]<<8));
|
||||
}
|
||||
else
|
||||
{ //bind error
|
||||
cmd_res_fail();
|
||||
logerr("bind() error.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void cmd_connect(void)
|
||||
{
|
||||
unsigned char params[10];
|
||||
unsigned char fd;
|
||||
struct sockaddr_in rm_addr;
|
||||
|
||||
//get params
|
||||
uart_read(params,7);
|
||||
fd=params[0];
|
||||
if(fd>=SOCKET_MAX || sockets[fd]==0)
|
||||
{ //wrong fd
|
||||
cmd_res_fail();
|
||||
logerr("CMD_CONNECT: Wrong socket descriptor, id=%i.",fd);
|
||||
}
|
||||
else
|
||||
{ //correct fd
|
||||
rm_addr.sin_family = AF_INET; //fix in proto?
|
||||
rm_addr.sin_addr.S_un.S_addr=htonl(params[4] | (params[3]<<8) | (params[2]<<16) | (params[1]<<24));
|
||||
rm_addr.sin_port=htons(params[5] | (params[6]<<8));
|
||||
if(connect(sockets[fd], (struct sockaddr *)&rm_addr, sizeof(rm_addr)) == 0)
|
||||
{ //connect ok
|
||||
cmd_res_ok();
|
||||
log_("Socket id=%i connected to %u.%u.%u.%u:%u.",fd,params[1],params[2],params[3],params[4], params[5] | (params[6]<<8));
|
||||
}
|
||||
else
|
||||
{ //connect error
|
||||
cmd_res_fail();
|
||||
logerr("connect() error.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void cmd_listen(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void cmd_accept(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void cmd_close(void)
|
||||
{
|
||||
unsigned char fd;
|
||||
|
||||
//get params
|
||||
uart_read(&fd,1);
|
||||
if(fd>=SOCKET_MAX || sockets[fd]==0)
|
||||
{ //wrong fd
|
||||
cmd_res_fail();
|
||||
logerr("CMD_CLOSE: Wrong socket descriptor, id=%i.",fd);
|
||||
}
|
||||
else
|
||||
{ //correct fd
|
||||
closesocket(sockets[fd]);
|
||||
sockets[fd]=0;
|
||||
cmd_res_ok();
|
||||
log_("Close socket, id=%i.",fd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void cmd_select(void)
|
||||
{
|
||||
unsigned char params[MAX_SELECT],tlen[3];
|
||||
fd_set fdrd;
|
||||
fd_set fdwr;
|
||||
fd_set fdexc;
|
||||
struct timeval tout={0,0};
|
||||
int n,nr,nw,ne,i,p;
|
||||
|
||||
//get nums & timeout
|
||||
uart_read(params,3);
|
||||
nr=params[0];
|
||||
nw=params[1];
|
||||
ne=params[2];
|
||||
n=nr+ne+nw;
|
||||
|
||||
if(n>MAX_SELECT || nr>MAX_SELECT || nw>MAX_SELECT || ne>MAX_SELECT)
|
||||
{ //too much sockets! error...
|
||||
while(n>0)
|
||||
{
|
||||
nr=(n>MAX_SELECT) ? MAX_SELECT : n;
|
||||
uart_read(params,nr);
|
||||
n-=nr;
|
||||
}
|
||||
cmd_res_fail();
|
||||
logerr("CMD_SELECT: Too much sockets.");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{ //ok, get fds
|
||||
uart_read(params,n);
|
||||
FD_ZERO(&fdrd);
|
||||
FD_ZERO(&fdwr);
|
||||
FD_ZERO(&fdexc);
|
||||
|
||||
//fill fd_set
|
||||
if(nr)
|
||||
{
|
||||
for(i=0;i<nr;++i)
|
||||
{
|
||||
if(sockets[params[i]]==0)
|
||||
{
|
||||
cmd_res_fail();
|
||||
logerr("CMD_SELECT: Wrong socket.");
|
||||
return;
|
||||
}
|
||||
FD_SET(sockets[params[i]], &fdrd);
|
||||
}
|
||||
}
|
||||
|
||||
if(nw)
|
||||
{
|
||||
for(i=0;i<nw;++i)
|
||||
{
|
||||
if(sockets[params[i+nr]]==0)
|
||||
{
|
||||
cmd_res_fail();
|
||||
logerr("CMD_SELECT: Wrong socket.");
|
||||
return;
|
||||
}
|
||||
FD_SET(sockets[params[i+nr]], &fdwr);
|
||||
}
|
||||
}
|
||||
|
||||
if(ne)
|
||||
{
|
||||
for(i=0;i<ne;++i)
|
||||
{
|
||||
if(sockets[params[i+nr+nw]]==0)
|
||||
{
|
||||
cmd_res_fail();
|
||||
logerr("CMD_SELECT: Wrong socket.");
|
||||
return;
|
||||
}
|
||||
FD_SET(sockets[params[i+nr+nw]], &fdexc);
|
||||
}
|
||||
}
|
||||
|
||||
n=select(FD_SETSIZE, &fdrd, &fdwr, &fdexc, &tout);
|
||||
|
||||
if(n==0)
|
||||
{ //no data on any socket
|
||||
params[0]=IC_CMD_RES_OK;
|
||||
params[1]=0;
|
||||
params[2]=0;
|
||||
params[3]=0;
|
||||
uart_write(params,4);
|
||||
log_("CMD_SELECT: No data.");
|
||||
}
|
||||
else if(n==SOCKET_ERROR)
|
||||
{ //socket error?????
|
||||
cmd_res_fail();
|
||||
logerr("CMD_SELECT: socket error (closed?).");
|
||||
}
|
||||
else
|
||||
{ //some sockets signalled
|
||||
//check all
|
||||
p=0;
|
||||
for(n=0,i=0;i<nr;++i)
|
||||
if(FD_ISSET(sockets[params[i]], &fdrd))
|
||||
params[p++]=params[i];
|
||||
tlen[0]=n;
|
||||
|
||||
for(n=0,i=0;i<nw;++i)
|
||||
if(FD_ISSET(sockets[params[i+nr]], &fdrd))
|
||||
params[p++]=params[i+nr];
|
||||
tlen[1]=n;
|
||||
|
||||
for(n=0,i=0;i<nr;++i)
|
||||
if(FD_ISSET(sockets[params[i]], &fdrd))
|
||||
params[p++]=params[i];
|
||||
tlen[2]=n;
|
||||
|
||||
uart_write(tlen,3);
|
||||
if(p) uart_write(params,p);
|
||||
log_("CMD_SELECT: %i sockets signalled.",p);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cmd_gethostbyname(void)
|
||||
{
|
||||
struct hostent *remoteHost;
|
||||
unsigned char params[10];
|
||||
unsigned char *buf;
|
||||
unsigned short len,sent;
|
||||
|
||||
//get params
|
||||
uart_read(params,2);
|
||||
len=params[0] + 256*params[1];
|
||||
buf=(unsigned char*)malloc(len+1);
|
||||
|
||||
if(buf)
|
||||
{ //mem ok
|
||||
uart_read(buf,len);
|
||||
buf[len]=0;
|
||||
remoteHost = gethostbyname(buf);
|
||||
if(remoteHost==NULL)
|
||||
{
|
||||
cmd_res_fail();
|
||||
logerr("CMD_GETHOSTBYNAME: gethostbyname(%s) failed.",buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd_res_ok();
|
||||
memcpy(params,remoteHost->h_addr_list[0],4);
|
||||
uart_write(params,4);
|
||||
log_("CMD_GETHOSTBYNAME: %s resolved to %d.%d.%d.%d.",buf,
|
||||
params[0],params[1],params[2],params[3]);
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd_res_fail();
|
||||
logerr("CMD_GETHOSTBYNAME: malloc() failed.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void cmd_gethostbyaddr(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cmd_send(void)
|
||||
{
|
||||
unsigned char params[10];
|
||||
unsigned char fd;
|
||||
unsigned char *buf;
|
||||
unsigned short len,sent;
|
||||
|
||||
//get params
|
||||
uart_read(params,4);
|
||||
fd=params[0];
|
||||
if(fd>=SOCKET_MAX || sockets[fd]==0)
|
||||
{ //wrong fd
|
||||
cmd_res_fail();
|
||||
logerr("CMD_SEND: Wrong socket descriptor, id=%i.",fd);
|
||||
}
|
||||
else
|
||||
{ //correct fd
|
||||
len=params[1] + 256*params[2];
|
||||
buf=(unsigned char*)malloc(len);
|
||||
|
||||
if(buf)
|
||||
{ //mem ok
|
||||
cmd_res_ok();
|
||||
//get data and send it to real socket
|
||||
uart_read(buf,len);
|
||||
sent=send(sockets[fd],buf,len,0);
|
||||
//report real sent/error
|
||||
params[0]=sent & 0xff; params[1]=(sent>>8) & 0xff;
|
||||
uart_write(params,2);
|
||||
|
||||
free(buf);
|
||||
log_("Socket id=%i send %u bytes.",fd,len);
|
||||
}
|
||||
else
|
||||
{ //no mem
|
||||
cmd_res_fail();
|
||||
logerr("CMD_SEND: no memory.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void cmd_recv(void)
|
||||
{
|
||||
unsigned char params[10];
|
||||
unsigned char fd;
|
||||
unsigned char *buf;
|
||||
unsigned short len,reallen;
|
||||
fd_set fdset;
|
||||
struct timeval tout={0,0};
|
||||
int n;
|
||||
|
||||
//get params
|
||||
uart_read(params,4);
|
||||
fd=params[0];
|
||||
if(fd>=SOCKET_MAX || sockets[fd]==0)
|
||||
{ //wrong fd
|
||||
cmd_res_fail();
|
||||
logerr("CMD_RECV: Wrong socket descriptor, id=%i.",fd);
|
||||
}
|
||||
else
|
||||
{ //correct fd
|
||||
len=params[1] + 256*params[2];
|
||||
buf=(unsigned char*)malloc(len+3);
|
||||
|
||||
if(buf)
|
||||
{ //mem ok
|
||||
FD_ZERO(&fdset); FD_SET(sockets[fd], &fdset);
|
||||
n=select(FD_SETSIZE, &fdset, NULL, NULL, &tout);
|
||||
|
||||
if(n==0)
|
||||
{ //timeout, no data, socket ok
|
||||
buf[0]=IC_CMD_RES_OK;
|
||||
buf[1]=0;
|
||||
buf[2]=0;
|
||||
uart_write(buf,3);
|
||||
log_("Socket id=%i recv 0 bytes.",fd);
|
||||
}
|
||||
else if(n==SOCKET_ERROR)
|
||||
{ //socket error
|
||||
cmd_res_fail();
|
||||
logerr("CMD_RECV: socket error (closed?), id=%i.",fd);
|
||||
}
|
||||
else
|
||||
{ //data present, read
|
||||
reallen=recv(sockets[fd],buf+3,len,0);
|
||||
if(reallen==0)
|
||||
{ //socket closed
|
||||
cmd_res_fail();
|
||||
log_("CMD_RECV: socket closed, id=%i.",fd);
|
||||
}
|
||||
else
|
||||
{
|
||||
//report real sent/error
|
||||
buf[0]=IC_CMD_RES_OK;
|
||||
buf[1]=reallen & 0xff; buf[2]=(reallen>>8) & 0xff;
|
||||
uart_write(buf,reallen+3);
|
||||
log_("Socket id=%i recv %u bytes.",fd,reallen);
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
else
|
||||
{ //no mem
|
||||
cmd_res_fail();
|
||||
logerr("CMD_RECV: no memory, id=%i.",fd);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void cmd_sendto(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void cmd_recvfrom(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
|
||||
#define SOCKET_MAX 20 //max sockets
|
||||
#define MAX_SELECT 20 //max total sockets for select
|
||||
|
||||
int init(char *comport);
|
||||
void process(void);
|
||||
|
||||
|
||||
void cmd_socket(void);
|
||||
void cmd_bind(void);
|
||||
void cmd_connect(void);
|
||||
void cmd_listen(void);
|
||||
void cmd_accept(void);
|
||||
void cmd_close(void);
|
||||
void cmd_select(void);
|
||||
|
||||
void cmd_gethostbyname(void);
|
||||
void cmd_gethostbyaddr(void);
|
||||
|
||||
void cmd_send(void);
|
||||
void cmd_recv(void);
|
||||
void cmd_sendto(void);
|
||||
void cmd_recvfrom(void);
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
|
||||
#define IC_CMD_SOCKET 0x01
|
||||
#define IC_CMD_BIND 0x02
|
||||
#define IC_CMD_CONNECT 0x03
|
||||
#define IC_CMD_LISTEN 0x04
|
||||
#define IC_CMD_ACCEPT 0x05
|
||||
#define IC_CMD_CLOSE 0x06
|
||||
#define IC_CMD_SELECT 0x07
|
||||
|
||||
#define IC_CMD_GETHOSTBYNAME 0X20
|
||||
#define IC_CMD_GETHOSTBYADDR 0X21
|
||||
|
||||
#define IC_CMD_SEND 0x10
|
||||
#define IC_CMD_RECV 0x11
|
||||
#define IC_CMD_SENDTO 0x18
|
||||
#define IC_CMD_RECVFROM 0x19
|
||||
|
||||
#define IC_CMD_RES_OK 0x00
|
||||
#define IC_CMD_RES_FAIL 0xff
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ic_comm.h"
|
||||
#include "ic_cmds.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if(argc<2)
|
||||
{
|
||||
log_("Usage: ic_emul.exe COMx");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(init(argv[1]) < 0)
|
||||
{
|
||||
logerr("Init error.");
|
||||
return -2;
|
||||
}
|
||||
|
||||
printf("ZX-Spectrum Internet Controller Emulator v0.1\n");
|
||||
process();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
void log_(const char *fmt, ...)
|
||||
{
|
||||
#if 1
|
||||
va_list ap;
|
||||
char *msg=(char*)malloc(1024);
|
||||
|
||||
if(msg)
|
||||
{
|
||||
va_start(ap, fmt);
|
||||
vsprintf(msg, fmt, ap);
|
||||
printf("Log: %s\n",msg);
|
||||
va_end(ap);
|
||||
free(msg);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
void logerr(const char *fmt, ...)
|
||||
{
|
||||
#if 1
|
||||
va_list ap;
|
||||
char *msg=(char*)malloc(1024);
|
||||
|
||||
if(msg)
|
||||
{
|
||||
va_start(ap, fmt);
|
||||
vsprintf(msg, fmt, ap);
|
||||
printf("Error: %s\n",msg);
|
||||
va_end(ap);
|
||||
free(msg);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
|
||||
void log_(const char *fmt, ...);
|
||||
void logerr(const char *fmt, ...);
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
@echo off
|
||||
|
||||
set TOOLS_PATH=...
|
||||
|
||||
set GCC_PATH=%TOOLS_PATH%\mingw\bin;%TOOLS_PATH%\mingw\msys\1.0\bin
|
||||
set PATH=%GCC_PATH%;%PATH%
|
||||
|
||||
gcc -c ic_main.c -o ic_main.o
|
||||
gcc -c ic_cmds.c -o ic_cmds.o
|
||||
gcc -c log.c -o log.o
|
||||
gcc -c uart.c -o uart.o
|
||||
gcc ic_main.o ic_cmds.o log.o uart.o -lws2_32 -o ic.exe
|
||||
@@ -0,0 +1,162 @@
|
||||
|
||||
|
||||
|
||||
|
||||
socket
|
||||
> byte #01
|
||||
byte address_family
|
||||
byte type
|
||||
byte protocol
|
||||
< byte res (0=ok)
|
||||
<? byte fd
|
||||
|
||||
bind
|
||||
> byte #02
|
||||
byte fd
|
||||
long my_addr
|
||||
word port
|
||||
< byte res (0=ok)
|
||||
|
||||
connect
|
||||
> byte #03
|
||||
byte fd
|
||||
long serv_addr
|
||||
word port
|
||||
< byte res (0=ok)
|
||||
|
||||
|
||||
listen
|
||||
> byte #04
|
||||
byte fd
|
||||
< byte res (0=ok)?
|
||||
|
||||
|
||||
accept
|
||||
> byte #05
|
||||
byte fd
|
||||
< byte res (0=ok)
|
||||
<???
|
||||
|
||||
|
||||
close
|
||||
> byte #06
|
||||
byte fd
|
||||
< byte res (0=ok)
|
||||
|
||||
|
||||
select
|
||||
> byte #07
|
||||
byte fd_read_cnt
|
||||
byte fd_write_cnt
|
||||
byte fd_except_cnt
|
||||
byte fd_read[fd_read_cnt]
|
||||
byte fd_write[fd_write_cnt]
|
||||
byte fd_exc[fd_exc_cnt]
|
||||
< byte res (0=ok)
|
||||
<? byte fd_read_sig
|
||||
<? byte fd_write_sig
|
||||
<? byte fd_except_sig
|
||||
<?? byte fd_read[fd_read_sig]
|
||||
<?? byte fd_write[fd_write_sig]
|
||||
<?? byte fd_exc[fd_exc_sig]
|
||||
|
||||
|
||||
|
||||
gethostbyname
|
||||
> byte #20
|
||||
> word name_len
|
||||
> ascii hostname
|
||||
< byte res (0=ok)
|
||||
<? long ip
|
||||
|
||||
gethostbyaddr
|
||||
> byte #21
|
||||
long addr
|
||||
byte type
|
||||
< byte res (0=ok)
|
||||
<???
|
||||
|
||||
|
||||
|
||||
|
||||
send
|
||||
> byte #10
|
||||
byte fd
|
||||
word buflen
|
||||
byte flags
|
||||
< byte res (0=ok)
|
||||
>? byte buf[buflen]
|
||||
<? word realsent (#ffff = error)
|
||||
|
||||
|
||||
|
||||
recv
|
||||
> byte #11
|
||||
byte fd
|
||||
word len
|
||||
byte flags
|
||||
< byte res (0=ok)
|
||||
>? word reallen
|
||||
>?? byte buf[reallen]
|
||||
|
||||
sendto
|
||||
> byte #18
|
||||
byte fd
|
||||
word len
|
||||
int flags
|
||||
long to
|
||||
< byte res (0=ok)
|
||||
>? byte buf[len]
|
||||
<? word realsent
|
||||
|
||||
recvfrom
|
||||
> byte #19
|
||||
byte fd
|
||||
word len
|
||||
< byte res (0=ok)
|
||||
>? word reallen
|
||||
>? byte buf[reallen]
|
||||
|
||||
|
||||
|
||||
|
||||
if_list
|
||||
|
||||
if_config
|
||||
|
||||
proxy_config
|
||||
|
||||
soft_reset
|
||||
|
||||
stats
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Types
|
||||
*/
|
||||
#define SOCK_STREAM 1 /* stream socket */
|
||||
#define SOCK_DGRAM 2 /* datagram socket */
|
||||
#define SOCK_RAW 3 /* raw-protocol interface */
|
||||
|
||||
|
||||
/*
|
||||
* Address families.
|
||||
*/
|
||||
#define AF_UNSPEC 0 /* unspecified */
|
||||
#define AF_INET 2 /* internetwork: UDP, TCP, etc. */
|
||||
#define AF_INET6 23 /* Internetwork Version 6 */
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
#include <windows.h>
|
||||
|
||||
HANDLE port;
|
||||
DCB dcb;
|
||||
COMMTIMEOUTS touts;
|
||||
|
||||
|
||||
|
||||
//init uart
|
||||
int uart_init(char *comport)
|
||||
{
|
||||
port = CreateFile(comport, GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (port==INVALID_HANDLE_VALUE) return -1;
|
||||
|
||||
if (GetCommState(port, &dcb))
|
||||
{
|
||||
dcb.BaudRate = CBR_115200;
|
||||
dcb.ByteSize = 8; dcb.Parity = 0; dcb.StopBits = 0;
|
||||
dcb.fAbortOnError = 0;
|
||||
SetCommState(port, &dcb);
|
||||
}
|
||||
|
||||
if (GetCommTimeouts(port, &touts))
|
||||
{
|
||||
touts.ReadIntervalTimeout = MAXDWORD;
|
||||
touts.ReadTotalTimeoutMultiplier = MAXDWORD;
|
||||
touts.ReadTotalTimeoutConstant = MAXDWORD;
|
||||
touts.WriteTotalTimeoutMultiplier = MAXDWORD;
|
||||
touts.WriteTotalTimeoutConstant = MAXDWORD;
|
||||
|
||||
SetCommTimeouts(port, &touts);
|
||||
}
|
||||
|
||||
// PurgeComm(port, PURGE_RXCLEAR+PURGE_TXCLEAR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//read byte (can use int)
|
||||
void uart_read(char *buf, int len)
|
||||
{
|
||||
unsigned long nread=0,s;
|
||||
|
||||
for(s=0; s<len;)
|
||||
{
|
||||
ReadFile(port, &buf[s], len, &nread, NULL);
|
||||
s+=nread;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//write byte 2 usart
|
||||
void uart_write(char *buf, int len)
|
||||
{
|
||||
unsigned long nread=0;
|
||||
|
||||
WriteFile(port, buf, len, &nread, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
|
||||
int uart_init(char *comport);
|
||||
void uart_read(char *buf, int len);
|
||||
void uart_write(char *buf, int len);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
ic.exe com5
|
||||
Binary file not shown.
@@ -0,0 +1,578 @@
|
||||
#ifdef __WIN32
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "ic_comm.h"
|
||||
#include "ic_cmds.h"
|
||||
#include "uart.h"
|
||||
#include "log.h"
|
||||
|
||||
#ifdef __WIN32
|
||||
//Winsock shit
|
||||
WORD wVersionRequested;
|
||||
WSADATA wsaData;
|
||||
#else
|
||||
typedef int SOCKET;
|
||||
#define INVALID_SOCKET -1
|
||||
#define SOCKET_ERROR -1
|
||||
#define closesocket close
|
||||
#endif
|
||||
|
||||
//vars
|
||||
SOCKET sockets[SOCKET_MAX];
|
||||
|
||||
|
||||
|
||||
//Init
|
||||
int init(char *sname, int baud)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<SOCKET_MAX; ++i)
|
||||
sockets[i]=0;
|
||||
|
||||
if(uart_init(sname, baud) < 0) return -1;
|
||||
|
||||
#ifdef __WIN32
|
||||
//Init winsock
|
||||
wVersionRequested = MAKEWORD(2,2);
|
||||
WSAStartup(wVersionRequested, &wsaData);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Process
|
||||
void process(void)
|
||||
{
|
||||
unsigned char cmd;
|
||||
|
||||
while(1)
|
||||
{
|
||||
//read command
|
||||
uart_read(&cmd,1);
|
||||
|
||||
switch(cmd)
|
||||
{
|
||||
case IC_CMD_NOP: cmd_nop(); break;
|
||||
case IC_CMD_SOCKET: cmd_socket(); break;
|
||||
case IC_CMD_BIND: cmd_bind(); break;
|
||||
case IC_CMD_CONNECT: cmd_connect(); break;
|
||||
case IC_CMD_LISTEN: cmd_listen(); break;
|
||||
case IC_CMD_ACCEPT: cmd_accept(); break;
|
||||
case IC_CMD_CLOSE: cmd_close(); break;
|
||||
case IC_CMD_SELECT: cmd_select(); break;
|
||||
|
||||
case IC_CMD_GETHOSTBYNAME: cmd_gethostbyname(); break;
|
||||
case IC_CMD_GETHOSTBYADDR: cmd_gethostbyaddr(); break;
|
||||
|
||||
case IC_CMD_SEND: cmd_send(); break;
|
||||
case IC_CMD_RECV: cmd_recv(); break;
|
||||
case IC_CMD_SENDTO: cmd_sendto(); break;
|
||||
case IC_CMD_RECVFROM: cmd_recvfrom(); break;
|
||||
|
||||
default:
|
||||
logerr("Wrong command #%02x!",cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cmd_res_fail(void)
|
||||
{
|
||||
unsigned char t=IC_CMD_RES_FAIL;
|
||||
uart_write(&t,1);
|
||||
}
|
||||
|
||||
void cmd_res_ok(void)
|
||||
{
|
||||
unsigned char t=IC_CMD_RES_OK;
|
||||
uart_write(&t,1);
|
||||
}
|
||||
|
||||
|
||||
//silently reply \0 for (re)sync purposes
|
||||
void cmd_nop(void)
|
||||
{
|
||||
unsigned char p=0;
|
||||
uart_write(&p,1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void cmd_socket(void)
|
||||
{
|
||||
unsigned char params[10];
|
||||
SOCKET tsock;
|
||||
int i;
|
||||
|
||||
//get params
|
||||
uart_read(params,3);
|
||||
//find free socket
|
||||
for(i=0; i<SOCKET_MAX; ++i)
|
||||
if(sockets[i]==0) break;
|
||||
|
||||
if(i==SOCKET_MAX)
|
||||
{ //not found, result=fail
|
||||
cmd_res_fail();
|
||||
logerr("CMD_SOCKET: No free sockets.");
|
||||
}
|
||||
else
|
||||
{ //found, create real socket
|
||||
tsock=socket((int)params[0],(int)params[1],(int)params[2]);
|
||||
|
||||
if(tsock==INVALID_SOCKET)
|
||||
{ //socket() fail
|
||||
cmd_res_fail();
|
||||
logerr("socket() failed.");
|
||||
}
|
||||
else
|
||||
{ //socket created
|
||||
sockets[i]=tsock;
|
||||
params[0]=IC_CMD_RES_OK; //res=ok
|
||||
params[1]=i; //fd
|
||||
uart_write(params,2);
|
||||
log_("Socket created, id=%i.",i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cmd_bind(void)
|
||||
{
|
||||
unsigned char params[10];
|
||||
unsigned char fd;
|
||||
struct sockaddr_in loc_addr;
|
||||
|
||||
//get params
|
||||
uart_read(params,7);
|
||||
fd=params[0];
|
||||
if(fd>=SOCKET_MAX || sockets[fd]==0)
|
||||
{ //wrong fd
|
||||
cmd_res_fail();
|
||||
logerr("CMD_BIND: Wrong socket descriptor, id=%i.",fd);
|
||||
}
|
||||
else
|
||||
{ //correct fd
|
||||
loc_addr.sin_family = AF_INET; //fix in proto?
|
||||
#ifdef __WIN32
|
||||
loc_addr.sin_addr.S_un.S_addr=htonl(params[1] | (params[2]<<8) | (params[3]<<16) | (params[4]<<24));
|
||||
#else
|
||||
loc_addr.sin_addr.s_addr=htonl(params[1] | (params[2]<<8) | (params[3]<<16) | (params[4]<<24));
|
||||
#endif
|
||||
loc_addr.sin_port=htons(params[5] | (params[6]<<8));
|
||||
if(bind(sockets[fd], (struct sockaddr *)&loc_addr, sizeof(loc_addr)) == 0)
|
||||
{ //bind ok
|
||||
cmd_res_ok();
|
||||
log_("Socket id=%i binded to %u.%u.%u.%u:%u.",fd,params[1],params[2],params[3],params[4], params[5] | (params[6]<<8));
|
||||
}
|
||||
else
|
||||
{ //bind error
|
||||
cmd_res_fail();
|
||||
logerr("bind() error.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void cmd_connect(void)
|
||||
{
|
||||
unsigned char params[10];
|
||||
unsigned char fd;
|
||||
struct sockaddr_in rm_addr;
|
||||
|
||||
//get params
|
||||
uart_read(params,7);
|
||||
fd=params[0];
|
||||
if(fd>=SOCKET_MAX || sockets[fd]==0)
|
||||
{ //wrong fd
|
||||
cmd_res_fail();
|
||||
logerr("CMD_CONNECT: Wrong socket descriptor, id=%i.",fd);
|
||||
}
|
||||
else
|
||||
{ //correct fd
|
||||
rm_addr.sin_family = AF_INET; //fix in proto?
|
||||
#ifdef __WIN32
|
||||
rm_addr.sin_addr.S_un.S_addr=htonl(params[4] | (params[3]<<8) | (params[2]<<16) | (params[1]<<24));
|
||||
#else
|
||||
rm_addr.sin_addr.s_addr=(params[1] | (params[2]<<8) | (params[3]<<16) | (params[4]<<24));
|
||||
#endif
|
||||
rm_addr.sin_port=htons(params[5] | (params[6]<<8));
|
||||
if(connect(sockets[fd], (struct sockaddr *)&rm_addr, sizeof(rm_addr)) == 0)
|
||||
{ //connect ok
|
||||
cmd_res_ok();
|
||||
log_("Socket id=%i connected to %u.%u.%u.%u:%u.",fd,params[1],params[2],params[3],params[4], params[5] | (params[6]<<8));
|
||||
}
|
||||
else
|
||||
{ //connect error
|
||||
cmd_res_fail();
|
||||
logerr("connect() error.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void cmd_listen(void)
|
||||
{
|
||||
logerr("CMD_LISTEN not implemented yet.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void cmd_accept(void)
|
||||
{
|
||||
logerr("CMD_ACCEPT not implemented yet.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void cmd_close(void)
|
||||
{
|
||||
unsigned char fd;
|
||||
|
||||
//get params
|
||||
uart_read(&fd,1);
|
||||
if(fd>=SOCKET_MAX || sockets[fd]==0)
|
||||
{ //wrong fd
|
||||
cmd_res_fail();
|
||||
logerr("CMD_CLOSE: Wrong socket descriptor, id=%i.",fd);
|
||||
}
|
||||
else
|
||||
{ //correct fd
|
||||
closesocket(sockets[fd]);
|
||||
sockets[fd]=0;
|
||||
cmd_res_ok();
|
||||
log_("Close socket, id=%i.",fd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void cmd_select(void)
|
||||
{
|
||||
unsigned char params[MAX_SELECT],tlen[3];
|
||||
fd_set fdrd;
|
||||
fd_set fdwr;
|
||||
fd_set fdexc;
|
||||
struct timeval tout={0,0};
|
||||
int n,nr,nw,ne,i,p;
|
||||
|
||||
//get nums & timeout
|
||||
uart_read(params,3);
|
||||
nr=params[0];
|
||||
nw=params[1];
|
||||
ne=params[2];
|
||||
n=nr+ne+nw;
|
||||
|
||||
if(n>MAX_SELECT || nr>MAX_SELECT || nw>MAX_SELECT || ne>MAX_SELECT)
|
||||
{ //too much sockets! error...
|
||||
while(n>0)
|
||||
{
|
||||
nr=(n>MAX_SELECT) ? MAX_SELECT : n;
|
||||
uart_read(params,nr);
|
||||
n-=nr;
|
||||
}
|
||||
cmd_res_fail();
|
||||
logerr("CMD_SELECT: Too much sockets.");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{ //ok, get fds
|
||||
uart_read(params,n);
|
||||
FD_ZERO(&fdrd);
|
||||
FD_ZERO(&fdwr);
|
||||
FD_ZERO(&fdexc);
|
||||
|
||||
//fill fd_set
|
||||
if(nr)
|
||||
{
|
||||
for(i=0;i<nr;++i)
|
||||
{
|
||||
if(sockets[params[i]]==0)
|
||||
{
|
||||
cmd_res_fail();
|
||||
logerr("CMD_SELECT: Wrong socket.");
|
||||
return;
|
||||
}
|
||||
FD_SET(sockets[params[i]], &fdrd);
|
||||
}
|
||||
}
|
||||
|
||||
if(nw)
|
||||
{
|
||||
for(i=0;i<nw;++i)
|
||||
{
|
||||
if(sockets[params[i+nr]]==0)
|
||||
{
|
||||
cmd_res_fail();
|
||||
logerr("CMD_SELECT: Wrong socket.");
|
||||
return;
|
||||
}
|
||||
FD_SET(sockets[params[i+nr]], &fdwr);
|
||||
}
|
||||
}
|
||||
|
||||
if(ne)
|
||||
{
|
||||
for(i=0;i<ne;++i)
|
||||
{
|
||||
if(sockets[params[i+nr+nw]]==0)
|
||||
{
|
||||
cmd_res_fail();
|
||||
logerr("CMD_SELECT: Wrong socket.");
|
||||
return;
|
||||
}
|
||||
FD_SET(sockets[params[i+nr+nw]], &fdexc);
|
||||
}
|
||||
}
|
||||
|
||||
n=select(FD_SETSIZE, &fdrd, &fdwr, &fdexc, &tout);
|
||||
|
||||
if(n==0)
|
||||
{ //no data on any socket
|
||||
params[0]=IC_CMD_RES_OK;
|
||||
params[1]=0;
|
||||
params[2]=0;
|
||||
params[3]=0;
|
||||
uart_write(params,4);
|
||||
log_("CMD_SELECT: No data.");
|
||||
}
|
||||
else if(n==SOCKET_ERROR)
|
||||
{ //socket error?????
|
||||
cmd_res_fail();
|
||||
logerr("CMD_SELECT: socket error (closed?).");
|
||||
}
|
||||
else
|
||||
{ //some sockets signalled
|
||||
//check all
|
||||
p=0;
|
||||
for(n=0,i=0;i<nr;++i)
|
||||
if(FD_ISSET(sockets[params[i]], &fdrd))
|
||||
params[p++]=params[i];
|
||||
tlen[0]=n;
|
||||
|
||||
for(n=0,i=0;i<nw;++i)
|
||||
if(FD_ISSET(sockets[params[i+nr]], &fdrd))
|
||||
params[p++]=params[i+nr];
|
||||
tlen[1]=n;
|
||||
|
||||
for(n=0,i=0;i<nr;++i)
|
||||
if(FD_ISSET(sockets[params[i]], &fdrd))
|
||||
params[p++]=params[i];
|
||||
tlen[2]=n;
|
||||
|
||||
uart_write(tlen,3);
|
||||
if(p) uart_write(params,p);
|
||||
log_("CMD_SELECT: %i sockets signalled.",p);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cmd_gethostbyname(void)
|
||||
{
|
||||
struct hostent *remoteHost;
|
||||
unsigned char params[10];
|
||||
unsigned char *buf;
|
||||
unsigned short len;
|
||||
|
||||
//get params
|
||||
uart_read(params,2);
|
||||
len=params[0] + 256*params[1];
|
||||
buf=(unsigned char*)malloc(len+1);
|
||||
|
||||
if(buf)
|
||||
{ //mem ok
|
||||
uart_read(buf,len);
|
||||
buf[len]=0;
|
||||
remoteHost = gethostbyname(buf);
|
||||
if(remoteHost==NULL)
|
||||
{
|
||||
cmd_res_fail();
|
||||
logerr("CMD_GETHOSTBYNAME: gethostbyname(%s) failed.",buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd_res_ok();
|
||||
memcpy(params,remoteHost->h_addr_list[0],4);
|
||||
uart_write(params,4);
|
||||
log_("Host %s resolved to %d.%d.%d.%d.",buf,
|
||||
params[0],params[1],params[2],params[3]);
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd_res_fail();
|
||||
logerr("CMD_GETHOSTBYNAME: malloc() failed.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void cmd_gethostbyaddr(void)
|
||||
{
|
||||
logerr("CMD_GETHOSTBYADDR not implemented yet.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cmd_send(void)
|
||||
{
|
||||
unsigned char params[10];
|
||||
unsigned char fd;
|
||||
unsigned char *buf;
|
||||
unsigned short len,sent;
|
||||
|
||||
//get params
|
||||
uart_read(params,4);
|
||||
fd=params[0];
|
||||
if(fd>=SOCKET_MAX || sockets[fd]==0)
|
||||
{ //wrong fd
|
||||
cmd_res_fail();
|
||||
logerr("CMD_SEND: Wrong socket descriptor, id=%i.",fd);
|
||||
}
|
||||
else
|
||||
{ //correct fd
|
||||
len=params[1] + 256*params[2];
|
||||
buf=(unsigned char*)malloc(len);
|
||||
|
||||
if(buf)
|
||||
{ //mem ok
|
||||
cmd_res_ok();
|
||||
//get data and send it to real socket
|
||||
uart_read(buf,len);
|
||||
sent=send(sockets[fd],buf,len,0);
|
||||
//report real sent/error
|
||||
params[0]=sent & 0xff; params[1]=(sent>>8) & 0xff;
|
||||
uart_write(params,2);
|
||||
|
||||
free(buf);
|
||||
log_("Socket id=%i send %u bytes.",fd,len);
|
||||
}
|
||||
else
|
||||
{ //no mem
|
||||
cmd_res_fail();
|
||||
logerr("CMD_SEND: no memory.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void cmd_recv(void)
|
||||
{
|
||||
unsigned char params[10];
|
||||
unsigned char fd;
|
||||
unsigned char *buf;
|
||||
unsigned short len,reallen;
|
||||
fd_set fdset;
|
||||
struct timeval tout={0,0};
|
||||
int n;
|
||||
|
||||
//get params
|
||||
uart_read(params,4);
|
||||
fd=params[0];
|
||||
if(fd>=SOCKET_MAX || sockets[fd]==0)
|
||||
{ //wrong fd
|
||||
cmd_res_fail();
|
||||
logerr("CMD_RECV: Wrong socket descriptor, id=%i.",fd);
|
||||
}
|
||||
else
|
||||
{ //correct fd
|
||||
len=params[1] + 256*params[2];
|
||||
buf=(unsigned char*)malloc(len+3);
|
||||
|
||||
if(buf)
|
||||
{ //mem ok
|
||||
FD_ZERO(&fdset); FD_SET(sockets[fd], &fdset);
|
||||
n=select(FD_SETSIZE, &fdset, NULL, NULL, &tout);
|
||||
|
||||
if(n==0)
|
||||
{ //timeout, no data, socket ok
|
||||
buf[0]=IC_CMD_RES_OK;
|
||||
buf[1]=0;
|
||||
buf[2]=0;
|
||||
uart_write(buf,3);
|
||||
log_("Socket id=%i recv 0 bytes.",fd);
|
||||
}
|
||||
else if(n==SOCKET_ERROR)
|
||||
{ //socket error
|
||||
cmd_res_fail();
|
||||
logerr("CMD_RECV: socket error (closed?), id=%i.",fd);
|
||||
}
|
||||
else
|
||||
{ //data present, read
|
||||
reallen=recv(sockets[fd],buf+3,len,0);
|
||||
if(reallen==0)
|
||||
{ //socket closed
|
||||
cmd_res_fail();
|
||||
log_("CMD_RECV: socket closed, id=%i.",fd);
|
||||
}
|
||||
else
|
||||
{
|
||||
//report real sent/error
|
||||
buf[0]=IC_CMD_RES_OK;
|
||||
buf[1]=reallen & 0xff; buf[2]=(reallen>>8) & 0xff;
|
||||
uart_write(buf,reallen+3);
|
||||
log_("Socket id=%i recv %u bytes.",fd,reallen);
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
else
|
||||
{ //no mem
|
||||
cmd_res_fail();
|
||||
logerr("CMD_RECV: no memory, id=%i.",fd);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void cmd_sendto(void)
|
||||
{
|
||||
logerr("CMD_SENDTO not implemented yet.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void cmd_recvfrom(void)
|
||||
{
|
||||
logerr("CMD_RECVFROM not implemented yet.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
|
||||
#define SOCKET_MAX 20 //max sockets
|
||||
#define MAX_SELECT 20 //max total sockets for select
|
||||
|
||||
int init(char *sname, int baud);
|
||||
void process(void);
|
||||
|
||||
|
||||
void cmd_nop(void);
|
||||
void cmd_socket(void);
|
||||
void cmd_bind(void);
|
||||
void cmd_connect(void);
|
||||
void cmd_listen(void);
|
||||
void cmd_accept(void);
|
||||
void cmd_close(void);
|
||||
void cmd_select(void);
|
||||
|
||||
void cmd_gethostbyname(void);
|
||||
void cmd_gethostbyaddr(void);
|
||||
|
||||
void cmd_send(void);
|
||||
void cmd_recv(void);
|
||||
void cmd_sendto(void);
|
||||
void cmd_recvfrom(void);
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
|
||||
#define IC_CMD_NOP 0x00
|
||||
#define IC_CMD_SOCKET 0x01
|
||||
#define IC_CMD_BIND 0x02
|
||||
#define IC_CMD_CONNECT 0x03
|
||||
#define IC_CMD_LISTEN 0x04
|
||||
#define IC_CMD_ACCEPT 0x05
|
||||
#define IC_CMD_CLOSE 0x06
|
||||
#define IC_CMD_SELECT 0x07
|
||||
|
||||
#define IC_CMD_GETHOSTBYNAME 0X20
|
||||
#define IC_CMD_GETHOSTBYADDR 0X21
|
||||
|
||||
#define IC_CMD_SEND 0x10
|
||||
#define IC_CMD_RECV 0x11
|
||||
#define IC_CMD_SENDTO 0x18
|
||||
#define IC_CMD_RECVFROM 0x19
|
||||
|
||||
#define IC_CMD_RES_OK 0x00
|
||||
#define IC_CMD_RES_FAIL 0xff
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ic_comm.h"
|
||||
#include "ic_cmds.h"
|
||||
#include "log.h"
|
||||
|
||||
int debug=0;
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
#ifdef __WIN32
|
||||
printf("Usage: ic.exe COMx [-b baudrate] [-q] [-q]\n\n");
|
||||
#else
|
||||
printf("Usage: ic /dev/ttyUSBx [-b baudrate] [-q] [-q]\n\n");
|
||||
#endif
|
||||
printf("Supported baud rates: 115200 (default), 57600, 38400,\n");
|
||||
printf(" 19200, 9600, 4800, 2400, 1200\n");
|
||||
printf("Use single -q for quiet mode,\n");
|
||||
printf("double -q for complete silence.\n");
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *sname=NULL,*p;
|
||||
int i, baud=115200, q=0;
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
p = argv[i];
|
||||
if (*p == '-')
|
||||
{
|
||||
if (strcmp(p, "-b") == 0) baud = atoi(argv[++i]);
|
||||
else if (strcmp(p, "-q") == 0) q++;
|
||||
else if (strcmp(p, "-d") == 0) debug=1;
|
||||
}
|
||||
else if (!sname) sname = p;
|
||||
else
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(!sname)
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
loginit(q);
|
||||
|
||||
if(init(sname, baud) < 0)
|
||||
{
|
||||
logerr("Init error.");
|
||||
return -2;
|
||||
}
|
||||
|
||||
if(q<2)
|
||||
{
|
||||
printf("ZX-Spectrum Internet Controller Emulator v0.2.\n");
|
||||
printf("Serial device used: %s at %d baud.\n", sname, baud);
|
||||
}
|
||||
|
||||
process();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
int loglvl=0;
|
||||
|
||||
void loginit(int lvl)
|
||||
{
|
||||
loglvl=lvl;
|
||||
}
|
||||
|
||||
void log_(const char *fmt, ...)
|
||||
{
|
||||
if(loglvl>0)
|
||||
return;
|
||||
#if 1
|
||||
va_list ap;
|
||||
char *msg=(char*)malloc(1024);
|
||||
|
||||
if(msg)
|
||||
{
|
||||
va_start(ap, fmt);
|
||||
vsprintf(msg, fmt, ap);
|
||||
printf("Log: %s\n",msg);
|
||||
va_end(ap);
|
||||
free(msg);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
void logerr(const char *fmt, ...)
|
||||
{
|
||||
if(loglvl>1)
|
||||
return;
|
||||
#if 1
|
||||
va_list ap;
|
||||
char *msg=(char*)malloc(1024);
|
||||
|
||||
if(msg)
|
||||
{
|
||||
va_start(ap, fmt);
|
||||
vsprintf(msg, fmt, ap);
|
||||
printf("Error: %s\n",msg);
|
||||
va_end(ap);
|
||||
free(msg);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
|
||||
void loginit(int lvl);
|
||||
void log_(const char *fmt, ...);
|
||||
void logerr(const char *fmt, ...);
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
@echo off
|
||||
|
||||
set TOOLS_PATH=D:\proj\zx\floppy-disk-ripper\_tools
|
||||
|
||||
set GCC_PATH=%TOOLS_PATH%\mingw\bin;%TOOLS_PATH%\mingw\msys\1.0\bin
|
||||
set PATH=%GCC_PATH%;%PATH%
|
||||
|
||||
gcc -Wall -Wno-pointer-sign -c ic_main.c -o ic_main.o
|
||||
gcc -Wall -Wno-pointer-sign -c ic_cmds.c -o ic_cmds.o
|
||||
gcc -Wall -Wno-pointer-sign -c log.c -o log.o
|
||||
gcc -Wall -Wno-pointer-sign -c uart_win.c -o uart.o
|
||||
gcc ic_main.o ic_cmds.o log.o uart.o -lws2_32 -o ic.exe
|
||||
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
gcc -Wall -Wno-pointer-sign -c ic_main.c -o ic_main.o
|
||||
gcc -Wall -Wno-pointer-sign -c ic_cmds.c -o ic_cmds.o
|
||||
gcc -Wall -Wno-pointer-sign -c log.c -o log.o
|
||||
gcc -Wall -Wno-pointer-sign -c uart_lin.c -o uart.o
|
||||
|
||||
gcc ic_main.o ic_cmds.o log.o uart.o -o ic
|
||||
@@ -0,0 +1,162 @@
|
||||
|
||||
|
||||
|
||||
|
||||
socket
|
||||
> byte #01
|
||||
byte address_family
|
||||
byte type
|
||||
byte protocol
|
||||
< byte res (0=ok)
|
||||
<? byte fd
|
||||
|
||||
bind
|
||||
> byte #02
|
||||
byte fd
|
||||
long my_addr
|
||||
word port
|
||||
< byte res (0=ok)
|
||||
|
||||
connect
|
||||
> byte #03
|
||||
byte fd
|
||||
long serv_addr
|
||||
word port
|
||||
< byte res (0=ok)
|
||||
|
||||
|
||||
listen
|
||||
> byte #04
|
||||
byte fd
|
||||
< byte res (0=ok)?
|
||||
|
||||
|
||||
accept
|
||||
> byte #05
|
||||
byte fd
|
||||
< byte res (0=ok)
|
||||
<???
|
||||
|
||||
|
||||
close
|
||||
> byte #06
|
||||
byte fd
|
||||
< byte res (0=ok)
|
||||
|
||||
|
||||
select
|
||||
> byte #07
|
||||
byte fd_read_cnt
|
||||
byte fd_write_cnt
|
||||
byte fd_except_cnt
|
||||
byte fd_read[fd_read_cnt]
|
||||
byte fd_write[fd_write_cnt]
|
||||
byte fd_exc[fd_exc_cnt]
|
||||
< byte res (0=ok)
|
||||
<? byte fd_read_sig
|
||||
<? byte fd_write_sig
|
||||
<? byte fd_except_sig
|
||||
<?? byte fd_read[fd_read_sig]
|
||||
<?? byte fd_write[fd_write_sig]
|
||||
<?? byte fd_exc[fd_exc_sig]
|
||||
|
||||
|
||||
|
||||
gethostbyname
|
||||
> byte #20
|
||||
> word name_len
|
||||
> ascii hostname
|
||||
< byte res (0=ok)
|
||||
<? long ip
|
||||
|
||||
gethostbyaddr
|
||||
> byte #21
|
||||
long addr
|
||||
byte type
|
||||
< byte res (0=ok)
|
||||
<???
|
||||
|
||||
|
||||
|
||||
|
||||
send
|
||||
> byte #10
|
||||
byte fd
|
||||
word buflen
|
||||
byte flags
|
||||
< byte res (0=ok)
|
||||
>? byte buf[buflen]
|
||||
<? word realsent (#ffff = error)
|
||||
|
||||
|
||||
|
||||
recv
|
||||
> byte #11
|
||||
byte fd
|
||||
word len
|
||||
byte flags
|
||||
< byte res (0=ok)
|
||||
>? word reallen
|
||||
>?? byte buf[reallen]
|
||||
|
||||
sendto
|
||||
> byte #18
|
||||
byte fd
|
||||
word len
|
||||
int flags
|
||||
long to
|
||||
< byte res (0=ok)
|
||||
>? byte buf[len]
|
||||
<? word realsent
|
||||
|
||||
recvfrom
|
||||
> byte #19
|
||||
byte fd
|
||||
word len
|
||||
< byte res (0=ok)
|
||||
>? word reallen
|
||||
>? byte buf[reallen]
|
||||
|
||||
|
||||
|
||||
|
||||
if_list
|
||||
|
||||
if_config
|
||||
|
||||
proxy_config
|
||||
|
||||
soft_reset
|
||||
|
||||
stats
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Types
|
||||
*/
|
||||
#define SOCK_STREAM 1 /* stream socket */
|
||||
#define SOCK_DGRAM 2 /* datagram socket */
|
||||
#define SOCK_RAW 3 /* raw-protocol interface */
|
||||
|
||||
|
||||
/*
|
||||
* Address families.
|
||||
*/
|
||||
#define AF_UNSPEC 0 /* unspecified */
|
||||
#define AF_INET 2 /* internetwork: UDP, TCP, etc. */
|
||||
#define AF_INET6 23 /* Internetwork Version 6 */
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
|
||||
int uart_init(char *sname, int baud);
|
||||
void uart_read(char *buf, int len);
|
||||
void uart_write(char *buf, int len);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <stdio.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "uart.h"
|
||||
|
||||
#define BAUD_ERROR -1U
|
||||
int fd;
|
||||
extern int debug;
|
||||
|
||||
|
||||
static tcflag_t get_baud(int baud)
|
||||
{
|
||||
switch(baud)
|
||||
{
|
||||
case 115200: return B115200;
|
||||
case 57600: return B57600;
|
||||
case 38400: return B38400;
|
||||
case 19200: return B19200;
|
||||
case 9600: return B9600;
|
||||
case 4800: return B4800;
|
||||
case 2400: return B2400;
|
||||
case 1200: return B1200;
|
||||
default: return BAUD_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//init uart
|
||||
int uart_init(char *sname, int baud)
|
||||
{
|
||||
struct termios /*otio,*/ ntio;
|
||||
tcflag_t BAUD;
|
||||
|
||||
//check/get baud rate
|
||||
BAUD = get_baud(baud);
|
||||
if(BAUD==BAUD_ERROR) return -1;
|
||||
|
||||
//open tty
|
||||
fd = open(sname, O_RDWR | O_NOCTTY);
|
||||
if(fd<0) return -1;
|
||||
|
||||
//save current port settings
|
||||
//tcgetattr(fd,&otio);
|
||||
|
||||
//set config
|
||||
bzero(&ntio, sizeof(ntio));
|
||||
ntio.c_cflag = BAUD | //baud rate
|
||||
CS8 | //8n1
|
||||
CLOCAL | //local connection, no modem control
|
||||
CREAD; //enable receiving characters
|
||||
ntio.c_iflag = IGNPAR; //ignore bytes with parity errors
|
||||
ntio.c_oflag = 0; //raw output
|
||||
ntio.c_lflag = 0; //non-canonical input
|
||||
|
||||
ntio.c_cc[VMIN] = 1; //wait for 1 byte minimum
|
||||
|
||||
//flush and apply new settings
|
||||
tcflush(fd, TCIFLUSH);
|
||||
tcsetattr(fd,TCSANOW,&ntio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//read bytes
|
||||
void uart_read(char *buf, int len)
|
||||
{
|
||||
unsigned long s=0;
|
||||
|
||||
while(s<len)
|
||||
{
|
||||
s+=read(fd,&buf[s],len-s);
|
||||
}
|
||||
if(debug){printf("read: ");for(s=0;s<len;s++) printf("%02x ",(unsigned char)buf[s]); printf("\n");}
|
||||
}
|
||||
|
||||
//write bytes
|
||||
void uart_write(char *buf, int len)
|
||||
{
|
||||
int s;
|
||||
|
||||
if(debug){printf("write: ");for(s=0;s<len;s++) printf("%02x ",(unsigned char)buf[s]); printf("\n");}
|
||||
write(fd,buf,len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
|
||||
HANDLE port;
|
||||
DCB dcb;
|
||||
COMMTIMEOUTS touts;
|
||||
extern int debug;
|
||||
|
||||
#define BAUD_ERROR -1U
|
||||
|
||||
|
||||
static DWORD get_baud(int baud)
|
||||
{
|
||||
switch(baud)
|
||||
{
|
||||
case 115200: return CBR_115200;
|
||||
case 57600: return CBR_57600;
|
||||
case 38400: return CBR_38400;
|
||||
case 19200: return CBR_19200;
|
||||
case 9600: return CBR_9600;
|
||||
case 4800: return CBR_4800;
|
||||
case 2400: return CBR_2400;
|
||||
case 1200: return CBR_1200;
|
||||
default: return BAUD_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//init uart
|
||||
int uart_init(char *sname, int baud)
|
||||
{
|
||||
char buf[16], *p;
|
||||
DWORD CBR;
|
||||
|
||||
//fix COMx name to \\.\COMx
|
||||
if(strncasecmp(sname,"com",3)==0 && strlen(sname)<7)
|
||||
{
|
||||
sprintf(buf,"\\\\.\\%s",sname);
|
||||
p=buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
p=sname;
|
||||
}
|
||||
|
||||
//check/get baud rate
|
||||
CBR = get_baud(baud);
|
||||
if(CBR==BAUD_ERROR) return -1;
|
||||
|
||||
//open serial line
|
||||
port = CreateFile(p, GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (port==INVALID_HANDLE_VALUE) return -1;
|
||||
|
||||
//set config
|
||||
if (GetCommState(port, &dcb))
|
||||
{
|
||||
dcb.BaudRate = CBR; //CBR_57600; //CBR_115200;
|
||||
dcb.ByteSize = 8; dcb.Parity = 0; dcb.StopBits = 0;
|
||||
dcb.fAbortOnError = 0;
|
||||
SetCommState(port, &dcb);
|
||||
}
|
||||
|
||||
//set timeouts
|
||||
if (GetCommTimeouts(port, &touts))
|
||||
{
|
||||
touts.ReadIntervalTimeout = MAXDWORD;
|
||||
touts.ReadTotalTimeoutMultiplier = MAXDWORD;
|
||||
touts.ReadTotalTimeoutConstant = MAXDWORD;
|
||||
touts.WriteTotalTimeoutMultiplier = MAXDWORD;
|
||||
touts.WriteTotalTimeoutConstant = MAXDWORD;
|
||||
|
||||
SetCommTimeouts(port, &touts);
|
||||
}
|
||||
|
||||
PurgeComm(port, PURGE_RXCLEAR+PURGE_TXCLEAR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//read bytes
|
||||
void uart_read(char *buf, int len)
|
||||
{
|
||||
unsigned long nread=0,s;
|
||||
|
||||
for(s=0; s<len;)
|
||||
{
|
||||
ReadFile(port, &buf[s], len-s, &nread, NULL);
|
||||
s+=nread;
|
||||
}
|
||||
if(debug){printf("read: ");for(s=0;s<len;s++) printf("%02x ",(unsigned char)buf[s]); printf("\n");}
|
||||
}
|
||||
|
||||
|
||||
//write bytes
|
||||
void uart_write(char *buf, int len)
|
||||
{
|
||||
unsigned long nread=0,s;
|
||||
|
||||
if(debug){printf("write: ");for(s=0;s<len;s++) printf("%02x ",(unsigned char)buf[s]); printf("\n");}
|
||||
WriteFile(port, buf, len, &nread, NULL);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,332 @@
|
||||
|
||||
module sockets
|
||||
|
||||
; command codes
|
||||
|
||||
IC_CMD_SOCKET equ 0x01
|
||||
IC_CMD_BIND equ 0x02
|
||||
IC_CMD_CONNECT equ 0x03
|
||||
IC_CMD_LISTEN equ 0x04
|
||||
IC_CMD_ACCEPT equ 0x05
|
||||
IC_CMD_CLOSE equ 0x06
|
||||
|
||||
IC_CMD_GETHOSTBYNAME equ 0x20
|
||||
IC_CMD_GETHOSTBYADDR equ 0x21
|
||||
|
||||
IC_CMD_SEND equ 0x10
|
||||
IC_CMD_RECV equ 0x11
|
||||
IC_CMD_SENDTO equ 0x18
|
||||
IC_CMD_RECVFROM equ 0x19
|
||||
|
||||
IC_CMD_RES_OK equ 0x00
|
||||
IC_CMD_RES_FAIL equ 0xff
|
||||
|
||||
; buffers
|
||||
|
||||
cmd_buffer ds 10
|
||||
|
||||
|
||||
|
||||
|
||||
;------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
;socket()
|
||||
;> byte #01
|
||||
; byte address_family
|
||||
; byte type
|
||||
; byte protocol
|
||||
;< byte res (0=ok)
|
||||
;<? byte fd
|
||||
|
||||
;IN:
|
||||
;l=address_family
|
||||
;h=sock_type
|
||||
;c=proto
|
||||
;OUT:
|
||||
;a=fd/INVALID_SOCKET
|
||||
socket
|
||||
ex de,hl
|
||||
ld hl,cmd_buffer
|
||||
ld (hl),IC_CMD_SOCKET:inc hl
|
||||
ld (hl),e:inc hl
|
||||
ld (hl),d:inc hl
|
||||
ld (hl),c
|
||||
|
||||
ld hl,cmd_buffer,bc,4
|
||||
call uart.Write
|
||||
call uart.GetChar
|
||||
or a:jr nz,socket_err
|
||||
call uart.GetChar
|
||||
ret
|
||||
|
||||
socket_err
|
||||
ld a,INVALID_SOCKET
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;bind()
|
||||
;> byte #02
|
||||
; byte fd
|
||||
; long my_addr
|
||||
; word port
|
||||
;< byte res (0=ok)
|
||||
|
||||
;IN:
|
||||
;a=fd
|
||||
;hl=address of ip and port (db a,b,c,d:dw port)
|
||||
;OUT:
|
||||
;a=res (0=ok)
|
||||
bind
|
||||
ex de,hl
|
||||
ld hl,cmd_buffer
|
||||
ld (hl),IC_CMD_BIND:inc hl
|
||||
ld (hl),a:inc hl
|
||||
ex de,hl
|
||||
ld bc,6:ldir ;copy ip+port
|
||||
|
||||
ld hl,cmd_buffer,c,8
|
||||
call uart.Write
|
||||
call uart.GetChar
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
;connect()
|
||||
;> byte #03
|
||||
; byte fd
|
||||
; long serv_addr
|
||||
; word port
|
||||
;< byte res (0=ok)
|
||||
|
||||
;IN:
|
||||
;a=fd
|
||||
;hl=address of ip and port (db a,b,c,d:dw port)
|
||||
;OUT:
|
||||
;a=res (0=ok)
|
||||
connect
|
||||
ex de,hl
|
||||
ld hl,cmd_buffer
|
||||
ld (hl),IC_CMD_CONNECT:inc hl
|
||||
ld (hl),a:inc hl
|
||||
ex de,hl
|
||||
ld bc,6:ldir ;copy ip+port
|
||||
|
||||
ld hl,cmd_buffer,c,8
|
||||
call uart.Write
|
||||
call uart.GetChar
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;close()
|
||||
;> byte #06
|
||||
; byte fd
|
||||
;< byte res (0=ok)
|
||||
|
||||
;IN:
|
||||
;a=fd
|
||||
;OUT:
|
||||
;a=res (0=ok)
|
||||
close
|
||||
push af
|
||||
ld a,IC_CMD_CLOSE:call uart.PutChar
|
||||
pop af:call uart.PutChar
|
||||
call uart.GetChar
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;send()
|
||||
;> byte #10
|
||||
; byte fd
|
||||
; word buflen
|
||||
; byte flags
|
||||
;< byte res (0=ok)
|
||||
;>? byte buf[buflen]
|
||||
;<? word realsent (#ffff = error)
|
||||
|
||||
;IN:
|
||||
;a=fd
|
||||
;hl=buf
|
||||
;bc=len
|
||||
;OUT:
|
||||
;a=res (0=ok)
|
||||
;bc=reallen
|
||||
send
|
||||
ld (send2+1),hl ;save buf addr
|
||||
ld (send1+1),bc ;save data len
|
||||
ld hl,cmd_buffer
|
||||
ld (hl),IC_CMD_SEND:inc hl
|
||||
ld (hl),a:inc hl
|
||||
ld (hl),c:inc hl
|
||||
ld (hl),b:inc hl
|
||||
ld (hl),0 ;flags, skipped now
|
||||
|
||||
ld hl,cmd_buffer,bc,5
|
||||
call uart.Write
|
||||
call uart.GetChar
|
||||
or a:ret nz ;ret if error
|
||||
|
||||
send1 ld bc,0
|
||||
ld a,b:or c:jr z,send_skip
|
||||
send2 ld hl,0
|
||||
call uart.Write ;put data
|
||||
|
||||
send_skip
|
||||
call uart.GetChar
|
||||
push af
|
||||
call uart.GetChar
|
||||
ld b,a
|
||||
pop af
|
||||
ld c,a ;bc=real len
|
||||
xor a
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;recv()
|
||||
;> byte #11
|
||||
; byte fd
|
||||
; word len
|
||||
; byte flags
|
||||
;< byte res (0=ok)
|
||||
;>? word reallen
|
||||
;>?? byte buf[reallen]
|
||||
|
||||
;IN:
|
||||
;a=fd
|
||||
;hl=buf
|
||||
;bc=len
|
||||
;OUT:
|
||||
;a=res (0=ok)
|
||||
;bc=reallen
|
||||
recv
|
||||
ld (recv1+1),hl ;save buf addr
|
||||
ld hl,cmd_buffer
|
||||
ld (hl),IC_CMD_RECV:inc hl
|
||||
ld (hl),a:inc hl
|
||||
ld (hl),c:inc hl
|
||||
ld (hl),b:inc hl
|
||||
ld (hl),0 ;flags, skipped now
|
||||
|
||||
ld hl,cmd_buffer,bc,5
|
||||
call uart.Write
|
||||
call uart.GetChar
|
||||
or a:ret nz ;ret if error
|
||||
|
||||
call uart.GetChar
|
||||
push af
|
||||
call uart.GetChar
|
||||
ld b,a
|
||||
pop af
|
||||
ld c,a ;bc=real len
|
||||
ld a,b
|
||||
or c
|
||||
jr z,recv_skip
|
||||
push bc
|
||||
recv_skip_header ld a,0
|
||||
or a
|
||||
jr nz,recv1
|
||||
push bc
|
||||
pop hl
|
||||
; skip http header
|
||||
2 call uart.GetChar
|
||||
dec hl
|
||||
cp #0d
|
||||
jr nz,2b
|
||||
call uart.GetChar
|
||||
dec hl
|
||||
cp #0a
|
||||
jr nz,2b
|
||||
call uart.GetChar
|
||||
dec hl
|
||||
cp #0d
|
||||
jr nz,2b
|
||||
call uart.GetChar
|
||||
dec hl
|
||||
cp #0a
|
||||
jr nz,2b
|
||||
ld b,h
|
||||
ld c,l
|
||||
ld (recv_skip_header+1),a
|
||||
pop hl
|
||||
push bc
|
||||
recv1 ld hl,0
|
||||
call uart.Read ;get data
|
||||
pop bc
|
||||
recv_skip
|
||||
xor a
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;gethostbyname
|
||||
;> byte #20
|
||||
;> word name_len
|
||||
;> ascii hostname
|
||||
;< byte res (0=ok)
|
||||
;<? long ip
|
||||
|
||||
;IN:
|
||||
;hl=name
|
||||
;bc=len
|
||||
;OUT:
|
||||
;a=res (0=ok)
|
||||
;hl:bc=ip
|
||||
gethostbyname
|
||||
ld (ghbn1+1),hl ;save name addr
|
||||
ld (ghbn2+1),bc ;save len
|
||||
ld hl,cmd_buffer
|
||||
ld (hl),IC_CMD_GETHOSTBYNAME:inc hl
|
||||
ld (hl),c:inc hl
|
||||
ld (hl),b:inc hl
|
||||
|
||||
ld hl,cmd_buffer,bc,3
|
||||
call uart.Write
|
||||
ghbn1 ld hl,0
|
||||
ghbn2 ld bc,0
|
||||
call uart.Write
|
||||
|
||||
call uart.GetChar
|
||||
or a:ret nz ;ret if error
|
||||
|
||||
ld hl,cmd_buffer,bc,4
|
||||
call uart.Read ;get data
|
||||
|
||||
ld hl,(cmd_buffer),bc,(cmd_buffer+2)
|
||||
xor a
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
|
||||
; socket types
|
||||
|
||||
SOCK_STREAM equ 1 ; stream socket (TCP)
|
||||
SOCK_DGRAM equ 2 ; datagram socket (UDP)
|
||||
|
||||
; address families
|
||||
|
||||
AF_INET equ 2 ; internetwork: UDP, TCP, etc.
|
||||
|
||||
; constants
|
||||
|
||||
INVALID_SOCKET equ #ff ;-1
|
||||
|
||||
|
||||
macro socket _xaf,_xst,_xproto
|
||||
ld hl,_xaf+256*_xst
|
||||
ld c,_xproto
|
||||
call sockets.socket
|
||||
endm
|
||||
|
||||
macro bind _xfd,_xaddr
|
||||
ld hl,_xaddr
|
||||
ld a,(_xfd)
|
||||
call sockets.bind
|
||||
endm
|
||||
|
||||
macro connect _xfd,_xaddr
|
||||
ld hl,_xaddr
|
||||
ld a,(_xfd)
|
||||
call sockets.connect
|
||||
endm
|
||||
|
||||
macro close _xfd
|
||||
ld a,(_xfd)
|
||||
call sockets.close
|
||||
endm
|
||||
|
||||
|
||||
|
||||
|
||||
macro send _xfd,_xaddr,_xlen
|
||||
ld hl,_xaddr,bc,_xlen
|
||||
ld a,(_xfd)
|
||||
call sockets.send
|
||||
endm
|
||||
|
||||
macro recv _xfd,_xaddr,_xlen
|
||||
ld hl,_xaddr,bc,_xlen
|
||||
ld a,(_xfd)
|
||||
call sockets.recv
|
||||
endm
|
||||
|
||||
macro gethostbyname _xname,_xlen
|
||||
ld hl,_xname,bc,_xlen
|
||||
call sockets.gethostbyname
|
||||
endm
|
||||
|
||||
|
||||
+213
@@ -0,0 +1,213 @@
|
||||
|
||||
module uart
|
||||
|
||||
|
||||
BASEREG EQU #F8EF
|
||||
|
||||
|
||||
;DLAB=0
|
||||
THR EQU BASEREG+#000 ;(W)Transmit Holding Register
|
||||
RBR EQU BASEREG+#000 ;(R)Receive Buffer Register
|
||||
IER EQU BASEREG+#100 ;(RW)Interrupt Enable Register
|
||||
|
||||
EDSSI EQU %1000 ;Enable Modem Status Interrupt
|
||||
ELSI EQU %0100 ;Enable Receiver Line Status Interrupt
|
||||
ETBEI EQU %0010 ;Enable Transmitter Holding Register Empty Interrupt
|
||||
ERBFI EQU %0001 ;Enable Received Data Available Interrupt
|
||||
|
||||
FCR EQU BASEREG+#200 ;(W)FIFO Control Register
|
||||
IIR EQU BASEREG+#200 ;(R)Interrupt Identification Register
|
||||
|
||||
LCR EQU BASEREG+#300 ;(RW)Line Control Register
|
||||
|
||||
DLAB EQU %10000000 ;Divisor Latch Access Bit
|
||||
SETBRK EQU %01000000 ;Set Break
|
||||
STKPAR EQU %00100000 ;Stick Parity
|
||||
EPS EQU %00010000 ;Even Parity Select
|
||||
PEN EQU %00001000 ;Parity Enable
|
||||
STB EQU %00000100 ;Number of Stop Bits
|
||||
WLSB1 EQU %00000010 ;Word Length Select #1
|
||||
WLSB0 EQU %00000001 ;Word Length Select #0
|
||||
|
||||
MCR EQU BASEREG+#400 ;(RW)Modem Control Register
|
||||
|
||||
RTS EQU %10 ;Request to Send
|
||||
DTR EQU %01 ;Data Terminal Ready
|
||||
|
||||
LSR EQU BASEREG+#500 ;(RW)Line Status Register
|
||||
|
||||
FIFOE EQU %10000000 ;Error in Receiver FIFO
|
||||
TEMT EQU %01000000 ;Transmitter Empty
|
||||
THRE EQU %00100000 ;Transmitter Holding Register Empty
|
||||
BI EQU %00010000 ;Break Interrupt (BI)
|
||||
FE EQU %00001000 ;Framing Error (FE)
|
||||
PE EQU %00000100 ;Parity Error (PE)
|
||||
OE EQU %00000010 ;Overrun Error (OE)
|
||||
DR EQU %00000001 ;Data Ready (DR)
|
||||
|
||||
|
||||
MSR EQU BASEREG+#600 ;(RW)Modem Status Register
|
||||
|
||||
DCD EQU %10000000 ;Data Carrier Detect
|
||||
RI EQU %01000000 ;Ring Indicator
|
||||
DSR EQU %00100000 ;Data Set Ready
|
||||
CTS EQU %00010000 ;Clear To Send
|
||||
DDCD EQU %00001000 ;Delta Data Carrier Detect
|
||||
TERI EQU %00000100 ;Trailing Edge Ring Indicator
|
||||
DDSR EQU %00000010 ;Delta Data Set Ready
|
||||
DCTS EQU %00000001 ;Delta Clear To Send
|
||||
|
||||
SCR EQU BASEREG+#700 ;(RW)Scratch Register
|
||||
|
||||
;DLAB=1
|
||||
DLL EQU BASEREG+#000 ;(RW)Divisor Latch LSB
|
||||
DLH EQU BASEREG+#100 ;(RW)Divisor Latch MSB
|
||||
|
||||
|
||||
;eRS232 for ZX-Evo
|
||||
ERS_DR EQU #00EF
|
||||
ERS_SR EQU #C2EF
|
||||
ERS_ST EQU #C3EF
|
||||
ERS_CR EQU #C7EF
|
||||
|
||||
|
||||
;set baud rate
|
||||
;hl=divider
|
||||
SetBaud
|
||||
ld bc,LCR
|
||||
in a,(c):or DLAB:out (c),a ;set DLAB=1
|
||||
|
||||
ld b,high DLL
|
||||
out (c),l ;low
|
||||
inc b
|
||||
out (c),h ;high
|
||||
|
||||
ld b,high LCR
|
||||
in a,(c):and !DLAB:out (c),a ;set DLAB=0
|
||||
|
||||
ld b,high ERS_CR
|
||||
ld a,#F1
|
||||
out (c),a
|
||||
ld a,#07
|
||||
out (c),a
|
||||
ret
|
||||
|
||||
|
||||
;set line control register
|
||||
;a=status
|
||||
SetLineControl
|
||||
ld bc,LCR
|
||||
out (c),a
|
||||
ret
|
||||
|
||||
|
||||
;put char
|
||||
;a=char
|
||||
PutChar
|
||||
ld bc,ERS_ST
|
||||
exa
|
||||
pc1 in f,(c):jr z,pc1 ;wait for room
|
||||
exa
|
||||
|
||||
ld b,high ERS_DR
|
||||
out (c),a
|
||||
ret
|
||||
|
||||
|
||||
|
||||
;get char
|
||||
;out: a=char
|
||||
GetChar
|
||||
ld bc,ERS_SR
|
||||
gc1 in f,(c):jr z,gc1 ;wait for data
|
||||
|
||||
ld b,high ERS_DR
|
||||
in a,(c)
|
||||
ret
|
||||
|
||||
|
||||
|
||||
;write block
|
||||
;hl=buffer addr
|
||||
;bc=len
|
||||
Write
|
||||
ld d,b
|
||||
ld e,c
|
||||
ww1 ld bc,ERS_ST
|
||||
in c,(c)
|
||||
jr z,ww1
|
||||
ld a,d
|
||||
or a
|
||||
jr nz,ww2
|
||||
ld a,e
|
||||
cp c
|
||||
jr nc,ww2
|
||||
ld c,e
|
||||
ww2 ex de,hl
|
||||
xor a
|
||||
ld b,a
|
||||
sbc hl,bc
|
||||
ex de,hl
|
||||
ld b,c
|
||||
ld c,low ERS_DR
|
||||
otir
|
||||
ld a,d
|
||||
or e
|
||||
jr nz,ww1
|
||||
ret
|
||||
|
||||
;read block
|
||||
;hl=buffer addr
|
||||
;bc=len
|
||||
Read
|
||||
ld d,b
|
||||
ld e,c
|
||||
rr1 ld bc,ERS_SR
|
||||
in c,(c)
|
||||
jr z,rr1
|
||||
ld a,d
|
||||
or a
|
||||
jr nz,rr2
|
||||
ld a,e
|
||||
cp c
|
||||
jr nc,rr2
|
||||
ld c,e
|
||||
rr2 ex de,hl
|
||||
xor a
|
||||
ld b,a
|
||||
sbc hl,bc
|
||||
ex de,hl
|
||||
ld b,c
|
||||
ld c,low ERS_DR
|
||||
inir
|
||||
cable_cancel_download ld a,0
|
||||
or a
|
||||
jp nz,cable_cancel_download_ex
|
||||
ld a,d
|
||||
or e
|
||||
jr nz,rr1
|
||||
ret
|
||||
|
||||
;;read block fast
|
||||
;;hl=buffer addr
|
||||
;;bc=len
|
||||
;Readf push hl:exx:pop hl
|
||||
; ld de,high LSR+256*high RBR ;+256
|
||||
;
|
||||
; ld c,low LSR
|
||||
;r0_ dup 16
|
||||
; ld b,e
|
||||
; in a,(c):and DR:jr z,$-4 ;wait
|
||||
;
|
||||
; ld b,d:ini
|
||||
; edup
|
||||
; exx
|
||||
; dup 16
|
||||
; dec bc
|
||||
; edup
|
||||
; ld a,b:or c
|
||||
; exx
|
||||
; jp nz,r0
|
||||
; ret
|
||||
|
||||
endmodule
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,169 @@
|
||||
device zxspectrum128
|
||||
|
||||
org #c000
|
||||
|
||||
include "sockets.mac"
|
||||
|
||||
|
||||
start_
|
||||
jp init
|
||||
jp get
|
||||
|
||||
|
||||
|
||||
init
|
||||
;init uart
|
||||
ld hl,2 ;BaudRate = 115200 / divfq;
|
||||
call uart.SetBaud
|
||||
|
||||
;init uart
|
||||
ld a,uart.WLSB1+uart.WLSB0 ;8 bit word, no parity
|
||||
call uart.SetLineControl
|
||||
|
||||
ret
|
||||
|
||||
; BUFFER equ 0
|
||||
; BUFFER_SIZE equ 1
|
||||
|
||||
GET_HDR dw 0
|
||||
GET_HDR_LEN dw 0
|
||||
GET_PAGE db 0
|
||||
host_addr_len dw 0
|
||||
host_addr dw 0
|
||||
|
||||
;in:
|
||||
;a=page
|
||||
;hl=get hdr
|
||||
;out:
|
||||
;a=0 - ok
|
||||
;hl=len_l
|
||||
;bc=len_h
|
||||
get
|
||||
ld (GET_HDR),hl
|
||||
ld (GET_PAGE),a
|
||||
;get host name
|
||||
g1 ld a,(hl)
|
||||
or a:jp z,get_err
|
||||
cp 'H':jr z,get_h1
|
||||
inc hl:jr g1
|
||||
|
||||
get_h1 inc hl
|
||||
ld a,(hl):cp 'o':jr nz,g1:inc hl
|
||||
ld a,(hl):cp 's':jr nz,g1:inc hl
|
||||
ld a,(hl):cp 't':jr nz,g1:inc hl
|
||||
ld a,(hl):cp ':':jr nz,g1:inc hl
|
||||
ld a,(hl):cp ' ':jr nz,g1:inc hl
|
||||
|
||||
ld (host_addr),hl
|
||||
ld bc,0
|
||||
gh1 ld a,(hl):cp 13:jr z,ghe
|
||||
cp ":":jr z,ghe
|
||||
cp "/":jr z,ghe ;?
|
||||
inc hl,bc:jr gh1
|
||||
|
||||
ghe ld (host_addr_len),bc
|
||||
|
||||
;get HDR len
|
||||
g2 ld a,(hl)
|
||||
or a:jr z,g3
|
||||
inc hl:jr g2
|
||||
|
||||
g3 ld de,(GET_HDR):or a:sbc hl,de:ld (GET_HDR_LEN),hl
|
||||
|
||||
;gethostbyname
|
||||
ld hl,(host_addr),bc,(host_addr_len)
|
||||
call sockets.gethostbyname
|
||||
or a:jp nz,get_err
|
||||
ld (server_addr),hl,(server_addr+2),bc
|
||||
|
||||
;create socket
|
||||
socket AF_INET,SOCK_STREAM,0
|
||||
cp INVALID_SOCKET:jp z,get_err
|
||||
ld (fd),a
|
||||
|
||||
;bind my socket
|
||||
bind fd,my_addr
|
||||
or a:jp nz,get_err
|
||||
|
||||
;connect to host
|
||||
connect fd,server_addr
|
||||
or a:jr nz,get_err
|
||||
|
||||
;send HTTP request
|
||||
send fd,(GET_HDR),(GET_HDR_LEN)
|
||||
or a:jr nz,get_err
|
||||
|
||||
ld ix,0 ;full pages got
|
||||
ld hl,#4000
|
||||
get_loop
|
||||
ld a,(GET_PAGE)
|
||||
ld bc,#11af:out (c),a
|
||||
ld de,#8000:ex de,hl:or a:sbc hl,de:ex de,hl ;de=len,hl=start
|
||||
;recv data
|
||||
; recv fd,BUFFER,BUFFER_SIZE
|
||||
push hl
|
||||
ld b,d,c,e
|
||||
ld a,(fd)
|
||||
call sockets.recv
|
||||
pop hl
|
||||
or a:jr nz,get_end
|
||||
; ld a,b:or c:jr z,get_end
|
||||
|
||||
add hl,bc
|
||||
bit 7,h
|
||||
jr z,get_loop
|
||||
|
||||
ld hl,GET_PAGE:inc (hl)
|
||||
ld hl,#4000
|
||||
inc ixl
|
||||
jr get_loop
|
||||
|
||||
get_end res 6,h:res 7,h
|
||||
ld de,0,b,0,c,ixl
|
||||
srl c:rr d:rr e
|
||||
srl c:rr d:rr e
|
||||
add hl,de ;bc:hl=len
|
||||
|
||||
|
||||
get_e ld a,(fd):cp #ff:jr z,noclose
|
||||
push hl,bc
|
||||
;close socket
|
||||
close fd
|
||||
pop bc,hl
|
||||
noclose ld a,#ff,(fd),a
|
||||
xor a
|
||||
ret
|
||||
|
||||
|
||||
get_err call get_e
|
||||
inc a
|
||||
ret
|
||||
|
||||
|
||||
;-----------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
fd db #ff ;socket fd
|
||||
my_addr db 0,0,0,0:dw 0 ;my ip+port
|
||||
|
||||
|
||||
|
||||
|
||||
server_addr db 93,158,134,3:dw 80
|
||||
|
||||
;code
|
||||
include "uart.a80"
|
||||
include "sockets.a80"
|
||||
|
||||
|
||||
end_
|
||||
|
||||
|
||||
;save snap
|
||||
SAVEBIN "_spg/zificom.bin",start_, end_-start_
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user