Properly support multiple clients

This commit is contained in:
dschmenk 2013-08-28 09:47:31 -07:00
parent c35c2e78d8
commit 86e09f6aa7

View File

@ -28,7 +28,7 @@
#define MAX_XFER 32 #define MAX_XFER 32
struct a2request { struct a2request {
int fd; int idx;
int type; int type;
int addr; int addr;
int count; int count;
@ -36,7 +36,18 @@ struct a2request {
char *buffer; char *buffer;
struct a2request *next; struct a2request *next;
} *a2reqlist = NULL, *a2reqfree = NULL; } *a2reqlist = NULL, *a2reqfree = NULL;
/*
* Client info
*/
#define CLIENT_OPEN 1
#define CLIENT_CLOSING 2
#define CLIENT_COUT 4
#define MAX_CLIENT 8
struct {
int fd;
int flags;
} a2client[MAX_CLIENT];
/* /*
* ASCII to scancode conversion * ASCII to scancode conversion
*/ */
@ -451,7 +462,7 @@ void prlog(char *str)
if (!isdaemon) if (!isdaemon)
puts(str); puts(str);
} }
struct a2request *addreq(int a2fd, int reqfd, int type, int addr, int count, char *buffer) struct a2request *addreq(int a2fd, int clidx, int type, int addr, int count, char *buffer)
{ {
char rwchar; char rwchar;
struct a2request *a2req = a2reqfree; struct a2request *a2req = a2reqfree;
@ -459,7 +470,7 @@ struct a2request *addreq(int a2fd, int reqfd, int type, int addr, int count, cha
a2req = malloc(sizeof(struct a2request)); a2req = malloc(sizeof(struct a2request));
else else
a2reqfree = a2reqfree->next; a2reqfree = a2reqfree->next;
a2req->fd = reqfd; a2req->idx = clidx;
a2req->type = type; a2req->type = type;
a2req->addr = addr; a2req->addr = addr;
a2req->count = count; a2req->count = count;
@ -502,13 +513,13 @@ void finreq(int a2fd, int status, int result)
/* /*
* Send result to socket. * Send result to socket.
*/ */
if (a2req->fd) if (a2client[a2req->idx].flags & CLIENT_OPEN)
{ {
if (a2req->type == 0x90) /* read bytes */ if (a2req->type == 0x90) /* read bytes */
write(a2req->fd, a2req->buffer, a2req->count); write(a2client[a2req->idx].fd, a2req->buffer, a2req->count);
finbuf[0] = status; finbuf[0] = status;
finbuf[1] = result; finbuf[1] = result;
write(a2req->fd, finbuf, 2); write(a2client[a2req->idx].fd, finbuf, 2);
} }
if (a2req->buffer) if (a2req->buffer)
{ {
@ -522,34 +533,53 @@ void finreq(int a2fd, int status, int result)
a2req->next = a2reqfree; a2req->next = a2reqfree;
a2reqfree = a2req; a2reqfree = a2req;
} }
void flushreqs(int a2fd, int status, int result) void flushreqs(int a2fd, int clidx, int status, int result)
{ {
char finbuf[2]; char finbuf[2];
struct a2request *a2req; struct a2request *a2req = a2reqlist, *a2reqprev = NULL;
while (a2req = a2reqlist) while (a2req)
{ {
/* if (clidx < 0 || clidx == a2req->idx)
* Send result to socket. {
*/ /*
if (a2req->fd) * Send result to socket.
{ */
if (a2req->type == 0x90) /* read bytes */ if (a2client[a2req->idx].flags & CLIENT_OPEN)
write(a2req->fd, a2req->buffer, a2req->count); {
finbuf[0] = status; if (a2req->type == 0x90) /* read bytes */
finbuf[1] = result; write(a2client[a2req->idx].fd, a2req->buffer, a2req->count);
write(a2req->fd, finbuf, 2); finbuf[0] = status;
} finbuf[1] = result;
if (a2req->buffer) write(a2client[a2req->idx].fd, finbuf, 2);
{ }
free(a2req->buffer); if (a2req->buffer)
a2req->buffer = NULL; {
} free(a2req->buffer);
/* a2req->buffer = NULL;
* Update lists. }
*/ /*
a2reqlist = a2req->next; * Update lists.
a2req->next = a2reqfree; */
a2reqfree = a2req; if (a2req == a2reqlist)
{
a2reqlist = a2req->next;
a2req->next = a2reqfree;
a2reqfree = a2req;
a2req = a2reqlist;
}
else
{
a2reqprev->next = a2req->next;
a2req->next = a2reqfree;
a2reqfree = a2req;
a2req = a2reqprev->next;
}
}
else
{
a2reqprev = a2req;
a2req = a2req->next;
}
} }
} }
void main(int argc, char **argv) void main(int argc, char **argv)
@ -557,8 +587,8 @@ void main(int argc, char **argv)
struct uinput_user_dev uidev; struct uinput_user_dev uidev;
struct termios oldtio,newtio; struct termios oldtio,newtio;
unsigned char iopkt[16]; unsigned char iopkt[16];
int i, c, lastbtn, cout; int i, c, rdycnt;
int a2fd, kbdfd, moufd, srvfd, reqfd, coutfd, maxfd; int a2fd, kbdfd, moufd, srvfd, maxfd;
struct sockaddr_in servaddr; struct sockaddr_in servaddr;
fd_set readset, openset; fd_set readset, openset;
char *devtty = "/dev/ttyAMA0"; /* default for Raspberry Pi */ char *devtty = "/dev/ttyAMA0"; /* default for Raspberry Pi */
@ -730,33 +760,43 @@ void main(int argc, char **argv)
die("error: socket create"); die("error: socket create");
if (bind(srvfd,(struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) if (bind(srvfd,(struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
die("error: bind socket"); die("error: bind socket");
if (listen(srvfd, 1) < 0) if (listen(srvfd, MAX_CLIENT - 1) < 0)
die("error: listen socket"); die("error: listen socket");
/* /*
* Come basck here on RESET. * Come basck here on RESET.
*/ */
reset: reset:
state = RUN; state = RUN;
cout = -1; for (i = 0; i < MAX_CLIENT; i++)
reqfd = coutfd = 0; {
a2client[i].fd = 0;
a2client[i].flags = 0;
}
maxfd = 0;
FD_ZERO(&openset); FD_ZERO(&openset);
FD_SET(a2fd, &openset); FD_SET(a2fd, &openset);
FD_SET(srvfd, &openset); FD_SET(srvfd, &openset);
maxfd = a2fd > srvfd ? a2fd : srvfd;
/* /*
* Event loop * Event loop
*/ */
prlog("a2pid: Enter event loop\n"); prlog("a2pid: Enter event loop\n");
while (state == RUN) while (state == RUN)
{ {
if (maxfd == 0)
{
maxfd = a2fd > srvfd ? a2fd : srvfd;
for (i = 0; i < MAX_CLIENT; i++)
maxfd = a2client[i].fd > maxfd ? a2client[i].fd : maxfd;
}
memcpy(&readset, &openset, sizeof(openset)); memcpy(&readset, &openset, sizeof(openset));
if (select(maxfd + 1, &readset, NULL, NULL, NULL) > 0) if ((rdycnt = select(maxfd + 1, &readset, NULL, NULL, NULL)) > 0)
{ {
/* /*
* Serial port to Apple II transaction. * Serial port to Apple II transaction.
*/ */
if (FD_ISSET(a2fd, &readset)) if (FD_ISSET(a2fd, &readset))
{ {
rdycnt--;
if (read(a2fd, iopkt, 3) == 3) if (read(a2fd, iopkt, 3) == 3)
{ {
// printf("a2pi: A2 Event [0x%02X] [0x%02X] [0x%02X]\n", iopkt[0], iopkt[1], iopkt[2]); // printf("a2pi: A2 Event [0x%02X] [0x%02X] [0x%02X]\n", iopkt[0], iopkt[1], iopkt[2]);
@ -767,7 +807,7 @@ reset:
iopkt[0] = 0x81; /* acknowledge */ iopkt[0] = 0x81; /* acknowledge */
write(a2fd, iopkt, 1); write(a2fd, iopkt, 1);
tcflush(a2fd, TCIFLUSH); tcflush(a2fd, TCIFLUSH);
flushreqs(a2fd, -1, -1); flushreqs(a2fd, 0, -1, -1);
break; break;
case 0x82: /* keyboard event */ case 0x82: /* keyboard event */
// printf("Keyboard Event: 0x%02X:%c\n", iopkt[1], iopkt[2] & 0x7F); // printf("Keyboard Event: 0x%02X:%c\n", iopkt[1], iopkt[2] & 0x7F);
@ -866,10 +906,9 @@ reset:
state = RESET; state = RESET;
break; break;
case 0x98: /* get output char from Apple II */ case 0x98: /* get output char from Apple II */
if (coutfd) for (i = 0; i < MAX_CLIENT; i++)
write(coutfd, iopkt, 2); if (a2client[i].flags & CLIENT_COUT)
else write(a2client[i].fd, iopkt, 2);
cout = iopkt[1];
break; break;
case 0x9E: /* request complete ok */ case 0x9E: /* request complete ok */
case 0x9F: /* request complete error */ case 0x9F: /* request complete error */
@ -900,117 +939,133 @@ reset:
else else
{ {
prlog("a2pid: error read serial port ????\n"); prlog("a2pid: error read serial port ????\n");
state = RESET; state = STOP;
} }
} }
/* /*
* Socket server connection. * Open client connection.
*/ */
if (FD_ISSET(srvfd, &readset)) if (FD_ISSET(srvfd, &readset))
{ {
reqfd = accept(srvfd, NULL, NULL); rdycnt--;
if (reqfd > 0) int clientfd = accept(srvfd, NULL, NULL);
FD_SET(reqfd, &openset); if (clientfd >= 0)
{
for (i = 0; i < MAX_CLIENT; i++)
{
if (a2client[i].flags == 0)
{
a2client[i].fd = clientfd;
a2client[i].flags = CLIENT_OPEN;
FD_SET(a2client[i].fd, &openset);
maxfd = a2client[i].fd > maxfd ? a2client[i].fd : maxfd;
prlog("a2pi: Client Connect\n");
break;
}
}
if (i >= MAX_CLIENT)
/*
* Out of client structures.
*/
close(clientfd);
}
else else
prlog("a2pid: error accept"); prlog("a2pid: error accept");
maxfd = reqfd > maxfd ? reqfd : maxfd;
prlog("a2pi: Client Connect\n");
} }
/* /*
* Socket client request. * Socket client request.
*/ */
if (reqfd > 0 && FD_ISSET(reqfd, &readset)) for (i = 0; rdycnt > 0 && i < MAX_CLIENT; i++)
{ {
int addr, count; if (a2client[i].flags && FD_ISSET(a2client[i].fd, &readset))
char *databuf;
if (read(reqfd, iopkt, 1) == 1)
{ {
// printf("a2pi: Client Request [0x%02X]\n", iopkt[0]); int addr, count;
switch (iopkt[0]) char *databuf;
rdycnt--;
if (read(a2client[i].fd, iopkt, 1) == 1)
{ {
case 0x90: /* read bytes */ // printf("a2pi: Client Request [0x%02X]\n", iopkt[0]);
if (read(reqfd, iopkt, 4) == 4) switch (iopkt[0])
{ {
addr = (unsigned char)iopkt[0] | ((unsigned char)iopkt[1] << 8); case 0x90: /* read bytes */
count = (unsigned char)iopkt[2] | ((unsigned char)iopkt[3] << 8); if (read(a2client[i].fd, iopkt, 4) == 4)
if (count)
{ {
databuf = malloc(count); addr = (unsigned char)iopkt[0] | ((unsigned char)iopkt[1] << 8);
addreq(a2fd, reqfd, 0x90, addr, count, databuf); count = (unsigned char)iopkt[2] | ((unsigned char)iopkt[3] << 8);
if (count)
{
databuf = malloc(count);
addreq(a2fd, i, 0x90, addr, count, databuf);
}
else
{
iopkt[0] = 0x9E;
iopkt[1] = 0x00;
write(a2client[i].fd, iopkt, 2);
}
} }
else break;
case 0x92: /* write bytes */
if (read(a2client[i].fd, iopkt, 4) == 4)
{ {
iopkt[0] = 0x9E; addr = (unsigned char)iopkt[0] | ((unsigned char)iopkt[1] << 8);
iopkt[1] = 0x00; count = (unsigned char)iopkt[2] | ((unsigned char)iopkt[3] << 8);
write(reqfd, iopkt, 2); if (count)
{
databuf = malloc(count);
if (read(a2client[i].fd, databuf, count) == count)
addreq(a2fd, i, 0x92, addr, count, databuf);
}
else
{
iopkt[0] = 0x9E;
iopkt[1] = 0x00;
write(a2client[i].fd, iopkt, 2);
}
} }
} break;
break; case 0x94: /* call */
case 0x92: /* write bytes */ if (read(a2client[i].fd, iopkt, 2) == 2)
if (read(reqfd, iopkt, 4) == 4)
{
addr = (unsigned char)iopkt[0] | ((unsigned char)iopkt[1] << 8);
count = (unsigned char)iopkt[2] | ((unsigned char)iopkt[3] << 8);
if (count)
{ {
databuf = malloc(count); addr = (unsigned char)iopkt[0] | ((unsigned char)iopkt[1] << 8);
if (read(reqfd, databuf, count) == count) addreq(a2fd, i, 0x94, addr, 0, NULL);
addreq(a2fd, reqfd, 0x92, addr, count, databuf);
} }
else break;
{ case 0x96: /* send input char to Apple II */
iopkt[0] = 0x9E; if (read(a2client[i].fd, iopkt, 1) == 1)
iopkt[1] = 0x00; addreq(a2fd, i, 0x96, iopkt[0], 0, NULL);
write(reqfd, iopkt, 2); break;
} case 0x98: /* get output chars from Apple II */
} a2client[i].flags |= CLIENT_COUT;
break; break;
case 0x94: /* call */ case 0xFF: /* close */
if (read(reqfd, iopkt, 2) == 2) a2client[i].flags = CLIENT_CLOSING;
{ break;
addr = (unsigned char)iopkt[0] | ((unsigned char)iopkt[1] << 8); default:
addreq(a2fd, reqfd, 0x94, addr, 0, NULL); prlog("a2pid: Unknown Request\n");
} }
break; }
case 0x96: /* send input char to Apple II */ else
if (read(reqfd, iopkt, 1) == 1) {
addreq(a2fd, reqfd, 0x96, iopkt[0], 0, NULL); /*
break; * Close client socket connection.
case 0x98: /* get output chars from Apple II */ */
if (cout >= 0) FD_CLR(a2client[i].fd, &openset);
{ close(a2client[i].fd);
iopkt[1] = cout; if (a2client[i].fd >= maxfd)
write(reqfd, iopkt, 2); maxfd = 0;
cout = -1; a2client[i].fd = 0;
} a2client[i].flags = 0;
coutfd = reqfd; flushreqs(a2fd, i, -1, -1);
break;
case 0xFF: /* close */
FD_CLR(reqfd, &openset);
close(reqfd);
reqfd = 0;
coutfd = 0;
maxfd = a2fd > srvfd ? a2fd : srvfd;
break;
default:
prlog("a2pid: Unknown Request\n");
} }
}
else
{
FD_CLR(reqfd, &openset);
close(reqfd);
reqfd = 0;
coutfd = 0;
maxfd = a2fd > srvfd ? a2fd : srvfd;
prlog("a2pid: error read socket ????");
} }
} }
} }
} }
flushreqs(a2fd, -1, -1); flushreqs(a2fd, -1, -1, -1);
if (reqfd > 0) for (i = 0; i < MAX_CLIENT; i++)
close(reqfd); if (a2client[i].flags)
close(a2client[i].fd);
if (state == RESET) if (state == RESET)
goto reset; goto reset;
shutdown(srvfd, SHUT_RDWR); shutdown(srvfd, SHUT_RDWR);